aboutsummaryrefslogtreecommitdiffstats
path: root/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'rpc')
-rw-r--r--rpc/json.go67
-rw-r--r--rpc/types.go115
-rw-r--r--rpc/types_test.go95
3 files changed, 34 insertions, 243 deletions
diff --git a/rpc/json.go b/rpc/json.go
index a7053e3f5..ac5a4acd3 100644
--- a/rpc/json.go
+++ b/rpc/json.go
@@ -17,6 +17,7 @@
package rpc
import (
+ "bytes"
"encoding/json"
"fmt"
"io"
@@ -256,8 +257,8 @@ func parseBatchRequest(incomingMsg json.RawMessage) ([]rpcRequest, bool, Error)
return requests, true, nil
}
-// ParseRequestArguments tries to parse the given params (json.RawMessage) with the given types. It returns the parsed
-// values or an error when the parsing failed.
+// ParseRequestArguments tries to parse the given params (json.RawMessage) with the given
+// types. It returns the parsed values or an error when the parsing failed.
func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interface{}) ([]reflect.Value, Error) {
if args, ok := params.(json.RawMessage); !ok {
return nil, &invalidParamsError{"Invalid params supplied"}
@@ -266,42 +267,42 @@ func (c *jsonCodec) ParseRequestArguments(argTypes []reflect.Type, params interf
}
}
-// parsePositionalArguments tries to parse the given args to an array of values with the given types.
-// It returns the parsed values or an error when the args could not be parsed. Missing optional arguments
-// are returned as reflect.Zero values.
-func parsePositionalArguments(args json.RawMessage, callbackArgs []reflect.Type) ([]reflect.Value, Error) {
- params := make([]interface{}, 0, len(callbackArgs))
- for _, t := range callbackArgs {
- params = append(params, reflect.New(t).Interface())
+// parsePositionalArguments tries to parse the given args to an array of values with the
+// given types. It returns the parsed values or an error when the args could not be
+// parsed. Missing optional arguments are returned as reflect.Zero values.
+func parsePositionalArguments(rawArgs json.RawMessage, types []reflect.Type) ([]reflect.Value, Error) {
+ // Read beginning of the args array.
+ dec := json.NewDecoder(bytes.NewReader(rawArgs))
+ if tok, _ := dec.Token(); tok != json.Delim('[') {
+ return nil, &invalidParamsError{"non-array args"}
}
-
- if err := json.Unmarshal(args, &params); err != nil {
- return nil, &invalidParamsError{err.Error()}
- }
-
- if len(params) > len(callbackArgs) {
- return nil, &invalidParamsError{fmt.Sprintf("too many params, want %d got %d", len(callbackArgs), len(params))}
+ // Read args.
+ args := make([]reflect.Value, 0, len(types))
+ for i := 0; dec.More(); i++ {
+ if i >= len(types) {
+ return nil, &invalidParamsError{fmt.Sprintf("too many arguments, want at most %d", len(types))}
+ }
+ argval := reflect.New(types[i])
+ if err := dec.Decode(argval.Interface()); err != nil {
+ return nil, &invalidParamsError{fmt.Sprintf("invalid argument %d: %v", i, err)}
+ }
+ if argval.IsNil() && types[i].Kind() != reflect.Ptr {
+ return nil, &invalidParamsError{fmt.Sprintf("missing value for required argument %d", i)}
+ }
+ args = append(args, argval.Elem())
}
-
- // assume missing params are null values
- for i := len(params); i < len(callbackArgs); i++ {
- params = append(params, nil)
+ // Read end of args array.
+ if _, err := dec.Token(); err != nil {
+ return nil, &invalidParamsError{err.Error()}
}
-
- argValues := make([]reflect.Value, len(params))
- for i, p := range params {
- // verify that JSON null values are only supplied for optional arguments (ptr types)
- if p == nil && callbackArgs[i].Kind() != reflect.Ptr {
- return nil, &invalidParamsError{fmt.Sprintf("invalid or missing value for params[%d]", i)}
- }
- if p == nil {
- argValues[i] = reflect.Zero(callbackArgs[i])
- } else { // deref pointers values creates previously with reflect.New
- argValues[i] = reflect.ValueOf(p).Elem()
+ // Set any missing args to nil.
+ for i := len(args); i < len(types); i++ {
+ if types[i].Kind() != reflect.Ptr {
+ return nil, &invalidParamsError{fmt.Sprintf("missing value for required argument %d", i)}
}
+ args = append(args, reflect.Zero(types[i]))
}
-
- return argValues, nil
+ return args, nil
}
// CreateResponse will create a JSON-RPC success response with the given id and reply as result.
diff --git a/rpc/types.go b/rpc/types.go
index ebe388373..01b95a170 100644
--- a/rpc/types.go
+++ b/rpc/types.go
@@ -17,8 +17,6 @@
package rpc
import (
- "bytes"
- "encoding/hex"
"fmt"
"math"
"math/big"
@@ -123,91 +121,6 @@ type ServerCodec interface {
Closed() <-chan interface{}
}
-// HexNumber serializes a number to hex format using the "%#x" format
-type HexNumber big.Int
-
-// NewHexNumber creates a new hex number instance which will serialize the given val with `%#x` on marshal.
-func NewHexNumber(val interface{}) *HexNumber {
- if val == nil {
- return nil // note, this doesn't catch nil pointers, only passing nil directly!
- }
-
- if v, ok := val.(*big.Int); ok {
- if v != nil {
- return (*HexNumber)(new(big.Int).Set(v))
- }
- return nil
- }
-
- rval := reflect.ValueOf(val)
-
- var unsigned uint64
- utype := reflect.TypeOf(unsigned)
- if t := rval.Type(); t.ConvertibleTo(utype) {
- hn := new(big.Int).SetUint64(rval.Convert(utype).Uint())
- return (*HexNumber)(hn)
- }
-
- var signed int64
- stype := reflect.TypeOf(signed)
- if t := rval.Type(); t.ConvertibleTo(stype) {
- hn := new(big.Int).SetInt64(rval.Convert(stype).Int())
- return (*HexNumber)(hn)
- }
-
- return nil
-}
-
-func (h *HexNumber) UnmarshalJSON(input []byte) error {
- length := len(input)
- if length >= 2 && input[0] == '"' && input[length-1] == '"' {
- input = input[1 : length-1]
- }
-
- hn := (*big.Int)(h)
- if _, ok := hn.SetString(string(input), 0); ok {
- return nil
- }
-
- return fmt.Errorf("Unable to parse number")
-}
-
-// MarshalJSON serialize the hex number instance to a hex representation.
-func (h *HexNumber) MarshalJSON() ([]byte, error) {
- if h != nil {
- hn := (*big.Int)(h)
- if hn.BitLen() == 0 {
- return []byte(`"0x0"`), nil
- }
- return []byte(fmt.Sprintf(`"0x%x"`, hn)), nil
- }
- return nil, nil
-}
-
-func (h *HexNumber) Int() int {
- hn := (*big.Int)(h)
- return int(hn.Int64())
-}
-
-func (h *HexNumber) Int64() int64 {
- hn := (*big.Int)(h)
- return hn.Int64()
-}
-
-func (h *HexNumber) Uint() uint {
- hn := (*big.Int)(h)
- return uint(hn.Uint64())
-}
-
-func (h *HexNumber) Uint64() uint64 {
- hn := (*big.Int)(h)
- return hn.Uint64()
-}
-
-func (h *HexNumber) BigInt() *big.Int {
- return (*big.Int)(h)
-}
-
var (
pendingBlockNumber = big.NewInt(-2)
latestBlockNumber = big.NewInt(-1)
@@ -274,31 +187,3 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
func (bn BlockNumber) Int64() int64 {
return (int64)(bn)
}
-
-// HexBytes JSON-encodes as hex with 0x prefix.
-type HexBytes []byte
-
-func (b HexBytes) MarshalJSON() ([]byte, error) {
- result := make([]byte, len(b)*2+4)
- copy(result, `"0x`)
- hex.Encode(result[3:], b)
- result[len(result)-1] = '"'
- return result, nil
-}
-
-func (b *HexBytes) UnmarshalJSON(input []byte) error {
- if len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' {
- input = input[1 : len(input)-1]
- }
- if !bytes.HasPrefix(input, []byte("0x")) {
- return fmt.Errorf("missing 0x prefix for hex byte array")
- }
- input = input[2:]
- if len(input) == 0 {
- *b = nil
- return nil
- }
- *b = make([]byte, len(input)/2)
- _, err := hex.Decode(*b, input)
- return err
-}
diff --git a/rpc/types_test.go b/rpc/types_test.go
deleted file mode 100644
index 5482557b8..000000000
--- a/rpc/types_test.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2015 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-package rpc
-
-import (
- "bytes"
- "encoding/json"
- "math/big"
- "testing"
-)
-
-func TestNewHexNumber(t *testing.T) {
- tests := []interface{}{big.NewInt(123), int64(123), uint64(123), int8(123), uint8(123)}
-
- for i, v := range tests {
- hn := NewHexNumber(v)
- if hn == nil {
- t.Fatalf("Unable to create hex number instance for tests[%d]", i)
- }
- if hn.Int64() != 123 {
- t.Fatalf("expected %d, got %d on value tests[%d]", 123, hn.Int64(), i)
- }
- }
-
- failures := []interface{}{"", nil, []byte{1, 2, 3, 4}}
- for i, v := range failures {
- hn := NewHexNumber(v)
- if hn != nil {
- t.Fatalf("Creating a nex number instance of %T should fail (failures[%d])", failures[i], i)
- }
- }
-}
-
-func TestHexNumberUnmarshalJSON(t *testing.T) {
- tests := []string{`"0x4d2"`, "1234", `"1234"`}
- for i, v := range tests {
- var hn HexNumber
- if err := json.Unmarshal([]byte(v), &hn); err != nil {
- t.Fatalf("Test %d failed - %s", i, err)
- }
-
- if hn.Int64() != 1234 {
- t.Fatalf("Expected %d, got %d for test[%d]", 1234, hn.Int64(), i)
- }
- }
-}
-
-func TestHexNumberMarshalJSON(t *testing.T) {
- hn := NewHexNumber(1234567890)
- got, err := json.Marshal(hn)
- if err != nil {
- t.Fatalf("Unable to marshal hex number - %s", err)
- }
-
- exp := []byte(`"0x499602d2"`)
- if bytes.Compare(exp, got) != 0 {
- t.Fatalf("Invalid json.Marshal, expected '%s', got '%s'", exp, got)
- }
-}
-
-var hexBytesTests = []struct{ in, out []byte }{
- {in: []byte(`"0x"`), out: []byte{}},
- {in: []byte(`"0x00"`), out: []byte{0}},
- {in: []byte(`"0x01ff"`), out: []byte{0x01, 0xFF}},
-}
-
-func TestHexBytes(t *testing.T) {
- for i, test := range hexBytesTests {
- var dec HexBytes
- if err := json.Unmarshal(test.in, &dec); err != nil {
- t.Fatalf("test %d: can't decode: %v", i, err)
- }
- enc, _ := json.Marshal(HexBytes(test.out))
- if !bytes.Equal(dec, test.out) {
- t.Errorf("test %d: wrong decoded value 0x%x", i, dec)
- }
- if !bytes.Equal(enc, test.in) {
- t.Errorf("test %d: wrong encoded value %#q", i, enc)
- }
- }
-}