Skip to content

Commit 02014b3

Browse files
authored
Speedup eth_getLogs (#3062)
* fetch txHash from txRecord + reduce blockHash call * minor fixes
1 parent 577e355 commit 02014b3

File tree

3 files changed

+35
-10
lines changed

3 files changed

+35
-10
lines changed

nimbus/core/chain/forked_chain.nim

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import
1414
chronicles,
15-
std/tables,
15+
std/[tables, algorithm],
1616
../../common,
1717
../../db/core_db,
1818
../../evm/types,
@@ -21,6 +21,8 @@ import
2121
../executor/process_block,
2222
./forked_chain/[chain_desc, chain_kvt, chain_branch]
2323

24+
from std/sequtils import mapIt
25+
2426
logScope:
2527
topics = "forked chain"
2628

@@ -632,6 +634,17 @@ func memoryTransaction*(c: ForkedChainRef, txHash: Hash32): Opt[(Transaction, Bl
632634
return Opt.some( (loc[].tx(index), loc[].number) )
633635
return Opt.none((Transaction, BlockNumber))
634636

637+
func memoryTxHashesForBlock*(c: ForkedChainRef, blockHash: Hash32): seq[Hash32] =
638+
var cachedTxHashes = newSeq[(Hash32, uint64)]()
639+
for txHash, (blkHash, txIdx) in c.txRecords.pairs:
640+
if blkHash == blockHash:
641+
cachedTxHashes.add((txHash, txIdx))
642+
643+
cachedTxHashes.sort(proc(a, b: (Hash32, uint64)): int =
644+
cmp(a[1], b[1])
645+
)
646+
cachedTxHashes.mapIt(it[0])
647+
635648
proc latestBlock*(c: ForkedChainRef): Block =
636649
if c.activeBranch.headNumber == c.baseBranch.tailNumber:
637650
# It's a base block

nimbus/rpc/filters.nim

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,30 @@ proc deriveLogs*(
6666
transactions: openArray[Transaction],
6767
receipts: openArray[Receipt],
6868
filterOptions: FilterOptions,
69+
txHashes: Opt[seq[Hash32]] = Opt.none(seq[Hash32])
6970
): seq[FilterLog] =
7071
## Derive log fields, does not deal with pending log, only the logs with
7172
## full data set
7273
doAssert(len(transactions) == len(receipts))
7374

75+
# Verify that txHashes is consistent with transactions
76+
if txHashes.isSome:
77+
doAssert(txHashes.get.len == len(transactions))
78+
79+
let blkHash = header.blockHash
7480
var resLogs: seq[FilterLog] = @[]
7581
var logIndex = 0'u64
7682

7783
for i, receipt in receipts:
7884
let logs = receipt.logs.filterIt(it.match(filterOptions.address, filterOptions.topics))
7985
if logs.len > 0:
8086
# TODO avoid recomputing entirely - we should have this cached somewhere
81-
let txHash = transactions[i].rlpHash
87+
let txHash =
88+
if txHashes.isSome:
89+
txHashes.get[i] # cached txHashes
90+
else:
91+
transactions[i].rlpHash
92+
8293
for log in logs:
8394
let filterLog = FilterLog(
8495
# TODO investigate how to handle this field
@@ -89,7 +100,7 @@ proc deriveLogs*(
89100
logIndex: Opt.some(Quantity(logIndex)),
90101
transactionIndex: Opt.some(Quantity(i)),
91102
transactionHash: Opt.some(txHash),
92-
blockHash: Opt.some(header.blockHash),
103+
blockHash: Opt.some(blkHash),
93104
blockNumber: Opt.some(Quantity(header.number)),
94105
address: log.address,
95106
data: log.data,

nimbus/rpc/server_api.nim

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -226,26 +226,27 @@ proc setupServerAPI*(api: ServerAPIRef, server: RpcServer, ctx: EthContext) =
226226
chain: ForkedChainRef, header: Header, opts: FilterOptions
227227
): Opt[seq[FilterLog]] {.gcsafe, raises: [].} =
228228
if headerBloomFilter(header, opts.address, opts.topics):
229-
let (receipts, txs) =
230-
if api.chain.isInMemory(header.blockHash):
231-
let blk = api.chain.memoryBlock(header.blockHash)
232-
(blk.receipts, blk.blk.transactions)
229+
let blkHash = header.blockHash
230+
let (receipts, txs, cachedHashes) =
231+
if api.chain.isInMemory(blkHash):
232+
let blk = api.chain.memoryBlock(blkHash)
233+
(blk.receipts, blk.blk.transactions, Opt.some(chain.memoryTxHashesForBlock(blkHash)))
233234
else:
234235
let rcs = chain.baseTxFrame.getReceipts(header.receiptsRoot).valueOr:
235236
return Opt.some(newSeq[FilterLog](0))
236237
let txs = chain.baseTxFrame.getTransactions(header.txRoot).valueOr:
237238
return Opt.some(newSeq[FilterLog](0))
238-
(rcs, txs)
239+
(rcs, txs, Opt.none(seq[Hash32]))
239240
# Note: this will hit assertion error if number of block transactions
240241
# do not match block receipts.
241242
# Although this is fine as number of receipts should always match number
242243
# of transactions
243244
if txs.len != receipts.len:
244245
warn "Transactions and receipts length mismatch",
245-
number = header.number, hash = header.blockHash.short,
246+
number = header.number, hash = blkHash.short,
246247
txs = txs.len, receipts = receipts.len
247248
return Opt.none(seq[FilterLog])
248-
let logs = deriveLogs(header, txs, receipts, opts)
249+
let logs = deriveLogs(header, txs, receipts, opts, cachedHashes)
249250
return Opt.some(logs)
250251
else:
251252
return Opt.some(newSeq[FilterLog](0))

0 commit comments

Comments
 (0)