chore: remove InspectorStack (#8073)

This commit is contained in:
Matthias Seitz
2024-05-03 14:15:04 +02:00
committed by GitHub
parent 067b0ff420
commit 90f3161256
10 changed files with 15 additions and 334 deletions

1
Cargo.lock generated
View File

@ -7278,7 +7278,6 @@ dependencies = [
"reth-primitives",
"reth-provider",
"reth-prune",
"reth-revm",
"reth-rpc",
"reth-rpc-engine-api",
"reth-stages",

View File

@ -20,7 +20,6 @@ use reth_revm::{
batch::{BlockBatchRecord, BlockExecutorStats},
db::states::bundle_state::BundleRetention,
eth_dao_fork::{DAO_HARDFORK_BENEFICIARY, DAO_HARDKFORK_ACCOUNTS},
stack::InspectorStack,
state_change::{apply_beacon_root_contract_call, post_block_balance_increments},
Evm, State,
};
@ -36,7 +35,6 @@ use tracing::debug;
pub struct EthExecutorProvider<EvmConfig = EthEvmConfig> {
chain_spec: Arc<ChainSpec>,
evm_config: EvmConfig,
inspector: Option<InspectorStack>,
}
impl EthExecutorProvider {
@ -54,13 +52,7 @@ impl EthExecutorProvider {
impl<EvmConfig> EthExecutorProvider<EvmConfig> {
/// Creates a new executor provider.
pub fn new(chain_spec: Arc<ChainSpec>, evm_config: EvmConfig) -> Self {
Self { chain_spec, evm_config, inspector: None }
}
/// Configures an optional inspector stack for debugging.
pub fn with_inspector(mut self, inspector: Option<InspectorStack>) -> Self {
self.inspector = inspector;
self
Self { chain_spec, evm_config }
}
}
@ -78,7 +70,6 @@ where
self.evm_config.clone(),
State::builder().with_database(db).with_bundle_update().without_state_clear().build(),
)
.with_inspector(self.inspector.clone())
}
}
@ -221,20 +212,12 @@ pub struct EthBlockExecutor<EvmConfig, DB> {
executor: EthEvmExecutor<EvmConfig>,
/// The state to use for execution
state: State<DB>,
/// Optional inspector stack for debugging
inspector: Option<InspectorStack>,
}
impl<EvmConfig, DB> EthBlockExecutor<EvmConfig, DB> {
/// Creates a new Ethereum block executor.
pub fn new(chain_spec: Arc<ChainSpec>, evm_config: EvmConfig, state: State<DB>) -> Self {
Self { executor: EthEvmExecutor { chain_spec, evm_config }, state, inspector: None }
}
/// Sets the inspector stack for debugging.
pub fn with_inspector(mut self, inspector: Option<InspectorStack>) -> Self {
self.inspector = inspector;
self
Self { executor: EthEvmExecutor { chain_spec, evm_config }, state }
}
#[inline]
@ -292,19 +275,9 @@ where
let env = self.evm_env_for_block(&block.header, total_difficulty);
let (receipts, gas_used) = {
if let Some(inspector) = self.inspector.as_mut() {
let evm = self.executor.evm_config.evm_with_env_and_inspector(
&mut self.state,
env,
inspector,
);
self.executor.execute_pre_and_transactions(block, evm)?
} else {
let evm = self.executor.evm_config.evm_with_env(&mut self.state, env);
self.executor.execute_pre_and_transactions(block, evm)?
}
};
let evm = self.executor.evm_config.evm_with_env(&mut self.state, env);
self.executor.execute_pre_and_transactions(block, evm)
}?;
// 3. apply post execution changes
self.post_execution(block, total_difficulty)?;
@ -507,7 +480,7 @@ mod tests {
}
fn executor_provider(chain_spec: Arc<ChainSpec>) -> EthExecutorProvider<EthEvmConfig> {
EthExecutorProvider { chain_spec, evm_config: Default::default(), inspector: None }
EthExecutorProvider { chain_spec, evm_config: Default::default() }
}
#[test]

View File

@ -1,7 +1,7 @@
//! clap [Args](clap::Args) for debugging purposes
use clap::Args;
use reth_primitives::{TxHash, B256};
use reth_primitives::B256;
use std::path::PathBuf;
/// Parameters for debugging purposes
@ -28,37 +28,6 @@ pub struct DebugArgs {
#[arg(long = "debug.max-block", help_heading = "Debug")]
pub max_block: Option<u64>,
/// Print opcode level traces directly to console during execution.
#[arg(long = "debug.print-inspector", help_heading = "Debug")]
pub print_inspector: bool,
/// Hook on a specific block during execution.
#[arg(
long = "debug.hook-block",
help_heading = "Debug",
conflicts_with = "hook_transaction",
conflicts_with = "hook_all"
)]
pub hook_block: Option<u64>,
/// Hook on a specific transaction during execution.
#[arg(
long = "debug.hook-transaction",
help_heading = "Debug",
conflicts_with = "hook_block",
conflicts_with = "hook_all"
)]
pub hook_transaction: Option<TxHash>,
/// Hook on every transaction in a block.
#[arg(
long = "debug.hook-all",
help_heading = "Debug",
conflicts_with = "hook_block",
conflicts_with = "hook_transaction"
)]
pub hook_all: bool,
/// If provided, the engine will skip `n` consecutive FCUs.
#[arg(long = "debug.skip-fcu", help_heading = "Debug")]
pub skip_fcu: Option<usize>,

View File

@ -85,8 +85,7 @@ where
) -> eyre::Result<(Self::EVM, Self::Executor)> {
let chain_spec = ctx.chain_spec();
let evm_config = EthEvmConfig::default();
let executor =
EthExecutorProvider::new(chain_spec, evm_config).with_inspector(ctx.inspector_stack());
let executor = EthExecutorProvider::new(chain_spec, evm_config);
Ok((evm_config, executor))
}

View File

@ -19,7 +19,6 @@ reth-blockchain-tree.workspace = true
reth-exex.workspace = true
reth-evm.workspace = true
reth-provider.workspace = true
reth-revm.workspace = true
reth-db.workspace = true
reth-rpc-engine-api.workspace = true
reth-rpc.workspace = true

View File

@ -27,7 +27,6 @@ use reth_node_core::{
};
use reth_primitives::{constants::eip4844::MAINNET_KZG_TRUSTED_SETUP, ChainSpec};
use reth_provider::{providers::BlockchainProvider, ChainSpecProvider};
use reth_revm::stack::{InspectorStack, InspectorStackConfig};
use reth_tasks::TaskExecutor;
use reth_transaction_pool::{PoolConfig, TransactionPool};
pub use states::*;
@ -461,28 +460,6 @@ impl<Node: FullNodeTypes> BuilderContext<Node> {
&self.config
}
/// Returns an inspector stack if configured.
///
/// This can be used to debug block execution.
pub fn inspector_stack(&self) -> Option<InspectorStack> {
use reth_revm::stack::Hook;
let stack_config = InspectorStackConfig {
use_printer_tracer: self.config.debug.print_inspector,
hook: if let Some(hook_block) = self.config.debug.hook_block {
Hook::Block(hook_block)
} else if let Some(tx) = self.config.debug.hook_transaction {
Hook::Transaction(tx)
} else if self.config.debug.hook_all {
Hook::All
} else {
// no inspector
return None
},
};
Some(InspectorStack::new(stack_config))
}
/// Returns the data dir of the node.
///
/// This gives access to all relevant files and directories of the node's datadir.

View File

@ -19,7 +19,6 @@ use reth_primitives::{
use reth_revm::{
batch::{BlockBatchRecord, BlockExecutorStats},
db::states::bundle_state::BundleRetention,
stack::InspectorStack,
state_change::{apply_beacon_root_contract_call, post_block_balance_increments},
Evm, State,
};
@ -35,7 +34,6 @@ use tracing::{debug, trace};
pub struct OpExecutorProvider<EvmConfig = OptimismEvmConfig> {
chain_spec: Arc<ChainSpec>,
evm_config: EvmConfig,
inspector: Option<InspectorStack>,
}
impl OpExecutorProvider {
@ -48,13 +46,7 @@ impl OpExecutorProvider {
impl<EvmConfig> OpExecutorProvider<EvmConfig> {
/// Creates a new executor provider.
pub fn new(chain_spec: Arc<ChainSpec>, evm_config: EvmConfig) -> Self {
Self { chain_spec, evm_config, inspector: None }
}
/// Configures an optional inspector stack for debugging.
pub fn with_inspector(mut self, inspector: Option<InspectorStack>) -> Self {
self.inspector = inspector;
self
Self { chain_spec, evm_config }
}
}
@ -72,7 +64,6 @@ where
self.evm_config.clone(),
State::builder().with_database(db).with_bundle_update().without_state_clear().build(),
)
.with_inspector(self.inspector.clone())
}
}
@ -268,20 +259,12 @@ pub struct OpBlockExecutor<EvmConfig, DB> {
executor: OpEvmExecutor<EvmConfig>,
/// The state to use for execution
state: State<DB>,
/// Optional inspector stack for debugging
inspector: Option<InspectorStack>,
}
impl<EvmConfig, DB> OpBlockExecutor<EvmConfig, DB> {
/// Creates a new Ethereum block executor.
pub fn new(chain_spec: Arc<ChainSpec>, evm_config: EvmConfig, state: State<DB>) -> Self {
Self { executor: OpEvmExecutor { chain_spec, evm_config }, state, inspector: None }
}
/// Sets the inspector stack for debugging.
pub fn with_inspector(mut self, inspector: Option<InspectorStack>) -> Self {
self.inspector = inspector;
self
Self { executor: OpEvmExecutor { chain_spec, evm_config }, state }
}
#[inline]
@ -337,19 +320,9 @@ where
let env = self.evm_env_for_block(&block.header, total_difficulty);
let (receipts, gas_used) = {
if let Some(inspector) = self.inspector.as_mut() {
let evm = self.executor.evm_config.evm_with_env_and_inspector(
&mut self.state,
env,
inspector,
);
self.executor.execute_pre_and_transactions(block, evm)?
} else {
let evm = self.executor.evm_config.evm_with_env(&mut self.state, env);
self.executor.execute_pre_and_transactions(block, evm)?
}
};
let evm = self.executor.evm_config.evm_with_env(&mut self.state, env);
self.executor.execute_pre_and_transactions(block, evm)
}?;
// 3. apply post execution changes
self.post_execution(block, total_difficulty)?;
@ -548,7 +521,7 @@ mod tests {
}
fn executor_provider(chain_spec: Arc<ChainSpec>) -> OpExecutorProvider<OptimismEvmConfig> {
OpExecutorProvider { chain_spec, evm_config: Default::default(), inspector: None }
OpExecutorProvider { chain_spec, evm_config: Default::default() }
}
#[test]

View File

@ -105,8 +105,7 @@ where
) -> eyre::Result<(Self::EVM, Self::Executor)> {
let chain_spec = ctx.chain_spec();
let evm_config = OptimismEvmConfig::default();
let executor =
OpExecutorProvider::new(chain_spec, evm_config).with_inspector(ctx.inspector_stack());
let executor = OpExecutorProvider::new(chain_spec, evm_config);
Ok((evm_config, executor))
}

View File

@ -19,11 +19,6 @@ pub mod state_change;
/// Ethereum DAO hardfork state change data.
pub mod eth_dao_fork;
/// An inspector stack abstracting the implementation details of
/// each inspector and allowing to hook on block/transaction execution,
/// used in the main Reth executor.
pub mod stack;
/// Common test helpers
#[cfg(any(test, feature = "test-utils"))]
pub mod test_utils;

View File

@ -1,202 +0,0 @@
use revm::{
inspectors::CustomPrintTracer,
interpreter::{CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter},
primitives::{Address, Env, Log, B256, U256},
Database, EvmContext, Inspector,
};
use std::fmt::Debug;
/// A hook to inspect the execution of the EVM.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum Hook {
/// No hook.
#[default]
None,
/// Hook on a specific block.
Block(u64),
/// Hook on a specific transaction hash.
Transaction(B256),
/// Hooks on every transaction in a block.
All,
}
impl Hook {
/// Returns `true` if this hook should be used.
#[inline]
pub fn is_enabled(&self, block_number: u64, tx_hash: &B256) -> bool {
match self {
Hook::None => false,
Hook::Block(block) => block_number == *block,
Hook::Transaction(hash) => hash == tx_hash,
Hook::All => true,
}
}
}
/// An inspector that calls multiple inspectors in sequence.
#[derive(Clone, Default)]
pub struct InspectorStack {
/// An inspector that prints the opcode traces to the console.
pub custom_print_tracer: Option<CustomPrintTracer>,
/// The provided hook
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 {
/// Creates a new inspector stack with the given configuration.
#[inline]
pub fn new(config: InspectorStackConfig) -> Self {
Self {
hook: config.hook,
custom_print_tracer: config.use_printer_tracer.then(Default::default),
}
}
/// Returns `true` if this inspector should be used.
#[inline]
pub fn should_inspect(&self, env: &Env, tx_hash: &B256) -> bool {
self.custom_print_tracer.is_some() &&
self.hook.is_enabled(env.block.number.saturating_to(), tx_hash)
}
}
/// Configuration for the inspectors.
#[derive(Clone, Copy, Debug, Default)]
pub struct InspectorStackConfig {
/// Enable revm inspector printer.
/// In execution this will print opcode level traces directly to console.
pub use_printer_tracer: bool,
/// Hook on a specific block or transaction.
pub hook: Hook,
}
/// Helper macro to call the same method on multiple inspectors without resorting to dynamic
/// dispatch.
#[macro_export]
macro_rules! call_inspectors {
([$($inspector:expr),+ $(,)?], |$id:ident $(,)?| $call:expr $(,)?) => {{$(
if let Some($id) = $inspector {
$call
}
)+}}
}
impl<DB> Inspector<DB> for InspectorStack
where
DB: Database,
{
#[inline]
fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut EvmContext<DB>) {
call_inspectors!([&mut self.custom_print_tracer], |inspector| {
inspector.initialize_interp(interp, context);
});
}
#[inline]
fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext<DB>) {
call_inspectors!([&mut self.custom_print_tracer], |inspector| {
inspector.step(interp, context);
});
}
#[inline]
fn step_end(&mut self, interp: &mut Interpreter, context: &mut EvmContext<DB>) {
call_inspectors!([&mut self.custom_print_tracer], |inspector| {
inspector.step_end(interp, context);
});
}
#[inline]
fn log(&mut self, context: &mut EvmContext<DB>, log: &Log) {
call_inspectors!([&mut self.custom_print_tracer], |inspector| {
inspector.log(context, log);
});
}
#[inline]
fn call(
&mut self,
context: &mut EvmContext<DB>,
inputs: &mut CallInputs,
) -> Option<CallOutcome> {
call_inspectors!([&mut self.custom_print_tracer], |inspector| {
if let Some(outcome) = inspector.call(context, inputs) {
return Some(outcome)
}
});
None
}
#[inline]
fn call_end(
&mut self,
context: &mut EvmContext<DB>,
inputs: &CallInputs,
outcome: CallOutcome,
) -> CallOutcome {
call_inspectors!([&mut self.custom_print_tracer], |inspector| {
let new_ret = inspector.call_end(context, inputs, outcome.clone());
// If the inspector returns a different ret or a revert with a non-empty message,
// we assume it wants to tell us something
if new_ret != outcome {
return new_ret
}
});
outcome
}
#[inline]
fn create(
&mut self,
context: &mut EvmContext<DB>,
inputs: &mut CreateInputs,
) -> Option<CreateOutcome> {
call_inspectors!([&mut self.custom_print_tracer], |inspector| {
if let Some(out) = inspector.create(context, inputs) {
return Some(out)
}
});
None
}
#[inline]
fn create_end(
&mut self,
context: &mut EvmContext<DB>,
inputs: &CreateInputs,
outcome: CreateOutcome,
) -> CreateOutcome {
call_inspectors!([&mut self.custom_print_tracer], |inspector| {
let new_ret = inspector.create_end(context, inputs, outcome.clone());
// If the inspector returns a different ret or a revert with a non-empty message,
// we assume it wants to tell us something
if new_ret != outcome {
return new_ret
}
});
outcome
}
#[inline]
fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) {
call_inspectors!([&mut self.custom_print_tracer], |inspector| {
Inspector::<DB>::selfdestruct(inspector, contract, target, value);
});
}
}