diff --git a/Cargo.lock b/Cargo.lock index 4ad04cc2b3..34d31998a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4558,6 +4558,7 @@ dependencies = [ "reth-network-api", "reth-primitives", "reth-provider", + "reth-revm-inspectors", "reth-rlp", "reth-rpc", "reth-rpc-builder", diff --git a/bin/reth/Cargo.toml b/bin/reth/Cargo.toml index ff1aa0aed3..f1952517c5 100644 --- a/bin/reth/Cargo.toml +++ b/bin/reth/Cargo.toml @@ -12,6 +12,7 @@ reth-primitives = { path = "../../crates/primitives", features = ["arbitrary"] } reth-db = { path = "../../crates/storage/db", features = ["mdbx", "test-utils"] } # TODO: Temporary use of the test-utils feature reth-provider = { path = "../../crates/storage/provider", features = ["test-utils"] } +reth-revm-inspectors = { path = "../../crates/revm/revm-inspectors" } reth-staged-sync = { path = "../../crates/staged-sync" } reth-stages = { path = "../../crates/stages"} reth-interfaces = { path = "../../crates/interfaces", features = ["test-utils"] } diff --git a/bin/reth/src/node/mod.rs b/bin/reth/src/node/mod.rs index 4a3e426a96..bb3641f2ab 100644 --- a/bin/reth/src/node/mod.rs +++ b/bin/reth/src/node/mod.rs @@ -37,8 +37,9 @@ use reth_network::{ error::NetworkError, FetchClient, NetworkConfig, NetworkHandle, NetworkManager, }; use reth_network_api::NetworkInfo; -use reth_primitives::{BlockHashOrNumber, ChainSpec, Head, Header, SealedHeader, H256}; +use reth_primitives::{BlockHashOrNumber, ChainSpec, Head, Header, SealedHeader, TxHash, H256}; use reth_provider::{BlockProvider, HeaderProvider, ShareableDatabase}; +use reth_revm_inspectors::stack::Hook; use reth_rpc_engine_api::{EngineApi, EngineApiHandle}; use reth_staged_sync::{ utils::{ @@ -128,6 +129,33 @@ pub struct Command { #[clap(flatten)] rpc: RpcServerArgs, + + #[arg(long = "debug.print-inspector", help_heading = "Debug")] + print_inspector: bool, + + #[arg( + long = "debug.hook-block", + help_heading = "Debug", + conflicts_with = "hook_transaction", + conflicts_with = "hook_all" + )] + hook_block: Option, + + #[arg( + long = "debug.hook-transaction", + help_heading = "Debug", + conflicts_with = "hook_block", + conflicts_with = "hook_all" + )] + hook_transaction: Option, + + #[arg( + long = "debug.hook-all", + help_heading = "Debug", + conflicts_with = "hook_block", + conflicts_with = "hook_transaction" + )] + hook_all: bool, } impl Command { @@ -478,8 +506,24 @@ impl Command { } let (tip_tx, tip_rx) = watch::channel(H256::zero()); + use reth_revm_inspectors::stack::InspectorStackConfig; let factory = reth_executor::Factory::new(self.chain.clone()); + let stack_config = InspectorStackConfig { + use_printer_tracer: self.print_inspector, + hook: if let Some(hook_block) = self.hook_block { + Hook::Block(hook_block) + } else if let Some(tx) = self.hook_transaction { + Hook::Transaction(tx) + } else if self.hook_all { + Hook::All + } else { + Hook::None + }, + }; + + let factory = factory.with_stack_config(stack_config); + let header_mode = if continuous { HeaderSyncMode::Continuous } else { HeaderSyncMode::Tip(tip_rx) }; let pipeline = builder diff --git a/crates/executor/src/factory.rs b/crates/executor/src/factory.rs index 5bd59d0297..43ce58ebe2 100644 --- a/crates/executor/src/factory.rs +++ b/crates/executor/src/factory.rs @@ -1,6 +1,9 @@ use reth_primitives::ChainSpec; use reth_provider::{ExecutorFactory, StateProvider}; -use reth_revm::database::{State, SubState}; +use reth_revm::{ + database::{State, SubState}, + stack::{InspectorStack, InspectorStackConfig}, +}; use crate::executor::Executor; use std::sync::Arc; @@ -9,12 +12,25 @@ use std::sync::Arc; #[derive(Clone, Debug)] pub struct Factory { chain_spec: Arc, + stack: Option, } impl Factory { /// Create new factory pub fn new(chain_spec: Arc) -> Self { - Self { chain_spec } + Self { chain_spec, stack: None } + } + + /// Sets the inspector stack for all generated executors. + pub fn with_stack(mut self, stack: InspectorStack) -> Self { + self.stack = Some(stack); + self + } + + /// Sets the inspector stack for all generated executors using the provided config. + pub fn with_stack_config(mut self, config: InspectorStackConfig) -> Self { + self.stack = Some(InspectorStack::new(config)); + self } } @@ -24,7 +40,12 @@ impl ExecutorFactory for Factory { /// Executor with [`StateProvider`] fn with_sp(&self, sp: SP) -> Self::Executor { let substate = SubState::new(State::new(sp)); - Executor::new(self.chain_spec.clone(), substate) + + let mut executor = Executor::new(self.chain_spec.clone(), substate); + if let Some(ref stack) = self.stack { + executor = executor.with_stack(stack.clone()); + } + executor } /// Return internal chainspec diff --git a/crates/revm/revm-inspectors/src/stack/mod.rs b/crates/revm/revm-inspectors/src/stack/mod.rs index 5a37169e2f..4490c88891 100644 --- a/crates/revm/revm-inspectors/src/stack/mod.rs +++ b/crates/revm/revm-inspectors/src/stack/mod.rs @@ -1,3 +1,5 @@ +use std::fmt::Debug; + use reth_primitives::{bytes::Bytes, Address, TxHash, H256}; use revm::{ inspectors::CustomPrintTracer, @@ -14,7 +16,7 @@ pub use maybe_owned::MaybeOwnedInspector; /// - Block: Hook on block execution /// - BlockWithIndex: Hook on block execution transaction index /// - Transaction: Hook on a specific transaction hash -#[derive(Default, Clone)] +#[derive(Debug, Default, Clone)] pub enum Hook { #[default] /// No hook. @@ -39,6 +41,15 @@ pub struct InspectorStack { pub hook: Hook, } +impl Debug for InspectorStack { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("InspectorStack") + .field("custom_print_tracer", &self.custom_print_tracer.is_some()) + .field("hook", &self.hook) + .finish() + } +} + impl InspectorStack { /// Create a new inspector stack. pub fn new(config: InspectorStackConfig) -> Self {