mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-22 19:29:39 +00:00
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,
|
||||
Name: "OnNEP11Payment",
|
||||
Item: stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewByteArray(nftOwnerHash.BytesBE()),
|
||||
stackitem.NewBuffer(nftOwnerHash.BytesBE()),
|
||||
stackitem.NewBigInteger(big.NewInt(1)),
|
||||
stackitem.NewByteArray(tokenID1),
|
||||
stackitem.NewByteArray([]byte("some_data")),
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package manifest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
ojson "github.com/virtuald/go-ordered-json"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -140,10 +142,7 @@ func (m *Manifest) ToStackItem() (stackitem.Item, error) {
|
|||
}
|
||||
trusts = stackitem.Make(tItems)
|
||||
}
|
||||
extra := stackitem.Make("null")
|
||||
if m.Extra != nil {
|
||||
extra = stackitem.NewByteArray(m.Extra)
|
||||
}
|
||||
extra := extraToStackItem(m.Extra)
|
||||
return stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.Make(m.Name),
|
||||
stackitem.Make(groups),
|
||||
|
@ -156,6 +155,29 @@ func (m *Manifest) ToStackItem() (stackitem.Item, error) {
|
|||
}), 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.
|
||||
func (m *Manifest) FromStackItem(item stackitem.Item) 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)
|
||||
})
|
||||
|
@ -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 {
|
||||
case ByteArrayT, BufferT:
|
||||
data := r.ReadVarBytes(MaxSize)
|
||||
if t == ByteArrayT {
|
||||
return NewByteArray(data)
|
||||
}
|
||||
return NewBuffer(data)
|
||||
case BooleanT:
|
||||
var b = r.ReadBool()
|
||||
return NewBool(b)
|
||||
|
|
Loading…
Reference in a new issue