algorand / go-algorand-sdk

Algorand Golang SDK

Home Page:https://pkg.go.dev/github.com/algorand/go-algorand-sdk/v2

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

  1. Encode struct containing a Block using the SDKs json encoder (example)
  2. 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