From 0b0d39f797e6077829d9de52fe31c1c446b93229 Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Wed, 9 Feb 2022 16:07:07 +0300 Subject: [PATCH 1/3] smartcontract: allow to use `*big.Int` numbers for integers Signed-off-by: Evgeniy Stratonikov --- pkg/rpc/client/native.go | 7 +++-- pkg/smartcontract/convertor.go | 2 +- pkg/smartcontract/convertor_test.go | 8 ++--- pkg/smartcontract/param_type.go | 13 +++++--- pkg/smartcontract/param_type_test.go | 28 +++++++++++++++-- pkg/smartcontract/parameter.go | 38 +++++++++++++++-------- pkg/smartcontract/parameter_test.go | 46 ++++++++++++++++++---------- 7 files changed, 98 insertions(+), 44 deletions(-) diff --git a/pkg/rpc/client/native.go b/pkg/rpc/client/native.go index 7839ab941..85a857ac3 100644 --- a/pkg/rpc/client/native.go +++ b/pkg/rpc/client/native.go @@ -5,6 +5,7 @@ package client import ( "errors" "fmt" + "math/big" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" @@ -55,11 +56,11 @@ func (c *Client) GetDesignatedByRole(role noderoles.Role, index uint32) (keys.Pu result, err := c.InvokeFunction(rmHash, "getDesignatedByRole", []smartcontract.Parameter{ { Type: smartcontract.IntegerType, - Value: int64(role), + Value: big.NewInt(int64(role)), }, { Type: smartcontract.IntegerType, - Value: int64(index), + Value: big.NewInt(int64(index)), }, }, nil) if err != nil { @@ -84,7 +85,7 @@ func (c *Client) NNSResolve(nnsHash util.Uint160, name string, typ nns.RecordTyp }, { Type: smartcontract.IntegerType, - Value: int64(typ), + Value: big.NewInt(int64(typ)), }, }, nil) if err != nil { diff --git a/pkg/smartcontract/convertor.go b/pkg/smartcontract/convertor.go index d4d9e45d7..fe977a91d 100644 --- a/pkg/smartcontract/convertor.go +++ b/pkg/smartcontract/convertor.go @@ -15,7 +15,7 @@ func ParameterFromStackItem(i stackitem.Item, seen map[stackitem.Item]bool) Para case *stackitem.BigInteger: return Parameter{ Type: IntegerType, - Value: i.Value().(*big.Int).Int64(), + Value: i.Value().(*big.Int), } case stackitem.Bool: return Parameter{ diff --git a/pkg/smartcontract/convertor_test.go b/pkg/smartcontract/convertor_test.go index bd1585609..3aaae34d5 100644 --- a/pkg/smartcontract/convertor_test.go +++ b/pkg/smartcontract/convertor_test.go @@ -18,7 +18,7 @@ var toContractParameterTestCases = []struct { stackitem.NewBool(true), }), result: Parameter{Type: ArrayType, Value: []Parameter{ - {Type: IntegerType, Value: int64(1)}, + {Type: IntegerType, Value: big.NewInt(1)}, {Type: BoolType, Value: true}, }}, }, @@ -37,7 +37,7 @@ var toContractParameterTestCases = []struct { { input: stackitem.NewArray([]stackitem.Item{stackitem.NewBigInteger(big.NewInt(2)), stackitem.NewBool(true)}), result: Parameter{Type: ArrayType, Value: []Parameter{ - {Type: IntegerType, Value: int64(2)}, + {Type: IntegerType, Value: big.NewInt(2)}, {Type: BoolType, Value: true}, }}, }, @@ -55,11 +55,11 @@ var toContractParameterTestCases = []struct { Type: MapType, Value: []ParameterPair{ { - Key: Parameter{Type: IntegerType, Value: int64(1)}, + Key: Parameter{Type: IntegerType, Value: big.NewInt(1)}, Value: Parameter{Type: BoolType, Value: true}, }, { Key: Parameter{Type: ByteArrayType, Value: []byte("qwerty")}, - Value: Parameter{Type: IntegerType, Value: int64(3)}, + Value: Parameter{Type: IntegerType, Value: big.NewInt(3)}, }, { Key: Parameter{Type: BoolType, Value: true}, diff --git a/pkg/smartcontract/param_type.go b/pkg/smartcontract/param_type.go index 2ea611a95..1f432536b 100644 --- a/pkg/smartcontract/param_type.go +++ b/pkg/smartcontract/param_type.go @@ -5,13 +5,14 @@ import ( "encoding/json" "errors" "fmt" - "strconv" + "math/big" "strings" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // ParamType represents the Type of the smart contract parameter. @@ -208,7 +209,11 @@ func adjustValToType(typ ParamType, val string) (interface{}, error) { return nil, errors.New("invalid boolean value") } case IntegerType: - return strconv.ParseInt(val, 10, 64) + bi, ok := new(big.Int).SetString(val, 10) + if !ok || stackitem.CheckIntegerSize(bi) != nil { + return nil, errors.New("invalid integer value") + } + return bi, nil case Hash160Type: u, err := address.StringToUint160(val) if err == nil { @@ -250,8 +255,8 @@ func adjustValToType(typ ParamType, val string) (interface{}, error) { func inferParamType(val string) ParamType { var err error - _, err = strconv.Atoi(val) - if err == nil { + bi, ok := new(big.Int).SetString(val, 10) + if ok && stackitem.CheckIntegerSize(bi) == nil { return IntegerType } diff --git a/pkg/smartcontract/param_type_test.go b/pkg/smartcontract/param_type_test.go index 1d3c54819..0620e52e1 100644 --- a/pkg/smartcontract/param_type_test.go +++ b/pkg/smartcontract/param_type_test.go @@ -2,9 +2,11 @@ package smartcontract import ( "encoding/hex" + "math/big" "testing" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -76,6 +78,7 @@ func TestParseParamType(t *testing.T) { } func TestInferParamType(t *testing.T) { + bi := new(big.Int).Lsh(big.NewInt(1), stackitem.MaxBigIntegerSizeBits-2) var inouts = []struct { in string out ParamType @@ -88,6 +91,15 @@ func TestInferParamType(t *testing.T) { }, { in: "0", out: IntegerType, + }, { + in: "8765432187654321111", + out: IntegerType, + }, { + in: bi.String(), + out: IntegerType, + }, { + in: bi.String() + "0", // big for Integer but is still a valid hex + out: ByteArrayType, }, { in: "2e10", out: ByteArrayType, @@ -150,6 +162,8 @@ func TestInferParamType(t *testing.T) { } func TestAdjustValToType(t *testing.T) { + bi := big.NewInt(1).Lsh(big.NewInt(1), stackitem.MaxBigIntegerSizeBits-2) + var inouts = []struct { typ ParamType val string @@ -190,15 +204,23 @@ func TestAdjustValToType(t *testing.T) { }, { typ: IntegerType, val: "0", - out: int64(0), + out: big.NewInt(0), }, { typ: IntegerType, val: "42", - out: int64(42), + out: big.NewInt(42), }, { typ: IntegerType, val: "-42", - out: int64(-42), + out: big.NewInt(-42), + }, { + typ: IntegerType, + val: bi.String(), + out: bi, + }, { + typ: IntegerType, + val: bi.String() + "0", + err: true, }, { typ: IntegerType, val: "q", diff --git a/pkg/smartcontract/parameter.go b/pkg/smartcontract/parameter.go index 91f773fed..02f84e32c 100644 --- a/pkg/smartcontract/parameter.go +++ b/pkg/smartcontract/parameter.go @@ -9,15 +9,17 @@ import ( "errors" "fmt" "math" + "math/big" "math/bits" "os" - "strconv" "strings" "unicode/utf8" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) // Parameter represents a smart contract parameter. @@ -65,13 +67,12 @@ func (p Parameter) MarshalJSON() ([]byte, error) { case BoolType, StringType, Hash160Type, Hash256Type: resultRawValue, resultErr = json.Marshal(p.Value) case IntegerType: - val, ok := p.Value.(int64) + val, ok := p.Value.(*big.Int) if !ok { resultErr = errors.New("invalid integer value") break } - valStr := strconv.FormatInt(val, 10) - resultRawValue = json.RawMessage(`"` + valStr + `"`) + resultRawValue = json.RawMessage(`"` + val.String() + `"`) case PublicKeyType, ByteArrayType, SignatureType: if p.Type == PublicKeyType { resultRawValue, resultErr = json.Marshal(hex.EncodeToString(p.Value.([]byte))) @@ -145,17 +146,22 @@ func (p *Parameter) UnmarshalJSON(data []byte) (err error) { p.Value = s case IntegerType: if err = json.Unmarshal(r.Value, &i); err == nil { - p.Value = i + p.Value = big.NewInt(i) return } // sometimes integer comes as string - if err = json.Unmarshal(r.Value, &s); err != nil { - return + if jErr := json.Unmarshal(r.Value, &s); jErr != nil { + return jErr } - if i, err = strconv.ParseInt(s, 10, 64); err != nil { - return + bi, ok := new(big.Int).SetString(s, 10) + if !ok { + // In this case previous err should mean string contains non-digit characters. + return err + } + err = stackitem.CheckIntegerSize(bi) + if err == nil { + p.Value = bi } - p.Value = i case ArrayType: // https://github.com/neo-project/neo/blob/3d59ecca5a8deb057bdad94b3028a6d5e25ac088/neo/Network/RPC/RpcServer.cs#L67 var rs []Parameter @@ -205,7 +211,8 @@ func (p *Parameter) EncodeBinary(w *io.BinWriter) { case StringType: w.WriteString(p.Value.(string)) case IntegerType: - w.WriteU64LE(uint64(p.Value.(int64))) + val := p.Value.(*big.Int) + w.WriteVarBytes(bigint.ToBytes(val)) case ArrayType: w.WriteArray(p.Value.([]Parameter)) case MapType: @@ -236,7 +243,11 @@ func (p *Parameter) DecodeBinary(r *io.BinReader) { case StringType: p.Value = r.ReadString() case IntegerType: - p.Value = int64(r.ReadU64LE()) + bs := r.ReadVarBytes(bigint.MaxBytesLen) + if r.Err != nil { + return + } + p.Value = bigint.FromBytes(bs) case ArrayType: ps := []Parameter{} r.ReadArray(&ps) @@ -318,6 +329,9 @@ func (p Parameter) TryParse(dest interface{}) error { return err } return nil + case **big.Int: + *dest = bigint.FromBytes(data) + return nil case *int64, *int32, *int16, *int8, *int, *uint64, *uint32, *uint16, *uint8, *uint: var size int switch dest.(type) { diff --git a/pkg/smartcontract/parameter_test.go b/pkg/smartcontract/parameter_test.go index 82aba2317..8fd87410f 100644 --- a/pkg/smartcontract/parameter_test.go +++ b/pkg/smartcontract/parameter_test.go @@ -5,7 +5,9 @@ import ( "encoding/hex" "encoding/json" "math" + "math/big" "reflect" + "strings" "testing" "github.com/nspcc-dev/neo-go/internal/testserdes" @@ -22,9 +24,13 @@ var marshalJSONTestCases = []struct { result string }{ { - input: Parameter{Type: IntegerType, Value: int64(12345)}, + input: Parameter{Type: IntegerType, Value: big.NewInt(12345)}, result: `{"type":"Integer","value":12345}`, }, + { + input: Parameter{Type: IntegerType, Value: new(big.Int).Lsh(big.NewInt(1), 254)}, + result: `{"type":"Integer","value":"` + new(big.Int).Lsh(big.NewInt(1), 254).String() + `"}`, + }, { input: Parameter{Type: StringType, Value: "Some string"}, result: `{"type":"String","value":"Some string"}`, @@ -57,7 +63,7 @@ var marshalJSONTestCases = []struct { Type: ArrayType, Value: []Parameter{ {Type: StringType, Value: "str 1"}, - {Type: IntegerType, Value: int64(2)}, + {Type: IntegerType, Value: big.NewInt(2)}, }, }, result: `{"type":"Array","value":[{"type":"String","value":"str 1"},{"type":"Integer","value":2}]}`, @@ -84,7 +90,7 @@ var marshalJSONTestCases = []struct { Value: []ParameterPair{ { Key: Parameter{Type: StringType, Value: "key1"}, - Value: Parameter{Type: IntegerType, Value: int64(1)}, + Value: Parameter{Type: IntegerType, Value: big.NewInt(1)}, }, { Key: Parameter{Type: StringType, Value: "key2"}, @@ -102,7 +108,7 @@ var marshalJSONTestCases = []struct { Key: Parameter{Type: StringType, Value: "key1"}, Value: Parameter{Type: ArrayType, Value: []Parameter{ {Type: StringType, Value: "str 1"}, - {Type: IntegerType, Value: int64(2)}, + {Type: IntegerType, Value: big.NewInt(2)}, }}, }, }, @@ -185,11 +191,11 @@ var unmarshalJSONTestCases = []struct { }, { input: `{"type":"Integer","value":12345}`, - result: Parameter{Type: IntegerType, Value: int64(12345)}, + result: Parameter{Type: IntegerType, Value: big.NewInt(12345)}, }, { input: `{"type":"Integer","value":"12345"}`, - result: Parameter{Type: IntegerType, Value: int64(12345)}, + result: Parameter{Type: IntegerType, Value: big.NewInt(12345)}, }, { input: `{"type":"ByteString","value":"` + hexToBase64("010203") + `"}`, @@ -215,7 +221,7 @@ var unmarshalJSONTestCases = []struct { Type: ArrayType, Value: []Parameter{ {Type: StringType, Value: "str 1"}, - {Type: IntegerType, Value: int64(2)}, + {Type: IntegerType, Value: big.NewInt(2)}, }, }, }, @@ -248,7 +254,7 @@ var unmarshalJSONTestCases = []struct { Value: []ParameterPair{ { Key: Parameter{Type: StringType, Value: "key1"}, - Value: Parameter{Type: IntegerType, Value: int64(1)}, + Value: Parameter{Type: IntegerType, Value: big.NewInt(1)}, }, { Key: Parameter{Type: StringType, Value: "key2"}, @@ -266,7 +272,7 @@ var unmarshalJSONTestCases = []struct { Key: Parameter{Type: StringType, Value: "key1"}, Value: Parameter{Type: ArrayType, Value: []Parameter{ {Type: StringType, Value: "str 1"}, - {Type: IntegerType, Value: int64(2)}, + {Type: IntegerType, Value: big.NewInt(2)}, }}, }, }, @@ -310,6 +316,8 @@ var unmarshalJSONErrorCases = []string{ `{"type": "String","value":1}`, // incorrect Value `{"type": "Integer","value": "nn"}`, // incorrect Integer value `{"type": "Integer","value": []}`, // incorrect Integer value + `{"type": "Integer","value":"` + + strings.Repeat("9", 100) + `"}`, // too big Integer `{"type": "Array","value": 123}`, // incorrect Array value `{"type": "Hash160","value": "0bcd"}`, // incorrect Uint160 value `{"type": "Hash256","value": "0bcd"}`, // incorrect Uint256 value @@ -330,7 +338,7 @@ func TestParam_UnmarshalJSON(t *testing.T) { } for _, input := range unmarshalJSONErrorCases { - assert.Error(t, json.Unmarshal([]byte(input), &s)) + assert.Error(t, json.Unmarshal([]byte(input), &s), input) } } @@ -370,6 +378,10 @@ var tryParseTestCases = []struct { input: []byte{0x63, 0x78, 0x29, 0xcd, 0x0b}, expected: int64(50686687331), }, + { + input: []byte{0x63, 0x78, 0x29, 0xcd, 0x0b}, + expected: big.NewInt(50686687331), + }, { input: []byte("this is a test string"), expected: "this is a test string", @@ -450,13 +462,13 @@ func TestNewParameterFromString(t *testing.T) { out: Parameter{StringType, "qwerty"}, }, { in: "42", - out: Parameter{IntegerType, int64(42)}, + out: Parameter{IntegerType, big.NewInt(42)}, }, { in: "Hello, 世界", out: Parameter{StringType, "Hello, 世界"}, }, { in: `\4\2`, - out: Parameter{IntegerType, int64(42)}, + out: Parameter{IntegerType, big.NewInt(42)}, }, { in: `\\4\2`, out: Parameter{StringType, `\42`}, @@ -465,7 +477,7 @@ func TestNewParameterFromString(t *testing.T) { out: Parameter{StringType, `\42`}, }, { in: "int:42", - out: Parameter{IntegerType, int64(42)}, + out: Parameter{IntegerType, big.NewInt(42)}, }, { in: "true", out: Parameter{BoolType, true}, @@ -544,8 +556,8 @@ func TestExpandParameterToEmitable(t *testing.T) { Expected: true, }, { - In: Parameter{Type: IntegerType, Value: int64(123)}, - Expected: int64(123), + In: Parameter{Type: IntegerType, Value: big.NewInt(123)}, + Expected: big.NewInt(123), }, { In: Parameter{Type: ByteArrayType, Value: []byte{1, 2, 3}}, @@ -575,7 +587,7 @@ func TestExpandParameterToEmitable(t *testing.T) { In: Parameter{Type: ArrayType, Value: []Parameter{ { Type: IntegerType, - Value: int64(123), + Value: big.NewInt(123), }, { Type: ByteArrayType, @@ -591,7 +603,7 @@ func TestExpandParameterToEmitable(t *testing.T) { }, }, }}, - Expected: []interface{}{int64(123), []byte{1, 2, 3}, []interface{}{true}}, + Expected: []interface{}{big.NewInt(123), []byte{1, 2, 3}, []interface{}{true}}, }, } bw := io.NewBufBinWriter() From fe0cd5fe32caf4cc387387b3a65622962a1ba500 Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Thu, 31 Mar 2022 09:42:46 +0300 Subject: [PATCH 2/3] smartcontract: remove `EncodeBinary` for `Parameter` It seems, we don't use it anywhere. Signed-off-by: Evgeniy Stratonikov --- pkg/smartcontract/parameter.go | 88 ----------------------------- pkg/smartcontract/parameter_test.go | 15 ----- 2 files changed, 103 deletions(-) diff --git a/pkg/smartcontract/parameter.go b/pkg/smartcontract/parameter.go index 02f84e32c..55683fa1a 100644 --- a/pkg/smartcontract/parameter.go +++ b/pkg/smartcontract/parameter.go @@ -8,7 +8,6 @@ import ( "encoding/json" "errors" "fmt" - "math" "math/big" "math/bits" "os" @@ -17,7 +16,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" - "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) @@ -196,92 +194,6 @@ func (p *Parameter) UnmarshalJSON(data []byte) (err error) { return } -// EncodeBinary implements io.Serializable interface. -func (p *Parameter) EncodeBinary(w *io.BinWriter) { - w.WriteB(byte(p.Type)) - switch p.Type { - case BoolType: - w.WriteBool(p.Value.(bool)) - case ByteArrayType, PublicKeyType, SignatureType: - if p.Value == nil { - w.WriteVarUint(math.MaxUint64) - } else { - w.WriteVarBytes(p.Value.([]byte)) - } - case StringType: - w.WriteString(p.Value.(string)) - case IntegerType: - val := p.Value.(*big.Int) - w.WriteVarBytes(bigint.ToBytes(val)) - case ArrayType: - w.WriteArray(p.Value.([]Parameter)) - case MapType: - w.WriteArray(p.Value.([]ParameterPair)) - case Hash160Type: - w.WriteBytes(p.Value.(util.Uint160).BytesBE()) - case Hash256Type: - w.WriteBytes(p.Value.(util.Uint256).BytesBE()) - case InteropInterfaceType, AnyType: - default: - w.Err = fmt.Errorf("unknown type: %x", p.Type) - } -} - -// DecodeBinary implements io.Serializable interface. -func (p *Parameter) DecodeBinary(r *io.BinReader) { - p.Type = ParamType(r.ReadB()) - switch p.Type { - case BoolType: - p.Value = r.ReadBool() - case ByteArrayType, PublicKeyType, SignatureType: - ln := r.ReadVarUint() - if ln != math.MaxUint64 { - b := make([]byte, ln) - r.ReadBytes(b) - p.Value = b - } - case StringType: - p.Value = r.ReadString() - case IntegerType: - bs := r.ReadVarBytes(bigint.MaxBytesLen) - if r.Err != nil { - return - } - p.Value = bigint.FromBytes(bs) - case ArrayType: - ps := []Parameter{} - r.ReadArray(&ps) - p.Value = ps - case MapType: - ps := []ParameterPair{} - r.ReadArray(&ps) - p.Value = ps - case Hash160Type: - var u util.Uint160 - r.ReadBytes(u[:]) - p.Value = u - case Hash256Type: - var u util.Uint256 - r.ReadBytes(u[:]) - p.Value = u - case InteropInterfaceType, AnyType: - default: - r.Err = fmt.Errorf("unknown type: %x", p.Type) - } -} - -// EncodeBinary implements io.Serializable interface. -func (p *ParameterPair) EncodeBinary(w *io.BinWriter) { - p.Key.EncodeBinary(w) - p.Value.EncodeBinary(w) -} - -// DecodeBinary implements io.Serializable interface. -func (p *ParameterPair) DecodeBinary(r *io.BinReader) { - p.Key.DecodeBinary(r) - p.Value.DecodeBinary(r) -} - // Params is an array of Parameter (TODO: drop it?). type Params []Parameter diff --git a/pkg/smartcontract/parameter_test.go b/pkg/smartcontract/parameter_test.go index 8fd87410f..e52cc67a1 100644 --- a/pkg/smartcontract/parameter_test.go +++ b/pkg/smartcontract/parameter_test.go @@ -10,7 +10,6 @@ import ( "strings" "testing" - "github.com/nspcc-dev/neo-go/internal/testserdes" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/util" @@ -526,20 +525,6 @@ func TestNewParameterFromString(t *testing.T) { } } -func TestEncodeDecodeBinary(t *testing.T) { - for _, tc := range marshalJSONTestCases { - testserdes.EncodeDecodeBinary(t, &tc.input, new(Parameter)) - } - - t.Run("unknown", func(t *testing.T) { - p := Parameter{Type: UnknownType} - _, err := testserdes.EncodeBinary(&p) - require.Error(t, err) - - require.Error(t, testserdes.DecodeBinary([]byte{0xAA}, &p)) - }) -} - func hexToBase64(s string) string { b, _ := hex.DecodeString(s) return base64.StdEncoding.EncodeToString(b) From 739db259e39a1feca182869543d631a9cd519068 Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Thu, 31 Mar 2022 09:55:25 +0300 Subject: [PATCH 3/3] smartcontract: remove unused `ParameterFromStackItem` It is exists from the times we used `smartcontract.Parameter` somewhere in the `NotificationEvent`/`ApplicationLog`. `stackitem.ToJSON` now handles this. Signed-off-by: Evgeniy Stratonikov --- pkg/smartcontract/convertor.go | 72 -------------------------- pkg/smartcontract/convertor_test.go | 79 ----------------------------- 2 files changed, 151 deletions(-) delete mode 100644 pkg/smartcontract/convertor.go delete mode 100644 pkg/smartcontract/convertor_test.go diff --git a/pkg/smartcontract/convertor.go b/pkg/smartcontract/convertor.go deleted file mode 100644 index fe977a91d..000000000 --- a/pkg/smartcontract/convertor.go +++ /dev/null @@ -1,72 +0,0 @@ -package smartcontract - -import ( - "fmt" - "math/big" - - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" -) - -// ParameterFromStackItem converts stackitem.Item to Parameter. -func ParameterFromStackItem(i stackitem.Item, seen map[stackitem.Item]bool) Parameter { - switch t := i.(type) { - case stackitem.Null, *stackitem.Pointer: - return NewParameter(AnyType) - case *stackitem.BigInteger: - return Parameter{ - Type: IntegerType, - Value: i.Value().(*big.Int), - } - case stackitem.Bool: - return Parameter{ - Type: BoolType, - Value: i.Value().(bool), - } - case *stackitem.ByteArray: - return Parameter{ - Type: ByteArrayType, - Value: i.Value().([]byte), - } - case *stackitem.Interop: - return Parameter{ - Type: InteropInterfaceType, - Value: nil, - } - case *stackitem.Buffer: - return Parameter{ - Type: ByteArrayType, - Value: i.Value().([]byte), - } - case *stackitem.Struct, *stackitem.Array: - var value []Parameter - - if !seen[i] { - seen[i] = true - for _, stackItem := range i.Value().([]stackitem.Item) { - parameter := ParameterFromStackItem(stackItem, seen) - value = append(value, parameter) - } - } - return Parameter{ - Type: ArrayType, - Value: value, - } - case *stackitem.Map: - value := make([]ParameterPair, 0) - if !seen[i] { - seen[i] = true - for _, element := range i.Value().([]stackitem.MapElement) { - value = append(value, ParameterPair{ - Key: ParameterFromStackItem(element.Key, seen), - Value: ParameterFromStackItem(element.Value, seen), - }) - } - } - return Parameter{ - Type: MapType, - Value: value, - } - default: - panic(fmt.Sprintf("unknown stack item type: %v", t)) - } -} diff --git a/pkg/smartcontract/convertor_test.go b/pkg/smartcontract/convertor_test.go deleted file mode 100644 index 3aaae34d5..000000000 --- a/pkg/smartcontract/convertor_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package smartcontract - -import ( - "math/big" - "testing" - - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/stretchr/testify/assert" -) - -var toContractParameterTestCases = []struct { - input stackitem.Item - result Parameter -}{ - { - input: stackitem.NewStruct([]stackitem.Item{ - stackitem.NewBigInteger(big.NewInt(1)), - stackitem.NewBool(true), - }), - result: Parameter{Type: ArrayType, Value: []Parameter{ - {Type: IntegerType, Value: big.NewInt(1)}, - {Type: BoolType, Value: true}, - }}, - }, - { - input: stackitem.NewBool(false), - result: Parameter{Type: BoolType, Value: false}, - }, - { - input: stackitem.NewByteArray([]byte{0x01, 0x02, 0x03}), - result: Parameter{Type: ByteArrayType, Value: []byte{0x01, 0x02, 0x03}}, - }, - { - input: stackitem.NewBuffer([]byte{0x01, 0x02, 0x03}), - result: Parameter{Type: ByteArrayType, Value: []byte{0x01, 0x02, 0x03}}, - }, - { - input: stackitem.NewArray([]stackitem.Item{stackitem.NewBigInteger(big.NewInt(2)), stackitem.NewBool(true)}), - result: Parameter{Type: ArrayType, Value: []Parameter{ - {Type: IntegerType, Value: big.NewInt(2)}, - {Type: BoolType, Value: true}, - }}, - }, - { - input: stackitem.NewInterop(nil), - result: Parameter{Type: InteropInterfaceType, Value: nil}, - }, - { - input: stackitem.NewMapWithValue([]stackitem.MapElement{ - {Key: stackitem.NewBigInteger(big.NewInt(1)), Value: stackitem.NewBool(true)}, - {Key: stackitem.NewByteArray([]byte("qwerty")), Value: stackitem.NewBigInteger(big.NewInt(3))}, - {Key: stackitem.NewBool(true), Value: stackitem.NewBool(false)}, - }), - result: Parameter{ - Type: MapType, - Value: []ParameterPair{ - { - Key: Parameter{Type: IntegerType, Value: big.NewInt(1)}, - Value: Parameter{Type: BoolType, Value: true}, - }, { - Key: Parameter{Type: ByteArrayType, Value: []byte("qwerty")}, - Value: Parameter{Type: IntegerType, Value: big.NewInt(3)}, - }, { - - Key: Parameter{Type: BoolType, Value: true}, - Value: Parameter{Type: BoolType, Value: false}, - }, - }, - }, - }, -} - -func TestToContractParameter(t *testing.T) { - for _, tc := range toContractParameterTestCases { - seen := make(map[stackitem.Item]bool) - res := ParameterFromStackItem(tc.input, seen) - assert.Equal(t, res, tc.result) - } -}