aboutsummaryrefslogtreecommitdiffstats
path: root/eth/filters/filter.go
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2018-07-12 22:36:07 +0800
committerPéter Szilágyi <peterke@gmail.com>2018-07-12 23:16:54 +0800
commite1f1d3085c6b868de93313700cac8a325e9b148b (patch)
treeb5a2c834735e0a1405a975d3552df07aebe0e2e0 /eth/filters/filter.go
parent96339daf40989072ff2a9e8b476da6698da45dc7 (diff)
downloadgo-tangerine-e1f1d3085c6b868de93313700cac8a325e9b148b.tar
go-tangerine-e1f1d3085c6b868de93313700cac8a325e9b148b.tar.gz
go-tangerine-e1f1d3085c6b868de93313700cac8a325e9b148b.tar.bz2
go-tangerine-e1f1d3085c6b868de93313700cac8a325e9b148b.tar.lz
go-tangerine-e1f1d3085c6b868de93313700cac8a325e9b148b.tar.xz
go-tangerine-e1f1d3085c6b868de93313700cac8a325e9b148b.tar.zst
go-tangerine-e1f1d3085c6b868de93313700cac8a325e9b148b.zip
accounts, eth, les: blockhash based filtering on all code paths
Diffstat (limited to 'eth/filters/filter.go')
-rw-r--r--eth/filters/filter.go77
1 files changed, 60 insertions, 17 deletions
diff --git a/eth/filters/filter.go b/eth/filters/filter.go
index 7000d74fa..071613ad7 100644
--- a/eth/filters/filter.go
+++ b/eth/filters/filter.go
@@ -18,6 +18,7 @@ package filters
import (
"context"
+ "errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
@@ -33,6 +34,7 @@ type Backend interface {
ChainDb() ethdb.Database
EventMux() *event.TypeMux
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)
+ HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error)
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error)
@@ -49,17 +51,19 @@ type Backend interface {
type Filter struct {
backend Backend
- db ethdb.Database
- begin, end int64
- addresses []common.Address
- topics [][]common.Hash
+ db ethdb.Database
+ addresses []common.Address
+ topics [][]common.Hash
+
+ block common.Hash // Block hash if filtering a single block
+ begin, end int64 // Range interval if filtering multiple blocks
matcher *bloombits.Matcher
}
-// New creates a new filter which uses a bloom filter on blocks to figure out whether
-// a particular block is interesting or not.
-func New(backend Backend, begin, end int64, addresses []common.Address, topics [][]common.Hash) *Filter {
+// NewRangeFilter creates a new filter which uses a bloom filter on blocks to
+// figure out whether a particular block is interesting or not.
+func NewRangeFilter(backend Backend, begin, end int64, addresses []common.Address, topics [][]common.Hash) *Filter {
// Flatten the address and topic filter clauses into a single bloombits filter
// system. Since the bloombits are not positional, nil topics are permitted,
// which get flattened into a nil byte slice.
@@ -78,23 +82,52 @@ func New(backend Backend, begin, end int64, addresses []common.Address, topics [
}
filters = append(filters, filter)
}
- // Assemble and return the filter
size, _ := backend.BloomStatus()
+ // Create a generic filter and convert it into a range filter
+ filter := newFilter(backend, addresses, topics)
+
+ filter.matcher = bloombits.NewMatcher(size, filters)
+ filter.begin = begin
+ filter.end = end
+
+ return filter
+}
+
+// NewBlockFilter creates a new filter which directly inspects the contents of
+// a block to figure out whether it is interesting or not.
+func NewBlockFilter(backend Backend, block common.Hash, addresses []common.Address, topics [][]common.Hash) *Filter {
+ // Create a generic filter and convert it into a block filter
+ filter := newFilter(backend, addresses, topics)
+ filter.block = block
+ return filter
+}
+
+// newFilter creates a generic filter that can either filter based on a block hash,
+// or based on range queries. The search criteria needs to be explicitly set.
+func newFilter(backend Backend, addresses []common.Address, topics [][]common.Hash) *Filter {
return &Filter{
backend: backend,
- begin: begin,
- end: end,
addresses: addresses,
topics: topics,
db: backend.ChainDb(),
- matcher: bloombits.NewMatcher(size, filters),
}
}
// Logs searches the blockchain for matching log entries, returning all from the
// first block that contains matches, updating the start of the filter accordingly.
func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
+ // If we're doing singleton block filtering, execute and return
+ if f.block != (common.Hash{}) {
+ header, err := f.backend.HeaderByHash(ctx, f.block)
+ if err != nil {
+ return nil, err
+ }
+ if header == nil {
+ return nil, errors.New("unknown block")
+ }
+ return f.blockLogs(ctx, header)
+ }
// Figure out the limits of the filter range
header, _ := f.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
if header == nil {
@@ -187,13 +220,23 @@ func (f *Filter) unindexedLogs(ctx context.Context, end uint64) ([]*types.Log, e
if header == nil || err != nil {
return logs, err
}
- if bloomFilter(header.Bloom, f.addresses, f.topics) {
- found, err := f.checkMatches(ctx, header)
- if err != nil {
- return logs, err
- }
- logs = append(logs, found...)
+ found, err := f.blockLogs(ctx, header)
+ if err != nil {
+ return logs, err
+ }
+ logs = append(logs, found...)
+ }
+ return logs, nil
+}
+
+// blockLogs returns the logs matching the filter criteria within a single block.
+func (f *Filter) blockLogs(ctx context.Context, header *types.Header) (logs []*types.Log, err error) {
+ if bloomFilter(header.Bloom, f.addresses, f.topics) {
+ found, err := f.checkMatches(ctx, header)
+ if err != nil {
+ return logs, err
}
+ logs = append(logs, found...)
}
return logs, nil
}