diff --git a/core/bloombits/matcher.go b/core/bloombits/matcher.go index f9d9aefc5a..3c9457ee9b 100644 --- a/core/bloombits/matcher.go +++ b/core/bloombits/matcher.go @@ -164,13 +164,16 @@ type Matcher struct { } // NewMatcher creates a new Matcher instance -func NewMatcher(sectionSize uint64) *Matcher { - return &Matcher{fetchers: make(map[uint]*fetcher), reqs: make(map[uint][]uint64), distCh: make(chan distReq, channelCap), sectionSize: sectionSize} +func NewMatcher(sectionSize uint64, addresses []common.Address, topics [][]common.Hash) *Matcher { + m := &Matcher{fetchers: make(map[uint]*fetcher), reqs: make(map[uint][]uint64), distCh: make(chan distReq, channelCap), sectionSize: sectionSize} + m.setAddresses(addresses) + m.setTopics(topics) + return m } -// SetAddresses matches only logs that are generated from addresses that are included +// setAddresses matches only logs that are generated from addresses that are included // in the given addresses. -func (m *Matcher) SetAddresses(addr []common.Address) { +func (m *Matcher) setAddresses(addr []common.Address) { m.addresses = make([]types.BloomIndexList, len(addr)) for i, b := range addr { m.addresses[i] = types.BloomIndexes(b.Bytes()) @@ -183,8 +186,8 @@ func (m *Matcher) SetAddresses(addr []common.Address) { } } -// SetTopics matches only logs that have topics matching the given topics. -func (m *Matcher) SetTopics(topics [][]common.Hash) { +// setTopics matches only logs that have topics matching the given topics. +func (m *Matcher) setTopics(topics [][]common.Hash) { m.topics = nil loop: for _, topicList := range topics { diff --git a/core/bloombits/matcher_test.go b/core/bloombits/matcher_test.go index a2f786204e..3b3436da76 100644 --- a/core/bloombits/matcher_test.go +++ b/core/bloombits/matcher_test.go @@ -94,7 +94,7 @@ func testServeMatcher(m *Matcher, stop chan struct{}, cnt *uint32) { } func testMatcher(t *testing.T, idxs [][]types.BloomIndexList, cnt uint64, stopOnMatches bool, expCount uint32) uint32 { - m := NewMatcher(testSectionSize) + m := NewMatcher(testSectionSize, nil, nil) for _, idxss := range idxs { for _, idxs := range idxss { diff --git a/eth/api_backend.go b/eth/api_backend.go index 6b675da22c..b960d5d9e0 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -213,6 +213,10 @@ func (b *EthApiBackend) GetBloomBits(ctx context.Context, bitIdx uint64, section return results, nil } +func (b *EthApiBackend) BloomBitsSectionSize() uint64 { + return bloomBitsSection +} + type EthApiState struct { state *state.StateDB } diff --git a/eth/filters/api.go b/eth/filters/api.go index 24ac789009..11767753e3 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -333,11 +333,7 @@ func (api *PublicFilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([ crit.ToBlock = big.NewInt(rpc.LatestBlockNumber.Int64()) } - filter := New(api.backend, api.bloomBitsSection) - filter.SetBeginBlock(crit.FromBlock.Int64()) - filter.SetEndBlock(crit.ToBlock.Int64()) - filter.SetAddresses(crit.Addresses) - filter.SetTopics(crit.Topics) + filter := New(api.backend, crit.FromBlock.Int64(), crit.ToBlock.Int64(), crit.Addresses, crit.Topics) logs, err := filter.Find(ctx) return returnLogs(logs), err @@ -373,19 +369,18 @@ func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]*ty return nil, fmt.Errorf("filter not found") } - filter := New(api.backend, api.bloomBitsSection) + var begin, end int64 if f.crit.FromBlock != nil { - filter.SetBeginBlock(f.crit.FromBlock.Int64()) + begin = f.crit.FromBlock.Int64() } else { - filter.SetBeginBlock(rpc.LatestBlockNumber.Int64()) + begin = rpc.LatestBlockNumber.Int64() } if f.crit.ToBlock != nil { - filter.SetEndBlock(f.crit.ToBlock.Int64()) + end = f.crit.ToBlock.Int64() } else { - filter.SetEndBlock(rpc.LatestBlockNumber.Int64()) + end = rpc.LatestBlockNumber.Int64() } - filter.SetAddresses(f.crit.Addresses) - filter.SetTopics(f.crit.Topics) + filter := New(api.backend, begin, end, f.crit.Addresses, f.crit.Topics) logs, err := filter.Find(ctx) if err != nil { diff --git a/eth/filters/bench_test.go b/eth/filters/bench_test.go index 64a9dc57b3..59183f4e42 100644 --- a/eth/filters/bench_test.go +++ b/eth/filters/bench_test.go @@ -167,14 +167,11 @@ func benchmarkBloomBits(b *testing.B, sectionSize uint64, comp int) { db, _ = ethdb.NewLDBDatabase(benchDataDir, 128, 1024) backend = &testBackend{mux, db} } - filter := New(backend, sectionSize) - filter.decompress = decompressFn var addr common.Address addr[0] = byte(i) addr[1] = byte(i / 256) - filter.SetAddresses([]common.Address{addr}) - filter.SetBeginBlock(0) - filter.SetEndBlock(int64(cnt*sectionSize - 1)) + filter := New(backend, 0, int64(cnt*sectionSize-1), []common.Address{addr}, nil) + filter.decompress = decompressFn if _, err := filter.Find(context.Background()); err != nil { b.Error("filter.Find error:", err) } @@ -233,11 +230,7 @@ func BenchmarkNoBloomBits(b *testing.B) { start := time.Now() mux := new(event.TypeMux) backend := &testBackend{mux, db} - filter := New(backend, 4096) // give any dummy section size, no bloombits data is available - var addr common.Address - filter.SetAddresses([]common.Address{addr}) - filter.SetBeginBlock(0) - filter.SetEndBlock(int64(headNum)) + filter := New(backend, 0, int64(headNum), []common.Address{common.Address{}}, nil) filter.Find(context.Background()) d := time.Since(start) fmt.Println("Finished running filter benchmarks") diff --git a/eth/filters/filter.go b/eth/filters/filter.go index 6f902c750c..a0dc230b38 100644 --- a/eth/filters/filter.go +++ b/eth/filters/filter.go @@ -38,6 +38,7 @@ type Backend interface { HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) GetBloomBits(ctx context.Context, bitIdx uint64, sectionIdxList []uint64) ([][]byte, error) + BloomBitsSectionSize() uint64 } // Filter can be used to retrieve and filter logs. @@ -58,41 +59,20 @@ type Filter struct { // 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, bloomBitsSection uint64) *Filter { +func New(backend Backend, begin, end int64, addresses []common.Address, topics [][]common.Hash) *Filter { return &Filter{ backend: backend, - bloomBitsSection: bloomBitsSection, + begin: begin, + end: end, + addresses: addresses, + topics: topics, + bloomBitsSection: backend.BloomBitsSectionSize(), db: backend.ChainDb(), - matcher: bloombits.NewMatcher(bloomBitsSection), + matcher: bloombits.NewMatcher(backend.BloomBitsSectionSize(), addresses, topics), decompress: bitutil.DecompressBytes, } } -// SetBeginBlock sets the earliest block for filtering. -// -1 = latest block (i.e., the current block) -// hash = particular hash from-to -func (f *Filter) SetBeginBlock(begin int64) { - f.begin = begin -} - -// SetEndBlock sets the latest block for filtering. -func (f *Filter) SetEndBlock(end int64) { - f.end = end -} - -// SetAddresses matches only logs that are generated from addresses that are included -// in the given addresses. -func (f *Filter) SetAddresses(addr []common.Address) { - f.addresses = addr - f.matcher.SetAddresses(addr) -} - -// SetTopics matches only logs that have topics matching the given topics. -func (f *Filter) SetTopics(topics [][]common.Hash) { - f.topics = topics - f.matcher.SetTopics(topics) -} - // FindOnce searches the blockchain for matching log entries, returning // all matching entries from the first block that contains matches, // updating the start point of the filter accordingly. If no results are diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index aa017c2ff5..0cf73c4a0c 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -75,6 +75,10 @@ func (b *testBackend) GetBloomBits(ctx context.Context, bitIdx uint64, sectionId return results, nil } +func (b *testBackend) BloomBitsSectionSize() uint64 { + return testBloomBitsSection +} + // TestBlockSubscription tests if a block subscription returns block hashes for posted chain events. // It creates multiple subscriptions: // - one at the start and should receive all posted chain events and a second (blockHashes) diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index 0848557dec..c92bec8518 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -105,10 +105,7 @@ func BenchmarkFilters(b *testing.B) { } b.ResetTimer() - filter := New(backend, testBloomBitsSection) - filter.SetAddresses([]common.Address{addr1, addr2, addr3, addr4}) - filter.SetBeginBlock(0) - filter.SetEndBlock(-1) + filter := New(backend, 0, -1, []common.Address{addr1, addr2, addr3, addr4}, nil) for i := 0; i < b.N; i++ { logs, _ := filter.Find(context.Background()) @@ -204,22 +201,14 @@ func TestFilters(t *testing.T) { } } - filter := New(backend, testBloomBitsSection) - filter.SetAddresses([]common.Address{addr}) - filter.SetTopics([][]common.Hash{{hash1, hash2, hash3, hash4}}) - filter.SetBeginBlock(0) - filter.SetEndBlock(-1) + filter := New(backend, 0, -1, []common.Address{addr}, [][]common.Hash{{hash1, hash2, hash3, hash4}}) logs, _ := filter.Find(context.Background()) if len(logs) != 4 { t.Error("expected 4 log, got", len(logs)) } - filter = New(backend, testBloomBitsSection) - filter.SetAddresses([]common.Address{addr}) - filter.SetTopics([][]common.Hash{{hash3}}) - filter.SetBeginBlock(900) - filter.SetEndBlock(999) + filter = New(backend, 900, 999, []common.Address{addr}, [][]common.Hash{{hash3}}) logs, _ = filter.Find(context.Background()) if len(logs) != 1 { t.Error("expected 1 log, got", len(logs)) @@ -228,11 +217,7 @@ func TestFilters(t *testing.T) { t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0]) } - filter = New(backend, testBloomBitsSection) - filter.SetAddresses([]common.Address{addr}) - filter.SetTopics([][]common.Hash{{hash3}}) - filter.SetBeginBlock(990) - filter.SetEndBlock(-1) + filter = New(backend, 990, -1, []common.Address{addr}, [][]common.Hash{{hash3}}) logs, _ = filter.Find(context.Background()) if len(logs) != 1 { t.Error("expected 1 log, got", len(logs)) @@ -241,10 +226,7 @@ func TestFilters(t *testing.T) { t.Errorf("expected log[0].Topics[0] to be %x, got %x", hash3, logs[0].Topics[0]) } - filter = New(backend, testBloomBitsSection) - filter.SetTopics([][]common.Hash{{hash1, hash2}}) - filter.SetBeginBlock(1) - filter.SetEndBlock(10) + filter = New(backend, 1, 10, nil, [][]common.Hash{{hash1, hash2}}) logs, _ = filter.Find(context.Background()) if len(logs) != 2 { @@ -252,10 +234,7 @@ func TestFilters(t *testing.T) { } failHash := common.BytesToHash([]byte("fail")) - filter = New(backend, testBloomBitsSection) - filter.SetTopics([][]common.Hash{{failHash}}) - filter.SetBeginBlock(0) - filter.SetEndBlock(-1) + filter = New(backend, 0, -1, nil, [][]common.Hash{{failHash}}) logs, _ = filter.Find(context.Background()) if len(logs) != 0 { @@ -263,20 +242,14 @@ func TestFilters(t *testing.T) { } failAddr := common.BytesToAddress([]byte("failmenow")) - filter = New(backend, testBloomBitsSection) - filter.SetAddresses([]common.Address{failAddr}) - filter.SetBeginBlock(0) - filter.SetEndBlock(-1) + filter = New(backend, 0, -1, []common.Address{failAddr}, nil) logs, _ = filter.Find(context.Background()) if len(logs) != 0 { t.Error("expected 0 log, got", len(logs)) } - filter = New(backend, testBloomBitsSection) - filter.SetTopics([][]common.Hash{{failHash}, {hash1}}) - filter.SetBeginBlock(0) - filter.SetEndBlock(-1) + filter = New(backend, 0, -1, nil, [][]common.Hash{{failHash}, {hash1}}) logs, _ = filter.Find(context.Background()) if len(logs) != 0 { diff --git a/les/api_backend.go b/les/api_backend.go index 175118e334..01d8584782 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -159,3 +159,7 @@ func (b *LesApiBackend) AccountManager() *accounts.Manager { func (b *LesApiBackend) GetBloomBits(ctx context.Context, bitIdx uint64, sectionIdxList []uint64) ([][]byte, error) { return nil, nil // implemented in a subsequent PR } + +func (b *LesApiBackend) BloomBitsSectionSize() uint64 { + return 0 +}