mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
eth/filter, core/bloombits: pass begin, end, addresses and topics at create time
This commit is contained in:
parent
c927db689f
commit
4f2b101d27
9 changed files with 48 additions and 92 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue