diff --git a/pkg/rpc/param.go b/pkg/rpc/param.go index 52360830d..08f50615c 100644 --- a/pkg/rpc/param.go +++ b/pkg/rpc/param.go @@ -1,6 +1,7 @@ package rpc import ( + "encoding/hex" "encoding/json" "fmt" @@ -24,6 +25,7 @@ const ( defaultT paramType = iota stringT numberT + arrayT ) func (p Param) String() string { @@ -46,6 +48,17 @@ func (p Param) GetUint256() (util.Uint256, error) { return util.Uint256DecodeReverseString(s) } +// GetBytesHex returns []byte value of the parameter if +// it is a hex-encoded string. +func (p Param) GetBytesHex() ([]byte, error) { + s, ok := p.Value.(string) + if !ok { + return nil, errors.New("must be a string") + } + + return hex.DecodeString(s) +} + // UnmarshalJSON implements json.Unmarshaler interface. func (p *Param) UnmarshalJSON(data []byte) error { var s string @@ -64,5 +77,13 @@ func (p *Param) UnmarshalJSON(data []byte) error { return nil } + var ps []Param + if err := json.Unmarshal(data, &ps); err == nil { + p.Type = arrayT + p.Value = ps + + return nil + } + return errors.New("unknown type") } diff --git a/pkg/rpc/param_test.go b/pkg/rpc/param_test.go new file mode 100644 index 000000000..fca26196b --- /dev/null +++ b/pkg/rpc/param_test.go @@ -0,0 +1,42 @@ +package rpc + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParam_UnmarshalJSON(t *testing.T) { + msg := `["str1", 123, ["str2", 3]]` + expected := Params{ + { + Type: stringT, + Value: "str1", + }, + { + Type: numberT, + Value: 123, + }, + { + Type: arrayT, + Value: []Param{ + { + Type: stringT, + Value: "str2", + }, + { + Type: numberT, + Value: 3, + }, + }, + }, + } + + var ps Params + require.NoError(t, json.Unmarshal([]byte(msg), &ps)) + require.Equal(t, expected, ps) + + msg = `[{"2": 3}]` + require.Error(t, json.Unmarshal([]byte(msg), &ps)) +} diff --git a/pkg/rpc/server.go b/pkg/rpc/server.go index c9e730321..507ae38f4 100644 --- a/pkg/rpc/server.go +++ b/pkg/rpc/server.go @@ -322,21 +322,22 @@ func (s *Server) getAccountState(reqParams Params, unspents bool) (interface{}, // invokescript implements the `invokescript` RPC call. func (s *Server) invokescript(reqParams Params) (interface{}, error) { - hexScript, ok := reqParams.ValueWithType(0, stringT) - if !ok { + if len(reqParams) < 1 { return nil, errInvalidParams } - script, err := hex.DecodeString(hexScript.GetString()) + + script, err := reqParams[0].GetBytesHex() if err != nil { - return nil, err + return nil, errInvalidParams } + vm, _ := s.chain.GetTestVM() vm.LoadScript(script) _ = vm.Run() result := &wrappers.InvokeResult{ State: vm.State(), GasConsumed: "0.1", - Script: hexScript.GetString(), + Script: reqParams[0].GetString(), Stack: vm.Estack(), } return result, nil @@ -346,11 +347,10 @@ func (s *Server) sendrawtransaction(reqParams Params) (interface{}, error) { var resultsErr error var results interface{} - param, ok := reqParams.ValueWithType(0, stringT) - if !ok { - resultsErr = errInvalidParams - } else if byteTx, err := hex.DecodeString(param.GetString()); err != nil { - resultsErr = errInvalidParams + if len(reqParams) < 1 { + return nil, errInvalidParams + } else if byteTx, err := reqParams[0].GetBytesHex(); err != nil { + return nil, errInvalidParams } else { r := io.NewBinReaderFromBuf(byteTx) tx := &transaction.Transaction{}