BlockFilterArgs

This commit is contained in:
Taylor Gerring 2015-03-27 15:54:54 +01:00
parent 2788fb4ce5
commit 9f84c78eb5
3 changed files with 319 additions and 62 deletions

View File

@ -471,42 +471,29 @@ func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) err
func toFilterOptions(options *BlockFilterArgs) *core.FilterOptions { func toFilterOptions(options *BlockFilterArgs) *core.FilterOptions {
var opts core.FilterOptions var opts core.FilterOptions
// Convert optional address slice/string to byte slice opts.Address = cAddress(options.Address)
if str, ok := options.Address.(string); ok { opts.Topics = cTopics(options.Topics)
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.Earliest = options.Earliest
opts.Latest = options.Latest 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 return &opts
} }
/* func cAddress(a []string) []common.Address {
Work() chan<- *types.Block bslice := make([]common.Address, len(a))
SetWorkCh(chan<- Work) for i, addr := range a {
Stop() bslice[i] = common.HexToAddress(addr)
Start() }
Rate() uint64 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
}

View File

@ -4,12 +4,17 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
// "errors" // "errors"
// "fmt" "fmt"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
const (
defaultLogLimit = 100
defaultLogOffset = 0
)
func blockHeightFromJson(msg json.RawMessage, number *int64) error { func blockHeightFromJson(msg json.RawMessage, number *int64) error {
var raw interface{} var raw interface{}
if err := json.Unmarshal(msg, &raw); err != nil { if err := json.Unmarshal(msg, &raw); err != nil {
@ -483,20 +488,20 @@ func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
type BlockFilterArgs struct { type BlockFilterArgs struct {
Earliest int64 Earliest int64
Latest int64 Latest int64
Address interface{} Address []string
Topics []interface{} Topics [][]string
Skip int Skip int
Max int Max int
} }
func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) { func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
var obj []struct { var obj []struct {
FromBlock interface{} `json:"fromBlock"` FromBlock interface{} `json:"fromBlock"`
ToBlock interface{} `json:"toBlock"` ToBlock interface{} `json:"toBlock"`
Limit interface{} `json:"limit"` Limit interface{} `json:"limit"`
Offset interface{} `json:"offset"` Offset interface{} `json:"offset"`
Address string `json:"address"` Address interface{} `json:"address"`
Topics []interface{} `json:"topics"` Topics interface{} `json:"topics"`
} }
if err = json.Unmarshal(b, &obj); err != nil { 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)) // return NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
var num int64 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 { if num < 0 {
args.Earliest = -1 //latest block args.Earliest = -1 //latest block
} else { } else {
args.Earliest = num args.Earliest = num
} }
if err := blockHeight(obj[0].ToBlock, &num); err != nil { // if blank than latest
return err if obj[0].ToBlock == nil {
num = -1
} else {
if err := blockHeight(obj[0].ToBlock, &num); err != nil {
return err
}
} }
args.Latest = num args.Latest = num
if err := numString(obj[0].Limit, &num); err != nil { if obj[0].Limit == nil {
return err num = defaultLogLimit
} else {
if err := numString(obj[0].Limit, &num); err != nil {
return err
}
} }
args.Max = int(num) args.Max = int(num)
if err := numString(obj[0].Offset, &num); err != nil { if obj[0].Offset == nil {
return err num = defaultLogOffset
} else {
if err := numString(obj[0].Offset, &num); err != nil {
return err
}
} }
args.Skip = int(num) args.Skip = int(num)
args.Address = obj[0].Address if obj[0].Address != nil {
args.Topics = obj[0].Topics 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 return nil
} }

View File

@ -804,14 +804,23 @@ func TestBlockFilterArgs(t *testing.T) {
"limit": "0x3", "limit": "0x3",
"offset": "0x0", "offset": "0x0",
"address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8", "address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
"topics": ["0x12341234"]}]` "topics":
[
["0xAA", "0xBB"],
["0xCC", "0xDD"]
]
}]`
expected := new(BlockFilterArgs) expected := new(BlockFilterArgs)
expected.Earliest = 1 expected.Earliest = 1
expected.Latest = 2 expected.Latest = 2
expected.Max = 3 expected.Max = 3
expected.Skip = 0 expected.Skip = 0
expected.Address = "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8" expected.Address = []string{"0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"}
// expected.Topics = []string{"0x12341234"} expected.Topics = [][]string{
[]string{"0xAA", "0xBB"},
[]string{"0xCC", "0xDD"},
}
args := new(BlockFilterArgs) args := new(BlockFilterArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil { 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) 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) t.Errorf("Address shoud be %#v but is %#v", expected.Address, args.Address)
} }
// if expected.Topics != args.Topics { if expected.Topics[0][0] != args.Topics[0][0] {
// t.Errorf("Topic shoud be %#v but is %#v", expected.Topic, args.Topic) 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) { func TestBlockFilterArgsWords(t *testing.T) {
t.Skip()
input := `[{ input := `[{
"fromBlock": "latest", "fromBlock": "latest",
"toBlock": "pending" "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 := `[{ input := `[{
"fromBlock": true, "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) 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) { func TestDbArgs(t *testing.T) {
input := `["testDB","myKey","0xbeef"]` input := `["testDB","myKey","0xbeef"]`
expected := new(DbArgs) expected := new(DbArgs)