state: fix MPTRoot JSONization

Match C# implementation. It's easier to do this by changing the structure
itself.
This commit is contained in:
Roman Khimov 2021-03-26 13:39:37 +03:00
parent 4c4a980cc0
commit 5f7ec6e784
6 changed files with 22 additions and 27 deletions

View file

@ -11,8 +11,8 @@ import (
type MPTRoot struct { type MPTRoot struct {
Version byte `json:"version"` Version byte `json:"version"`
Index uint32 `json:"index"` Index uint32 `json:"index"`
Root util.Uint256 `json:"stateroot"` Root util.Uint256 `json:"roothash"`
Witness *transaction.Witness `json:"witness,omitempty"` Witness []transaction.Witness `json:"witnesses"`
} }
// Hash returns hash of s. // Hash returns hash of s.
@ -39,20 +39,11 @@ func (s *MPTRoot) EncodeBinaryUnsigned(w *io.BinWriter) {
// DecodeBinary implements io.Serializable. // DecodeBinary implements io.Serializable.
func (s *MPTRoot) DecodeBinary(r *io.BinReader) { func (s *MPTRoot) DecodeBinary(r *io.BinReader) {
s.DecodeBinaryUnsigned(r) s.DecodeBinaryUnsigned(r)
r.ReadArray(&s.Witness, 1)
var ws []transaction.Witness
r.ReadArray(&ws, 1)
if len(ws) == 1 {
s.Witness = &ws[0]
}
} }
// EncodeBinary implements io.Serializable. // EncodeBinary implements io.Serializable.
func (s *MPTRoot) EncodeBinary(w *io.BinWriter) { func (s *MPTRoot) EncodeBinary(w *io.BinWriter) {
s.EncodeBinaryUnsigned(w) s.EncodeBinaryUnsigned(w)
if s.Witness == nil { w.WriteArray(s.Witness)
w.WriteVarUint(0)
} else {
w.WriteArray([]*transaction.Witness{s.Witness})
}
} }

View file

@ -17,6 +17,7 @@ func testStateRoot() *MPTRoot {
Version: byte(rand.Uint32()), Version: byte(rand.Uint32()),
Index: rand.Uint32(), Index: rand.Uint32(),
Root: random.Uint256(), Root: random.Uint256(),
Witness: []transaction.Witness{},
} }
} }
@ -25,10 +26,10 @@ func TestStateRoot_Serializable(t *testing.T) {
testserdes.EncodeDecodeBinary(t, r, new(MPTRoot)) testserdes.EncodeDecodeBinary(t, r, new(MPTRoot))
t.Run("WithWitness", func(t *testing.T) { t.Run("WithWitness", func(t *testing.T) {
r.Witness = &transaction.Witness{ r.Witness = []transaction.Witness{{
InvocationScript: random.Bytes(10), InvocationScript: random.Bytes(10),
VerificationScript: random.Bytes(11), VerificationScript: random.Bytes(11),
} }}
testserdes.EncodeDecodeBinary(t, r, new(MPTRoot)) testserdes.EncodeDecodeBinary(t, r, new(MPTRoot))
}) })
} }
@ -43,7 +44,7 @@ func TestMPTRoot_MarshalJSON(t *testing.T) {
js := []byte(`{ js := []byte(`{
"version": 1, "version": 1,
"index": 3000000, "index": 3000000,
"stateroot": "0xb2fd7e368a848ef70d27cf44940a35237333ed05f1d971c9408f0eb285e0b6f3" "roothash": "0xb2fd7e368a848ef70d27cf44940a35237333ed05f1d971c9408f0eb285e0b6f3"
}`) }`)
rs := new(MPTRoot) rs := new(MPTRoot)
@ -51,7 +52,7 @@ func TestMPTRoot_MarshalJSON(t *testing.T) {
require.EqualValues(t, 1, rs.Version) require.EqualValues(t, 1, rs.Version)
require.EqualValues(t, 3000000, rs.Index) require.EqualValues(t, 3000000, rs.Index)
require.Nil(t, rs.Witness) require.Equal(t, 0, len(rs.Witness))
u, err := util.Uint256DecodeStringLE("b2fd7e368a848ef70d27cf44940a35237333ed05f1d971c9408f0eb285e0b6f3") u, err := util.Uint256DecodeStringLE("b2fd7e368a848ef70d27cf44940a35237333ed05f1d971c9408f0eb285e0b6f3")
require.NoError(t, err) require.NoError(t, err)

View file

@ -132,6 +132,9 @@ func (s *Module) VerifyStateRoot(r *state.MPTRoot) error {
if err != nil { if err != nil {
return errors.New("can't get previous state root") return errors.New("can't get previous state root")
} }
if len(r.Witness) != 1 {
return errors.New("no witness")
}
return s.verifyWitness(r) return s.verifyWitness(r)
} }
@ -142,5 +145,5 @@ func (s *Module) verifyWitness(r *state.MPTRoot) error {
s.mtx.Lock() s.mtx.Lock()
h := s.getKeyCacheForHeight(r.Index).validatorsHash h := s.getKeyCacheForHeight(r.Index).validatorsHash
s.mtx.Unlock() s.mtx.Unlock()
return s.bc.VerifyWitness(h, r, r.Witness, maxVerificationGAS) return s.bc.VerifyWitness(h, r, &r.Witness[0], maxVerificationGAS)
} }

View file

@ -69,7 +69,7 @@ func (s *Module) AddStateRoot(sr *state.MPTRoot) error {
if err != nil { if err != nil {
return err return err
} }
if local.Witness != nil { if len(local.Witness) != 0 {
return nil return nil
} }
if err := s.putStateRoot(key, sr); err != nil { if err := s.putStateRoot(key, sr); err != nil {

View file

@ -40,10 +40,10 @@ func testSignStateRoot(t *testing.T, r *state.MPTRoot, pubs keys.PublicKeys, acc
script, err := smartcontract.CreateMajorityMultiSigRedeemScript(pubs.Copy()) script, err := smartcontract.CreateMajorityMultiSigRedeemScript(pubs.Copy())
require.NoError(t, err) require.NoError(t, err)
r.Witness = &transaction.Witness{ r.Witness = []transaction.Witness{{
VerificationScript: script, VerificationScript: script,
InvocationScript: w.Bytes(), InvocationScript: w.Bytes(),
} }}
data, err := testserdes.EncodeBinary(stateroot.NewMessage(stateroot.RootT, r)) data, err := testserdes.EncodeBinary(stateroot.NewMessage(stateroot.RootT, r))
require.NoError(t, err) require.NoError(t, err)
return data return data
@ -132,8 +132,8 @@ func TestStateRoot(t *testing.T) {
r, err = srv.GetStateRoot(updateIndex + 1) r, err = srv.GetStateRoot(updateIndex + 1)
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, r.Witness) require.NotEqual(t, 0, len(r.Witness))
require.Equal(t, h, r.Witness.ScriptHash()) require.Equal(t, h, r.Witness[0].ScriptHash())
} }
func TestStateRootInitNonZeroHeight(t *testing.T) { func TestStateRootInitNonZeroHeight(t *testing.T) {

View file

@ -81,8 +81,8 @@ func (r *incompleteRoot) finalize(stateValidators keys.PublicKeys) (*state.MPTRo
for i := range sigs { for i := range sigs {
emit.Bytes(w.BinWriter, sigs[i]) emit.Bytes(w.BinWriter, sigs[i])
} }
r.root.Witness = &transaction.Witness{ r.root.Witness = []transaction.Witness{{
InvocationScript: w.Bytes(), InvocationScript: w.Bytes(),
} }}
return r.root, true return r.root, true
} }