Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 0db3e11

Browse files
Andres AdjimannMicaiahReid
Andres Adjimann
authored andcommitted
feat: get logs from a fork network directly
1 parent 3b2b474 commit 0db3e11

File tree

2 files changed

+59
-30
lines changed

2 files changed

+59
-30
lines changed

src/chains/ethereum/ethereum/src/data-managers/blocklog-manager.ts

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -39,38 +39,59 @@ export default class BlockLogManager extends Manager<BlockLogs> {
3939

4040
const logs = await this.get(blockNumber);
4141
return logs ? [...logs.filter(addresses, topics)] : [];
42-
} else {
43-
const { addresses, topics, fromBlock, toBlockNumber } = parseFilter(
44-
filter,
45-
blockchain
46-
);
47-
48-
const pendingLogsPromises: Promise<BlockLogs>[] = [
49-
this.get(fromBlock.toBuffer())
50-
];
51-
52-
const fromBlockNumber = fromBlock.toNumber();
53-
// if we have a range of blocks to search, do that here:
54-
if (fromBlockNumber !== toBlockNumber) {
55-
// fetch all the blockLogs in-between `fromBlock` and `toBlock` (excluding
56-
// from, because we already started fetching that one)
57-
for (let i = fromBlockNumber + 1, l = toBlockNumber + 1; i < l; i++) {
58-
pendingLogsPromises.push(this.get(Quantity.toBuffer(i)));
59-
}
60-
}
42+
}
43+
const { addresses, topics, fromBlock, toBlock } = parseFilter(
44+
filter,
45+
blockchain
46+
);
47+
const from = Quantity.min(fromBlock, toBlock);
48+
const fork = this.#blockchain.fallback;
49+
if (!fork) {
50+
return await this.getLocal(from.toNumber(), toBlock.toNumber(), filter);
51+
}
52+
const ret: Ethereum.Logs = [];
53+
if (fork.isValidForkBlockNumber(from)) {
54+
ret.push(...await this.getFromFork(from, Quantity.min(toBlock, fork.blockNumber), filter));
55+
}
56+
if (!fork.isValidForkBlockNumber(toBlock)) {
57+
ret.push(...await this.getLocal(fork.blockNumber.toNumber() + 1, toBlock.toNumber(), filter));
58+
}
59+
return ret;
60+
}
6161

62-
// now filter and compute all the blocks' blockLogs (in block order)
63-
return Promise.all(pendingLogsPromises).then(blockLogsRange => {
64-
const filteredBlockLogs: Ethereum.Logs = [];
65-
blockLogsRange.forEach(blockLogs => {
66-
// TODO(perf): this loops over all addresses for every block.
67-
// Maybe make it loop only once?
68-
// Issue: https://github.com/trufflesuite/ganache/issues/3482
69-
if (blockLogs)
70-
filteredBlockLogs.push(...blockLogs.filter(addresses, topics));
71-
});
72-
return filteredBlockLogs;
62+
getLocal(from: number, toBlockNumber: number, filter: FilterArgs): Promise<Ethereum.Logs> {
63+
const { addresses, topics } = parseFilter(filter, this.#blockchain);
64+
const pendingLogsPromises: Promise<BlockLogs>[] = [];
65+
for (let i = from; i <= toBlockNumber; i++) {
66+
pendingLogsPromises.push(this.get(Quantity.toBuffer(i)));
67+
}
68+
return Promise.all(pendingLogsPromises).then(blockLogsRange => {
69+
const filteredBlockLogs: Ethereum.Logs = [];
70+
blockLogsRange.forEach(blockLogs => {
71+
// TODO(perf): this loops over all addresses for every block.
72+
// Maybe make it loop only once?
73+
// Issue: https://github.com/trufflesuite/ganache/issues/3482
74+
if (blockLogs)
75+
filteredBlockLogs.push(...blockLogs.filter(addresses, topics));
7376
});
77+
return filteredBlockLogs;
78+
});
79+
}
80+
81+
async getFromFork(from: Quantity, to: Quantity, filter: FilterArgs): Promise<Ethereum.Logs> {
82+
const { topics } = parseFilter(filter, this.#blockchain);
83+
const f = this.#blockchain.fallback;
84+
if (!f || !f.isValidForkBlockNumber(from)) {
85+
return [];
7486
}
87+
return await f.request<Ethereum.Logs | null>(
88+
"eth_getLogs",
89+
[{
90+
fromBlock: from,
91+
toBlock: f.selectValidForkBlockNumber(to),
92+
address: filter.address ? (Array.isArray(filter.address) ? filter.address : [filter.address]) : [],
93+
topics
94+
}]
95+
);
7596
}
7697
}

src/packages/utils/src/things/json-rpc/json-rpc-quantity.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ export class Quantity extends BaseJsonRpcType {
1818
return new Quantity(value, nullable);
1919
}
2020

21+
public static min(a: Quantity, b: Quantity) {
22+
return a.toBigInt() < b.toBigInt() ? a : b;
23+
}
24+
25+
public static max(a: Quantity, b: Quantity) {
26+
return a.toBigInt() < b.toBigInt() ? b : a;
27+
}
28+
2129
constructor(value: JsonRpcInputArg, nullable?: boolean) {
2230
super(value);
2331
if (value === "0x") {

0 commit comments

Comments
 (0)