forked from TrueCloudLab/neoneo-go
Merge pull request #2413 from nspcc-dev/smartcontract-big-numbers
smartcontract: allow to use `*big.Int` numbers for integers
This commit is contained in:
commit
2d60d4021b
7 changed files with 86 additions and 286 deletions
|
@ -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 {
|
||||
|
|
|
@ -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).Int64(),
|
||||
}
|
||||
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))
|
||||
}
|
||||
}
|
|
@ -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: int64(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: int64(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: int64(1)},
|
||||
Value: Parameter{Type: BoolType, Value: true},
|
||||
}, {
|
||||
Key: Parameter{Type: ByteArrayType, Value: []byte("qwerty")},
|
||||
Value: Parameter{Type: IntegerType, Value: int64(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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -8,16 +8,16 @@ import (
|
|||
"encoding/json"
|
||||
"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/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
||||
"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 +65,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 +144,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
|
||||
|
@ -190,87 +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:
|
||||
w.WriteU64LE(uint64(p.Value.(int64)))
|
||||
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:
|
||||
p.Value = int64(r.ReadU64LE())
|
||||
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
|
||||
|
||||
|
@ -318,6 +241,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) {
|
||||
|
|
|
@ -5,10 +5,11 @@ import (
|
|||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"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"
|
||||
|
@ -22,9 +23,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 +62,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 +89,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 +107,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 +190,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 +220,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 +253,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 +271,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 +315,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 +337,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 +377,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 +461,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 +476,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},
|
||||
|
@ -514,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)
|
||||
|
@ -544,8 +541,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 +572,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 +588,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()
|
||||
|
|
Loading…
Reference in a new issue