Skip to content

Commit

Permalink
feat: impl trace_filter
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse committed Sep 30, 2023
1 parent f42ebf3 commit b0fe3d7
Showing 1 changed file with 60 additions and 8 deletions.
68 changes: 60 additions & 8 deletions crates/rpc/rpc/src/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::{
utils::recover_raw_transaction,
EthTransactions,
},
result::internal_rpc_err,
TracingCallGuard,
};
use async_trait::async_trait;
Expand Down Expand Up @@ -249,12 +248,16 @@ where
}
}

/// Returns all traces for the given transaction hash
/// Returns all transaction traces that match the given filter.
///
/// This is similar to [Self::trace_block] but only returns traces for transactions that match
/// the filter.
pub async fn trace_filter(
&self,
filter: TraceFilter,
) -> EthResult<Vec<LocalizedTransactionTrace>> {
let TraceFilter { from_block, to_block, from_address, to_address, after, count } = filter;
let matcher = filter.matcher();
let TraceFilter { from_block, to_block, after: _after, count: _count, .. } = filter;
let start = from_block.unwrap_or(0);
let end = if let Some(to_block) = to_block {
to_block
Expand All @@ -265,15 +268,64 @@ where
// ensure that the range is not too large, since we need to fetch all blocks in the range
let distance = end.saturating_sub(start);
if distance > 100 {
return Err(
EthApiError::InvalidParams("Block range too large; currently limited to 100 blocks".to_string())
)
return Err(EthApiError::InvalidParams(
"Block range too large; currently limited to 100 blocks".to_string(),
))
}

// fetch all blocks in that range
let blocks = self.provider().block_range(start..=end)?;

// find relevant blocks to trace
let mut target_blocks = Vec::new();
for block in blocks {
let mut transaction_indices = HashSet::new();
for (tx_idx, tx) in block.body.iter().enumerate() {
let from = tx.recover_signer().ok_or(BlockError::InvalidSignature)?;
let to = tx.to();
if matcher.matches(from, to) {
transaction_indices.insert(tx_idx as u64);
}
}
if !transaction_indices.is_empty() {
target_blocks.push((block.number, transaction_indices));
}
}

self.provider().block_ran
// TODO: this could be optimized to only trace the block until the highest matching index in
// that block

// trace all relevant blocks
let mut block_traces = Vec::with_capacity(target_blocks.len());
for (num, indices) in target_blocks {
let traces = self.trace_block_with(
num.into(),
TracingInspectorConfig::default_parity(),
move |tx_info, inspector, res, _, _| {
if let Some(idx) = tx_info.index {
if !indices.contains(&idx) {
// only record traces for relevant transactions
return Ok(None)
}
}
let traces = inspector
.with_transaction_gas_used(res.gas_used())
.into_parity_builder()
.into_localized_transaction_traces(tx_info);
Ok(Some(traces))
},
);
block_traces.push(traces);
}

let block_traces = futures::future::try_join_all(block_traces).await?;
let all_traces = block_traces
.into_iter()
.flatten()
.flat_map(|traces| traces.into_iter().flatten().flat_map(|traces| traces.into_iter()))
.collect();

todo!()
Ok(all_traces)
}

/// Returns all traces for the given transaction hash
Expand Down

0 comments on commit b0fe3d7

Please sign in to comment.