diff --git a/pkg/rpcclient/rpc.go b/pkg/rpcclient/rpc.go index abfed089f..049f46a46 100644 --- a/pkg/rpcclient/rpc.go +++ b/pkg/rpcclient/rpc.go @@ -1047,7 +1047,7 @@ func (c *Client) AddNetworkFee(tx *transaction.Transaction, extraFee int64, accs var ef int64 for i, cosigner := range tx.Signers { if accs[i].Contract.Deployed { - res, err := c.InvokeContractVerify(cosigner.Account, smartcontract.Params{}, tx.Signers) + res, err := c.InvokeContractVerify(cosigner.Account, []smartcontract.Parameter{}, tx.Signers) if err != nil { return fmt.Errorf("failed to invoke verify: %w", err) } diff --git a/pkg/services/rpcsrv/client_test.go b/pkg/services/rpcsrv/client_test.go index 219963faf..4c12cf9d1 100644 --- a/pkg/services/rpcsrv/client_test.go +++ b/pkg/services/rpcsrv/client_test.go @@ -773,7 +773,7 @@ func TestInvokeVerify(t *testing.T) { require.NoError(t, err) t.Run("positive, with signer", func(t *testing.T) { - res, err := c.InvokeContractVerify(contract, smartcontract.Params{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) + res, err := c.InvokeContractVerify(contract, []smartcontract.Parameter{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) require.NoError(t, err) require.Equal(t, "HALT", res.State) require.Equal(t, 1, len(res.Stack)) @@ -782,7 +782,7 @@ func TestInvokeVerify(t *testing.T) { t.Run("positive, historic, by height, with signer", func(t *testing.T) { h := chain.BlockHeight() - 1 - res, err := c.InvokeContractVerifyAtHeight(h, contract, smartcontract.Params{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) + res, err := c.InvokeContractVerifyAtHeight(h, contract, []smartcontract.Parameter{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) require.NoError(t, err) require.Equal(t, "HALT", res.State) require.Equal(t, 1, len(res.Stack)) @@ -790,7 +790,7 @@ func TestInvokeVerify(t *testing.T) { }) t.Run("positive, historic, by block, with signer", func(t *testing.T) { - res, err := c.InvokeContractVerifyAtBlock(chain.GetHeaderHash(int(chain.BlockHeight())-1), contract, smartcontract.Params{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) + res, err := c.InvokeContractVerifyAtBlock(chain.GetHeaderHash(int(chain.BlockHeight())-1), contract, []smartcontract.Parameter{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) require.NoError(t, err) require.Equal(t, "HALT", res.State) require.Equal(t, 1, len(res.Stack)) @@ -801,7 +801,7 @@ func TestInvokeVerify(t *testing.T) { h := chain.BlockHeight() - 1 sr, err := chain.GetStateModule().GetStateRoot(h) require.NoError(t, err) - res, err := c.InvokeContractVerifyWithState(sr.Root, contract, smartcontract.Params{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) + res, err := c.InvokeContractVerifyWithState(sr.Root, contract, []smartcontract.Parameter{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) require.NoError(t, err) require.Equal(t, "HALT", res.State) require.Equal(t, 1, len(res.Stack)) @@ -810,13 +810,13 @@ func TestInvokeVerify(t *testing.T) { t.Run("bad, historic, by hash: contract not found", func(t *testing.T) { var h uint32 = 1 - _, err = c.InvokeContractVerifyAtHeight(h, contract, smartcontract.Params{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) + _, err = c.InvokeContractVerifyAtHeight(h, contract, []smartcontract.Parameter{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) require.Error(t, err) require.True(t, strings.Contains(err.Error(), core.ErrUnknownVerificationContract.Error())) // contract wasn't deployed at block #1 yet }) t.Run("bad, historic, by block: contract not found", func(t *testing.T) { - _, err = c.InvokeContractVerifyAtBlock(chain.GetHeaderHash(1), contract, smartcontract.Params{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) + _, err = c.InvokeContractVerifyAtBlock(chain.GetHeaderHash(1), contract, []smartcontract.Parameter{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) require.Error(t, err) require.True(t, strings.Contains(err.Error(), core.ErrUnknownVerificationContract.Error())) // contract wasn't deployed at block #1 yet }) @@ -825,13 +825,13 @@ func TestInvokeVerify(t *testing.T) { var h uint32 = 1 sr, err := chain.GetStateModule().GetStateRoot(h) require.NoError(t, err) - _, err = c.InvokeContractVerifyWithState(sr.Root, contract, smartcontract.Params{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) + _, err = c.InvokeContractVerifyWithState(sr.Root, contract, []smartcontract.Parameter{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}) require.Error(t, err) require.True(t, strings.Contains(err.Error(), core.ErrUnknownVerificationContract.Error())) // contract wasn't deployed at block #1 yet }) t.Run("positive, with signer and witness", func(t *testing.T) { - res, err := c.InvokeContractVerify(contract, smartcontract.Params{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}, transaction.Witness{InvocationScript: []byte{byte(opcode.PUSH1), byte(opcode.RET)}}) + res, err := c.InvokeContractVerify(contract, []smartcontract.Parameter{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}, transaction.Witness{InvocationScript: []byte{byte(opcode.PUSH1), byte(opcode.RET)}}) require.NoError(t, err) require.Equal(t, "HALT", res.State) require.Equal(t, 1, len(res.Stack)) @@ -839,12 +839,12 @@ func TestInvokeVerify(t *testing.T) { }) t.Run("error, invalid witness number", func(t *testing.T) { - _, err := c.InvokeContractVerify(contract, smartcontract.Params{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}, transaction.Witness{InvocationScript: []byte{byte(opcode.PUSH1), byte(opcode.RET)}}, transaction.Witness{InvocationScript: []byte{byte(opcode.RET)}}) + _, err := c.InvokeContractVerify(contract, []smartcontract.Parameter{}, []transaction.Signer{{Account: testchain.PrivateKeyByID(0).PublicKey().GetScriptHash()}}, transaction.Witness{InvocationScript: []byte{byte(opcode.PUSH1), byte(opcode.RET)}}, transaction.Witness{InvocationScript: []byte{byte(opcode.RET)}}) require.Error(t, err) }) t.Run("false", func(t *testing.T) { - res, err := c.InvokeContractVerify(contract, smartcontract.Params{}, []transaction.Signer{{Account: util.Uint160{}}}) + res, err := c.InvokeContractVerify(contract, []smartcontract.Parameter{}, []transaction.Signer{{Account: util.Uint160{}}}) require.NoError(t, err) require.Equal(t, "HALT", res.State) require.Equal(t, 1, len(res.Stack)) diff --git a/pkg/smartcontract/parameter.go b/pkg/smartcontract/parameter.go index 97cb04a2c..3cecd259c 100644 --- a/pkg/smartcontract/parameter.go +++ b/pkg/smartcontract/parameter.go @@ -3,19 +3,16 @@ package smartcontract import ( "bytes" "encoding/base64" - "encoding/binary" "encoding/hex" "encoding/json" "errors" "fmt" "math/big" - "math/bits" "os" "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/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) @@ -194,123 +191,6 @@ func (p *Parameter) UnmarshalJSON(data []byte) (err error) { return } -// Params is an array of Parameter (TODO: drop it?). -type Params []Parameter - -// TryParseArray converts an array of Parameter into an array of more appropriate things. -func (p Params) TryParseArray(vals ...interface{}) error { - var ( - err error - i int - par Parameter - ) - if len(p) != len(vals) { - return errors.New("receiver array doesn't fit the Params length") - } - for i, par = range p { - if err = par.TryParse(vals[i]); err != nil { - return err - } - } - return nil -} - -// TryParse converts one Parameter into something more appropriate. -func (p Parameter) TryParse(dest interface{}) error { - var ( - err error - ok bool - data []byte - ) - switch p.Type { - case ByteArrayType: - if data, ok = p.Value.([]byte); !ok { - return fmt.Errorf("failed to cast %s to []byte", p.Value) - } - switch dest := dest.(type) { - case *util.Uint160: - if *dest, err = util.Uint160DecodeBytesBE(data); err != nil { - return err - } - return nil - case *[]byte: - *dest = data - return nil - case *util.Uint256: - if *dest, err = util.Uint256DecodeBytesLE(data); err != nil { - 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) { - case *int64, *uint64: - size = 64 - case *int32, *uint32: - size = 32 - case *int16, *uint16: - size = 16 - case *int8, *uint8: - size = 8 - case *int, *uint: - size = bits.UintSize - } - - i, err := bytesToUint64(data, size) - if err != nil { - return err - } - - switch dest := dest.(type) { - case *int64: - *dest = int64(i) - case *int32: - *dest = int32(i) - case *int16: - *dest = int16(i) - case *int8: - *dest = int8(i) - case *int: - *dest = int(i) - case *uint64: - *dest = i - case *uint32: - *dest = uint32(i) - case *uint16: - *dest = uint16(i) - case *uint8: - *dest = uint8(i) - case *uint: - *dest = uint(i) - } - case *string: - *dest = string(data) - return nil - default: - return fmt.Errorf("cannot cast param of type %s to type %s", p.Type, dest) - } - default: - return errors.New("cannot define param type") - } - return nil -} - -func bytesToUint64(b []byte, size int) (uint64, error) { - var length = size / 8 - if len(b) > length { - return 0, fmt.Errorf("input doesn't fit into %d bits", size) - } - if len(b) < length { - data := make([]byte, length) - copy(data, b) - return binary.LittleEndian.Uint64(data), nil - } - return binary.LittleEndian.Uint64(b), nil -} - // NewParameterFromString returns a new Parameter initialized from the given // string in neo-go-specific format. It is intended to be used in user-facing // interfaces and has some heuristics in it to simplify parameter passing. The exact diff --git a/pkg/smartcontract/parameter_test.go b/pkg/smartcontract/parameter_test.go index e52cc67a1..51b5931c4 100644 --- a/pkg/smartcontract/parameter_test.go +++ b/pkg/smartcontract/parameter_test.go @@ -6,7 +6,6 @@ import ( "encoding/json" "math" "math/big" - "reflect" "strings" "testing" @@ -341,89 +340,6 @@ func TestParam_UnmarshalJSON(t *testing.T) { } } -var tryParseTestCases = []struct { - input interface{} - expected interface{} -}{ - { - input: []byte{ - 0x0b, 0xcd, 0x29, 0x78, 0x63, 0x4d, 0x96, 0x1c, 0x24, 0xf5, - 0xae, 0xa0, 0x80, 0x22, 0x97, 0xff, 0x12, 0x87, 0x24, 0xd6, - }, - expected: util.Uint160{ - 0x0b, 0xcd, 0x29, 0x78, 0x63, 0x4d, 0x96, 0x1c, 0x24, 0xf5, - 0xae, 0xa0, 0x80, 0x22, 0x97, 0xff, 0x12, 0x87, 0x24, 0xd6, - }, - }, - { - input: []byte{ - 0xf0, 0x37, 0x30, 0x8f, 0xa0, 0xab, 0x18, 0x15, - 0x5b, 0xcc, 0xfc, 0x08, 0x48, 0x54, 0x68, 0xc1, - 0x12, 0x40, 0x9e, 0xa5, 0x06, 0x45, 0x95, 0x69, - 0x9e, 0x98, 0xc5, 0x45, 0xf2, 0x45, 0xf3, 0x2d, - }, - expected: util.Uint256{ - 0x2d, 0xf3, 0x45, 0xf2, 0x45, 0xc5, 0x98, 0x9e, - 0x69, 0x95, 0x45, 0x06, 0xa5, 0x9e, 0x40, 0x12, - 0xc1, 0x68, 0x54, 0x48, 0x08, 0xfc, 0xcc, 0x5b, - 0x15, 0x18, 0xab, 0xa0, 0x8f, 0x30, 0x37, 0xf0, - }, - }, - { - input: []byte{0, 1, 2, 3, 4, 9, 8, 6}, - expected: []byte{0, 1, 2, 3, 4, 9, 8, 6}, - }, - { - 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", - }, -} - -func TestParam_TryParse(t *testing.T) { - for _, tc := range tryParseTestCases { - t.Run(reflect.TypeOf(tc.expected).String(), func(t *testing.T) { - input := Parameter{ - Type: ByteArrayType, - Value: tc.input, - } - - val := reflect.New(reflect.TypeOf(tc.expected)) - assert.NoError(t, input.TryParse(val.Interface())) - assert.Equal(t, tc.expected, val.Elem().Interface()) - }) - } - - t.Run("[]Uint160", func(t *testing.T) { - exp1 := util.Uint160{1, 2, 3, 4, 5} - exp2 := util.Uint160{9, 8, 7, 6, 5} - - params := Params{ - { - Type: ByteArrayType, - Value: exp1.BytesBE(), - }, - { - Type: ByteArrayType, - Value: exp2.BytesBE(), - }, - } - - var out1, out2 util.Uint160 - - assert.NoError(t, params.TryParseArray(&out1, &out2)) - assert.Equal(t, exp1, out1) - assert.Equal(t, exp2, out2) - }) -} - func TestParamType_String(t *testing.T) { types := []ParamType{ SignatureType,