@@ -5,6 +5,7 @@ import Blockchain from "../blockchain";
55import { parseFilter , parseFilterDetails } from "../helpers/filter-parsing" ;
66import { Ethereum } from "../api-types" ;
77import { GanacheLevelUp } from "../database" ;
8+ type Topic = string | string [ ] ;
89
910export default class BlockLogManager extends Manager < BlockLogs > {
1011 #blockchain: Blockchain ;
@@ -28,6 +29,19 @@ export default class BlockLogManager extends Manager<BlockLogs> {
2829 return log ;
2930 }
3031
32+ async getRange ( fromBlockNumber : string | Buffer , toBlockNumber : string | Buffer , topics : Topic [ ] , address : String | String [ ] ) {
33+ const blockchain = this . #blockchain;
34+ if ( ! blockchain . fallback ) {
35+ throw new Error ( "Not a forked instance" ) ;
36+ }
37+ const res = await this . #blockchain. fallback . request < any [ ] | null > (
38+ "eth_getLogs" ,
39+ [ { address, topics, fromBlock : Quantity . from ( fromBlockNumber ) , toBlock : Quantity . from ( toBlockNumber ) } ]
40+ ) ;
41+ return BlockLogs . fromJSON ( res ) ;
42+
43+ }
44+
3145 async getLogs ( filter : FilterArgs ) : Promise < Ethereum . Logs > {
3246 const blockchain = this . #blockchain;
3347 if ( "blockHash" in filter ) {
@@ -44,19 +58,34 @@ export default class BlockLogManager extends Manager<BlockLogs> {
4458 filter ,
4559 blockchain
4660 ) ;
47-
48- const pendingLogsPromises : Promise < BlockLogs > [ ] = [
49- this . get ( fromBlock . toBuffer ( ) )
50- ] ;
61+ const pendingLogsPromises : Promise < BlockLogs > [ ] = [ ] ;
5162
5263 const fromBlockNumber = fromBlock . toNumber ( ) ;
5364 // if we have a range of blocks to search, do that here:
5465 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 ) ) ) ;
66+ if (
67+ ! blockchain . fallback || // We're not a forked chain
68+ blockchain . fallback . blockNumber < fromBlock // Or we are, but only querying post-fork
69+ ) {
70+ // fetch all the blockLogs in-between `fromBlock` and `toBlock`
71+ for ( let i = fromBlockNumber , l = toBlockNumber + 1 ; i < l ; i ++ ) {
72+ pendingLogsPromises . push ( this . get ( Quantity . toBuffer ( i ) ) ) ;
73+ }
74+ } else {
75+ // Fetch all the logs from fromBlockNumber to forkBlock in one request
76+ let addressesAsStrings : String [ ] | String ;
77+ if ( Array . isArray ( addresses ) ) {
78+ addressesAsStrings = addresses . map ( x => `0x${ x . toString ( 'hex' ) } ` )
79+ }
80+ pendingLogsPromises . push ( this . getRange ( Quantity . from ( fromBlockNumber ) . toString ( ) , Quantity . from ( toBlockNumber ) . toString ( ) , topics , addressesAsStrings ) ) ;
81+ // fetch all the blockLogs in-between `forkBlock` + 1 and `toBlock` locally in the
82+ // way that we normally do
83+ for ( let i = blockchain . fallback . blockNumber . toNumber ( ) + 1 , l = toBlockNumber + 1 ; i < l ; i ++ ) {
84+ pendingLogsPromises . push ( this . get ( Quantity . toBuffer ( i ) ) ) ;
85+ }
5986 }
87+ } else {
88+ pendingLogsPromises . push ( this . get ( Quantity . toBuffer ( fromBlockNumber ) ) ) ;
6089 }
6190
6291 // now filter and compute all the blocks' blockLogs (in block order)
0 commit comments