Skip to content
This repository was archived by the owner on Dec 23, 2024. It is now read-only.

Commit e38b9f1

Browse files
authored
eth/filters: exit early if topics-filter has more than 4 topics (#28494)
Currently, geth's will return `[]` for any `len(topics) > 4` log filter. The EVM only supports up to four logs, via LOG4 opcode, so larger criterias fail. This change makes the filter query exit early in those cases.
1 parent f7dde2a commit e38b9f1

File tree

3 files changed

+14
-0
lines changed

3 files changed

+14
-0
lines changed

eth/filters/api.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,12 @@ var (
3737
errInvalidTopic = errors.New("invalid topic(s)")
3838
errFilterNotFound = errors.New("filter not found")
3939
errInvalidBlockRange = errors.New("invalid block range params")
40+
errExceedMaxTopics = errors.New("exceed max topics")
4041
)
4142

43+
// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0
44+
const maxTopics = 4
45+
4246
// filter is a helper struct that holds meta information over the filter type
4347
// and associated subscription in the event system.
4448
type filter struct {
@@ -334,6 +338,9 @@ func (api *FilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) {
334338

335339
// GetLogs returns logs matching the given argument that are stored within the state.
336340
func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
341+
if len(crit.Topics) > maxTopics {
342+
return nil, errExceedMaxTopics
343+
}
337344
var filter *Filter
338345
if crit.BlockHash != nil {
339346
// Block filter requested, construct a single-shot filter

eth/filters/filter_system.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ func (es *EventSystem) subscribe(sub *subscription) *Subscription {
299299
// given criteria to the given logs channel. Default value for the from and to
300300
// block is "latest". If the fromBlock > toBlock an error is returned.
301301
func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) (*Subscription, error) {
302+
if len(crit.Topics) > maxTopics {
303+
return nil, errExceedMaxTopics
304+
}
302305
var from, to rpc.BlockNumber
303306
if crit.FromBlock == nil {
304307
from = rpc.LatestBlockNumber

eth/filters/filter_system_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,8 @@ func TestLogFilterCreation(t *testing.T) {
386386
{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false},
387387
// from block "higher" than to block
388388
{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, false},
389+
// topics more then 4
390+
{FilterCriteria{Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, false},
389391
}
390392
)
391393

@@ -420,6 +422,7 @@ func TestInvalidLogFilterCreation(t *testing.T) {
420422
0: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
421423
1: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)},
422424
2: {FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)},
425+
3: {Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
423426
}
424427

425428
for i, test := range testCases {
@@ -445,6 +448,7 @@ func TestInvalidGetLogsRequest(t *testing.T) {
445448
0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)},
446449
1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)},
447450
2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
451+
3: {BlockHash: &blockHash, Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
448452
}
449453

450454
for i, test := range testCases {

0 commit comments

Comments
 (0)