@@ -39,38 +39,59 @@ export default class BlockLogManager extends Manager<BlockLogs> {
39
39
40
40
const logs = await this . get ( blockNumber ) ;
41
41
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
+ }
61
61
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 ) ) ;
73
76
} ) ;
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 [ ] ;
74
86
}
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
+ ) ;
75
96
}
76
97
}
0 commit comments