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.
This commit is contained in:
parent
f7dde2a96c
commit
e38b9f1830
@ -37,8 +37,12 @@ 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")
|
||||
)
|
||||
|
||||
// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0
|
||||
const maxTopics = 4
|
||||
|
||||
// filter is a helper struct that holds meta information over the filter type
|
||||
// and associated subscription in the event system.
|
||||
type filter struct {
|
||||
@ -334,6 +338,9 @@ func (api *FilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) {
|
||||
|
||||
// GetLogs returns logs matching the given argument that are stored within the state.
|
||||
func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
|
||||
if len(crit.Topics) > maxTopics {
|
||||
return nil, errExceedMaxTopics
|
||||
}
|
||||
var filter *Filter
|
||||
if crit.BlockHash != nil {
|
||||
// Block filter requested, construct a single-shot filter
|
||||
|
@ -299,6 +299,9 @@ func (es *EventSystem) subscribe(sub *subscription) *Subscription {
|
||||
// given criteria to the given logs channel. Default value for the from and to
|
||||
// block is "latest". If the fromBlock > toBlock an error is returned.
|
||||
func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) (*Subscription, error) {
|
||||
if len(crit.Topics) > maxTopics {
|
||||
return nil, errExceedMaxTopics
|
||||
}
|
||||
var from, to rpc.BlockNumber
|
||||
if crit.FromBlock == nil {
|
||||
from = rpc.LatestBlockNumber
|
||||
|
@ -386,6 +386,8 @@ func TestLogFilterCreation(t *testing.T) {
|
||||
{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false},
|
||||
// from block "higher" than to block
|
||||
{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, false},
|
||||
// topics more then 4
|
||||
{FilterCriteria{Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, false},
|
||||
}
|
||||
)
|
||||
|
||||
@ -420,6 +422,7 @@ func TestInvalidLogFilterCreation(t *testing.T) {
|
||||
0: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
|
||||
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{{}, {}, {}, {}, {}}},
|
||||
}
|
||||
|
||||
for i, test := range testCases {
|
||||
@ -445,6 +448,7 @@ func TestInvalidGetLogsRequest(t *testing.T) {
|
||||
0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)},
|
||||
1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)},
|
||||
2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
|
||||
3: {BlockHash: &blockHash, Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
|
||||
}
|
||||
|
||||
for i, test := range testCases {
|
||||
|
Loading…
Reference in New Issue
Block a user