diff --git a/types/upgrade.go b/types/upgrade.go index 263870973..5857a4c1f 100644 --- a/types/upgrade.go +++ b/types/upgrade.go @@ -4,6 +4,8 @@ import "fmt" var UpgradeMgr = NewUpgradeManager(UpgradeConfig{}) +const FixSignBytesOverflow = "FixSignBytesOverflow" // fix json unmarshal overflow when build SignBytes + var MainNetConfig = UpgradeConfig{ HeightMap: map[string]int64{}, } diff --git a/types/utils.go b/types/utils.go index 10ec85472..d880f9983 100644 --- a/types/utils.go +++ b/types/utils.go @@ -1,6 +1,7 @@ package types import ( + "bytes" "encoding/json" "time" @@ -15,7 +16,14 @@ import ( // If the passed JSON isn't valid it will return an error. func SortJSON(toSortJSON []byte) ([]byte, error) { var c interface{} - err := json.Unmarshal(toSortJSON, &c) + var err error + if !IsUpgrade(FixSignBytesOverflow) { + err = json.Unmarshal(toSortJSON, &c) + } else { + decoder := json.NewDecoder(bytes.NewReader(toSortJSON)) + decoder.UseNumber() + err = decoder.Decode(&c) + } if err != nil { return nil, err } diff --git a/types/utils_test.go b/types/utils_test.go index 467669186..ef0b9ec68 100644 --- a/types/utils_test.go +++ b/types/utils_test.go @@ -45,6 +45,36 @@ func TestSortJSON(t *testing.T) { } } +func TestSortJSONOverflow(t *testing.T) { + UpgradeMgr.AddUpgradeHeight(FixSignBytesOverflow, 100) + UpgradeMgr.SetHeight(100) + + cases := []struct { + unsortedJSON string + want string + wantErr bool + }{ + // from the TXSpec: + {unsortedJSON: `{"chain_id":"test-chain-1","sequence":1,"msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":9007199326368011,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":9007199326368011,"denom":"atom"}]}]},"alt_bytes":null}`, + want: `{"alt_bytes":null,"chain_id":"test-chain-1","msg_bytes":{"inputs":[{"address":"696E707574","coins":[{"amount":9007199326368011,"denom":"atom"}]}],"outputs":[{"address":"6F7574707574","coins":[{"amount":9007199326368011,"denom":"atom"}]}]},"sequence":1}`, + wantErr: false}, + } + + for tcIndex, tc := range cases { + got, err := SortJSON([]byte(tc.unsortedJSON)) + if tc.wantErr { + require.NotNil(t, err, "tc #%d", tcIndex) + require.Panics(t, func() { MustSortJSON([]byte(tc.unsortedJSON)) }) + } else { + require.Nil(t, err, "tc #%d, err=%s", tcIndex, err) + require.NotPanics(t, func() { MustSortJSON([]byte(tc.unsortedJSON)) }) + require.Equal(t, got, MustSortJSON([]byte(tc.unsortedJSON))) + } + + require.Equal(t, string(got), tc.want) + } +} + func TestTimeFormatAndParse(t *testing.T) { cases := []struct { RFC3339NanoStr string