Skip to content

Commit 55cdc41

Browse files
committed
Fix validation of max addresses/topics on filter-related endpoints
1 parent d71dd08 commit 55cdc41

File tree

7 files changed

+40
-6
lines changed

7 files changed

+40
-6
lines changed

api/pull.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ func (api *PullAPI) NewFilter(ctx context.Context, criteria filters.FilterCriter
247247
return "", err
248248
}
249249

250+
if !logs.ValidCriteriaLimits(criteria) {
251+
return "", errs.ErrExceedLogQueryLimit
252+
}
253+
250254
latest, err := api.blocks.LatestEVMHeight()
251255
if err != nil {
252256
return "", err

api/stream.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/onflow/flow-evm-gateway/config"
1515
ethTypes "github.com/onflow/flow-evm-gateway/eth/types"
1616
"github.com/onflow/flow-evm-gateway/models"
17+
errs "github.com/onflow/flow-evm-gateway/models/errors"
1718
"github.com/onflow/flow-evm-gateway/services/logs"
1819
"github.com/onflow/flow-evm-gateway/storage"
1920
)
@@ -92,6 +93,10 @@ func (s *StreamAPI) NewPendingTransactions(ctx context.Context, fullTx *bool) (*
9293

9394
// Logs creates a subscription that fires for all new log that match the given filter criteria.
9495
func (s *StreamAPI) Logs(ctx context.Context, criteria filters.FilterCriteria) (*rpc.Subscription, error) {
96+
if !logs.ValidCriteriaLimits(criteria) {
97+
return nil, errs.ErrExceedLogQueryLimit
98+
}
99+
95100
return newSubscription(
96101
ctx,
97102
s.logger,

models/errors/errors.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var (
1616
ErrEndpointNotSupported = errors.New("endpoint is not supported")
1717
ErrRateLimit = errors.New("limit of requests per second reached")
1818
ErrIndexOnlyMode = errors.New("transaction submission not allowed in index-only mode")
19+
ErrExceedLogQueryLimit = errors.New("exceed max addresses or topics per search position")
1920

2021
// General errors
2122

services/logs/filter.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"github.com/onflow/flow-evm-gateway/storage"
1212
)
1313

14+
const LogQueryLimit = 1000
15+
1416
// RangeFilter matches all the indexed logs within the range defined as
1517
// start and end block height. The start must be strictly smaller or equal than end value.
1618
type RangeFilter struct {
@@ -24,6 +26,10 @@ func NewRangeFilter(
2426
criteria filters.FilterCriteria,
2527
receipts storage.ReceiptIndexer,
2628
) (*RangeFilter, error) {
29+
if !ValidCriteriaLimits(criteria) {
30+
return nil, errs.ErrExceedLogQueryLimit
31+
}
32+
2733
// make sure that beginning number is not bigger than end
2834
if start > end {
2935
return nil, fmt.Errorf(
@@ -100,6 +106,10 @@ func NewIDFilter(
100106
blocks storage.BlockIndexer,
101107
receipts storage.ReceiptIndexer,
102108
) (*IDFilter, error) {
109+
if !ValidCriteriaLimits(criteria) {
110+
return nil, errs.ErrExceedLogQueryLimit
111+
}
112+
103113
if criteria.BlockHash == nil {
104114
return nil, fmt.Errorf("filter criteria should have a non-nil block hash")
105115
}
@@ -161,6 +171,20 @@ func ExactMatch(log *gethTypes.Log, criteria filters.FilterCriteria) bool {
161171
return slices.Contains(criteria.Addresses, log.Address)
162172
}
163173

174+
func ValidCriteriaLimits(criteria filters.FilterCriteria) bool {
175+
if len(criteria.Addresses) > LogQueryLimit {
176+
return false
177+
}
178+
179+
for _, topics := range criteria.Topics {
180+
if len(topics) > LogQueryLimit {
181+
return false
182+
}
183+
}
184+
185+
return true
186+
}
187+
164188
// bloomMatch takes a bloom value and tests if the addresses and topics provided pass the bloom filter.
165189
// This acts as a fast probabilistic test that might produce false-positives but not false-negatives.
166190
// If true is returned we should further check against the exactMatch to really make sure the log is matched.

tests/web3js/eth_filter_endpoints_test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ describe('eth_newFilter', async () => {
7575
let response = await helpers.callRPCMethod('eth_newFilter', [blockRangeFilter])
7676
assert.equal(response.status, 200)
7777
assert.isDefined(response.body.error)
78-
assert.equal(response.body.error.message, 'invalid argument 0: exceed max addresses')
78+
assert.equal(response.body.error.message, 'exceed max addresses or topics per search position')
7979

8080
let blockHashFilter = {
8181
blockHash: latestBlock.hash,
@@ -86,7 +86,7 @@ describe('eth_newFilter', async () => {
8686
response = await helpers.callRPCMethod('eth_newFilter', [blockHashFilter])
8787
assert.equal(response.status, 200)
8888
assert.isDefined(response.body.error)
89-
assert.equal(response.body.error.message, 'invalid argument 0: exceed max addresses')
89+
assert.equal(response.body.error.message, 'exceed max addresses or topics per search position')
9090
})
9191

9292
it('should validate max number of sub-topics', async () => {

tests/web3js/eth_logs_filtering_test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ it('validates max number of allowed addresses', async () => {
252252
let response = await helpers.callRPCMethod('eth_getLogs', [blockRangeFilter])
253253
assert.equal(response.status, 200)
254254
assert.isDefined(response.body.error)
255-
assert.equal(response.body.error.message, 'invalid argument 0: exceed max addresses')
255+
assert.equal(response.body.error.message, 'exceed max addresses or topics per search position')
256256

257257
let blockHashFilter = {
258258
blockHash: latestBlock.hash,
@@ -263,7 +263,7 @@ it('validates max number of allowed addresses', async () => {
263263
response = await helpers.callRPCMethod('eth_getLogs', [blockHashFilter])
264264
assert.equal(response.status, 200)
265265
assert.isDefined(response.body.error)
266-
assert.equal(response.body.error.message, 'invalid argument 0: exceed max addresses')
266+
assert.equal(response.body.error.message, 'exceed max addresses or topics per search position')
267267
})
268268

269269
it('validates max number of allowed sub-topics', async () => {

tests/web3js/eth_streaming_filters_test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ it('should validate max number of addresses', async () => {
254254
} catch (err) {
255255
assert.equal(
256256
err.innerError.message,
257-
'invalid argument 1: exceed max addresses'
257+
'exceed max addresses or topics per search position'
258258
)
259259
}
260260

@@ -270,7 +270,7 @@ it('should validate max number of addresses', async () => {
270270
} catch (err) {
271271
assert.equal(
272272
err.innerError.message,
273-
'invalid argument 1: exceed max addresses'
273+
'exceed max addresses or topics per search position'
274274
)
275275
}
276276

0 commit comments

Comments
 (0)