瀏覽代碼

Merge pull request #579 from tgerring/rpcargs

RPC Args
Jeffrey Wilcke 10 年之前
父節點
當前提交
b9ca5eef58
共有 7 個文件被更改,包括 1066 次插入358 次删除
  1. 0 23
      core/filter.go
  2. 8 81
      rpc/api.go
  3. 303 150
      rpc/args.go
  4. 695 97
      rpc/args_test.go
  5. 16 0
      rpc/messages.go
  6. 9 0
      rpc/messages_test.go
  7. 35 7
      xeth/xeth.go

+ 0 - 23
core/filter.go

@@ -12,17 +12,6 @@ type AccountChange struct {
 	Address, StateAddress []byte
 }
 
-type FilterOptions struct {
-	Earliest int64
-	Latest   int64
-
-	Address []common.Address
-	Topics  [][]common.Hash
-
-	Skip int
-	Max  int
-}
-
 // Filtering interface
 type Filter struct {
 	eth      Backend
@@ -44,18 +33,6 @@ func NewFilter(eth Backend) *Filter {
 	return &Filter{eth: eth}
 }
 
-// SetOptions copies the filter options to the filter it self. The reason for this "silly" copy
-// is simply because named arguments in this case is extremely nice and readable.
-func (self *Filter) SetOptions(options *FilterOptions) {
-	self.earliest = options.Earliest
-	self.latest = options.Latest
-	self.skip = options.Skip
-	self.max = options.Max
-	self.address = options.Address
-	self.topics = options.Topics
-
-}
-
 // Set the earliest and latest block for filtering.
 // -1 = latest block (i.e., the current block)
 // hash = particular hash from-to

+ 8 - 81
rpc/api.go

@@ -6,7 +6,6 @@ import (
 	"sync"
 
 	"github.com/ethereum/go-ethereum/common"
-	"github.com/ethereum/go-ethereum/core"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/xeth"
 )
@@ -82,10 +81,6 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 			return err
 		}
 
-		if err := args.requirements(); err != nil {
-			return err
-		}
-
 		v := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance()
 		*reply = common.ToHex(v.Bytes())
 	case "eth_getStorage", "eth_storageAt":
@@ -94,19 +89,12 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 			return err
 		}
 
-		if err := args.requirements(); err != nil {
-			return err
-		}
-
 		*reply = api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Storage()
 	case "eth_getStorageAt":
 		args := new(GetStorageAtArgs)
 		if err := json.Unmarshal(req.Params, &args); err != nil {
 			return err
 		}
-		if err := args.requirements(); err != nil {
-			return err
-		}
 
 		state := api.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address)
 		value := state.StorageString(args.Key)
@@ -118,11 +106,6 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 			return err
 		}
 
-		err := args.requirements()
-		if err != nil {
-			return err
-		}
-
 		*reply = api.xethAtStateNum(args.BlockNumber).TxCountAt(args.Address)
 	case "eth_getBlockTransactionCountByHash":
 		args := new(GetBlockByHashArgs)
@@ -163,9 +146,6 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 		if err := json.Unmarshal(req.Params, &args); err != nil {
 			return err
 		}
-		if err := args.requirements(); err != nil {
-			return err
-		}
 		*reply = api.xethAtStateNum(args.BlockNumber).CodeAt(args.Address)
 	case "eth_sendTransaction", "eth_transact":
 		args := new(NewTxArgs)
@@ -173,10 +153,6 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 			return err
 		}
 
-		if err := args.requirements(); err != nil {
-			return err
-		}
-
 		v, err := api.xeth().Transact(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
 		if err != nil {
 			return err
@@ -267,8 +243,8 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 			return NewValidationError("Index", "does not exist")
 		}
 
-		uhash := br.Uncles[args.Index].Hex()
-		uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash))
+		uhash := br.Uncles[args.Index]
+		uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.Hex()))
 
 		*reply = uncle
 	case "eth_getUncleByBlockNumberAndIndex":
@@ -285,8 +261,8 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 			return NewValidationError("Index", "does not exist")
 		}
 
-		uhash := v.Uncles[args.Index].Hex()
-		uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash))
+		uhash := v.Uncles[args.Index]
+		uncle := NewBlockRes(api.xeth().EthBlockByHash(uhash.Hex()))
 
 		*reply = uncle
 	case "eth_getCompilers":
@@ -300,18 +276,13 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 			return err
 		}
 
-		opts := toFilterOptions(args)
-		id := api.xeth().RegisterFilter(opts)
+		id := api.xeth().RegisterFilter(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics)
 		*reply = common.ToHex(big.NewInt(int64(id)).Bytes())
 	case "eth_newBlockFilter":
 		args := new(FilterStringArgs)
 		if err := json.Unmarshal(req.Params, &args); err != nil {
 			return err
 		}
-		if err := args.requirements(); err != nil {
-			return err
-		}
-
 		id := api.xeth().NewFilterString(args.Word)
 		*reply = common.ToHex(big.NewInt(int64(id)).Bytes())
 	case "eth_uninstallFilter":
@@ -337,8 +308,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 		if err := json.Unmarshal(req.Params, &args); err != nil {
 			return err
 		}
-		opts := toFilterOptions(args)
-		*reply = NewLogsRes(api.xeth().AllLogs(opts))
+		*reply = NewLogsRes(api.xeth().AllLogs(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics))
 	case "eth_getWork":
 		api.xeth().SetMining(true)
 		*reply = api.xeth().RemoteMining().GetWork()
@@ -347,7 +317,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 		if err := json.Unmarshal(req.Params, &args); err != nil {
 			return err
 		}
-		*reply = api.xeth().RemoteMining().SubmitWork(args.Nonce, args.Digest, args.Header)
+		*reply = api.xeth().RemoteMining().SubmitWork(args.Nonce, common.HexToHash(args.Digest), common.HexToHash(args.Header))
 	case "db_putString":
 		args := new(DbArgs)
 		if err := json.Unmarshal(req.Params, &args); err != nil {
@@ -433,7 +403,7 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 			return err
 		}
 		opts := new(xeth.Options)
-		opts.From = args.From
+		// opts.From = args.From
 		opts.To = args.To
 		opts.Topics = args.Topics
 		id := api.xeth().NewWhisperFilter(opts)
@@ -483,46 +453,3 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
 	rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
 	return nil
 }
-
-func toFilterOptions(options *BlockFilterArgs) *core.FilterOptions {
-	var opts core.FilterOptions
-
-	// Convert optional address slice/string to byte slice
-	if str, ok := options.Address.(string); ok {
-		opts.Address = []common.Address{common.HexToAddress(str)}
-	} else if slice, ok := options.Address.([]interface{}); ok {
-		bslice := make([]common.Address, len(slice))
-		for i, addr := range slice {
-			if saddr, ok := addr.(string); ok {
-				bslice[i] = common.HexToAddress(saddr)
-			}
-		}
-		opts.Address = bslice
-	}
-
-	opts.Earliest = options.Earliest
-	opts.Latest = options.Latest
-
-	topics := make([][]common.Hash, len(options.Topics))
-	for i, topicDat := range options.Topics {
-		if slice, ok := topicDat.([]interface{}); ok {
-			topics[i] = make([]common.Hash, len(slice))
-			for j, topic := range slice {
-				topics[i][j] = common.HexToHash(topic.(string))
-			}
-		} else if str, ok := topicDat.(string); ok {
-			topics[i] = []common.Hash{common.HexToHash(str)}
-		}
-	}
-	opts.Topics = topics
-
-	return &opts
-}
-
-/*
-	Work() chan<- *types.Block
-	SetWorkCh(chan<- Work)
-	Stop()
-	Start()
-	Rate() uint64
-*/

+ 303 - 150
rpc/args.go

@@ -3,14 +3,27 @@ package rpc
 import (
 	"bytes"
 	"encoding/json"
-	"errors"
+	// "errors"
 	"fmt"
 	"math/big"
 
 	"github.com/ethereum/go-ethereum/common"
 )
 
-func blockHeight(raw interface{}, number *int64) (err error) {
+const (
+	defaultLogLimit  = 100
+	defaultLogOffset = 0
+)
+
+func blockHeightFromJson(msg json.RawMessage, number *int64) error {
+	var raw interface{}
+	if err := json.Unmarshal(msg, &raw); err != nil {
+		return NewDecodeParamError(err.Error())
+	}
+	return blockHeight(raw, number)
+}
+
+func blockHeight(raw interface{}, number *int64) error {
 	// Parse as integer
 	num, ok := raw.(float64)
 	if ok {
@@ -21,7 +34,7 @@ func blockHeight(raw interface{}, number *int64) (err error) {
 	// Parse as string/hexstring
 	str, ok := raw.(string)
 	if !ok {
-		return NewDecodeParamError("BlockNumber is not a string")
+		return NewInvalidTypeError("", "not a number or string")
 	}
 
 	switch str {
@@ -36,26 +49,55 @@ func blockHeight(raw interface{}, number *int64) (err error) {
 	return nil
 }
 
-func toNumber(v interface{}) (int64, error) {
-	var str string
-	if v != nil {
-		var ok bool
-		str, ok = v.(string)
-		if !ok {
-			return 0, errors.New("is not a string or undefined")
-		}
-	} else {
-		str = "latest"
+func numString(raw interface{}, number *int64) error {
+	// Parse as integer
+	num, ok := raw.(float64)
+	if ok {
+		*number = int64(num)
+		return nil
 	}
 
-	switch str {
-	case "latest":
-		return -1, nil
-	default:
-		return int64(common.Big(v.(string)).Int64()), nil
+	// Parse as string/hexstring
+	str, ok := raw.(string)
+	if !ok {
+		return NewInvalidTypeError("", "not a number or string")
 	}
+	*number = common.String2Big(str).Int64()
+
+	return nil
 }
 
+// func toNumber(v interface{}) (int64, error) {
+// 	var str string
+// 	if v != nil {
+// 		var ok bool
+// 		str, ok = v.(string)
+// 		if !ok {
+// 			return 0, errors.New("is not a string or undefined")
+// 		}
+// 	} else {
+// 		str = "latest"
+// 	}
+
+// 	switch str {
+// 	case "latest":
+// 		return -1, nil
+// 	default:
+// 		return int64(common.Big(v.(string)).Int64()), nil
+// 	}
+// }
+
+// func hashString(raw interface{}, hash *string) error {
+// 	argstr, ok := raw.(string)
+// 	if !ok {
+// 		return NewInvalidTypeError("", "not a string")
+// 	}
+// 	v := common.IsHex(argstr)
+// 	hash = &argstr
+
+// 	return nil
+// }
+
 type GetBlockByHashArgs struct {
 	BlockHash  string
 	IncludeTxs bool
@@ -74,7 +116,7 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
 
 	argstr, ok := obj[0].(string)
 	if !ok {
-		return NewDecodeParamError("BlockHash not a string")
+		return NewInvalidTypeError("blockHash", "not a string")
 	}
 	args.BlockHash = argstr
 
@@ -103,8 +145,10 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
 
 	if v, ok := obj[0].(float64); ok {
 		args.BlockNumber = int64(v)
+	} else if v, ok := obj[0].(string); ok {
+		args.BlockNumber = common.Big(v).Int64()
 	} else {
-		args.BlockNumber = common.Big(obj[0].(string)).Int64()
+		return NewInvalidTypeError("blockNumber", "not a number or string")
 	}
 
 	if len(obj) > 1 {
@@ -127,7 +171,14 @@ type NewTxArgs struct {
 
 func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
 	var obj []json.RawMessage
-	var ext struct{ From, To, Value, Gas, GasPrice, Data string }
+	var ext struct {
+		From     string
+		To       string
+		Value    interface{}
+		Gas      interface{}
+		GasPrice interface{}
+		Data     string
+	}
 
 	// Decode byte slice to array of RawMessages
 	if err := json.Unmarshal(b, &obj); err != nil {
@@ -144,33 +195,49 @@ func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
 		return NewDecodeParamError(err.Error())
 	}
 
-	// var ok bool
+	if len(ext.From) == 0 {
+		return NewValidationError("from", "is required")
+	}
+
 	args.From = ext.From
 	args.To = ext.To
-	args.Value = common.String2Big(ext.Value)
-	args.Gas = common.String2Big(ext.Gas)
-	args.GasPrice = common.String2Big(ext.GasPrice)
 	args.Data = ext.Data
 
-	// Check for optional BlockNumber param
-	if len(obj) > 1 {
-		var raw interface{}
-		if err = json.Unmarshal(obj[1], &raw); err != nil {
-			return NewDecodeParamError(err.Error())
+	var num int64
+	if ext.Value == nil {
+		return NewValidationError("value", "is required")
+	} else {
+		if err := numString(ext.Value, &num); err != nil {
+			return err
 		}
+	}
+	args.Value = big.NewInt(num)
 
-		if err := blockHeight(raw, &args.BlockNumber); err != nil {
+	if ext.Gas == nil {
+		return NewValidationError("gas", "is required")
+	} else {
+		if err := numString(ext.Gas, &num); err != nil {
 			return err
 		}
 	}
+	args.Gas = big.NewInt(num)
 
-	return nil
-}
+	if ext.GasPrice == nil {
+		return NewValidationError("gasprice", "is required")
+	} else {
+		if err := numString(ext.GasPrice, &num); err != nil {
+			return err
+		}
+	}
+	args.GasPrice = big.NewInt(num)
 
-func (args *NewTxArgs) requirements() error {
-	if len(args.From) == 0 {
-		return NewValidationError("From", "Is required")
+	// Check for optional BlockNumber param
+	if len(obj) > 1 {
+		if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
+			return err
+		}
 	}
+
 	return nil
 }
 
@@ -191,7 +258,7 @@ func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
 
 	addstr, ok := obj[0].(string)
 	if !ok {
-		return NewDecodeParamError("Address is not a string")
+		return NewInvalidTypeError("address", "not a string")
 	}
 	args.Address = addstr
 
@@ -204,13 +271,6 @@ func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
 	return nil
 }
 
-func (args *GetStorageArgs) requirements() error {
-	if len(args.Address) == 0 {
-		return NewValidationError("Address", "cannot be blank")
-	}
-	return nil
-}
-
 type GetStorageAtArgs struct {
 	Address     string
 	Key         string
@@ -229,13 +289,13 @@ func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
 
 	addstr, ok := obj[0].(string)
 	if !ok {
-		return NewDecodeParamError("Address is not a string")
+		return NewInvalidTypeError("address", "not a string")
 	}
 	args.Address = addstr
 
 	keystr, ok := obj[1].(string)
 	if !ok {
-		return NewDecodeParamError("Key is not a string")
+		return NewInvalidTypeError("key", "not a string")
 	}
 	args.Key = keystr
 
@@ -248,17 +308,6 @@ func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
 	return nil
 }
 
-func (args *GetStorageAtArgs) requirements() error {
-	if len(args.Address) == 0 {
-		return NewValidationError("Address", "cannot be blank")
-	}
-
-	if len(args.Key) == 0 {
-		return NewValidationError("Key", "cannot be blank")
-	}
-	return nil
-}
-
 type GetTxCountArgs struct {
 	Address     string
 	BlockNumber int64
@@ -276,7 +325,7 @@ func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
 
 	addstr, ok := obj[0].(string)
 	if !ok {
-		return NewDecodeParamError("Address is not a string")
+		return NewInvalidTypeError("address", "not a string")
 	}
 	args.Address = addstr
 
@@ -289,13 +338,6 @@ func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
 	return nil
 }
 
-func (args *GetTxCountArgs) requirements() error {
-	if len(args.Address) == 0 {
-		return NewValidationError("Address", "cannot be blank")
-	}
-	return nil
-}
-
 type GetBalanceArgs struct {
 	Address     string
 	BlockNumber int64
@@ -313,7 +355,7 @@ func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
 
 	addstr, ok := obj[0].(string)
 	if !ok {
-		return NewDecodeParamError("Address is not a string")
+		return NewInvalidTypeError("address", "not a string")
 	}
 	args.Address = addstr
 
@@ -326,13 +368,6 @@ func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
 	return nil
 }
 
-func (args *GetBalanceArgs) requirements() error {
-	if len(args.Address) == 0 {
-		return NewValidationError("Address", "cannot be blank")
-	}
-	return nil
-}
-
 type GetDataArgs struct {
 	Address     string
 	BlockNumber int64
@@ -350,7 +385,7 @@ func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
 
 	addstr, ok := obj[0].(string)
 	if !ok {
-		return NewDecodeParamError("Address is not a string")
+		return NewInvalidTypeError("address", "not a string")
 	}
 	args.Address = addstr
 
@@ -363,13 +398,6 @@ func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
 	return nil
 }
 
-func (args *GetDataArgs) requirements() error {
-	if len(args.Address) == 0 {
-		return NewValidationError("Address", "cannot be blank")
-	}
-	return nil
-}
-
 type BlockNumIndexArgs struct {
 	BlockNumber int64
 	Index       int64
@@ -386,16 +414,14 @@ func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) {
 		return NewInsufficientParamsError(len(obj), 1)
 	}
 
-	arg0, ok := obj[0].(string)
-	if !ok {
-		return NewDecodeParamError("BlockNumber is not string")
+	if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
+		return err
 	}
-	args.BlockNumber = common.Big(arg0).Int64()
 
 	if len(obj) > 1 {
 		arg1, ok := obj[1].(string)
 		if !ok {
-			return NewDecodeParamError("Index not a string")
+			return NewInvalidTypeError("index", "not a string")
 		}
 		args.Index = common.Big(arg1).Int64()
 	}
@@ -421,14 +447,14 @@ func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) {
 
 	arg0, ok := obj[0].(string)
 	if !ok {
-		return NewDecodeParamError("Hash not a string")
+		return NewInvalidTypeError("hash", "not a string")
 	}
 	args.Hash = arg0
 
 	if len(obj) > 1 {
 		arg1, ok := obj[1].(string)
 		if !ok {
-			return NewDecodeParamError("Index not a string")
+			return NewInvalidTypeError("index", "not a string")
 		}
 		args.Index = common.Big(arg1).Int64()
 	}
@@ -450,28 +476,32 @@ func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
 	if len(obj) < 1 {
 		return NewInsufficientParamsError(len(obj), 1)
 	}
-	args.Data = obj[0].(string)
 
+	argstr, ok := obj[0].(string)
+	if !ok {
+		return NewInvalidTypeError("data", "is not a string")
+	}
+	args.Data = argstr
 	return nil
 }
 
 type BlockFilterArgs struct {
 	Earliest int64
 	Latest   int64
-	Address  interface{}
-	Topics   []interface{}
+	Address  []string
+	Topics   [][]string
 	Skip     int
 	Max      int
 }
 
 func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
 	var obj []struct {
-		FromBlock interface{}   `json:"fromBlock"`
-		ToBlock   interface{}   `json:"toBlock"`
-		Limit     string        `json:"limit"`
-		Offset    string        `json:"offset"`
-		Address   string        `json:"address"`
-		Topics    []interface{} `json:"topics"`
+		FromBlock interface{} `json:"fromBlock"`
+		ToBlock   interface{} `json:"toBlock"`
+		Limit     interface{} `json:"limit"`
+		Offset    interface{} `json:"offset"`
+		Address   interface{} `json:"address"`
+		Topics    interface{} `json:"topics"`
 	}
 
 	if err = json.Unmarshal(b, &obj); err != nil {
@@ -482,19 +512,113 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
 		return NewInsufficientParamsError(len(obj), 1)
 	}
 
-	args.Earliest, err = toNumber(obj[0].ToBlock)
-	if err != nil {
-		return NewDecodeParamError(fmt.Sprintf("FromBlock %v", err))
+	// args.Earliest, err = toNumber(obj[0].ToBlock)
+	// if err != nil {
+	// 	return NewDecodeParamError(fmt.Sprintf("FromBlock %v", err))
+	// }
+	// args.Latest, err = toNumber(obj[0].FromBlock)
+	// if err != nil {
+	// 	return NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
+
+	var num int64
+
+	// if blank then latest
+	if obj[0].FromBlock == nil {
+		num = -1
+	} else {
+		if err := blockHeight(obj[0].FromBlock, &num); err != nil {
+			return err
+		}
 	}
-	args.Latest, err = toNumber(obj[0].FromBlock)
-	if err != nil {
-		return NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
+	// if -2 or other "silly" number, use latest
+	if num < 0 {
+		args.Earliest = -1 //latest block
+	} else {
+		args.Earliest = num
 	}
 
-	args.Max = int(common.Big(obj[0].Limit).Int64())
-	args.Skip = int(common.Big(obj[0].Offset).Int64())
-	args.Address = obj[0].Address
-	args.Topics = obj[0].Topics
+	// if blank than latest
+	if obj[0].ToBlock == nil {
+		num = -1
+	} else {
+		if err := blockHeight(obj[0].ToBlock, &num); err != nil {
+			return err
+		}
+	}
+	args.Latest = num
+
+	if obj[0].Limit == nil {
+		num = defaultLogLimit
+	} else {
+		if err := numString(obj[0].Limit, &num); err != nil {
+			return err
+		}
+	}
+	args.Max = int(num)
+
+	if obj[0].Offset == nil {
+		num = defaultLogOffset
+	} else {
+		if err := numString(obj[0].Offset, &num); err != nil {
+			return err
+		}
+	}
+	args.Skip = int(num)
+
+	if obj[0].Address != nil {
+		marg, ok := obj[0].Address.([]interface{})
+		if ok {
+			v := make([]string, len(marg))
+			for i, arg := range marg {
+				argstr, ok := arg.(string)
+				if !ok {
+					return NewInvalidTypeError(fmt.Sprintf("address[%d]", i), "is not a string")
+				}
+				v[i] = argstr
+			}
+			args.Address = v
+		} else {
+			argstr, ok := obj[0].Address.(string)
+			if ok {
+				v := make([]string, 1)
+				v[0] = argstr
+				args.Address = v
+			} else {
+				return NewInvalidTypeError("address", "is not a string or array")
+			}
+		}
+	}
+
+	if obj[0].Topics != nil {
+		other, ok := obj[0].Topics.([]interface{})
+		if ok {
+			topicdbl := make([][]string, len(other))
+			for i, iv := range other {
+				if argstr, ok := iv.(string); ok {
+					// Found a string, push into first element of array
+					topicsgl := make([]string, 1)
+					topicsgl[0] = argstr
+					topicdbl[i] = topicsgl
+				} else if argarray, ok := iv.([]interface{}); ok {
+					// Found an array of other
+					topicdbl[i] = make([]string, len(argarray))
+					for j, jv := range argarray {
+						if v, ok := jv.(string); ok {
+							topicdbl[i][j] = v
+						} else {
+							return NewInvalidTypeError(fmt.Sprintf("topic[%d][%d]", i, j), "is not a string")
+						}
+					}
+				} else {
+					return NewInvalidTypeError(fmt.Sprintf("topic[%d]", i), "not a string or array")
+				}
+			}
+			args.Topics = topicdbl
+			return nil
+		} else {
+			return NewInvalidTypeError("topic", "is not a string or array")
+		}
+	}
 
 	return nil
 }
@@ -519,19 +643,19 @@ func (args *DbArgs) UnmarshalJSON(b []byte) (err error) {
 	var ok bool
 
 	if objstr, ok = obj[0].(string); !ok {
-		return NewDecodeParamError("Database is not a string")
+		return NewInvalidTypeError("database", "not a string")
 	}
 	args.Database = objstr
 
 	if objstr, ok = obj[1].(string); !ok {
-		return NewDecodeParamError("Key is not a string")
+		return NewInvalidTypeError("key", "not a string")
 	}
 	args.Key = objstr
 
 	if len(obj) > 2 {
 		objstr, ok = obj[2].(string)
 		if !ok {
-			return NewDecodeParamError("Value is not a string")
+			return NewInvalidTypeError("value", "not a string")
 		}
 
 		args.Value = []byte(objstr)
@@ -570,19 +694,19 @@ func (args *DbHexArgs) UnmarshalJSON(b []byte) (err error) {
 	var ok bool
 
 	if objstr, ok = obj[0].(string); !ok {
-		return NewDecodeParamError("Database is not a string")
+		return NewInvalidTypeError("database", "not a string")
 	}
 	args.Database = objstr
 
 	if objstr, ok = obj[1].(string); !ok {
-		return NewDecodeParamError("Key is not a string")
+		return NewInvalidTypeError("key", "not a string")
 	}
 	args.Key = objstr
 
 	if len(obj) > 2 {
 		objstr, ok = obj[2].(string)
 		if !ok {
-			return NewDecodeParamError("Value is not a string")
+			return NewInvalidTypeError("value", "not a string")
 		}
 
 		args.Value = common.FromHex(objstr)
@@ -616,8 +740,8 @@ func (args *WhisperMessageArgs) UnmarshalJSON(b []byte) (err error) {
 		To       string
 		From     string
 		Topics   []string
-		Priority string
-		Ttl      string
+		Priority interface{}
+		Ttl      interface{}
 	}
 
 	if err = json.Unmarshal(b, &obj); err != nil {
@@ -631,8 +755,17 @@ func (args *WhisperMessageArgs) UnmarshalJSON(b []byte) (err error) {
 	args.To = obj[0].To
 	args.From = obj[0].From
 	args.Topics = obj[0].Topics
-	args.Priority = uint32(common.Big(obj[0].Priority).Int64())
-	args.Ttl = uint32(common.Big(obj[0].Ttl).Int64())
+
+	var num int64
+	if err := numString(obj[0].Priority, &num); err != nil {
+		return err
+	}
+	args.Priority = uint32(num)
+
+	if err := numString(obj[0].Ttl, &num); err != nil {
+		return err
+	}
+	args.Ttl = uint32(num)
 
 	return nil
 }
@@ -643,14 +776,18 @@ type CompileArgs struct {
 
 func (args *CompileArgs) UnmarshalJSON(b []byte) (err error) {
 	var obj []interface{}
-	r := bytes.NewReader(b)
-	if err := json.NewDecoder(r).Decode(&obj); err != nil {
+	if err := json.Unmarshal(b, &obj); err != nil {
 		return NewDecodeParamError(err.Error())
 	}
 
-	if len(obj) > 0 {
-		args.Source = obj[0].(string)
+	if len(obj) < 1 {
+		return NewInsufficientParamsError(len(obj), 1)
 	}
+	argstr, ok := obj[0].(string)
+	if !ok {
+		return NewInvalidTypeError("arg0", "is not a string")
+	}
+	args.Source = argstr
 
 	return nil
 }
@@ -673,20 +810,15 @@ func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
 	var argstr string
 	argstr, ok := obj[0].(string)
 	if !ok {
-		return NewDecodeParamError("Filter is not a string")
+		return NewInvalidTypeError("filter", "not a string")
 	}
-	args.Word = argstr
-
-	return nil
-}
-
-func (args *FilterStringArgs) requirements() error {
-	switch args.Word {
+	switch argstr {
 	case "latest", "pending":
 		break
 	default:
 		return NewValidationError("Word", "Must be `latest` or `pending`")
 	}
+	args.Word = argstr
 	return nil
 }
 
@@ -695,9 +827,8 @@ type FilterIdArgs struct {
 }
 
 func (args *FilterIdArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []string
-	r := bytes.NewReader(b)
-	if err := json.NewDecoder(r).Decode(&obj); err != nil {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
 		return NewDecodeParamError(err.Error())
 	}
 
@@ -705,7 +836,11 @@ func (args *FilterIdArgs) UnmarshalJSON(b []byte) (err error) {
 		return NewInsufficientParamsError(len(obj), 1)
 	}
 
-	args.Id = int(common.Big(obj[0]).Int64())
+	var num int64
+	if err := numString(obj[0], &num); err != nil {
+		return err
+	}
+	args.Id = int(num)
 
 	return nil
 }
@@ -715,9 +850,8 @@ type WhisperIdentityArgs struct {
 }
 
 func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []string
-	r := bytes.NewReader(b)
-	if err := json.NewDecoder(r).Decode(&obj); err != nil {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
 		return NewDecodeParamError(err.Error())
 	}
 
@@ -725,7 +859,14 @@ func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) {
 		return NewInsufficientParamsError(len(obj), 1)
 	}
 
-	args.Identity = obj[0]
+	argstr, ok := obj[0].(string)
+	if !ok {
+		return NewInvalidTypeError("arg0", "not a string")
+	}
+	// if !common.IsHex(argstr) {
+	// 	return NewValidationError("arg0", "not a hexstring")
+	// }
+	args.Identity = argstr
 
 	return nil
 }
@@ -738,9 +879,8 @@ type WhisperFilterArgs struct {
 
 func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
 	var obj []struct {
-		To     string
-		From   string
-		Topics []string
+		To     interface{}
+		Topics []interface{}
 	}
 
 	if err = json.Unmarshal(b, &obj); err != nil {
@@ -751,17 +891,30 @@ func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
 		return NewInsufficientParamsError(len(obj), 1)
 	}
 
-	args.To = obj[0].To
-	args.From = obj[0].From
-	args.Topics = obj[0].Topics
+	var argstr string
+	argstr, ok := obj[0].To.(string)
+	if !ok {
+		return NewInvalidTypeError("to", "is not a string")
+	}
+	args.To = argstr
+
+	t := make([]string, len(obj[0].Topics))
+	for i, j := range obj[0].Topics {
+		argstr, ok := j.(string)
+		if !ok {
+			return NewInvalidTypeError("topics["+string(i)+"]", "is not a string")
+		}
+		t[i] = argstr
+	}
+	args.Topics = t
 
 	return nil
 }
 
 type SubmitWorkArgs struct {
 	Nonce  uint64
-	Header common.Hash
-	Digest common.Hash
+	Header string
+	Digest string
 }
 
 func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
@@ -777,21 +930,21 @@ func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
 	var objstr string
 	var ok bool
 	if objstr, ok = obj[0].(string); !ok {
-		return NewDecodeParamError("Nonce is not a string")
+		return NewInvalidTypeError("nonce", "not a string")
 	}
 
 	args.Nonce = common.String2Big(objstr).Uint64()
 	if objstr, ok = obj[1].(string); !ok {
-		return NewDecodeParamError("Header is not a string")
+		return NewInvalidTypeError("header", "not a string")
 	}
 
-	args.Header = common.HexToHash(objstr)
+	args.Header = objstr
 
 	if objstr, ok = obj[2].(string); !ok {
-		return NewDecodeParamError("Digest is not a string")
+		return NewInvalidTypeError("digest", "not a string")
 	}
 
-	args.Digest = common.HexToHash(objstr)
+	args.Digest = objstr
 
 	return nil
 }

文件差異過大導致無法顯示
+ 695 - 97
rpc/args_test.go


+ 16 - 0
rpc/messages.go

@@ -21,6 +21,22 @@ import (
 	"fmt"
 )
 
+type InvalidTypeError struct {
+	method string
+	msg    string
+}
+
+func (e *InvalidTypeError) Error() string {
+	return fmt.Sprintf("invalid type on field %s: %s", e.method, e.msg)
+}
+
+func NewInvalidTypeError(method, msg string) *InvalidTypeError {
+	return &InvalidTypeError{
+		method: method,
+		msg:    msg,
+	}
+}
+
 type InsufficientParamsError struct {
 	have int
 	want int

+ 9 - 0
rpc/messages_test.go

@@ -4,6 +4,15 @@ import (
 	"testing"
 )
 
+func TestInvalidTypeError(t *testing.T) {
+	err := NewInvalidTypeError("testField", "not string")
+	expected := "invalid type on field testField: not string"
+
+	if err.Error() != expected {
+		t.Error(err.Error())
+	}
+}
+
 func TestInsufficientParamsError(t *testing.T) {
 	err := NewInsufficientParamsError(0, 1)
 	expected := "insufficient params, want 1 have 0"

+ 35 - 7
xeth/xeth.go

@@ -110,6 +110,24 @@ func (self *XEth) stop() {
 	close(self.quit)
 }
 
+func cAddress(a []string) []common.Address {
+	bslice := make([]common.Address, len(a))
+	for i, addr := range a {
+		bslice[i] = common.HexToAddress(addr)
+	}
+	return bslice
+}
+
+func cTopics(t [][]string) [][]common.Hash {
+	topics := make([][]common.Hash, len(t))
+	for i, iv := range t {
+		for j, jv := range iv {
+			topics[i][j] = common.HexToHash(jv)
+		}
+	}
+	return topics
+}
+
 func (self *XEth) DefaultGas() *big.Int      { return defaultGas }
 func (self *XEth) DefaultGasPrice() *big.Int { return defaultGasPrice }
 
@@ -228,15 +246,15 @@ func (self *XEth) IsMining() bool {
 }
 
 func (self *XEth) EthVersion() string {
-	return string(self.backend.EthVersion())
+	return fmt.Sprintf("%d", self.backend.EthVersion())
 }
 
 func (self *XEth) NetworkVersion() string {
-	return string(self.backend.NetVersion())
+	return fmt.Sprintf("%d", self.backend.NetVersion())
 }
 
 func (self *XEth) WhisperVersion() string {
-	return string(self.backend.ShhVersion())
+	return fmt.Sprintf("%d", self.backend.ShhVersion())
 }
 
 func (self *XEth) ClientVersion() string {
@@ -301,10 +319,15 @@ func (self *XEth) SecretToAddress(key string) string {
 	return common.ToHex(pair.Address())
 }
 
-func (self *XEth) RegisterFilter(args *core.FilterOptions) int {
+func (self *XEth) RegisterFilter(earliest, latest int64, skip, max int, address []string, topics [][]string) int {
 	var id int
 	filter := core.NewFilter(self.backend)
-	filter.SetOptions(args)
+	filter.SetEarliestBlock(earliest)
+	filter.SetLatestBlock(latest)
+	filter.SetSkip(skip)
+	filter.SetMax(max)
+	filter.SetAddress(cAddress(address))
+	filter.SetTopics(cTopics(topics))
 	filter.LogsCallback = func(logs state.Logs) {
 		self.logMut.Lock()
 		defer self.logMut.Unlock()
@@ -380,9 +403,14 @@ func (self *XEth) Logs(id int) state.Logs {
 	return nil
 }
 
-func (self *XEth) AllLogs(args *core.FilterOptions) state.Logs {
+func (self *XEth) AllLogs(earliest, latest int64, skip, max int, address []string, topics [][]string) state.Logs {
 	filter := core.NewFilter(self.backend)
-	filter.SetOptions(args)
+	filter.SetEarliestBlock(earliest)
+	filter.SetLatestBlock(latest)
+	filter.SetSkip(skip)
+	filter.SetMax(max)
+	filter.SetAddress(cAddress(address))
+	filter.SetTopics(cTopics(topics))
 
 	return filter.Find()
 }

部分文件因文件數量過多而無法顯示