BlockFilterArgs
This commit is contained in:
parent
2788fb4ce5
commit
9f84c78eb5
51
rpc/api.go
51
rpc/api.go
|
@ -471,42 +471,29 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
|
|||
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.Address = cAddress(options.Address)
|
||||
opts.Topics = cTopics(options.Topics)
|
||||
|
||||
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
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
|
116
rpc/args.go
116
rpc/args.go
|
@ -4,12 +4,17 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
// "errors"
|
||||
// "fmt"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultLogLimit = 100
|
||||
defaultLogOffset = 0
|
||||
)
|
||||
|
||||
func blockHeightFromJson(msg json.RawMessage, number *int64) error {
|
||||
var raw interface{}
|
||||
if err := json.Unmarshal(msg, &raw); err != nil {
|
||||
|
@ -483,20 +488,20 @@ func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
|
|||
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 interface{} `json:"limit"`
|
||||
Offset interface{} `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 {
|
||||
|
@ -516,33 +521,104 @@ func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
|
|||
// return NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
|
||||
|
||||
var num int64
|
||||
if err := blockHeight(obj[0].FromBlock, &num); err != nil {
|
||||
return err
|
||||
|
||||
// if blank then latest
|
||||
if obj[0].FromBlock == nil {
|
||||
num = -1
|
||||
} else {
|
||||
if err := blockHeight(obj[0].FromBlock, &num); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// if -2 or other "silly" number, use latest
|
||||
if num < 0 {
|
||||
args.Earliest = -1 //latest block
|
||||
} else {
|
||||
args.Earliest = num
|
||||
}
|
||||
|
||||
if err := blockHeight(obj[0].ToBlock, &num); err != nil {
|
||||
return err
|
||||
// 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 err := numString(obj[0].Limit, &num); err != nil {
|
||||
return err
|
||||
if obj[0].Limit == nil {
|
||||
num = defaultLogLimit
|
||||
} else {
|
||||
if err := numString(obj[0].Limit, &num); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
args.Max = int(num)
|
||||
|
||||
if err := numString(obj[0].Offset, &num); err != nil {
|
||||
return err
|
||||
|
||||
if obj[0].Offset == nil {
|
||||
num = defaultLogOffset
|
||||
} else {
|
||||
if err := numString(obj[0].Offset, &num); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
args.Skip = int(num)
|
||||
|
||||
args.Address = obj[0].Address
|
||||
args.Topics = obj[0].Topics
|
||||
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
|
||||
}
|
||||
|
|
214
rpc/args_test.go
214
rpc/args_test.go
|
@ -804,14 +804,23 @@ func TestBlockFilterArgs(t *testing.T) {
|
|||
"limit": "0x3",
|
||||
"offset": "0x0",
|
||||
"address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
|
||||
"topics": ["0x12341234"]}]`
|
||||
"topics":
|
||||
[
|
||||
["0xAA", "0xBB"],
|
||||
["0xCC", "0xDD"]
|
||||
]
|
||||
}]`
|
||||
|
||||
expected := new(BlockFilterArgs)
|
||||
expected.Earliest = 1
|
||||
expected.Latest = 2
|
||||
expected.Max = 3
|
||||
expected.Skip = 0
|
||||
expected.Address = "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"
|
||||
// expected.Topics = []string{"0x12341234"}
|
||||
expected.Address = []string{"0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"}
|
||||
expected.Topics = [][]string{
|
||||
[]string{"0xAA", "0xBB"},
|
||||
[]string{"0xCC", "0xDD"},
|
||||
}
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
|
@ -834,17 +843,73 @@ func TestBlockFilterArgs(t *testing.T) {
|
|||
t.Errorf("Skip shoud be %#v but is %#v", expected.Skip, args.Skip)
|
||||
}
|
||||
|
||||
if expected.Address != args.Address {
|
||||
if expected.Address[0] != args.Address[0] {
|
||||
t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
|
||||
}
|
||||
|
||||
// if expected.Topics != args.Topics {
|
||||
// t.Errorf("Topic shoud be %#v but is %#v", expected.Topic, args.Topic)
|
||||
// }
|
||||
if expected.Topics[0][0] != args.Topics[0][0] {
|
||||
t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
|
||||
}
|
||||
if expected.Topics[0][1] != args.Topics[0][1] {
|
||||
t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
|
||||
}
|
||||
if expected.Topics[1][0] != args.Topics[1][0] {
|
||||
t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
|
||||
}
|
||||
if expected.Topics[1][1] != args.Topics[1][1] {
|
||||
t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsDefaults(t *testing.T) {
|
||||
input := `[{
|
||||
"address": ["0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"],
|
||||
"topics": ["0xAA","0xBB"]
|
||||
}]`
|
||||
expected := new(BlockFilterArgs)
|
||||
expected.Earliest = -1
|
||||
expected.Latest = -1
|
||||
expected.Max = 100
|
||||
expected.Skip = 0
|
||||
expected.Address = []string{"0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"}
|
||||
expected.Topics = [][]string{[]string{"0xAA"}, []string{"0xBB"}}
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if expected.Earliest != args.Earliest {
|
||||
t.Errorf("Earliest shoud be %#v but is %#v", expected.Earliest, args.Earliest)
|
||||
}
|
||||
|
||||
if expected.Latest != args.Latest {
|
||||
t.Errorf("Latest shoud be %#v but is %#v", expected.Latest, args.Latest)
|
||||
}
|
||||
|
||||
if expected.Max != args.Max {
|
||||
t.Errorf("Max shoud be %#v but is %#v", expected.Max, args.Max)
|
||||
}
|
||||
|
||||
if expected.Skip != args.Skip {
|
||||
t.Errorf("Skip shoud be %#v but is %#v", expected.Skip, args.Skip)
|
||||
}
|
||||
|
||||
if expected.Address[0] != args.Address[0] {
|
||||
t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
|
||||
}
|
||||
|
||||
if expected.Topics[0][0] != args.Topics[0][0] {
|
||||
t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
|
||||
}
|
||||
|
||||
if expected.Topics[1][0] != args.Topics[1][0] {
|
||||
t.Errorf("Topics shoud be %#v but is %#v", expected.Topics, args.Topics)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsWords(t *testing.T) {
|
||||
t.Skip()
|
||||
input := `[{
|
||||
"fromBlock": "latest",
|
||||
"toBlock": "pending"
|
||||
|
@ -867,10 +932,33 @@ func TestBlockFilterArgsWords(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsBool(t *testing.T) {
|
||||
func TestBlockFilterArgsInvalid(t *testing.T) {
|
||||
input := `{}`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
str := ExpectDecodeParamError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsFromBool(t *testing.T) {
|
||||
input := `[{
|
||||
"fromBlock": true,
|
||||
"toBlock": false
|
||||
"toBlock": "pending"
|
||||
}]`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsToBool(t *testing.T) {
|
||||
input := `[{
|
||||
"fromBlock": "pending",
|
||||
"toBlock": true
|
||||
}]`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
|
@ -890,6 +978,112 @@ func TestBlockFilterArgsEmptyArgs(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsLimitInvalid(t *testing.T) {
|
||||
input := `[{"limit": false}]`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsOffsetInvalid(t *testing.T) {
|
||||
input := `[{"offset": true}]`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsAddressInt(t *testing.T) {
|
||||
input := `[{
|
||||
"address": 1,
|
||||
"topics": "0x12341234"}]`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsAddressSliceInt(t *testing.T) {
|
||||
input := `[{
|
||||
"address": [1],
|
||||
"topics": "0x12341234"}]`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsTopicInt(t *testing.T) {
|
||||
input := `[{
|
||||
"address": ["0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"],
|
||||
"topics": 1}]`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsTopicSliceInt(t *testing.T) {
|
||||
input := `[{
|
||||
"address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
|
||||
"topics": [1]}]`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsTopicSliceInt2(t *testing.T) {
|
||||
input := `[{
|
||||
"address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
|
||||
"topics": ["0xAA", [1]]}]`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
str := ExpectInvalidTypeError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockFilterArgsTopicComplex(t *testing.T) {
|
||||
input := `[{
|
||||
"address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
|
||||
"topics": ["0xAA", ["0xBB", "0xCC"]]
|
||||
}]`
|
||||
|
||||
args := new(BlockFilterArgs)
|
||||
if err := json.Unmarshal([]byte(input), &args); err != nil {
|
||||
t.Error(err)
|
||||
fmt.Printf("%v\n", args)
|
||||
return
|
||||
}
|
||||
|
||||
if args.Topics[0][0] != "0xAA" {
|
||||
t.Errorf("Topic should be %s but is %s", "0xAA", args.Topics[0][0])
|
||||
}
|
||||
|
||||
if args.Topics[1][0] != "0xBB" {
|
||||
t.Errorf("Topic should be %s but is %s", "0xBB", args.Topics[0][0])
|
||||
}
|
||||
|
||||
if args.Topics[1][1] != "0xCC" {
|
||||
t.Errorf("Topic should be %s but is %s", "0xCC", args.Topics[0][0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestDbArgs(t *testing.T) {
|
||||
input := `["testDB","myKey","0xbeef"]`
|
||||
expected := new(DbArgs)
|
||||
|
|
Loading…
Reference in New Issue