eth/filters: simplify query object decoding

This commit is contained in:
Felix Lange 2016-11-28 02:21:46 +01:00
parent ec5f531f4b
commit be746628c7

View File

@ -17,7 +17,6 @@
package filters package filters
import ( import (
"encoding/hex"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@ -28,6 +27,7 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
@ -459,52 +459,28 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
if raw.Addresses != nil { if raw.Addresses != nil {
// raw.Address can contain a single address or an array of addresses // raw.Address can contain a single address or an array of addresses
var addresses []common.Address switch rawAddr := raw.Addresses.(type) {
if strAddrs, ok := raw.Addresses.([]interface{}); ok { case []interface{}:
for i, addr := range strAddrs { for i, addr := range rawAddr {
if strAddr, ok := addr.(string); ok { if strAddr, ok := addr.(string); ok {
if len(strAddr) >= 2 && strAddr[0] == '0' && (strAddr[1] == 'x' || strAddr[1] == 'X') { addr, err := decodeAddress(strAddr)
strAddr = strAddr[2:] if err != nil {
} return fmt.Errorf("invalid address at index %d: %v", i, err)
if decAddr, err := hex.DecodeString(strAddr); err == nil {
addresses = append(addresses, common.BytesToAddress(decAddr))
} else {
return fmt.Errorf("invalid address given")
} }
args.Addresses = append(args.Addresses, addr)
} else { } else {
return fmt.Errorf("invalid address on index %d", i) return fmt.Errorf("non-string address at index %d", i)
} }
} }
} else if singleAddr, ok := raw.Addresses.(string); ok { case string:
if len(singleAddr) >= 2 && singleAddr[0] == '0' && (singleAddr[1] == 'x' || singleAddr[1] == 'X') { addr, err := decodeAddress(rawAddr)
singleAddr = singleAddr[2:] if err != nil {
return fmt.Errorf("invalid address: %v", err)
} }
if decAddr, err := hex.DecodeString(singleAddr); err == nil { args.Addresses = []common.Address{addr}
addresses = append(addresses, common.BytesToAddress(decAddr)) default:
} else { return errors.New("invalid addresses in query")
return fmt.Errorf("invalid address given")
}
} else {
return errors.New("invalid address(es) given")
} }
args.Addresses = addresses
}
// helper function which parses a string to a topic hash
topicConverter := func(raw string) (common.Hash, error) {
if len(raw) == 0 {
return common.Hash{}, nil
}
if len(raw) >= 2 && raw[0] == '0' && (raw[1] == 'x' || raw[1] == 'X') {
raw = raw[2:]
}
if len(raw) != 2*common.HashLength {
return common.Hash{}, errors.New("invalid topic(s)")
}
if decAddr, err := hex.DecodeString(raw); err == nil {
return common.BytesToHash(decAddr), nil
}
return common.Hash{}, errors.New("invalid topic(s)")
} }
// topics is an array consisting of strings and/or arrays of strings. // topics is an array consisting of strings and/or arrays of strings.
@ -512,20 +488,25 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
if len(raw.Topics) > 0 { if len(raw.Topics) > 0 {
args.Topics = make([][]common.Hash, len(raw.Topics)) args.Topics = make([][]common.Hash, len(raw.Topics))
for i, t := range raw.Topics { for i, t := range raw.Topics {
if t == nil { // ignore topic when matching logs switch topic := t.(type) {
case nil:
// ignore topic when matching logs
args.Topics[i] = []common.Hash{common.Hash{}} args.Topics[i] = []common.Hash{common.Hash{}}
} else if topic, ok := t.(string); ok { // match specific topic
top, err := topicConverter(topic) case string:
// match specific topic
top, err := decodeTopic(topic)
if err != nil { if err != nil {
return err return err
} }
args.Topics[i] = []common.Hash{top} args.Topics[i] = []common.Hash{top}
} else if topics, ok := t.([]interface{}); ok { // or case e.g. [null, "topic0", "topic1"] case []interface{}:
for _, rawTopic := range topics { // or case e.g. [null, "topic0", "topic1"]
for _, rawTopic := range topic {
if rawTopic == nil { if rawTopic == nil {
args.Topics[i] = append(args.Topics[i], common.Hash{}) args.Topics[i] = append(args.Topics[i], common.Hash{})
} else if topic, ok := rawTopic.(string); ok { } else if topic, ok := rawTopic.(string); ok {
parsed, err := topicConverter(topic) parsed, err := decodeTopic(topic)
if err != nil { if err != nil {
return err return err
} }
@ -534,7 +515,7 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
return fmt.Errorf("invalid topic(s)") return fmt.Errorf("invalid topic(s)")
} }
} }
} else { default:
return fmt.Errorf("invalid topic(s)") return fmt.Errorf("invalid topic(s)")
} }
} }
@ -542,3 +523,19 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
return nil return nil
} }
func decodeAddress(s string) (common.Address, error) {
b, err := hexutil.Decode(s)
if err == nil && len(b) != common.AddressLength {
err = fmt.Errorf("hex has invalid length %d after decoding", len(b))
}
return common.BytesToAddress(b), err
}
func decodeTopic(s string) (common.Hash, error) {
b, err := hexutil.Decode(s)
if err == nil && len(b) != common.HashLength {
err = fmt.Errorf("hex has invalid length %d after decoding", len(b))
}
return common.BytesToHash(b), err
}