From 5794bdb1697256568328e1c286ed6811af86fcf6 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 3 Jun 2020 18:09:28 +0300 Subject: [PATCH] state: implement JSON marshaling for MPT* items --- pkg/core/state/mpt_root.go | 55 ++++++++++++++++++++++++++++----- pkg/core/state/mpt_root_test.go | 39 +++++++++++++++++++++++ 2 files changed, 87 insertions(+), 7 deletions(-) diff --git a/pkg/core/state/mpt_root.go b/pkg/core/state/mpt_root.go index facf3da45..dea3f62fa 100644 --- a/pkg/core/state/mpt_root.go +++ b/pkg/core/state/mpt_root.go @@ -1,6 +1,9 @@ package state import ( + "encoding/json" + "errors" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/io" @@ -9,16 +12,16 @@ import ( // MPTRootBase represents storage state root. type MPTRootBase struct { - Version byte - Index uint32 - PrevHash util.Uint256 - Root util.Uint256 + Version byte `json:"version"` + Index uint32 `json:"index"` + PrevHash util.Uint256 `json:"prehash"` + Root util.Uint256 `json:"stateroot"` } // MPTRoot represents storage state root together with sign info. type MPTRoot struct { MPTRootBase - Witness *transaction.Witness + Witness *transaction.Witness `json:"witness,omitempty"` } // MPTRootStateFlag represents verification state of the state root. @@ -33,8 +36,8 @@ const ( // MPTRootState represents state root together with its verification state. type MPTRootState struct { - MPTRoot - Flag MPTRootStateFlag + MPTRoot `json:"stateroot"` + Flag MPTRootStateFlag `json:"flag"` } // EncodeBinary implements io.Serializable. @@ -103,3 +106,41 @@ func (s *MPTRoot) EncodeBinary(w *io.BinWriter) { w.WriteArray([]*transaction.Witness{s.Witness}) } } + +// String implements fmt.Stringer. +func (f MPTRootStateFlag) String() string { + switch f { + case Unverified: + return "Unverified" + case Verified: + return "Verified" + case Invalid: + return "Invalid" + default: + return "" + } +} + +// MarshalJSON implements json.Marshaler. +func (f MPTRootStateFlag) MarshalJSON() ([]byte, error) { + return []byte(`"` + f.String() + `"`), nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (f *MPTRootStateFlag) UnmarshalJSON(data []byte) error { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return err + } + switch s { + case "Unverified": + *f = Unverified + case "Verified": + *f = Verified + case "Invalid": + *f = Invalid + default: + return errors.New("unknown flag") + } + return nil +} diff --git a/pkg/core/state/mpt_root_test.go b/pkg/core/state/mpt_root_test.go index 15a3ca043..f1c0b5c61 100644 --- a/pkg/core/state/mpt_root_test.go +++ b/pkg/core/state/mpt_root_test.go @@ -1,12 +1,14 @@ package state import ( + "encoding/json" "math/rand" "testing" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/internal/random" "github.com/nspcc-dev/neo-go/pkg/internal/testserdes" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" ) @@ -59,3 +61,40 @@ func TestMPTRootStateUnverifiedByDefault(t *testing.T) { var r MPTRootState require.Equal(t, Unverified, r.Flag) } + +func TestMPTRoot_MarshalJSON(t *testing.T) { + t.Run("Good", func(t *testing.T) { + r := testStateRoot() + rs := &MPTRootState{ + MPTRoot: *r, + Flag: Verified, + } + testserdes.MarshalUnmarshalJSON(t, rs, new(MPTRootState)) + }) + + t.Run("Compatibility", func(t *testing.T) { + js := []byte(`{ + "flag": "Unverified", + "stateroot": { + "version": 1, + "index": 3000000, + "prehash": "0x4f30f43af8dd2262fc331c45bfcd9066ebbacda204e6e81371cbd884fe7d6c90", + "stateroot": "0xb2fd7e368a848ef70d27cf44940a35237333ed05f1d971c9408f0eb285e0b6f3" + }}`) + + rs := new(MPTRootState) + require.NoError(t, json.Unmarshal(js, &rs)) + + require.EqualValues(t, 1, rs.Version) + require.EqualValues(t, 3000000, rs.Index) + require.Nil(t, rs.Witness) + + u, err := util.Uint256DecodeStringLE("4f30f43af8dd2262fc331c45bfcd9066ebbacda204e6e81371cbd884fe7d6c90") + require.NoError(t, err) + require.Equal(t, u, rs.PrevHash) + + u, err = util.Uint256DecodeStringLE("b2fd7e368a848ef70d27cf44940a35237333ed05f1d971c9408f0eb285e0b6f3") + require.NoError(t, err) + require.Equal(t, u, rs.Root) + }) +}