@@ -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}
0 commit comments