From 65397b70870a1e7377c333a6cde8d7f27cd69b4b Mon Sep 17 00:00:00 2001 From: Eshaan Bansal Date: Sat, 26 Oct 2024 23:23:30 +0530 Subject: [PATCH] perf: avoid redundant tx receipt fetching in verify_logs (#397) * perf: avoid redundant tx receipt fetching in verify_logs * rebase with master --- core/src/execution/mod.rs | 52 +++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/core/src/execution/mod.rs b/core/src/execution/mod.rs index 4d54b3e1..bc8979d6 100644 --- a/core/src/execution/mod.rs +++ b/core/src/execution/mod.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use alloy::network::ReceiptResponse; use alloy::primitives::{keccak256, Address, B256, U256}; @@ -290,27 +290,43 @@ impl> ExecutionClient { } async fn verify_logs(&self, logs: &[Log]) -> Result<()> { - for log in logs.iter() { - // For every log - // Get the hash of the tx that generated it - let tx_hash = log - .transaction_hash - .ok_or(eyre::eyre!("tx hash not found in log"))?; - - // Get its proven receipt - let receipt = self - .get_transaction_receipt(tx_hash) - .await? - .ok_or(ExecutionError::NoReceiptForTransaction(tx_hash))?; + // Collect all (unique) tx hashes + let txs_hash = logs + .iter() + .map(|log| { + log.transaction_hash + .ok_or(eyre::eyre!("tx hash not found in log")) + }) + .collect::, _>>()?; + + // Collect all (proven) tx receipts as a map of tx hash to receipt + let receipts_fut = txs_hash.iter().map(|&tx_hash| async move { + let receipt = self.get_transaction_receipt(tx_hash).await; + receipt?.map(|r| (tx_hash, r)).ok_or(eyre::eyre!( + ExecutionError::NoReceiptForTransaction(tx_hash) + )) + }); + let receipts = join_all(receipts_fut).await; + let receipts: HashMap<_, _> = receipts.into_iter().collect::>()?; + + // Map tx hashes to encoded logs + let receipts_logs_encoded: HashMap<_, _> = receipts + .iter() + .map(|(tx_hash, receipt)| { + let encoded_logs = N::receipt_logs(&receipt) + .iter() + .map(|l| encode(&l.inner)) + .collect::>(); + (tx_hash, encoded_logs) + }) + .collect(); + for log in logs.iter() { // Check if the receipt contains the desired log // Encoding logs for comparison - let receipt_logs_encoded = N::receipt_logs(&receipt) - .iter() - .map(|log| encode(&log.inner)) - .collect::>(); - + let tx_hash = log.transaction_hash.unwrap(); let log_encoded = encode(&log.inner); + let receipt_logs_encoded = receipts_logs_encoded.get(&tx_hash).unwrap(); if !receipt_logs_encoded.contains(&log_encoded) { return Err(ExecutionError::MissingLog(