JSON encoding of maps with non-string key types is invalid
joe-p opened this issue · comments
Subject of the issue
When encoding a Block
, StateProofTracking
in BlockHeader
is not encoded properly.
Your environment
github.com/algorand/go-algorand-sdk/v2 v2.0.0-20230531123858-3a0efd6a6398
Steps to reproduce
- Encode struct containing a
Block
using the SDKs json encoder (example) - Attempt to parse JSON
Expected behaviour
JSON is valid
Actual behaviour
JSON is invalid
{
"block": {
"earn": 218288,
"fees": "x/zNsljw1BicK/i21o7ml1CGQrCtAB8x/LkYw1S6hZo=",
"frac": 6886250026,
"gen": "mainnet-v1.0",
"gh": "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=",
"prev": "xCmYWnlpSojf4tTZU2YadEuXGnYIIXk/z1c1boljiJE=",
"proto": "https://github.com/algorandfoundation/specs/tree/44fa607d6051730f5264526bf3c108d51f0eadb6",
"rnd": 29701220,
"rwcalr": 30000000,
"rwd": "/v////////////////////////////////////////8=",
"seed": "rInPcDh6pYvqsftiiafUypkEx03k8uGEoHTHZV/ErOE=",
"spt": {
0: {
"n": 29701120
}
},
"tc": 1122697227,
"ts": 1686458129,
"txn": "efCwo3+8txC+NwGmie+xaEO5dM/tFGrnhcrrodqhNQU=",
"txn256": "JAaTbwP8QApV3OSv1oW5EMVShslCIiJDKIQPJM5qi+Q="
}
}
Note the key under spt
is 0
. JSON keys should be wrapped in double quotes
I'm not sure if this is strictly a bug. The SDK copies over the type definitions from go-algorand
, which defines a couple fields as map[uint64]
, e.g. StateProofTracking and LocalDeltas. If we change these to a map[string]
, we'd deviate from the go-algorand source code and trigger errors in cross-repo consistency checkers.
The other solution is to leave this part of the SDK as-is and defer struct parsing/JSON conversion to the client by letting them convert these two fields before using a json encoder. Interested to hear your thoughts as well.
I talked about this with @winder and it seems like this issue should be fixed once algorand/go-codec#4 is merged and available in the sdk
That sounds good, I forgot that our codec repo was mega out of date.
Different flavor of the same issue but posting here for clarity and posterity's sake... basically any map that has a non-string key type will not get properly encoded. This affects other maps with integer keys like local deltas, but also more complex keys. For example, Txleases
:
"Txleases": {
{
"Lease": "PwvoKrpv440AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"Sender": "pFRedFkfkmKiIT+/WF/OEujrmHGIhB3HTP0uXHCPdKE="
}: 29701261
}
After looking into it a bit more algorand/go-codec#4 will fix the encoding for numeric keys, so local deltas, createables, and spt, but there will still be a problem with encoding LedgerStateDelta.Txleases
because the key is Txlease
.
From the ecnoding/json docs:
Map values encode as JSON objects. The map's key type must either be a string, an integer type, or implement encoding.TextMarshaler.
This means Txlease
will need to implement TextMarshaler
and TextUnmarshaler
cc @Eric-Warehime about the txlease issue