@@ -26,6 +26,8 @@ use crate::{data_source::DataSource, Chain};
26
26
pub type EventSignature = H256 ;
27
27
pub type FunctionSelector = [ u8 ; 4 ] ;
28
28
29
+ const ETH_GET_LOGS_MAX_CONTRACTS : usize = 1000 ;
30
+
29
31
#[ derive( Clone , Debug ) ]
30
32
pub struct EthereumContractCall {
31
33
pub address : Address ,
@@ -70,6 +72,22 @@ pub struct EthGetLogsFilter {
70
72
pub event_signatures : Vec < EventSignature > ,
71
73
}
72
74
75
+ impl EthGetLogsFilter {
76
+ fn from_contract ( address : Address ) -> Self {
77
+ EthGetLogsFilter {
78
+ contracts : vec ! [ address] ,
79
+ event_signatures : vec ! [ ] ,
80
+ }
81
+ }
82
+
83
+ fn from_event ( event : EventSignature ) -> Self {
84
+ EthGetLogsFilter {
85
+ contracts : vec ! [ ] ,
86
+ event_signatures : vec ! [ event] ,
87
+ }
88
+ }
89
+ }
90
+
73
91
impl fmt:: Display for EthGetLogsFilter {
74
92
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
75
93
if self . contracts . len ( ) == 1 {
@@ -209,10 +227,7 @@ impl EthereumLogFilter {
209
227
210
228
// First add the wildcard event filters.
211
229
for wildcard_event in self . wildcard_events {
212
- filters. push ( EthGetLogsFilter {
213
- contracts : vec ! [ ] ,
214
- event_signatures : vec ! [ wildcard_event] ,
215
- } )
230
+ filters. push ( EthGetLogsFilter :: from_event ( wildcard_event) )
216
231
}
217
232
218
233
// The current algorithm is to repeatedly find the maximum cardinality vertex and turn all
@@ -230,31 +245,37 @@ impl EthereumLogFilter {
230
245
// might cause the filter to become too broad, so at the moment it seems excessive.
231
246
let mut g = self . contracts_and_events_graph ;
232
247
while g. edge_count ( ) > 0 {
248
+ let mut push_filter = |filter : EthGetLogsFilter | {
249
+ // Sanity checks:
250
+ // - The filter is not a wildcard because all nodes have neighbors.
251
+ // - The graph is bipartite.
252
+ assert ! ( filter. contracts. len( ) > 0 && filter. event_signatures. len( ) > 0 ) ;
253
+ assert ! ( filter. contracts. len( ) == 1 || filter. event_signatures. len( ) == 1 ) ;
254
+ filters. push ( filter) ;
255
+ } ;
256
+
233
257
// If there are edges, there are vertexes.
234
258
let max_vertex = g. nodes ( ) . max_by_key ( |& n| g. neighbors ( n) . count ( ) ) . unwrap ( ) ;
235
259
let mut filter = match max_vertex {
236
- LogFilterNode :: Contract ( address) => EthGetLogsFilter {
237
- contracts : vec ! [ address] ,
238
- event_signatures : vec ! [ ] ,
239
- } ,
240
- LogFilterNode :: Event ( event_sig) => EthGetLogsFilter {
241
- contracts : vec ! [ ] ,
242
- event_signatures : vec ! [ event_sig] ,
243
- } ,
260
+ LogFilterNode :: Contract ( address) => EthGetLogsFilter :: from_contract ( address) ,
261
+ LogFilterNode :: Event ( event_sig) => EthGetLogsFilter :: from_event ( event_sig) ,
244
262
} ;
245
263
for neighbor in g. neighbors ( max_vertex) {
246
264
match neighbor {
247
- LogFilterNode :: Contract ( address) => filter. contracts . push ( address) ,
265
+ LogFilterNode :: Contract ( address) => {
266
+ if filter. contracts . len ( ) == ETH_GET_LOGS_MAX_CONTRACTS {
267
+ // The batch size was reached, register the filter and start a new one.
268
+ let event = filter. event_signatures [ 0 ] ;
269
+ push_filter ( filter) ;
270
+ filter = EthGetLogsFilter :: from_event ( event) ;
271
+ }
272
+ filter. contracts . push ( address) ;
273
+ }
248
274
LogFilterNode :: Event ( event_sig) => filter. event_signatures . push ( event_sig) ,
249
275
}
250
276
}
251
277
252
- // Sanity checks:
253
- // - The filter is not a wildcard because all nodes have neighbors.
254
- // - The graph is bipartite.
255
- assert ! ( filter. contracts. len( ) > 0 && filter. event_signatures. len( ) > 0 ) ;
256
- assert ! ( filter. contracts. len( ) == 1 || filter. event_signatures. len( ) == 1 ) ;
257
- filters. push ( filter) ;
278
+ push_filter ( filter) ;
258
279
g. remove_node ( max_vertex) ;
259
280
}
260
281
filters. into_iter ( )
@@ -794,6 +815,11 @@ fn complete_log_filter() {
794
815
. collect:: <BTreeSet <_>>( ) ,
795
816
events
796
817
) ;
818
+
819
+ // Assert that chunking works.
820
+ for filter in logs_filters {
821
+ assert ! ( filter. contracts. len( ) <= 1000 ) ;
822
+ }
797
823
}
798
824
}
799
825
}
0 commit comments