Merge pull request #2026 from nspcc-dev/fix-state
Fix manifest `Extra` field marshaling
This commit is contained in:
commit
3646270af0
4 changed files with 54 additions and 7 deletions
|
@ -312,7 +312,7 @@ func TestNEP11_OwnerOf_BalanceOf_Transfer(t *testing.T) {
|
||||||
ScriptHash: verifyH,
|
ScriptHash: verifyH,
|
||||||
Name: "OnNEP11Payment",
|
Name: "OnNEP11Payment",
|
||||||
Item: stackitem.NewArray([]stackitem.Item{
|
Item: stackitem.NewArray([]stackitem.Item{
|
||||||
stackitem.NewByteArray(nftOwnerHash.BytesBE()),
|
stackitem.NewBuffer(nftOwnerHash.BytesBE()),
|
||||||
stackitem.NewBigInteger(big.NewInt(1)),
|
stackitem.NewBigInteger(big.NewInt(1)),
|
||||||
stackitem.NewByteArray(tokenID1),
|
stackitem.NewByteArray(tokenID1),
|
||||||
stackitem.NewByteArray([]byte("some_data")),
|
stackitem.NewByteArray([]byte("some_data")),
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package manifest
|
package manifest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
ojson "github.com/virtuald/go-ordered-json"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -140,10 +142,7 @@ func (m *Manifest) ToStackItem() (stackitem.Item, error) {
|
||||||
}
|
}
|
||||||
trusts = stackitem.Make(tItems)
|
trusts = stackitem.Make(tItems)
|
||||||
}
|
}
|
||||||
extra := stackitem.Make("null")
|
extra := extraToStackItem(m.Extra)
|
||||||
if m.Extra != nil {
|
|
||||||
extra = stackitem.NewByteArray(m.Extra)
|
|
||||||
}
|
|
||||||
return stackitem.NewStruct([]stackitem.Item{
|
return stackitem.NewStruct([]stackitem.Item{
|
||||||
stackitem.Make(m.Name),
|
stackitem.Make(m.Name),
|
||||||
stackitem.Make(groups),
|
stackitem.Make(groups),
|
||||||
|
@ -156,6 +155,29 @@ func (m *Manifest) ToStackItem() (stackitem.Item, error) {
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extraToStackItem removes indentation from `Extra` field in JSON and
|
||||||
|
// converts it to a byte-array stack item.
|
||||||
|
func extraToStackItem(rawExtra []byte) stackitem.Item {
|
||||||
|
extra := stackitem.Make("null")
|
||||||
|
if rawExtra == nil || string(rawExtra) == "null" {
|
||||||
|
return extra
|
||||||
|
}
|
||||||
|
|
||||||
|
d := ojson.NewDecoder(bytes.NewReader(rawExtra))
|
||||||
|
// The result is put directly in the database and affects state-root calculation,
|
||||||
|
// thus use ordered map to stay compatible with C# implementation.
|
||||||
|
d.UseOrderedObject()
|
||||||
|
// Prevent accidental precision loss.
|
||||||
|
d.UseNumber()
|
||||||
|
|
||||||
|
var obj interface{}
|
||||||
|
|
||||||
|
// The error can't really occur because `json.RawMessage` is already a valid json.
|
||||||
|
_ = d.Decode(&obj)
|
||||||
|
res, _ := ojson.Marshal(obj)
|
||||||
|
return stackitem.NewByteArray(res)
|
||||||
|
}
|
||||||
|
|
||||||
// FromStackItem converts stackitem.Item to Manifest.
|
// FromStackItem converts stackitem.Item to Manifest.
|
||||||
func (m *Manifest) FromStackItem(item stackitem.Item) error {
|
func (m *Manifest) FromStackItem(item stackitem.Item) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -289,7 +289,7 @@ func TestManifestToStackItem(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Extra: []byte(`even not a json allowed`),
|
Extra: []byte(`"even string allowed"`),
|
||||||
}
|
}
|
||||||
check(t, expected)
|
check(t, expected)
|
||||||
})
|
})
|
||||||
|
@ -395,3 +395,25 @@ func TestABI_FromStackItemErrors(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExtraToStackItem(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
raw, expected string
|
||||||
|
}{
|
||||||
|
{"null", "null"},
|
||||||
|
{"1", "1"},
|
||||||
|
{"1.23456789101112131415", "1.23456789101112131415"},
|
||||||
|
{`"string with space"`, `"string with space"`},
|
||||||
|
{`{ "a":1, "sss" : {"m" : 1, "a" : 2} , "x" : 2 ,"c" :3,"z":4, "s":"5"}`,
|
||||||
|
`{"a":1,"sss":{"m":1,"a":2},"x":2,"c":3,"z":4,"s":"5"}`},
|
||||||
|
{` [ 1, "array", { "d": "z", "a":"x", "c" : "y", "b":3}]`,
|
||||||
|
`[1,"array",{"d":"z","a":"x","c":"y","b":3}]`},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
res := extraToStackItem([]byte(tc.raw))
|
||||||
|
actual, ok := res.Value().([]byte)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, tc.expected, string(actual))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -129,7 +129,10 @@ func decodeBinaryStackItem(r *io.BinReader, allowInvalid bool) Item {
|
||||||
switch t {
|
switch t {
|
||||||
case ByteArrayT, BufferT:
|
case ByteArrayT, BufferT:
|
||||||
data := r.ReadVarBytes(MaxSize)
|
data := r.ReadVarBytes(MaxSize)
|
||||||
return NewByteArray(data)
|
if t == ByteArrayT {
|
||||||
|
return NewByteArray(data)
|
||||||
|
}
|
||||||
|
return NewBuffer(data)
|
||||||
case BooleanT:
|
case BooleanT:
|
||||||
var b = r.ReadBool()
|
var b = r.ReadBool()
|
||||||
return NewBool(b)
|
return NewBool(b)
|
||||||
|
|
Loading…
Reference in a new issue