From 3a90eac8b101ff5a5f459595d7a716ba6522d695 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 15 Jun 2023 13:13:51 +0200 Subject: [PATCH] fix: exclude calls to precompiles in call graphs (#3141) --- .../revm/revm-inspectors/src/tracing/arena.rs | 38 ++++++++++++++++--- .../revm/revm-inspectors/src/tracing/mod.rs | 15 +++++++- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/crates/revm/revm-inspectors/src/tracing/arena.rs b/crates/revm/revm-inspectors/src/tracing/arena.rs index 9e8ffa02ef..fc7d12896f 100644 --- a/crates/revm/revm-inspectors/src/tracing/arena.rs +++ b/crates/revm/revm-inspectors/src/tracing/arena.rs @@ -11,7 +11,16 @@ pub struct CallTraceArena { impl CallTraceArena { /// Pushes a new trace into the arena, returning the trace ID - pub(crate) fn push_trace(&mut self, mut entry: usize, new_trace: CallTrace) -> usize { + /// + /// This appends a new trace to the arena, and also inserts a new entry in the node's parent + /// node children set if `attach_to_parent` is `true`. E.g. if calls to precompiles should + /// not be included in the call graph this should be called with [PushTraceKind::PushOnly]. + pub(crate) fn push_trace( + &mut self, + mut entry: usize, + kind: PushTraceKind, + new_trace: CallTrace, + ) -> usize { loop { match new_trace.depth { // The entry node, just update it @@ -22,9 +31,6 @@ impl CallTraceArena { // We found the parent node, add the new trace as a child _ if self.arena[entry].trace.depth == new_trace.depth - 1 => { let id = self.arena.len(); - - let trace_location = self.arena[entry].children.len(); - self.arena[entry].ordering.push(LogCallOrder::Call(trace_location)); let node = CallTraceNode { parent: Some(entry), trace: new_trace, @@ -32,7 +38,14 @@ impl CallTraceArena { ..Default::default() }; self.arena.push(node); - self.arena[entry].children.push(id); + + // also track the child in the parent node + if kind.is_attach_to_parent() { + let parent = &mut self.arena[entry]; + let trace_location = parent.children.len(); + parent.ordering.push(LogCallOrder::Call(trace_location)); + parent.children.push(id); + } return id } @@ -45,6 +58,21 @@ impl CallTraceArena { } } +/// How to push a trace into the arena +pub(crate) enum PushTraceKind { + /// This will _only_ push the trace into the arena. + PushOnly, + /// This will push the trace into the arena, and also insert a new entry in the node's parent + /// node children set. + PushAndAttachToParent, +} + +impl PushTraceKind { + fn is_attach_to_parent(&self) -> bool { + matches!(self, PushTraceKind::PushAndAttachToParent) + } +} + impl Default for CallTraceArena { fn default() -> Self { // The first node is the root node diff --git a/crates/revm/revm-inspectors/src/tracing/mod.rs b/crates/revm/revm-inspectors/src/tracing/mod.rs index 26504a71d6..0ea99f90dd 100644 --- a/crates/revm/revm-inspectors/src/tracing/mod.rs +++ b/crates/revm/revm-inspectors/src/tracing/mod.rs @@ -21,7 +21,10 @@ mod fourbyte; mod opcount; mod types; mod utils; -use crate::tracing::types::{CallTraceNode, StorageChange}; +use crate::tracing::{ + arena::PushTraceKind, + types::{CallTraceNode, StorageChange}, +}; pub use builder::{geth::GethTraceBuilder, parity::ParityTraceBuilder}; pub use config::TracingInspectorConfig; pub use fourbyte::FourByteInspector; @@ -126,8 +129,18 @@ impl TracingInspector { caller: Address, maybe_precompile: Option, ) { + // This will only be true if the inspector is configured to exclude precompiles and the call + // is to a precompile + let push_kind = if maybe_precompile.unwrap_or(false) { + // We don't want to track precompiles + PushTraceKind::PushOnly + } else { + PushTraceKind::PushAndAttachToParent + }; + self.trace_stack.push(self.traces.push_trace( 0, + push_kind, CallTrace { depth, address,