forked from TrueCloudLab/neoneo-go
core: remove System.Json.[Serialize, Deserialize] interops
And move their tests to native StdLib.
This commit is contained in:
parent
f65485b735
commit
4d2ad4b9e2
7 changed files with 44 additions and 130 deletions
|
@ -75,8 +75,6 @@ func TestSyscallExecution(t *testing.T) {
|
||||||
"iterator.Create": {interopnames.SystemIteratorCreate, []string{pubs}, false},
|
"iterator.Create": {interopnames.SystemIteratorCreate, []string{pubs}, false},
|
||||||
"iterator.Next": {interopnames.SystemIteratorNext, []string{"iterator.Iterator{}"}, false},
|
"iterator.Next": {interopnames.SystemIteratorNext, []string{"iterator.Iterator{}"}, false},
|
||||||
"iterator.Value": {interopnames.SystemIteratorValue, []string{"iterator.Iterator{}"}, false},
|
"iterator.Value": {interopnames.SystemIteratorValue, []string{"iterator.Iterator{}"}, false},
|
||||||
"json.FromJSON": {interopnames.SystemJSONDeserialize, []string{b}, false},
|
|
||||||
"json.ToJSON": {interopnames.SystemJSONSerialize, []string{b}, false},
|
|
||||||
"runtime.CheckWitness": {interopnames.SystemRuntimeCheckWitness, []string{b}, false},
|
"runtime.CheckWitness": {interopnames.SystemRuntimeCheckWitness, []string{b}, false},
|
||||||
"runtime.GasLeft": {interopnames.SystemRuntimeGasLeft, nil, false},
|
"runtime.GasLeft": {interopnames.SystemRuntimeGasLeft, nil, false},
|
||||||
"runtime.GetCallingScriptHash": {interopnames.SystemRuntimeGetCallingScriptHash, nil, false},
|
"runtime.GetCallingScriptHash": {interopnames.SystemRuntimeGetCallingScriptHash, nil, false},
|
||||||
|
|
|
@ -23,8 +23,6 @@ const (
|
||||||
SystemIteratorCreate = "System.Iterator.Create"
|
SystemIteratorCreate = "System.Iterator.Create"
|
||||||
SystemIteratorNext = "System.Iterator.Next"
|
SystemIteratorNext = "System.Iterator.Next"
|
||||||
SystemIteratorValue = "System.Iterator.Value"
|
SystemIteratorValue = "System.Iterator.Value"
|
||||||
SystemJSONDeserialize = "System.Json.Deserialize"
|
|
||||||
SystemJSONSerialize = "System.Json.Serialize"
|
|
||||||
SystemRuntimeCheckWitness = "System.Runtime.CheckWitness"
|
SystemRuntimeCheckWitness = "System.Runtime.CheckWitness"
|
||||||
SystemRuntimeGasLeft = "System.Runtime.GasLeft"
|
SystemRuntimeGasLeft = "System.Runtime.GasLeft"
|
||||||
SystemRuntimeGetCallingScriptHash = "System.Runtime.GetCallingScriptHash"
|
SystemRuntimeGetCallingScriptHash = "System.Runtime.GetCallingScriptHash"
|
||||||
|
@ -73,8 +71,6 @@ var names = []string{
|
||||||
SystemIteratorCreate,
|
SystemIteratorCreate,
|
||||||
SystemIteratorNext,
|
SystemIteratorNext,
|
||||||
SystemIteratorValue,
|
SystemIteratorValue,
|
||||||
SystemJSONDeserialize,
|
|
||||||
SystemJSONSerialize,
|
|
||||||
SystemRuntimeCheckWitness,
|
SystemRuntimeCheckWitness,
|
||||||
SystemRuntimeGasLeft,
|
SystemRuntimeGasLeft,
|
||||||
SystemRuntimeGetCallingScriptHash,
|
SystemRuntimeGetCallingScriptHash,
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
package json
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Serialize handles System.JSON.Serialize syscall.
|
|
||||||
func Serialize(ic *interop.Context) error {
|
|
||||||
item := ic.VM.Estack().Pop().Item()
|
|
||||||
data, err := stackitem.ToJSON(item)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ic.VM.Estack().PushVal(data)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize handles System.JSON.Deserialize syscall.
|
|
||||||
func Deserialize(ic *interop.Context) error {
|
|
||||||
data := ic.VM.Estack().Pop().Bytes()
|
|
||||||
item, err := stackitem.FromJSON(data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ic.VM.Estack().PushVal(item)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
package json
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
serializeID = interopnames.ToID([]byte(interopnames.SystemJSONSerialize))
|
|
||||||
deserializeID = interopnames.ToID([]byte(interopnames.SystemJSONDeserialize))
|
|
||||||
)
|
|
||||||
|
|
||||||
var jsonInterops = []interop.Function{
|
|
||||||
{ID: serializeID, Func: Serialize},
|
|
||||||
{ID: deserializeID, Func: Deserialize},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
interop.Sort(jsonInterops)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTestFunc(id uint32, arg interface{}, result interface{}) func(t *testing.T) {
|
|
||||||
prog := make([]byte, 5)
|
|
||||||
prog[0] = byte(opcode.SYSCALL)
|
|
||||||
binary.LittleEndian.PutUint32(prog[1:], id)
|
|
||||||
|
|
||||||
return func(t *testing.T) {
|
|
||||||
ic := &interop.Context{}
|
|
||||||
ic.Functions = append(ic.Functions, jsonInterops)
|
|
||||||
v := ic.SpawnVM()
|
|
||||||
v.LoadScript(prog)
|
|
||||||
v.Estack().PushVal(arg)
|
|
||||||
if result == nil {
|
|
||||||
require.Error(t, v.Run())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
require.NoError(t, v.Run())
|
|
||||||
require.Equal(t, stackitem.Make(result), v.Estack().Pop().Item())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerialize(t *testing.T) {
|
|
||||||
t.Run("Serialize", func(t *testing.T) {
|
|
||||||
t.Run("Good", getTestFunc(serializeID, 42, []byte("42")))
|
|
||||||
t.Run("Bad", func(t *testing.T) {
|
|
||||||
arr := stackitem.NewArray([]stackitem.Item{
|
|
||||||
stackitem.NewByteArray(make([]byte, stackitem.MaxSize/2)),
|
|
||||||
stackitem.NewByteArray(make([]byte, stackitem.MaxSize/2)),
|
|
||||||
})
|
|
||||||
getTestFunc(serializeID, arr, nil)(t)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
t.Run("Deserialize", func(t *testing.T) {
|
|
||||||
t.Run("Good", getTestFunc(deserializeID, []byte("42"), 42))
|
|
||||||
t.Run("Bad", getTestFunc(deserializeID, []byte("{]"), nil))
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -15,7 +15,6 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/crypto"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/crypto"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/iterator"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/iterator"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/json"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
|
@ -50,8 +49,6 @@ var systemInterops = []interop.Function{
|
||||||
{Name: interopnames.SystemIteratorCreate, Func: iterator.Create, Price: 1 << 4, ParamCount: 1},
|
{Name: interopnames.SystemIteratorCreate, Func: iterator.Create, Price: 1 << 4, ParamCount: 1},
|
||||||
{Name: interopnames.SystemIteratorNext, Func: iterator.Next, Price: 1 << 15, ParamCount: 1},
|
{Name: interopnames.SystemIteratorNext, Func: iterator.Next, Price: 1 << 15, ParamCount: 1},
|
||||||
{Name: interopnames.SystemIteratorValue, Func: iterator.Value, Price: 1 << 4, ParamCount: 1},
|
{Name: interopnames.SystemIteratorValue, Func: iterator.Value, Price: 1 << 4, ParamCount: 1},
|
||||||
{Name: interopnames.SystemJSONDeserialize, Func: json.Deserialize, Price: 1 << 14, ParamCount: 1},
|
|
||||||
{Name: interopnames.SystemJSONSerialize, Func: json.Serialize, Price: 1 << 12, ParamCount: 1},
|
|
||||||
{Name: interopnames.SystemRuntimeCheckWitness, Func: runtime.CheckWitness, Price: 1 << 10,
|
{Name: interopnames.SystemRuntimeCheckWitness, Func: runtime.CheckWitness, Price: 1 << 10,
|
||||||
RequiredFlags: callflag.NoneFlag, ParamCount: 1},
|
RequiredFlags: callflag.NoneFlag, ParamCount: 1},
|
||||||
{Name: interopnames.SystemRuntimeGasLeft, Func: runtime.GasLeft, Price: 1 << 4},
|
{Name: interopnames.SystemRuntimeGasLeft, Func: runtime.GasLeft, Price: 1 << 4},
|
||||||
|
|
|
@ -94,3 +94,47 @@ func TestStdLibItoaAtoi(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStdLibJSON(t *testing.T) {
|
||||||
|
s := newStd()
|
||||||
|
ic := &interop.Context{VM: vm.New()}
|
||||||
|
var actual stackitem.Item
|
||||||
|
|
||||||
|
t.Run("JSONSerialize", func(t *testing.T) {
|
||||||
|
t.Run("Good", func(t *testing.T) {
|
||||||
|
require.NotPanics(t, func() {
|
||||||
|
actual = s.jsonSerialize(ic, []stackitem.Item{stackitem.Make(42)})
|
||||||
|
})
|
||||||
|
|
||||||
|
require.Equal(t, stackitem.Make([]byte("42")), actual)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Bad", func(t *testing.T) {
|
||||||
|
arr := stackitem.NewArray([]stackitem.Item{
|
||||||
|
stackitem.NewByteArray(make([]byte, stackitem.MaxSize/2)),
|
||||||
|
stackitem.NewByteArray(make([]byte, stackitem.MaxSize/2)),
|
||||||
|
})
|
||||||
|
require.Panics(t, func() {
|
||||||
|
_ = s.jsonSerialize(ic, []stackitem.Item{arr})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("JSONDeserialize", func(t *testing.T) {
|
||||||
|
t.Run("Good", func(t *testing.T) {
|
||||||
|
require.NotPanics(t, func() {
|
||||||
|
actual = s.jsonDeserialize(ic, []stackitem.Item{stackitem.Make("42")})
|
||||||
|
})
|
||||||
|
|
||||||
|
require.Equal(t, stackitem.Make(42), actual)
|
||||||
|
})
|
||||||
|
t.Run("Bad", func(t *testing.T) {
|
||||||
|
require.Panics(t, func() {
|
||||||
|
_ = s.jsonDeserialize(ic, []stackitem.Item{stackitem.Make("{]")})
|
||||||
|
})
|
||||||
|
require.Panics(t, func() {
|
||||||
|
_ = s.jsonDeserialize(ic, []stackitem.Item{stackitem.NewInterop(nil)})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
Package json provides various JSON serialization/deserialization routines.
|
|
||||||
*/
|
|
||||||
package json
|
|
||||||
|
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/neogointernal"
|
|
||||||
|
|
||||||
// ToJSON serializes value to json. It uses `System.Json.Serialize` syscall.
|
|
||||||
// Serialization format is the following:
|
|
||||||
// []byte -> base64 string
|
|
||||||
// bool -> json boolean
|
|
||||||
// nil -> Null
|
|
||||||
// string -> base64 encoded sequence of underlying bytes
|
|
||||||
// (u)int* -> integer, only value in -2^53..2^53 are allowed
|
|
||||||
// []interface{} -> json array
|
|
||||||
// map[type1]type2 -> json object with string keys marshaled as strings (not base64).
|
|
||||||
func ToJSON(item interface{}) []byte {
|
|
||||||
return neogointernal.Syscall1("System.Json.Serialize", item).([]byte)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromJSON deserializes value from json. It uses `System.Json.Deserialize` syscall.
|
|
||||||
// It performs deserialization as follows:
|
|
||||||
// strings -> []byte (string) from base64
|
|
||||||
// integers -> (u)int* types
|
|
||||||
// null -> interface{}(nil)
|
|
||||||
// arrays -> []interface{}
|
|
||||||
// maps -> map[string]interface{}
|
|
||||||
func FromJSON(data []byte) interface{} {
|
|
||||||
return neogointernal.Syscall1("System.Json.Deserialize", data).(interface{})
|
|
||||||
}
|
|
Loading…
Reference in a new issue