diff --git a/core/filtermaps/matcher.go b/core/filtermaps/matcher.go index 8e2d236b6b..02fb6ed82d 100644 --- a/core/filtermaps/matcher.go +++ b/core/filtermaps/matcher.go @@ -11,6 +11,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +// ErrMatchAll is returned when the specified filter matches everything. +// Handling this case in filtermaps would require an extra special case and +// would actually be slower than reverting to legacy filter. +var ErrMatchAll = errors.New("match all patterns not supported") + // MatcherBackend defines the functions required for searching in the log index // data structure. It is currently implemented by FilterMapsMatcherBackend but // once EIP-7745 is implemented and active, these functions can also be trustlessly @@ -198,6 +203,9 @@ func getPotentialMatches(ctx context.Context, backend MatcherBackend, firstBlock } // get the actual logs located at the matching log value indices for _, m := range matches { + if m == nil { + return nil, ErrMatchAll + } mlogs, err := getLogsFromMatches(ctx, backend, firstIndex, lastIndex, m) if err != nil { return logs, err diff --git a/eth/filters/filter.go b/eth/filters/filter.go index 343fa5f0ff..7b0be8d024 100644 --- a/eth/filters/filter.go +++ b/eth/filters/filter.go @@ -154,6 +154,30 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) { mb := f.sys.backend.NewMatcherBackend() logs, _, _, _, err := filtermaps.GetPotentialMatches(ctx, mb, uint64(f.begin), uint64(f.end), f.addresses, f.topics) mb.Close() + if err == filtermaps.ErrMatchAll { + // revert to legacy filter + hdr, _ := f.sys.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber) + if hdr == nil { + return nil, errors.New("latest header not found") + } + headNumber := hdr.Number.Int64() + if f.begin > headNumber { + f.begin = headNumber + } + if f.end > headNumber { + f.end = headNumber + } + logChan, errChan := f.rangeLogsAsync(ctx) + var logs []*types.Log + for { + select { + case log := <-logChan: + logs = append(logs, log) + case err := <-errChan: + return logs, err + } + } + } fmLogs := filterLogs(logs, nil, nil, f.addresses, f.topics) log.Debug("Finished log search", "run time", time.Since(start), "true matches", len(fmLogs), "false positives", len(logs)-len(fmLogs)) return fmLogs, err