Skip to content

Commit a429a50

Browse files
s1nabrilliant-lx
authored andcommitted
eth/filters: fix getLogs for pending block (ethereum#24949)
* eth/filters: fix pending for getLogs * add pending method to test backend * fix block range validation
1 parent ea52f6c commit a429a50

File tree

4 files changed

+59
-17
lines changed

4 files changed

+59
-17
lines changed

accounts/abi/bind/backends/simulated.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ type SimulatedBackend struct {
6363
database ethdb.Database // In memory database to store our testing data
6464
blockchain *core.BlockChain // Ethereum blockchain to handle the consensus
6565

66-
mu sync.Mutex
67-
pendingBlock *types.Block // Currently pending block that will be imported on request
68-
pendingState *state.StateDB // Currently pending state that will be the active on request
66+
mu sync.Mutex
67+
pendingBlock *types.Block // Currently pending block that will be imported on request
68+
pendingState *state.StateDB // Currently pending state that will be the active on request
69+
pendingReceipts types.Receipts // Currently receipts for the pending block
6970

7071
events *filters.EventSystem // Event system for filtering log events live
7172

@@ -84,8 +85,8 @@ func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.Genesis
8485
database: database,
8586
blockchain: blockchain,
8687
config: genesis.Config,
87-
events: filters.NewEventSystem(&filterBackend{database, blockchain}, false),
8888
}
89+
backend.events = filters.NewEventSystem(&filterBackend{database, blockchain, backend}, false)
8990
backend.rollback(blockchain.CurrentBlock())
9091
return backend
9192
}
@@ -662,7 +663,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
662663
return fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce)
663664
}
664665
// Include tx in chain
665-
blocks, _ := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
666+
blocks, receipts := core.GenerateChain(b.config, block, ethash.NewFaker(), b.database, 1, func(number int, block *core.BlockGen) {
666667
for _, tx := range b.pendingBlock.Transactions() {
667668
block.AddTxWithChain(b.blockchain, tx)
668669
}
@@ -672,6 +673,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
672673

673674
b.pendingBlock = blocks[0]
674675
b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil)
676+
b.pendingReceipts = receipts[0]
675677
return nil
676678
}
677679

@@ -683,7 +685,7 @@ func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.Filter
683685
var filter *filters.Filter
684686
if query.BlockHash != nil {
685687
// Block filter requested, construct a single-shot filter
686-
filter = filters.NewBlockFilter(&filterBackend{b.database, b.blockchain}, *query.BlockHash, query.Addresses, query.Topics)
688+
filter = filters.NewBlockFilter(&filterBackend{b.database, b.blockchain, b}, *query.BlockHash, query.Addresses, query.Topics)
687689
} else {
688690
// Initialize unset filter boundaries to run from genesis to chain head
689691
from := int64(0)
@@ -695,7 +697,7 @@ func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.Filter
695697
to = query.ToBlock.Int64()
696698
}
697699
// Construct the range filter
698-
filter = filters.NewRangeFilter(&filterBackend{b.database, b.blockchain}, from, to, query.Addresses, query.Topics, false)
700+
filter = filters.NewRangeFilter(&filterBackend{b.database, b.blockchain, b}, from, to, query.Addresses, query.Topics, false)
699701
}
700702
// Run the filter and return all the logs
701703
logs, err := filter.Logs(ctx)
@@ -816,8 +818,9 @@ func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList }
816818
// filterBackend implements filters.Backend to support filtering for logs without
817819
// taking bloom-bits acceleration structures into account.
818820
type filterBackend struct {
819-
db ethdb.Database
820-
bc *core.BlockChain
821+
db ethdb.Database
822+
bc *core.BlockChain
823+
backend *SimulatedBackend
821824
}
822825

823826
func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db }
@@ -834,6 +837,10 @@ func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*t
834837
return fb.bc.GetHeaderByHash(hash), nil
835838
}
836839

840+
func (fb *filterBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
841+
return fb.backend.pendingBlock, fb.backend.pendingReceipts
842+
}
843+
837844
func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
838845
number := rawdb.ReadHeaderNumber(fb.db, hash)
839846
if number == nil {

eth/filters/filter.go

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type Backend interface {
3939
HeaderByHash(ctx context.Context, blockHash common.Hash) (*types.Header, error)
4040
GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error)
4141
GetLogs(ctx context.Context, blockHash common.Hash) ([][]*types.Log, error)
42+
PendingBlockAndReceipts() (*types.Block, types.Receipts)
4243

4344
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
4445
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
@@ -134,29 +135,38 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
134135
}
135136
return f.blockLogs(ctx, header)
136137
}
138+
// Short-cut if all we care about is pending logs
139+
if f.begin == rpc.PendingBlockNumber.Int64() {
140+
if f.end != rpc.PendingBlockNumber.Int64() {
141+
return nil, errors.New("invalid block range")
142+
}
143+
return f.pendingLogs()
144+
}
137145
// Figure out the limits of the filter range
138146
header, _ := f.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
139147
if header == nil {
140148
return nil, nil
141149
}
142-
head := header.Number.Uint64()
143-
144-
if f.begin == -1 {
150+
var (
151+
head = header.Number.Uint64()
152+
end = uint64(f.end)
153+
pending = f.end == rpc.PendingBlockNumber.Int64()
154+
)
155+
if f.begin == rpc.LatestBlockNumber.Int64() {
145156
f.begin = int64(head)
146157
}
147-
end := uint64(f.end)
148-
if f.end == -1 {
158+
if f.end == rpc.LatestBlockNumber.Int64() || f.end == rpc.PendingBlockNumber.Int64() {
149159
end = head
150160
}
151161
if f.rangeLimit && (int64(end)-f.begin) > maxFilterBlockRange {
152162
return nil, fmt.Errorf("exceed maximum block range: %d", maxFilterBlockRange)
153163
}
154164
// Gather all indexed logs, and finish with non indexed ones
155165
var (
156-
logs []*types.Log
157-
err error
166+
logs []*types.Log
167+
err error
168+
size, sections = f.backend.BloomStatus()
158169
)
159-
size, sections := f.backend.BloomStatus()
160170
if indexed := sections * size; indexed > uint64(f.begin) {
161171
if indexed > end {
162172
logs, err = f.indexedLogs(ctx, end)
@@ -169,6 +179,13 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
169179
}
170180
rest, err := f.unindexedLogs(ctx, end)
171181
logs = append(logs, rest...)
182+
if pending {
183+
pendingLogs, err := f.pendingLogs()
184+
if err != nil {
185+
return nil, err
186+
}
187+
logs = append(logs, pendingLogs...)
188+
}
172189
return logs, err
173190
}
174191

@@ -281,6 +298,19 @@ func (f *Filter) checkMatches(ctx context.Context, header *types.Header) (logs [
281298
return nil, nil
282299
}
283300

301+
// pendingLogs returns the logs matching the filter criteria within the pending block.
302+
func (f *Filter) pendingLogs() ([]*types.Log, error) {
303+
block, receipts := f.backend.PendingBlockAndReceipts()
304+
if bloomFilter(block.Bloom(), f.addresses, f.topics) {
305+
var unfiltered []*types.Log
306+
for _, r := range receipts {
307+
unfiltered = append(unfiltered, r.Logs...)
308+
}
309+
return filterLogs(unfiltered, nil, nil, f.addresses, f.topics), nil
310+
}
311+
return nil, nil
312+
}
313+
284314
func includes(addresses []common.Address, a common.Address) bool {
285315
for _, addr := range addresses {
286316
if addr == a {

eth/filters/filter_system_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ func (b *testBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types
106106
return logs, nil
107107
}
108108

109+
func (b *testBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) {
110+
return nil, nil
111+
}
112+
109113
func (b *testBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
110114
return b.txFeed.Subscribe(ch)
111115
}

internal/ethapi/backend.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ type Backend interface {
6767
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)
6868
StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error)
6969
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
70+
PendingBlockAndReceipts() (*types.Block, types.Receipts)
7071
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
7172
GetTd(ctx context.Context, hash common.Hash) *big.Int
7273
GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error)

0 commit comments

Comments
 (0)