diff --git a/Cargo.toml b/Cargo.toml index 2dc9ec5..78436e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trevm" -version = "0.27.7" +version = "0.27.8" rust-version = "1.83.0" edition = "2021" authors = ["init4"] diff --git a/src/evm.rs b/src/evm.rs index 0f67e37..bccf3c8 100644 --- a/src/evm.rs +++ b/src/evm.rs @@ -828,6 +828,66 @@ where } } +// Layered inspector +impl Trevm, TrevmState> +where + Db: Database, + Outer: Inspector>, + Inner: Inspector>, +{ + /// Remove the outer-layer inspector, leaving the inner-layer inspector in + /// place. + pub fn take_outer(self) -> (Outer, Trevm) { + let (outer, inner) = self.inner.inspector.into_parts(); + + ( + outer, + Trevm { + inner: Box::new(Evm { + ctx: self.inner.ctx, + inspector: inner, + instruction: self.inner.instruction, + precompiles: self.inner.precompiles, + frame_stack: self.inner.frame_stack, + }), + state: self.state, + }, + ) + } + + /// Remove the outer-layer inspector, leaving the inner-layer inspector in + /// place. + pub fn remove_outer(self) -> Trevm { + self.take_outer().1 + } + + /// Remove the inner-layer inspector, leaving the outer-layer inspector in + /// place. + pub fn take_inner(self) -> (Inner, Trevm) { + let (outer, inner) = self.inner.inspector.into_parts(); + + ( + inner, + Trevm { + inner: Box::new(Evm { + ctx: self.inner.ctx, + inspector: outer, + instruction: self.inner.instruction, + precompiles: self.inner.precompiles, + frame_stack: self.inner.frame_stack, + }), + state: self.state, + }, + ) + } + + /// Remove the inner-layer inspector, leaving the outer-layer inspector in + /// place. + pub fn remove_inner(self) -> Trevm { + self.take_inner().1 + } +} + // --- ALL STATES, WITH State impl Trevm diff --git a/src/inspectors/layer.rs b/src/inspectors/layer.rs index 9c8705c..b959f1f 100644 --- a/src/inspectors/layer.rs +++ b/src/inspectors/layer.rs @@ -41,12 +41,18 @@ impl Layered { Layered { outer: self, inner } } - /// Get a reference to the current inspector. + /// Decompose the [`Layered`] inspector into its outer and inner + /// inspectors. + pub fn into_parts(self) -> (Outer, Inner) { + (self.outer, self.inner) + } + + /// Get a reference to the outer inspector. pub const fn outer(&self) -> &Outer { &self.outer } - /// Get a mutable reference to the current inspector. + /// Get a mutable reference to the outer inspector. pub const fn outer_mut(&mut self) -> &mut Outer { &mut self.outer } diff --git a/src/inspectors/mod.rs b/src/inspectors/mod.rs index e54efc5..18bb7e4 100644 --- a/src/inspectors/mod.rs +++ b/src/inspectors/mod.rs @@ -6,6 +6,8 @@ pub use timeout::TimeLimit; #[cfg(feature = "tracing-inspectors")] mod tracing; +#[cfg(feature = "tracing-inspectors")] +pub use tracing::TracingInspectorOutput; mod set; pub use set::InspectorSet; diff --git a/src/inspectors/tracing.rs b/src/inspectors/tracing.rs index 628fbb2..1f5b1a2 100644 --- a/src/inspectors/tracing.rs +++ b/src/inspectors/tracing.rs @@ -1,7 +1,57 @@ use crate::{helpers::Ctx, inspectors::InspectorWithOutput}; use alloy::rpc::types::trace::geth::FourByteFrame; use revm::Database; -use revm_inspectors::tracing::FourByteInspector; +use revm_inspectors::tracing::{ + CallTraceArena, FourByteInspector, GethTraceBuilder, ParityTraceBuilder, TracingInspector, +}; + +/// Output produced by the [`TracingInspector`]. +#[derive(Clone, Debug)] +pub struct TracingInspectorOutput { + traces: CallTraceArena, +} + +impl TracingInspectorOutput { + /// Creates a new output instance. + pub const fn new(traces: CallTraceArena) -> Self { + Self { traces } + } + + /// Returns a reference to the traces produced by the inspector. + pub const fn traces(&self) -> &CallTraceArena { + &self.traces + } + + /// Consumes the output and produces a Parity trace builder. + pub fn into_parity_builder(self) -> ParityTraceBuilder { + // NB: the second arguments are actually currently unused. This is + // weird. + ParityTraceBuilder::new(self.traces.into_nodes(), None, Default::default()) + } + + /// Consumes the output and produces a Geth trace builder. + pub fn into_geth_builder(self) -> GethTraceBuilder<'static> { + GethTraceBuilder::new(self.traces.into_nodes()) + } +} + +impl InspectorWithOutput> for TracingInspector { + type Output = TracingInspectorOutput; + + fn has_output(&self) -> bool { + !self.traces().nodes().is_empty() + } + + fn reset_output(&mut self) { + self.fuse(); + } + + fn take_output(&mut self) -> Self::Output { + let this = self.clone(); + self.fuse(); + TracingInspectorOutput::new(this.into_traces()) + } +} impl InspectorWithOutput> for FourByteInspector { type Output = FourByteFrame;