diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs index 67709ca2e047..66856f9ac3f6 100644 --- a/crates/ethereum/evm/src/execute.rs +++ b/crates/ethereum/evm/src/execute.rs @@ -31,7 +31,7 @@ use reth_revm::{ BundleAccount, State, }, state_change::post_block_balance_increments, - Evm, + Evm, State }; use revm_primitives::{ db::{Database, DatabaseCommit}, @@ -382,7 +382,13 @@ where // NOTE: we need to merge keep the reverts for the bundle retention self.state.merge_transitions(BundleRetention::Reverts); - Ok(BlockExecutionOutput { state: self.state.take_bundle(), receipts, requests, gas_used }) + Ok(BlockExecutionOutput { + state: self.state.take_bundle(), + cache: core::mem::take(&mut self.state.cache), + receipts, + requests, + gas_used, + }) } } diff --git a/crates/evm/execution-types/src/execute.rs b/crates/evm/execution-types/src/execute.rs index 2933fd59815f..d197cb5001c1 100644 --- a/crates/evm/execution-types/src/execute.rs +++ b/crates/evm/execution-types/src/execute.rs @@ -1,5 +1,5 @@ use reth_primitives::{Request, U256}; -use revm::db::BundleState; +use revm::{db::BundleState, CacheState}; /// A helper type for ethereum block inputs that consists of a block and the total difficulty. #[derive(Debug)] @@ -30,6 +30,8 @@ impl<'a, Block> From<(&'a Block, U256)> for BlockExecutionInput<'a, Block> { pub struct BlockExecutionOutput { /// The changed state of the block after execution. pub state: BundleState, + /// cache state of the block after execution. + pub cache: CacheState, /// All the receipts of the transactions in the block. pub receipts: Vec, /// All the EIP-7685 requests of the transactions in the block. diff --git a/crates/evm/src/test_utils.rs b/crates/evm/src/test_utils.rs index c3aa34a56a45..f535e7840eb4 100644 --- a/crates/evm/src/test_utils.rs +++ b/crates/evm/src/test_utils.rs @@ -55,6 +55,7 @@ impl Executor for MockExecutorProvider { self.exec_results.lock().pop().unwrap(); Ok(BlockExecutionOutput { state: bundle, + cache: Default::default(), receipts: receipts.into_iter().flatten().flatten().collect(), requests: requests.into_iter().flatten().collect(), gas_used: 0, diff --git a/crates/node/builder/src/rpc.rs b/crates/node/builder/src/rpc.rs index 64ce0b8ffa89..cae9f15fa703 100644 --- a/crates/node/builder/src/rpc.rs +++ b/crates/node/builder/src/rpc.rs @@ -192,6 +192,7 @@ pub struct RpcRegistry { TaskExecutor, Node::Provider, EthApi, + Node::Executor, >, } @@ -207,6 +208,7 @@ where TaskExecutor, Node::Provider, EthApi, + Node::Executor, >; fn deref(&self) -> &Self::Target { @@ -322,6 +324,7 @@ where .with_events(node.provider().clone()) .with_executor(node.task_executor().clone()) .with_evm_config(node.evm_config().clone()) + .with_block_executor(node.block_executor().clone()) .build_with_auth_server(module_config, engine_api, EthApi::eth_api_builder()); let mut registry = RpcRegistry { registry }; diff --git a/crates/optimism/evm/src/execute.rs b/crates/optimism/evm/src/execute.rs index d921b817659e..2d9bbc10ead6 100644 --- a/crates/optimism/evm/src/execute.rs +++ b/crates/optimism/evm/src/execute.rs @@ -364,6 +364,7 @@ where Ok(BlockExecutionOutput { state: self.state.take_bundle(), + cache: core::mem::take(&mut self.state.cache), receipts, requests: vec![], gas_used, diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index 53802e5221a6..a2777d79e024 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -16,7 +16,7 @@ //! Configure only an http server with a selection of [`RethRpcModule`]s //! //! ``` -//! use reth_evm::ConfigureEvm; +//! use reth_evm::{execute::BlockExecutorProvider, ConfigureEvm}; //! use reth_network_api::{NetworkInfo, Peers}; //! use reth_provider::{AccountReader, CanonStateSubscriptions, ChangeSetReader, FullRpcProvider}; //! use reth_rpc::EthApi; @@ -26,18 +26,20 @@ //! use reth_tasks::TokioTaskExecutor; //! use reth_transaction_pool::TransactionPool; //! -//! pub async fn launch( +//! pub async fn launch( //! provider: Provider, //! pool: Pool, //! network: Network, //! events: Events, //! evm_config: EvmConfig, +//! block_executor: BlockExecutor, //! ) where //! Provider: FullRpcProvider + AccountReader + ChangeSetReader, //! Pool: TransactionPool + 'static, //! Network: NetworkInfo + Peers + Clone + 'static, //! Events: CanonStateSubscriptions + Clone + 'static, //! EvmConfig: ConfigureEvm, +//! BlockExecutor: BlockExecutorProvider, //! { //! // configure the rpc module per transport //! let transports = TransportRpcModuleConfig::default().with_http(vec![ @@ -53,6 +55,7 @@ //! TokioTaskExecutor::default(), //! events, //! evm_config, +//! block_executor, //! ) //! .build(transports, Box::new(EthApi::with_spawner)); //! let handle = RpcServerConfig::default() @@ -67,7 +70,7 @@ //! //! ``` //! use reth_engine_primitives::EngineTypes; -//! use reth_evm::ConfigureEvm; +//! use reth_evm::{execute::BlockExecutorProvider, ConfigureEvm}; //! use reth_network_api::{NetworkInfo, Peers}; //! use reth_provider::{AccountReader, CanonStateSubscriptions, ChangeSetReader, FullRpcProvider}; //! use reth_rpc::EthApi; @@ -80,13 +83,23 @@ //! use reth_tasks::TokioTaskExecutor; //! use reth_transaction_pool::TransactionPool; //! use tokio::try_join; -//! pub async fn launch( +//! pub async fn launch< +//! Provider, +//! Pool, +//! Network, +//! Events, +//! EngineApi, +//! EngineT, +//! EvmConfig, +//! BlockExecutor, +//! >( //! provider: Provider, //! pool: Pool, //! network: Network, //! events: Events, //! engine_api: EngineApi, //! evm_config: EvmConfig, +//! block_executor: BlockExecutor, //! ) where //! Provider: FullRpcProvider + AccountReader + ChangeSetReader, //! Pool: TransactionPool + 'static, @@ -95,6 +108,7 @@ //! EngineApi: EngineApiServer, //! EngineT: EngineTypes, //! EvmConfig: ConfigureEvm, +//! BlockExecutor: BlockExecutorProvider, //! { //! // configure the rpc module per transport //! let transports = TransportRpcModuleConfig::default().with_http(vec![ @@ -110,6 +124,7 @@ //! TokioTaskExecutor::default(), //! events, //! evm_config, +//! block_executor, //! ); //! //! // configure the server modules @@ -152,7 +167,7 @@ use jsonrpsee::{ }; use reth_chainspec::ChainSpec; use reth_engine_primitives::EngineTypes; -use reth_evm::ConfigureEvm; +use reth_evm::{execute::BlockExecutorProvider, ConfigureEvm}; use reth_network_api::{noop::NoopNetwork, NetworkInfo, Peers}; use reth_provider::{ AccountReader, BlockReader, CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader, @@ -211,7 +226,7 @@ use reth_node_core::rpc::types::AnyTransactionReceipt; /// Convenience function for starting a server in one step. #[allow(clippy::too_many_arguments)] -pub async fn launch( +pub async fn launch( provider: Provider, pool: Pool, network: Network, @@ -221,6 +236,7 @@ pub async fn launch( events: Events, evm_config: EvmConfig, eth: DynEthApiBuilder, + block_executor: BlockExecutor, ) -> Result where Provider: FullRpcProvider + AccountReader + ChangeSetReader, @@ -232,13 +248,22 @@ where EthApi: FullEthApiServer< NetworkTypes: alloy_network::Network, >, + BlockExecutor: BlockExecutorProvider, { let module_config = module_config.into(); server_config .into() .start( - &RpcModuleBuilder::new(provider, pool, network, executor, events, evm_config) - .build(module_config, eth), + &RpcModuleBuilder::new( + provider, + pool, + network, + executor, + events, + evm_config, + block_executor, + ) + .build(module_config, eth), ) .await } @@ -247,7 +272,7 @@ where /// /// This is the main entrypoint and the easiest way to configure an RPC server. #[derive(Debug, Clone)] -pub struct RpcModuleBuilder { +pub struct RpcModuleBuilder { /// The Provider type to when creating all rpc handlers provider: Provider, /// The Pool type to when creating all rpc handlers @@ -260,12 +285,14 @@ pub struct RpcModuleBuilder { events: Events, /// Defines how the EVM should be configured before execution. evm_config: EvmConfig, + /// The provider for getting a block executor that executes blocks + block_executor: BlockExecutor, } // === impl RpcBuilder === -impl - RpcModuleBuilder +impl + RpcModuleBuilder { /// Create a new instance of the builder pub const fn new( @@ -275,32 +302,33 @@ impl executor: Tasks, events: Events, evm_config: EvmConfig, + block_executor: BlockExecutor, ) -> Self { - Self { provider, pool, network, executor, events, evm_config } + Self { provider, pool, network, executor, events, evm_config, block_executor } } /// Configure the provider instance. pub fn with_provider

( self, provider: P, - ) -> RpcModuleBuilder + ) -> RpcModuleBuilder where P: BlockReader + StateProviderFactory + EvmEnvProvider + 'static, { - let Self { pool, network, executor, events, evm_config, .. } = self; - RpcModuleBuilder { provider, network, pool, executor, events, evm_config } + let Self { pool, network, executor, events, evm_config, block_executor, .. } = self; + RpcModuleBuilder { provider, network, pool, executor, events, evm_config, block_executor } } /// Configure the transaction pool instance. pub fn with_pool

( self, pool: P, - ) -> RpcModuleBuilder + ) -> RpcModuleBuilder where P: TransactionPool + 'static, { - let Self { provider, network, executor, events, evm_config, .. } = self; - RpcModuleBuilder { provider, network, pool, executor, events, evm_config } + let Self { provider, network, executor, events, evm_config, block_executor, .. } = self; + RpcModuleBuilder { provider, network, pool, executor, events, evm_config, block_executor } } /// Configure a [`NoopTransactionPool`] instance. @@ -310,8 +338,16 @@ impl /// [`EthApi`](reth_rpc::eth::EthApi) which requires a [`TransactionPool`] implementation. pub fn with_noop_pool( self, - ) -> RpcModuleBuilder { - let Self { provider, executor, events, network, evm_config, .. } = self; + ) -> RpcModuleBuilder< + Provider, + NoopTransactionPool, + Network, + Tasks, + Events, + EvmConfig, + BlockExecutor, + > { + let Self { provider, executor, events, network, evm_config, block_executor, .. } = self; RpcModuleBuilder { provider, executor, @@ -319,6 +355,7 @@ impl network, evm_config, pool: NoopTransactionPool::default(), + block_executor, } } @@ -326,12 +363,12 @@ impl pub fn with_network( self, network: N, - ) -> RpcModuleBuilder + ) -> RpcModuleBuilder where N: NetworkInfo + Peers + 'static, { - let Self { provider, pool, executor, events, evm_config, .. } = self; - RpcModuleBuilder { provider, network, pool, executor, events, evm_config } + let Self { provider, pool, executor, events, evm_config, block_executor, .. } = self; + RpcModuleBuilder { provider, network, pool, executor, events, evm_config, block_executor } } /// Configure a [`NoopNetwork`] instance. @@ -341,8 +378,9 @@ impl /// [`EthApi`](reth_rpc::eth::EthApi) which requires a [`NetworkInfo`] implementation. pub fn with_noop_network( self, - ) -> RpcModuleBuilder { - let Self { provider, pool, executor, events, evm_config, .. } = self; + ) -> RpcModuleBuilder + { + let Self { provider, pool, executor, events, evm_config, block_executor, .. } = self; RpcModuleBuilder { provider, pool, @@ -350,6 +388,7 @@ impl events, network: NoopNetwork::default(), evm_config, + block_executor, } } @@ -357,12 +396,12 @@ impl pub fn with_executor( self, executor: T, - ) -> RpcModuleBuilder + ) -> RpcModuleBuilder where T: TaskSpawner + 'static, { - let Self { pool, network, provider, events, evm_config, .. } = self; - RpcModuleBuilder { provider, network, pool, executor, events, evm_config } + let Self { pool, network, provider, events, evm_config, block_executor, .. } = self; + RpcModuleBuilder { provider, network, pool, executor, events, evm_config, block_executor } } /// Configure [`TokioTaskExecutor`] as the task executor to use for additional tasks. @@ -371,8 +410,16 @@ impl /// [`TokioTaskExecutor`]. pub fn with_tokio_executor( self, - ) -> RpcModuleBuilder { - let Self { pool, network, provider, events, evm_config, .. } = self; + ) -> RpcModuleBuilder< + Provider, + Pool, + Network, + TokioTaskExecutor, + Events, + EvmConfig, + BlockExecutor, + > { + let Self { pool, network, provider, events, evm_config, block_executor, .. } = self; RpcModuleBuilder { provider, network, @@ -380,6 +427,7 @@ impl events, executor: TokioTaskExecutor::default(), evm_config, + block_executor, } } @@ -387,29 +435,41 @@ impl pub fn with_events( self, events: E, - ) -> RpcModuleBuilder + ) -> RpcModuleBuilder where E: CanonStateSubscriptions + 'static, { - let Self { provider, pool, executor, network, evm_config, .. } = self; - RpcModuleBuilder { provider, network, pool, executor, events, evm_config } + let Self { provider, pool, executor, network, evm_config, block_executor, .. } = self; + RpcModuleBuilder { provider, network, pool, executor, events, evm_config, block_executor } } /// Configure the evm configuration type pub fn with_evm_config( self, evm_config: E, - ) -> RpcModuleBuilder + ) -> RpcModuleBuilder where E: ConfigureEvm + 'static, { - let Self { provider, pool, executor, network, events, .. } = self; - RpcModuleBuilder { provider, network, pool, executor, events, evm_config } + let Self { provider, pool, executor, network, events, block_executor, .. } = self; + RpcModuleBuilder { provider, network, pool, executor, events, evm_config, block_executor } + } + + /// Configure the block executor provider + pub fn with_block_executor( + self, + block_executor: BE, + ) -> RpcModuleBuilder + where + BE: BlockExecutorProvider, + { + let Self { provider, network, pool, executor, events, evm_config, .. } = self; + RpcModuleBuilder { provider, network, pool, executor, events, evm_config, block_executor } } } -impl - RpcModuleBuilder +impl + RpcModuleBuilder where Provider: FullRpcProvider + AccountReader + ChangeSetReader, Pool: TransactionPool + 'static, @@ -417,6 +477,7 @@ where Tasks: TaskSpawner + Clone + 'static, Events: CanonStateSubscriptions + Clone + 'static, EvmConfig: ConfigureEvm, + BlockExecutor: BlockExecutorProvider, { /// Configures all [`RpcModule`]s specific to the given [`TransportRpcModuleConfig`] which can /// be used to start the transport server(s). @@ -433,7 +494,7 @@ where ) -> ( TransportRpcModules, AuthRpcModule, - RpcRegistryInner, + RpcRegistryInner, ) where EngineT: EngineTypes, @@ -442,12 +503,20 @@ where NetworkTypes: alloy_network::Network, >, { - let Self { provider, pool, network, executor, events, evm_config } = self; + let Self { provider, pool, network, executor, events, evm_config, block_executor } = self; let config = module_config.config.clone().unwrap_or_default(); let mut registry = RpcRegistryInner::new( - provider, pool, network, executor, events, config, evm_config, eth, + provider, + pool, + network, + executor, + events, + config, + evm_config, + eth, + block_executor, ); let modules = registry.create_transport_rpc_modules(module_config); @@ -466,6 +535,7 @@ where /// /// ```no_run /// use reth_evm::ConfigureEvm; + /// use reth_evm_ethereum::execute::EthExecutorProvider; /// use reth_network_api::noop::NoopNetwork; /// use reth_provider::test_utils::{NoopProvider, TestCanonStateSubscriptions}; /// use reth_rpc::EthApi; @@ -481,6 +551,7 @@ where /// .with_executor(TokioTaskExecutor::default()) /// .with_events(TestCanonStateSubscriptions::default()) /// .with_evm_config(evm) + /// .with_block_executor(EthExecutorProvider::mainnet()) /// .into_registry(Default::default(), Box::new(EthApi::with_spawner)); /// /// let eth_api = registry.eth_api(); @@ -490,12 +561,22 @@ where self, config: RpcModuleConfig, eth: DynEthApiBuilder, - ) -> RpcRegistryInner + ) -> RpcRegistryInner where EthApi: 'static, { - let Self { provider, pool, network, executor, events, evm_config } = self; - RpcRegistryInner::new(provider, pool, network, executor, events, config, evm_config, eth) + let Self { provider, pool, network, executor, events, evm_config, block_executor } = self; + RpcRegistryInner::new( + provider, + pool, + network, + executor, + events, + config, + evm_config, + eth, + block_executor, + ) } /// Configures all [`RpcModule`]s specific to the given [`TransportRpcModuleConfig`] which can @@ -512,7 +593,7 @@ where { let mut modules = TransportRpcModules::default(); - let Self { provider, pool, network, executor, events, evm_config } = self; + let Self { provider, pool, network, executor, events, evm_config, block_executor } = self; if !module_config.is_empty() { let TransportRpcModuleConfig { http, ws, ipc, config } = module_config.clone(); @@ -526,6 +607,7 @@ where config.unwrap_or_default(), evm_config, eth, + block_executor, ); modules.config = module_config; @@ -538,9 +620,9 @@ where } } -impl Default for RpcModuleBuilder<(), (), (), (), (), ()> { +impl Default for RpcModuleBuilder<(), (), (), (), (), (), ()> { fn default() -> Self { - Self::new((), (), (), (), (), ()) + Self::new((), (), (), (), (), (), ()) } } @@ -614,12 +696,13 @@ impl RpcModuleConfigBuilder { /// A Helper type the holds instances of the configured modules. #[derive(Debug, Clone)] -pub struct RpcRegistryInner { +pub struct RpcRegistryInner { provider: Provider, pool: Pool, network: Network, executor: Tasks, events: Events, + block_executor: BlockExecutor, /// Holds a all `eth_` namespace handlers eth: EthHandlers, /// to put trace calls behind semaphore @@ -630,8 +713,8 @@ pub struct RpcRegistryInner { // === impl RpcRegistryInner === -impl - RpcRegistryInner +impl + RpcRegistryInner where Provider: StateProviderFactory + BlockReader + EvmEnvProvider + Clone + Unpin + 'static, Pool: Send + Sync + Clone + 'static, @@ -639,6 +722,7 @@ where Events: CanonStateSubscriptions + Clone + 'static, Tasks: TaskSpawner + Clone + 'static, EthApi: 'static, + BlockExecutor: BlockExecutorProvider, { /// Creates a new, empty instance. #[allow(clippy::too_many_arguments)] @@ -659,6 +743,7 @@ where Events, EthApi, >, + block_executor: BlockExecutor, ) -> Self where EvmConfig: ConfigureEvm, @@ -686,12 +771,13 @@ where modules: Default::default(), blocking_pool_guard, events, + block_executor, } } } -impl - RpcRegistryInner +impl + RpcRegistryInner { /// Returns a reference to the installed [`EthApi`](reth_rpc::eth::EthApi). pub const fn eth_api(&self) -> &EthApi { @@ -746,8 +832,8 @@ impl } } -impl - RpcRegistryInner +impl + RpcRegistryInner where Network: NetworkInfo + Clone + 'static, Provider: ChainSpecProvider, @@ -783,13 +869,14 @@ where } } -impl - RpcRegistryInner +impl + RpcRegistryInner where Provider: FullRpcProvider + AccountReader + ChangeSetReader, Network: NetworkInfo + Peers + Clone + 'static, Tasks: TaskSpawner + Clone + 'static, EthApi: Clone, + BlockExecutor: BlockExecutorProvider, { /// Register Eth Namespace /// @@ -943,12 +1030,17 @@ where /// # Panics /// /// If called outside of the tokio runtime. See also [`Self::eth_api`] - pub fn debug_api(&self) -> DebugApi + pub fn debug_api(&self) -> DebugApi where EthApi: EthApiSpec + EthTransactions + TraceExt, + BlockExecutor: BlockExecutorProvider, { - let eth_api = self.eth_api().clone(); - DebugApi::new(self.provider.clone(), eth_api, self.blocking_pool_guard.clone()) + DebugApi::new( + self.provider.clone(), + self.eth_api().clone(), + self.block_executor.clone(), + self.blocking_pool_guard.clone(), + ) } /// Instantiates `NetApi` @@ -970,8 +1062,8 @@ where } } -impl - RpcRegistryInner +impl + RpcRegistryInner where Provider: FullRpcProvider + AccountReader + ChangeSetReader, Pool: TransactionPool + 'static, @@ -981,6 +1073,7 @@ where EthApi: FullEthApiServer< NetworkTypes: alloy_network::Network, >, + BlockExecutor: BlockExecutorProvider, { /// Configures the auth module that includes the /// * `engine_` namespace @@ -1072,6 +1165,7 @@ where RethRpcModule::Debug => DebugApi::new( self.provider.clone(), eth_api.clone(), + self.block_executor.clone(), self.blocking_pool_guard.clone(), ) .into_rpc() @@ -1680,7 +1774,7 @@ impl TransportRpcModules { /// Returns [Ok(false)] if no http transport is configured. pub fn merge_http(&mut self, other: impl Into) -> Result { if let Some(ref mut http) = self.http { - return http.merge(other.into()).map(|_| true) + return http.merge(other.into()).map(|_| true); } Ok(false) } @@ -1692,7 +1786,7 @@ impl TransportRpcModules { /// Returns [Ok(false)] if no ws transport is configured. pub fn merge_ws(&mut self, other: impl Into) -> Result { if let Some(ref mut ws) = self.ws { - return ws.merge(other.into()).map(|_| true) + return ws.merge(other.into()).map(|_| true); } Ok(false) } @@ -1704,7 +1798,7 @@ impl TransportRpcModules { /// Returns [Ok(false)] if no ipc transport is configured. pub fn merge_ipc(&mut self, other: impl Into) -> Result { if let Some(ref mut ipc) = self.ipc { - return ipc.merge(other.into()).map(|_| true) + return ipc.merge(other.into()).map(|_| true); } Ok(false) } diff --git a/crates/rpc/rpc-builder/tests/it/utils.rs b/crates/rpc/rpc-builder/tests/it/utils.rs index ee7a064abda0..5a51943f3175 100644 --- a/crates/rpc/rpc-builder/tests/it/utils.rs +++ b/crates/rpc/rpc-builder/tests/it/utils.rs @@ -3,10 +3,13 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use reth_beacon_consensus::BeaconConsensusEngineHandle; use reth_chainspec::MAINNET; use reth_ethereum_engine_primitives::EthEngineTypes; -use reth_evm_ethereum::EthEvmConfig; +use reth_evm_ethereum::{execute::EthExecutorProvider, EthEvmConfig}; use reth_network_api::noop::NoopNetwork; use reth_payload_builder::test_utils::spawn_test_payload_service; -use reth_provider::test_utils::{NoopProvider, TestCanonStateSubscriptions}; +use reth_provider::{ + test_utils::{NoopProvider, TestCanonStateSubscriptions}, + ChainSpecProvider, +}; use reth_rpc::EthApi; use reth_rpc_builder::{ auth::{AuthRpcModule, AuthServerConfig, AuthServerHandle}, @@ -123,12 +126,15 @@ pub fn test_rpc_builder() -> RpcModuleBuilder< TokioTaskExecutor, TestCanonStateSubscriptions, EthEvmConfig, + EthExecutorProvider, > { + let provider = NoopProvider::default(); RpcModuleBuilder::default() - .with_provider(NoopProvider::default()) + .with_provider(provider) .with_pool(TestPoolBuilder::default().into()) .with_network(NoopNetwork::default()) .with_executor(TokioTaskExecutor::default()) .with_events(TestCanonStateSubscriptions::default()) .with_evm_config(EthEvmConfig::new(MAINNET.clone())) + .with_block_executor(EthExecutorProvider::ethereum(provider.chain_spec())) } diff --git a/crates/rpc/rpc/src/debug.rs b/crates/rpc/rpc/src/debug.rs index 95af81a7bd86..2352b866c335 100644 --- a/crates/rpc/rpc/src/debug.rs +++ b/crates/rpc/rpc/src/debug.rs @@ -4,7 +4,7 @@ use async_trait::async_trait; use jsonrpsee::core::RpcResult; use reth_chainspec::{ChainSpec, EthereumHardforks}; use reth_evm::{ - system_calls::{pre_block_beacon_root_contract_call, pre_block_blockhashes_contract_call}, + execute::{BlockExecutorProvider, Executor}, ConfigureEvmEnv, }; use reth_primitives::{Block, BlockId, BlockNumberOrTag, TransactionSignedEcRecovered}; @@ -32,9 +32,8 @@ use reth_rpc_types::{ use reth_tasks::pool::BlockingTaskGuard; use reth_trie::{HashedPostState, HashedStorage}; use revm::{ - db::{states::bundle_state::BundleRetention, CacheDB}, + db::CacheDB, primitives::{db::DatabaseCommit, BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg}, - StateBuilder, }; use revm_inspectors::tracing::{ FourByteInspector, MuxInspector, TracingInspector, TracingInspectorConfig, TransactionContext, @@ -46,16 +45,22 @@ use tokio::sync::{AcquireError, OwnedSemaphorePermit}; /// `debug` API implementation. /// /// This type provides the functionality for handling `debug` related requests. -pub struct DebugApi { - inner: Arc>, +pub struct DebugApi { + inner: Arc>, } // === impl DebugApi === -impl DebugApi { +impl DebugApi { /// Create a new instance of the [`DebugApi`] - pub fn new(provider: Provider, eth: Eth, blocking_task_guard: BlockingTaskGuard) -> Self { - let inner = Arc::new(DebugApiInner { provider, eth_api: eth, blocking_task_guard }); + pub fn new( + provider: Provider, + eth: Eth, + block_executor: BlockExecutor, + blocking_task_guard: BlockingTaskGuard, + ) -> Self { + let inner = + Arc::new(DebugApiInner { provider, eth_api: eth, block_executor, blocking_task_guard }); Self { inner } } @@ -67,7 +72,7 @@ impl DebugApi { // === impl DebugApi === -impl DebugApi +impl DebugApi where Provider: BlockReaderIdExt + HeaderProvider @@ -76,6 +81,7 @@ where + EvmEnvProvider + 'static, Eth: EthApiTypes + TraceExt + 'static, + BlockExecutor: BlockExecutorProvider, { /// Acquires a permit to execute a tracing call. async fn acquire_trace_permit(&self) -> Result { @@ -569,75 +575,37 @@ where block_id: BlockNumberOrTag, include_preimages: bool, ) -> Result { - let ((cfg, block_env, _), maybe_block) = futures::try_join!( - self.inner.eth_api.evm_env_at(block_id.into()), - self.inner.eth_api.block_with_senders(block_id.into()), - )?; - let block = maybe_block.ok_or(EthApiError::HeaderNotFound(block_id.into()))?; + let block = self + .inner + .eth_api + .block_with_senders(block_id.into()) + .await? + .ok_or(EthApiError::HeaderNotFound(block_id.into()))?; let this = self.clone(); self.inner .eth_api .spawn_with_state_at_block(block.parent_hash.into(), move |state| { - let evm_config = Call::evm_config(this.eth_api()).clone(); - let mut db = StateBuilder::new() - .with_database(StateProviderDatabase::new(state)) - .with_bundle_update() - .build(); - - pre_block_beacon_root_contract_call( - &mut db, - &evm_config, - &this.inner.provider.chain_spec(), - &cfg, - &block_env, - block.parent_beacon_block_root, - ) - .map_err(|err| EthApiError::Internal(err.into()))?; - - // apply eip-2935 blockhashes update - pre_block_blockhashes_contract_call( - &mut db, - &evm_config, - &this.inner.provider.chain_spec(), - &cfg, - &block_env, - block.parent_hash, - ) - .map_err(|err| EthApiError::Internal(err.into()))?; - - // Re-execute all of the transactions in the block to load all touched accounts into - // the cache DB. - for tx in block.into_transactions_ecrecovered() { - let env = EnvWithHandlerCfg { - env: Env::boxed( - cfg.cfg_env.clone(), - block_env.clone(), - evm_config.tx_env(&tx), - ), - handler_cfg: cfg.handler_cfg, - }; - - let (res, _) = this.inner.eth_api.transact(&mut db, env)?; - db.commit(res.state); - } - - // Merge all state transitions - db.merge_transitions(BundleRetention::Reverts); + let db = StateProviderDatabase::new(&state); + let block_executor = this.inner.block_executor.executor(db); + let block_execution_output = block_executor + .execute((&block.clone().unseal(), block.difficulty).into()) + .map_err(|err| EthApiError::Internal(err.into()))?; - // Take the bundle state - let bundle_state = db.take_bundle(); + let bundle_state = block_execution_output.state; + let cache_state = block_execution_output.cache; // Initialize a map of preimages. - let mut state_preimages = HashMap::new(); + let mut state_preimages: HashMap, Bytes> = + HashMap::new(); // Grab all account proofs for the data accessed during block execution. // // Note: We grab *all* accounts in the cache here, as the `BundleState` prunes // referenced accounts + storage slots. let mut hashed_state = HashedPostState::from_bundle_state(&bundle_state.state); - for (address, account) in db.cache.accounts { + for (address, account) in cache_state.accounts { let hashed_address = keccak256(address); hashed_state.accounts.insert( hashed_address, @@ -668,11 +636,8 @@ where } // Generate an execution witness for the aggregated state of accessed accounts. - // Destruct the cache database to retrieve the state provider. - let state_provider = db.database.into_inner(); - let witness = state_provider - .witness(HashedPostState::default(), hashed_state) - .map_err(Into::into)?; + let witness = + state.witness(HashedPostState::default(), hashed_state).map_err(Into::into)?; Ok(ExecutionWitness { witness, @@ -803,7 +768,7 @@ where } #[async_trait] -impl DebugApiServer for DebugApi +impl DebugApiServer for DebugApi where Provider: BlockReaderIdExt + HeaderProvider @@ -812,6 +777,7 @@ where + EvmEnvProvider + 'static, Eth: EthApiSpec + EthTransactions + TraceExt + 'static, + BlockExecutor: BlockExecutorProvider, { /// Handler for `debug_getRawHeader` async fn raw_header(&self, block_id: BlockId) -> RpcResult { @@ -1190,23 +1156,25 @@ where } } -impl std::fmt::Debug for DebugApi { +impl std::fmt::Debug for DebugApi { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("DebugApi").finish_non_exhaustive() } } -impl Clone for DebugApi { +impl Clone for DebugApi { fn clone(&self) -> Self { Self { inner: Arc::clone(&self.inner) } } } -struct DebugApiInner { +struct DebugApiInner { /// The provider that can interact with the chain. provider: Provider, /// The implementation of `eth` API eth_api: Eth, + /// block executor for debug & trace apis + block_executor: BlockExecutor, // restrict the number of concurrent calls to blocking calls blocking_task_guard: BlockingTaskGuard, } diff --git a/examples/rpc-db/src/main.rs b/examples/rpc-db/src/main.rs index e7409417fb47..892dd9981236 100644 --- a/examples/rpc-db/src/main.rs +++ b/examples/rpc-db/src/main.rs @@ -33,8 +33,8 @@ use reth::rpc::builder::{ // Configuring the network parts, ideally also wouldn't need to think about this. use myrpc_ext::{MyRpcExt, MyRpcExtApiServer}; use reth::{blockchain_tree::noop::NoopBlockchainTree, tasks::TokioTaskExecutor}; -use reth_node_ethereum::{EthEvmConfig, EthereumNode}; -use reth_provider::test_utils::TestCanonStateSubscriptions; +use reth_node_ethereum::{EthEvmConfig, EthExecutorProvider, EthereumNode}; +use reth_provider::{test_utils::TestCanonStateSubscriptions, ChainSpecProvider}; // Custom rpc extension pub mod myrpc_ext; @@ -67,7 +67,9 @@ async fn main() -> eyre::Result<()> { .with_noop_network() .with_executor(TokioTaskExecutor::default()) .with_evm_config(EthEvmConfig::new(spec)) - .with_events(TestCanonStateSubscriptions::default()); + .with_events(TestCanonStateSubscriptions::default()) + .with_block_executor(EthExecutorProvider::ethereum(provider.chain_spec())); +>>>>>>> 7d9b7e746 (Add block_executor to debug_execution_witness to execute blocks) // Pick which namespaces to expose. let config = TransportRpcModuleConfig::default().with_http([RethRpcModule::Eth]);