diff --git a/crates/revm/revm-inspectors/src/tracing/builder/geth.rs b/crates/revm/revm-inspectors/src/tracing/builder/geth.rs index b6cbc7c00..f65ef8126 100644 --- a/crates/revm/revm-inspectors/src/tracing/builder/geth.rs +++ b/crates/revm/revm-inspectors/src/tracing/builder/geth.rs @@ -46,7 +46,7 @@ impl GethTraceBuilder { while let Some(CallTraceStepStackItem { trace_node, step, call_child_id }) = step_stack.pop_back() { - let mut log: StructLog = step.into(); + let mut log = step.convert_to_geth_struct_log(opts); // Fill in memory and storage depending on the options if !opts.disable_storage.unwrap_or_default() { @@ -56,13 +56,6 @@ impl GethTraceBuilder { log.storage = Some(contract_storage.clone()); } } - if opts.disable_stack.unwrap_or_default() { - log.stack = None; - } - - if !opts.enable_memory.unwrap_or_default() { - log.memory = None; - } if opts.enable_return_data.unwrap_or_default() { log.return_data = trace_node.trace.last_call_return_value.clone().map(Into::into); diff --git a/crates/revm/revm-inspectors/src/tracing/types.rs b/crates/revm/revm-inspectors/src/tracing/types.rs index 700c445f8..e651eefac 100644 --- a/crates/revm/revm-inspectors/src/tracing/types.rs +++ b/crates/revm/revm-inspectors/src/tracing/types.rs @@ -3,7 +3,7 @@ use crate::tracing::utils::convert_memory; use reth_primitives::{abi::decode_revert_reason, bytes::Bytes, Address, H256, U256}; use reth_rpc_types::trace::{ - geth::{CallFrame, CallLogFrame, StructLog}, + geth::{CallFrame, CallLogFrame, GethDefaultTracingOptions, StructLog}, parity::{ Action, ActionType, CallAction, CallOutput, CallType, ChangedType, CreateAction, CreateOutput, Delta, SelfdestructAction, StateDiff, TraceOutput, TraceResult, @@ -423,73 +423,88 @@ pub(crate) struct RawLog { /// Represents a tracked call step during execution #[derive(Clone, Debug, PartialEq, Eq)] -pub struct CallTraceStep { +pub(crate) struct CallTraceStep { // Fields filled in `step` /// Call depth - pub depth: u64, + pub(crate) depth: u64, /// Program counter before step execution - pub pc: usize, + pub(crate) pc: usize, /// Opcode to be executed - pub op: OpCode, + pub(crate) op: OpCode, /// Current contract address - pub contract: Address, + pub(crate) contract: Address, /// Stack before step execution - pub stack: Stack, + pub(crate) stack: Stack, /// Memory before step execution - pub memory: Memory, + pub(crate) memory: Memory, /// Size of memory - pub memory_size: usize, + pub(crate) memory_size: usize, /// Remaining gas before step execution - pub gas: u64, + pub(crate) gas: u64, /// Gas refund counter before step execution - pub gas_refund_counter: u64, + pub(crate) gas_refund_counter: u64, // Fields filled in `step_end` /// Gas cost of step execution - pub gas_cost: u64, + pub(crate) gas_cost: u64, /// Change of the contract state after step execution (effect of the SLOAD/SSTORE instructions) - pub storage_change: Option, + pub(crate) storage_change: Option, /// Final status of the call - pub status: InstructionResult, + pub(crate) status: InstructionResult, } // === impl CallTraceStep === impl CallTraceStep { + /// Converts this step into a geth [StructLog] + /// + /// This sets memory and stack capture based on the `opts` parameter. + pub(crate) fn convert_to_geth_struct_log(&self, opts: &GethDefaultTracingOptions) -> StructLog { + let mut log = StructLog { + depth: self.depth, + error: self.as_error(), + gas: self.gas, + gas_cost: self.gas_cost, + op: self.op.to_string(), + pc: self.pc as u64, + refund_counter: (self.gas_refund_counter > 0).then_some(self.gas_refund_counter), + // Filled, if not disabled manually + stack: None, + // Filled in `CallTraceArena::geth_trace` as a result of compounding all slot changes + return_data: None, + // Filled via trace object + storage: None, + // Only enabled if `opts.enable_memory` is true + memory: None, + // This is None in the rpc response + memory_size: None, + }; + + if opts.is_stack_enabled() { + log.stack = Some(self.stack.data().clone()); + } + + if opts.is_memory_enabled() { + log.memory = Some(convert_memory(self.memory.data())); + } + + log + } + // Returns true if the status code is an error or revert, See [InstructionResult::Revert] - pub fn is_error(&self) -> bool { + pub(crate) fn is_error(&self) -> bool { self.status as u8 >= InstructionResult::Revert as u8 } /// Returns the error message if it is an erroneous result. - pub fn as_error(&self) -> Option { + pub(crate) fn as_error(&self) -> Option { self.is_error().then(|| format!("{:?}", self.status)) } } -impl From<&CallTraceStep> for StructLog { - fn from(step: &CallTraceStep) -> Self { - StructLog { - depth: step.depth, - error: step.as_error(), - gas: step.gas, - gas_cost: step.gas_cost, - memory: Some(convert_memory(step.memory.data())), - op: step.op.to_string(), - pc: step.pc as u64, - refund_counter: (step.gas_refund_counter > 0).then_some(step.gas_refund_counter), - stack: Some(step.stack.data().clone()), - // Filled in `CallTraceArena::geth_trace` as a result of compounding all slot changes - return_data: None, - storage: None, - memory_size: Some(step.memory_size as u64), - } - } -} - /// Represents a storage change during execution #[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct StorageChange { - pub key: U256, - pub value: U256, - pub had_value: Option, +pub(crate) struct StorageChange { + pub(crate) key: U256, + pub(crate) value: U256, + pub(crate) had_value: Option, } diff --git a/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs b/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs index 1caeffc7e..a9c99b8f2 100644 --- a/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs +++ b/crates/rpc/rpc-types/src/eth/trace/geth/mod.rs @@ -316,6 +316,28 @@ pub struct GethDefaultTracingOptions { pub limit: Option, } +impl GethDefaultTracingOptions { + /// Returns `true` if return data capture is enabled + pub fn is_return_data_enabled(&self) -> bool { + self.enable_return_data.unwrap_or(false) + } + + /// Returns `true` if memory capture is enabled + pub fn is_memory_enabled(&self) -> bool { + self.enable_memory.unwrap_or(false) + } + + /// Returns `true` if stack capture is enabled + pub fn is_stack_enabled(&self) -> bool { + !self.disable_stack.unwrap_or(false) + } + + /// Returns `true` if storage capture is enabled + pub fn is_storage_enabled(&self) -> bool { + !self.disable_storage.unwrap_or(false) + } +} + /// Bindings for additional `debug_traceCall` options /// /// See