Skip to content

Commit 4d4947e

Browse files
author
Matthieu Vachon
authored
Avoid parsing X triggers if the filter is empty (#3083)
When a filter is empty, it means it cannot match anything. By guarding the parsing of the triggers upfront, we avoid looping through lot's of element in the blocks, this is especially true for full blocks that contain all the transactions. Remove a `clone()` that can be delayed to later at the same time. Fixes #3080
1 parent 2aaf85a commit 4d4947e

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

chain/ethereum/src/adapter.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -400,13 +400,15 @@ impl FromIterator<(BlockNumber, Address, FunctionSelector)> for EthereumCallFilt
400400
}
401401
}
402402

403-
impl From<EthereumBlockFilter> for EthereumCallFilter {
404-
fn from(ethereum_block_filter: EthereumBlockFilter) -> Self {
403+
impl From<&EthereumBlockFilter> for EthereumCallFilter {
404+
fn from(ethereum_block_filter: &EthereumBlockFilter) -> Self {
405405
Self {
406406
contract_addresses_function_signatures: ethereum_block_filter
407407
.contract_addresses
408-
.into_iter()
409-
.map(|(start_block_opt, address)| (address, (start_block_opt, HashSet::default())))
408+
.iter()
409+
.map(|(start_block_opt, address)| {
410+
(address.clone(), (*start_block_opt, HashSet::default()))
411+
})
410412
.collect::<HashMap<Address, (BlockNumber, HashSet<FunctionSelector>)>>(),
411413
}
412414
}
@@ -483,6 +485,16 @@ impl EthereumBlockFilter {
483485
fn requires_traces(&self) -> bool {
484486
!self.contract_addresses.is_empty()
485487
}
488+
489+
/// An empty filter is one that never matches.
490+
pub fn is_empty(&self) -> bool {
491+
// If we are triggering every block, we are of course not empty
492+
if self.trigger_every_block {
493+
return false;
494+
}
495+
496+
self.contract_addresses.is_empty()
497+
}
486498
}
487499

488500
#[derive(Clone)]

chain/ethereum/src/chain.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ impl TriggersAdapterTrait<Chain> for TriggersAdapter {
505505
&full_block.ethereum_block,
506506
));
507507
triggers.append(&mut parse_call_triggers(&filter.call, &full_block)?);
508-
triggers.append(&mut parse_block_triggers(filter.block.clone(), &full_block));
508+
triggers.append(&mut parse_block_triggers(&filter.block, &full_block));
509509
Ok(BlockWithTriggers::new(block, triggers))
510510
}
511511
}

chain/ethereum/src/ethereum_adapter.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,7 @@ pub(crate) async fn blocks_with_triggers(
13881388
// and the blocks yielded need to be deduped. If any error occurs
13891389
// while searching for a trigger type, the entire operation fails.
13901390
let eth = adapter.clone();
1391-
let call_filter = EthereumCallFilter::from(filter.block.clone());
1391+
let call_filter = EthereumCallFilter::from(&filter.block);
13921392

13931393
let mut trigger_futs: futures::stream::FuturesUnordered<
13941394
Box<dyn Future<Item = Vec<EthereumTrigger>, Error = Error> + Send>,
@@ -1590,6 +1590,10 @@ pub(crate) fn parse_log_triggers(
15901590
log_filter: &EthereumLogFilter,
15911591
block: &EthereumBlock,
15921592
) -> Vec<EthereumTrigger> {
1593+
if log_filter.is_empty() {
1594+
return vec![];
1595+
}
1596+
15931597
block
15941598
.transaction_receipts
15951599
.iter()
@@ -1607,6 +1611,10 @@ pub(crate) fn parse_call_triggers(
16071611
call_filter: &EthereumCallFilter,
16081612
block: &EthereumBlockWithCalls,
16091613
) -> anyhow::Result<Vec<EthereumTrigger>> {
1614+
if call_filter.is_empty() {
1615+
return Ok(vec![]);
1616+
}
1617+
16101618
match &block.calls {
16111619
Some(calls) => calls
16121620
.iter()
@@ -1625,9 +1633,13 @@ pub(crate) fn parse_call_triggers(
16251633
}
16261634

16271635
pub(crate) fn parse_block_triggers(
1628-
block_filter: EthereumBlockFilter,
1636+
block_filter: &EthereumBlockFilter,
16291637
block: &EthereumBlockWithCalls,
16301638
) -> Vec<EthereumTrigger> {
1639+
if block_filter.is_empty() {
1640+
return vec![];
1641+
}
1642+
16311643
let block_ptr = BlockPtr::from(&block.ethereum_block);
16321644
let trigger_every_block = block_filter.trigger_every_block;
16331645
let call_filter = EthereumCallFilter::from(block_filter);

0 commit comments

Comments
 (0)