From a8be68a82c20ecf6b50ea66d8a706a3493c9bce0 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sat, 17 Jun 2023 19:15:00 +0200 Subject: [PATCH] fix: prevent panic in trace call (#3216) --- .../src/tracing/builder/parity.rs | 16 ++++++++++++++-- crates/revm/revm-inspectors/src/tracing/types.rs | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/crates/revm/revm-inspectors/src/tracing/builder/parity.rs b/crates/revm/revm-inspectors/src/tracing/builder/parity.rs index 422842904e..3798d19f86 100644 --- a/crates/revm/revm-inspectors/src/tracing/builder/parity.rs +++ b/crates/revm/revm-inspectors/src/tracing/builder/parity.rs @@ -8,6 +8,8 @@ use revm::{ use std::collections::HashSet; /// A type for creating parity style traces +/// +/// Note: Parity style traces always ignore calls to precompiles. #[derive(Clone, Debug)] pub struct ParityTraceBuilder { /// Recorded trace nodes @@ -27,7 +29,12 @@ impl ParityTraceBuilder { self.nodes.iter().map(|node| node.trace.caller).collect() } - /// Returns the trace addresses of all transactions in the set + /// Returns the trace addresses of all call nodes in the set + /// + /// Each entry in the returned vector represents the [Self::trace_address] of the corresponding + /// node in the nodes set. + /// + /// CAUTION: This also includes precompiles, which have an empty trace address. fn trace_addresses(&self) -> Vec> { let mut all_addresses = Vec::with_capacity(self.nodes.len()); for idx in 0..self.nodes.len() { @@ -44,6 +51,8 @@ impl ParityTraceBuilder { /// # Panics /// /// if the `idx` does not belong to a node + /// + /// Note: if the call node of `idx` is a precompile, the returned trace address will be empty. fn trace_address(&self, idx: usize) -> Vec { if idx == 0 { // root call has empty traceAddress @@ -51,6 +60,9 @@ impl ParityTraceBuilder { } let mut graph = vec![]; let mut node = &self.nodes[idx]; + if node.is_precompile() { + return graph + } while let Some(parent) = node.parent { // the index of the child call in the arena let child_idx = node.idx; @@ -60,7 +72,7 @@ impl ParityTraceBuilder { .children .iter() .position(|child| *child == child_idx) - .expect("child exists in parent"); + .expect("non precompile child call exists in parent"); graph.push(call_idx); } graph.reverse(); diff --git a/crates/revm/revm-inspectors/src/tracing/types.rs b/crates/revm/revm-inspectors/src/tracing/types.rs index 85b28052a7..43681a5b8e 100644 --- a/crates/revm/revm-inspectors/src/tracing/types.rs +++ b/crates/revm/revm-inspectors/src/tracing/types.rs @@ -242,6 +242,7 @@ impl CallTraceNode { } /// Returns true if this is a call to a precompile + #[inline] pub(crate) fn is_precompile(&self) -> bool { self.trace.maybe_precompile.unwrap_or(false) }