diff --git a/eth/filters/api.go b/eth/filters/api.go index d4dadeb908..e4e2246de6 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -33,14 +33,19 @@ import ( ) var ( - errInvalidTopic = errors.New("invalid topic(s)") - errFilterNotFound = errors.New("filter not found") - errInvalidBlockRange = errors.New("invalid block range params") - errExceedMaxTopics = errors.New("exceed max topics") + errInvalidTopic = errors.New("invalid topic(s)") + errFilterNotFound = errors.New("filter not found") + errInvalidBlockRange = errors.New("invalid block range params") + errExceedMaxTopics = errors.New("exceed max topics") + errExceedMaxAddresses = errors.New("exceed max addresses") ) -// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0 -const maxTopics = 4 +const ( + // The maximum number of addresses allowed in a filter criteria + maxAddresses = 1000 + // The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0 + maxTopics = 4 +) // filter is a helper struct that holds meta information over the filter type // and associated subscription in the event system. @@ -333,6 +338,9 @@ func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*type if len(crit.Topics) > maxTopics { return nil, errExceedMaxTopics } + if len(crit.Addresses) > maxAddresses { + return nil, errExceedMaxAddresses + } var filter *Filter if crit.BlockHash != nil { @@ -510,6 +518,9 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error { // raw.Address can contain a single address or an array of addresses switch rawAddr := raw.Addresses.(type) { case []interface{}: + if len(rawAddr) > maxAddresses { + return errExceedMaxAddresses + } for i, addr := range rawAddr { if strAddr, ok := addr.(string); ok { addr, err := decodeAddress(strAddr) diff --git a/eth/filters/api_test.go b/eth/filters/api_test.go index 8b35f77dcf..d30ce6d487 100644 --- a/eth/filters/api_test.go +++ b/eth/filters/api_test.go @@ -19,6 +19,7 @@ package filters import ( "encoding/json" "fmt" + "strings" "testing" "github.com/XinFinOrg/XDPoSChain/common" @@ -182,4 +183,15 @@ func TestUnmarshalJSONNewFilterArgs(t *testing.T) { if len(test7.Topics[2]) != 0 { t.Fatalf("expected 0 topics, got %d topics", len(test7.Topics[2])) } + + // multiple address exceeding max + var test8 FilterCriteria + addresses := make([]string, maxAddresses+1) + for i := 0; i < maxAddresses+1; i++ { + addresses[i] = fmt.Sprintf(`"%s"`, common.HexToAddress(fmt.Sprintf("0x%x", i)).Hex()) + } + vector = fmt.Sprintf(`{"address": [%s]}`, strings.Join(addresses, ", ")) + if err := json.Unmarshal([]byte(vector), &test8); err != errExceedMaxAddresses { + t.Fatal("expected errExceedMaxAddresses, got", err) + } } diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go index 7a7cd38c9d..a9359993b3 100644 --- a/eth/filters/filter_system.go +++ b/eth/filters/filter_system.go @@ -303,6 +303,9 @@ func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*typ if len(crit.Topics) > maxTopics { return nil, errExceedMaxTopics } + if len(crit.Addresses) > maxAddresses { + return nil, errExceedMaxAddresses + } var from, to rpc.BlockNumber if crit.FromBlock == nil { from = rpc.LatestBlockNumber diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index 281a5a274a..2c55993baa 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -353,6 +353,7 @@ func TestInvalidLogFilterCreation(t *testing.T) { 1: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)}, 2: {FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)}, 3: {Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, + 4: {Addresses: make([]common.Address, maxAddresses+1)}, } for i, test := range testCases { @@ -379,6 +380,7 @@ func TestInvalidGetLogsRequest(t *testing.T) { 1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)}, 2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, 3: {BlockHash: &blockHash, Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, + 4: {BlockHash: &blockHash, Addresses: make([]common.Address, maxAddresses+1)}, } for i, test := range testCases {