feat(witness): use block executor to execute block inside debug_execution_witness (#11149)

This commit is contained in:
Francis Li
2024-09-24 09:48:32 -07:00
committed by GitHub
parent 4da5f1f388
commit d3114b4eec
5 changed files with 245 additions and 166 deletions

View File

@ -192,6 +192,7 @@ pub struct RpcRegistry<Node: FullNodeComponents, EthApi: EthApiTypes> {
TaskExecutor,
Node::Provider,
EthApi,
Node::Executor,
>,
}
@ -207,6 +208,7 @@ where
TaskExecutor,
Node::Provider,
EthApi,
Node::Executor,
>;
fn deref(&self) -> &Self::Target {
@ -316,6 +318,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 };

View File

@ -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_primitives::Header;
//! use reth_provider::{AccountReader, CanonStateSubscriptions, ChangeSetReader, FullRpcProvider};
@ -27,18 +27,20 @@
//! use reth_tasks::TokioTaskExecutor;
//! use reth_transaction_pool::TransactionPool;
//!
//! pub async fn launch<Provider, Pool, Network, Events, EvmConfig>(
//! pub async fn launch<Provider, Pool, Network, Events, EvmConfig, BlockExecutor>(
//! 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<Header = Header>,
//! BlockExecutor: BlockExecutorProvider,
//! {
//! // configure the rpc module per transport
//! let transports = TransportRpcModuleConfig::default().with_http(vec![
@ -54,6 +56,7 @@
//! TokioTaskExecutor::default(),
//! events,
//! evm_config,
//! block_executor,
//! )
//! .build(transports, Box::new(EthApi::with_spawner));
//! let handle = RpcServerConfig::default()
@ -68,7 +71,7 @@
//!
//! ```
//! use reth_engine_primitives::EngineTypes;
//! use reth_evm::ConfigureEvm;
//! use reth_evm::{execute::BlockExecutorProvider, ConfigureEvm};
//! use reth_network_api::{NetworkInfo, Peers};
//! use reth_primitives::Header;
//! use reth_provider::{AccountReader, CanonStateSubscriptions, ChangeSetReader, FullRpcProvider};
@ -82,13 +85,23 @@
//! use reth_tasks::TokioTaskExecutor;
//! use reth_transaction_pool::TransactionPool;
//! use tokio::try_join;
//! pub async fn launch<Provider, Pool, Network, Events, EngineApi, EngineT, EvmConfig>(
//! 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,
@ -97,6 +110,7 @@
//! EngineApi: EngineApiServer<EngineT>,
//! EngineT: EngineTypes,
//! EvmConfig: ConfigureEvm<Header = Header>,
//! BlockExecutor: BlockExecutorProvider,
//! {
//! // configure the rpc module per transport
//! let transports = TransportRpcModuleConfig::default().with_http(vec![
@ -112,6 +126,7 @@
//! TokioTaskExecutor::default(),
//! events,
//! evm_config,
//! block_executor,
//! );
//!
//! // configure the server modules
@ -154,7 +169,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_primitives::Header;
use reth_provider::{
@ -212,7 +227,7 @@ pub use metrics::{MeteredRequestFuture, RpcRequestMetricsService};
/// Convenience function for starting a server in one step.
#[allow(clippy::too_many_arguments)]
pub async fn launch<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi>(
pub async fn launch<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi, BlockExecutor>(
provider: Provider,
pool: Pool,
network: Network,
@ -222,6 +237,7 @@ pub async fn launch<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi>(
events: Events,
evm_config: EvmConfig,
eth: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
block_executor: BlockExecutor,
) -> Result<RpcServerHandle, RpcError>
where
Provider: FullRpcProvider + AccountReader + ChangeSetReader,
@ -231,12 +247,21 @@ where
Events: CanonStateSubscriptions + Clone + 'static,
EvmConfig: ConfigureEvm<Header = reth_primitives::Header>,
EthApi: FullEthApiServer,
BlockExecutor: BlockExecutorProvider,
{
let module_config = module_config.into();
server_config
.into()
.start(
&RpcModuleBuilder::new(provider, pool, network, executor, events, evm_config)
&RpcModuleBuilder::new(
provider,
pool,
network,
executor,
events,
evm_config,
block_executor,
)
.build(module_config, eth),
)
.await
@ -246,7 +271,7 @@ where
///
/// This is the main entrypoint and the easiest way to configure an RPC server.
#[derive(Debug, Clone)]
pub struct RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig> {
pub struct RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor> {
/// The Provider type to when creating all rpc handlers
provider: Provider,
/// The Pool type to when creating all rpc handlers
@ -259,12 +284,14 @@ pub struct RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig> {
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<Provider, Pool, Network, Tasks, Events, EvmConfig>
RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig>
impl<Provider, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor>
RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor>
{
/// Create a new instance of the builder
pub const fn new(
@ -274,32 +301,33 @@ impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
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<P>(
self,
provider: P,
) -> RpcModuleBuilder<P, Pool, Network, Tasks, Events, EvmConfig>
) -> RpcModuleBuilder<P, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor>
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<P>(
self,
pool: P,
) -> RpcModuleBuilder<Provider, P, Network, Tasks, Events, EvmConfig>
) -> RpcModuleBuilder<Provider, P, Network, Tasks, Events, EvmConfig, BlockExecutor>
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.
@ -309,14 +337,23 @@ impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
/// [`EthApi`](reth_rpc::eth::EthApi) which requires a [`TransactionPool`] implementation.
pub fn with_noop_pool(
self,
) -> RpcModuleBuilder<Provider, NoopTransactionPool, Network, Tasks, Events, EvmConfig> {
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,
events,
network,
evm_config,
block_executor,
pool: NoopTransactionPool::default(),
}
}
@ -325,12 +362,12 @@ impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
pub fn with_network<N>(
self,
network: N,
) -> RpcModuleBuilder<Provider, Pool, N, Tasks, Events, EvmConfig>
) -> RpcModuleBuilder<Provider, Pool, N, Tasks, Events, EvmConfig, BlockExecutor>
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.
@ -340,8 +377,9 @@ impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
/// [`EthApi`](reth_rpc::eth::EthApi) which requires a [`NetworkInfo`] implementation.
pub fn with_noop_network(
self,
) -> RpcModuleBuilder<Provider, Pool, NoopNetwork, Tasks, Events, EvmConfig> {
let Self { provider, pool, executor, events, evm_config, .. } = self;
) -> RpcModuleBuilder<Provider, Pool, NoopNetwork, Tasks, Events, EvmConfig, BlockExecutor>
{
let Self { provider, pool, executor, events, evm_config, block_executor, .. } = self;
RpcModuleBuilder {
provider,
pool,
@ -349,6 +387,7 @@ impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
events,
network: NoopNetwork::default(),
evm_config,
block_executor,
}
}
@ -356,12 +395,12 @@ impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
pub fn with_executor<T>(
self,
executor: T,
) -> RpcModuleBuilder<Provider, Pool, Network, T, Events, EvmConfig>
) -> RpcModuleBuilder<Provider, Pool, Network, T, Events, EvmConfig, BlockExecutor>
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.
@ -370,8 +409,16 @@ impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
/// [`TokioTaskExecutor`].
pub fn with_tokio_executor(
self,
) -> RpcModuleBuilder<Provider, Pool, Network, TokioTaskExecutor, Events, EvmConfig> {
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,
@ -379,6 +426,7 @@ impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
events,
executor: TokioTaskExecutor::default(),
evm_config,
block_executor,
}
}
@ -386,29 +434,41 @@ impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
pub fn with_events<E>(
self,
events: E,
) -> RpcModuleBuilder<Provider, Pool, Network, Tasks, E, EvmConfig>
) -> RpcModuleBuilder<Provider, Pool, Network, Tasks, E, EvmConfig, BlockExecutor>
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<E>(
self,
evm_config: E,
) -> RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, E>
) -> RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, E, BlockExecutor>
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<BE>(
self,
block_executor: BE,
) -> RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, BE>
where
BE: BlockExecutorProvider,
{
let Self { provider, network, pool, executor, events, evm_config, .. } = self;
RpcModuleBuilder { provider, network, pool, executor, events, evm_config, block_executor }
}
}
impl<Provider, Pool, Network, Tasks, Events, EvmConfig>
RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig>
impl<Provider, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor>
RpcModuleBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, BlockExecutor>
where
Provider: FullRpcProvider + AccountReader + ChangeSetReader,
Pool: TransactionPool + 'static,
@ -416,6 +476,7 @@ where
Tasks: TaskSpawner + Clone + 'static,
Events: CanonStateSubscriptions + Clone + 'static,
EvmConfig: ConfigureEvm<Header = Header>,
BlockExecutor: BlockExecutorProvider,
{
/// Configures all [`RpcModule`]s specific to the given [`TransportRpcModuleConfig`] which can
/// be used to start the transport server(s).
@ -432,19 +493,27 @@ where
) -> (
TransportRpcModules,
AuthRpcModule,
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi>,
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>,
)
where
EngineT: EngineTypes,
EngineApi: EngineApiServer<EngineT>,
EthApi: FullEthApiServer,
{
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);
@ -463,6 +532,7 @@ where
///
/// ```no_run
/// use reth_evm::ConfigureEvm;
/// use reth_evm_ethereum::execute::EthExecutorProvider;
/// use reth_network_api::noop::NoopNetwork;
/// use reth_primitives::Header;
/// use reth_provider::test_utils::{NoopProvider, TestCanonStateSubscriptions};
@ -479,6 +549,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();
@ -488,12 +559,22 @@ where
self,
config: RpcModuleConfig,
eth: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
) -> RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi>
) -> RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
where
EthApi: EthApiTypes + '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
@ -508,7 +589,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();
@ -522,6 +603,7 @@ where
config.unwrap_or_default(),
evm_config,
eth,
block_executor,
);
modules.config = module_config;
@ -534,9 +616,9 @@ where
}
}
impl Default for RpcModuleBuilder<(), (), (), (), (), ()> {
impl Default for RpcModuleBuilder<(), (), (), (), (), (), ()> {
fn default() -> Self {
Self::new((), (), (), (), (), ())
Self::new((), (), (), (), (), (), ())
}
}
@ -610,12 +692,21 @@ impl RpcModuleConfigBuilder {
/// A Helper type the holds instances of the configured modules.
#[derive(Debug, Clone)]
pub struct RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi: EthApiTypes> {
pub struct RpcRegistryInner<
Provider,
Pool,
Network,
Tasks,
Events,
EthApi: EthApiTypes,
BlockExecutor,
> {
provider: Provider,
pool: Pool,
network: Network,
executor: Tasks,
events: Events,
block_executor: BlockExecutor,
/// Holds a all `eth_` namespace handlers
eth: EthHandlers<Provider, Pool, Network, Events, EthApi>,
/// to put trace calls behind semaphore
@ -626,8 +717,8 @@ pub struct RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi: EthA
// === impl RpcRegistryInner ===
impl<Provider, Pool, Network, Tasks, Events, EthApi>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi>
impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
where
Provider: StateProviderFactory + BlockReader + EvmEnvProvider + Clone + Unpin + 'static,
Pool: Send + Sync + Clone + 'static,
@ -635,6 +726,7 @@ where
Events: CanonStateSubscriptions + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,
EthApi: EthApiTypes + 'static,
BlockExecutor: BlockExecutorProvider,
{
/// Creates a new, empty instance.
#[allow(clippy::too_many_arguments)]
@ -655,6 +747,7 @@ where
Events,
EthApi,
>,
block_executor: BlockExecutor,
) -> Self
where
EvmConfig: ConfigureEvm<Header = Header>,
@ -681,12 +774,13 @@ where
modules: Default::default(),
blocking_pool_guard,
events,
block_executor,
}
}
}
impl<Provider, Pool, Network, Tasks, Events, EthApi>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi>
impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
where
EthApi: EthApiTypes,
{
@ -743,12 +837,13 @@ where
}
}
impl<Provider, Pool, Network, Tasks, Events, EthApi>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi>
impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
where
Network: NetworkInfo + Clone + 'static,
EthApi: EthApiTypes,
Provider: ChainSpecProvider<ChainSpec = ChainSpec>,
BlockExecutor: BlockExecutorProvider,
{
/// Instantiates `AdminApi`
pub fn admin_api(&self) -> AdminApi<Network>
@ -781,8 +876,8 @@ where
}
}
impl<Provider, Pool, Network, Tasks, Events, EthApi>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi>
impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
where
Provider: FullRpcProvider + AccountReader + ChangeSetReader,
Network: NetworkInfo + Peers + Clone + 'static,
@ -792,6 +887,7 @@ where
RpcBlock<EthApi::NetworkTypes>,
RpcReceipt<EthApi::NetworkTypes>,
> + EthApiTypes,
BlockExecutor: BlockExecutorProvider,
{
/// Register Eth Namespace
///
@ -893,13 +989,14 @@ where
}
}
impl<Provider, Pool, Network, Tasks, Events, EthApi>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi>
impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
where
Provider: FullRpcProvider + AccountReader + ChangeSetReader,
Network: NetworkInfo + Peers + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,
EthApi: EthApiTypes,
BlockExecutor: BlockExecutorProvider,
{
/// Instantiates `TraceApi`
///
@ -935,12 +1032,17 @@ where
/// # Panics
///
/// If called outside of the tokio runtime. See also [`Self::eth_api`]
pub fn debug_api(&self) -> DebugApi<Provider, EthApi>
pub fn debug_api(&self) -> DebugApi<Provider, EthApi, BlockExecutor>
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.blocking_pool_guard.clone(),
self.block_executor.clone(),
)
}
/// Instantiates `NetApi`
@ -962,8 +1064,8 @@ where
}
}
impl<Provider, Pool, Network, Tasks, Events, EthApi>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi>
impl<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi, BlockExecutor>
where
Provider: FullRpcProvider + AccountReader + ChangeSetReader,
Pool: TransactionPool + 'static,
@ -971,6 +1073,7 @@ where
Tasks: TaskSpawner + Clone + 'static,
Events: CanonStateSubscriptions + Clone + 'static,
EthApi: FullEthApiServer,
BlockExecutor: BlockExecutorProvider,
{
/// Configures the auth module that includes the
/// * `engine_` namespace
@ -1063,6 +1166,7 @@ where
self.provider.clone(),
eth_api.clone(),
self.blocking_pool_guard.clone(),
self.block_executor.clone(),
)
.into_rpc()
.into(),

View File

@ -3,7 +3,7 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use reth_beacon_consensus::BeaconConsensusEngineHandle;
use reth_chainspec::MAINNET;
use reth_ethereum_engine_primitives::{EthEngineTypes, EthereumEngineValidator};
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};
@ -124,6 +124,7 @@ pub fn test_rpc_builder() -> RpcModuleBuilder<
TokioTaskExecutor,
TestCanonStateSubscriptions,
EthEvmConfig,
EthExecutorProvider<EthEvmConfig>,
> {
RpcModuleBuilder::default()
.with_provider(NoopProvider::default())
@ -132,4 +133,5 @@ pub fn test_rpc_builder() -> RpcModuleBuilder<
.with_executor(TokioTaskExecutor::default())
.with_events(TestCanonStateSubscriptions::default())
.with_evm_config(EthEvmConfig::new(MAINNET.clone()))
.with_block_executor(EthExecutorProvider::ethereum(MAINNET.clone()))
}

View File

@ -14,7 +14,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};
@ -35,7 +35,6 @@ use reth_trie::{HashedPostState, HashedStorage};
use revm::{
db::CacheDB,
primitives::{db::DatabaseCommit, BlockEnv, CfgEnvWithHandlerCfg, Env, EnvWithHandlerCfg},
StateBuilder,
};
use revm_inspectors::tracing::{
FourByteInspector, MuxInspector, TracingInspector, TracingInspectorConfig, TransactionContext,
@ -47,16 +46,22 @@ use tokio::sync::{AcquireError, OwnedSemaphorePermit};
/// `debug` API implementation.
///
/// This type provides the functionality for handling `debug` related requests.
pub struct DebugApi<Provider, Eth> {
inner: Arc<DebugApiInner<Provider, Eth>>,
pub struct DebugApi<Provider, Eth, BlockExecutor> {
inner: Arc<DebugApiInner<Provider, Eth, BlockExecutor>>,
}
// === impl DebugApi ===
impl<Provider, Eth> DebugApi<Provider, Eth> {
impl<Provider, Eth, BlockExecutor> DebugApi<Provider, Eth, BlockExecutor> {
/// 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,
blocking_task_guard: BlockingTaskGuard,
block_executor: BlockExecutor,
) -> Self {
let inner =
Arc::new(DebugApiInner { provider, eth_api: eth, blocking_task_guard, block_executor });
Self { inner }
}
@ -68,7 +73,7 @@ impl<Provider, Eth> DebugApi<Provider, Eth> {
// === impl DebugApi ===
impl<Provider, Eth> DebugApi<Provider, Eth>
impl<Provider, Eth, BlockExecutor> DebugApi<Provider, Eth, BlockExecutor>
where
Provider: BlockReaderIdExt
+ HeaderProvider
@ -77,6 +82,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<OwnedSemaphorePermit, AcquireError> {
@ -600,107 +606,67 @@ where
block_id: BlockNumberOrTag,
include_preimages: bool,
) -> Result<ExecutionWitness, Eth::Error> {
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 this = self.clone();
let block = this
.inner
.eth_api
.block_with_senders(block_id.into())
.await?
.ok_or(EthApiError::HeaderNotFound(block_id.into()))?;
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)).build();
.spawn_with_state_at_block(block.parent_hash.into(), move |state_provider| {
let db = StateProviderDatabase::new(&state_provider);
let block_executor = this.inner.block_executor.executor(db);
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);
}
// No need to merge transitions and create the bundle state, we will use Revm's
// cache directly.
// Initialize a map of preimages.
let mut state_preimages = 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. Cache is a superset of `BundleState`, so we
// can just query it to get the latest state of all accounts and storage slots.
let mut hashed_state = HashedPostState::default();
for (address, account) in db.cache.accounts {
let mut keys = HashMap::new();
let _ = block_executor
.execute_with_state_witness(
(&block.clone().unseal(), block.difficulty).into(),
|statedb| {
for (address, account) in &statedb.cache.accounts {
let hashed_address = keccak256(address);
hashed_state.accounts.insert(
hashed_address,
account.account.as_ref().map(|a| a.info.clone().into()),
);
let storage = hashed_state
.storages
.entry(hashed_address)
.or_insert_with(|| HashedStorage::new(account.status.was_destroyed()));
let storage =
hashed_state.storages.entry(hashed_address).or_insert_with(
|| HashedStorage::new(account.status.was_destroyed()),
);
if let Some(account) = account.account {
if let Some(account) = &account.account {
if include_preimages {
state_preimages
.insert(hashed_address, alloy_rlp::encode(address).into());
keys.insert(
hashed_address,
alloy_rlp::encode(address).into(),
);
}
for (slot, value) in account.storage {
let slot = B256::from(slot);
for (slot, value) in &account.storage {
let slot = B256::from(*slot);
let hashed_slot = keccak256(slot);
storage.storage.insert(hashed_slot, value);
storage.storage.insert(hashed_slot, *value);
if include_preimages {
state_preimages.insert(hashed_slot, alloy_rlp::encode(slot).into());
keys.insert(
hashed_slot,
alloy_rlp::encode(slot).into(),
);
}
}
}
}
},
)
.map_err(|err| EthApiError::Internal(err.into()))?;
// 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 state =
state_provider.witness(Default::default(), hashed_state).map_err(Into::into)?;
Ok(ExecutionWitness { state, keys: include_preimages.then_some(state_preimages) })
Ok(ExecutionWitness { state, keys: include_preimages.then_some(keys) })
})
.await
}
@ -852,7 +818,7 @@ where
}
#[async_trait]
impl<Provider, Eth> DebugApiServer for DebugApi<Provider, Eth>
impl<Provider, Eth, BlockExecutor> DebugApiServer for DebugApi<Provider, Eth, BlockExecutor>
where
Provider: BlockReaderIdExt
+ HeaderProvider
@ -861,6 +827,7 @@ where
+ EvmEnvProvider
+ 'static,
Eth: EthApiSpec + EthTransactions + TraceExt + 'static,
BlockExecutor: BlockExecutorProvider,
{
/// Handler for `debug_getRawHeader`
async fn raw_header(&self, block_id: BlockId) -> RpcResult<Bytes> {
@ -1239,23 +1206,25 @@ where
}
}
impl<Provider, Eth> std::fmt::Debug for DebugApi<Provider, Eth> {
impl<Provider, Eth, BlockExecutor> std::fmt::Debug for DebugApi<Provider, Eth, BlockExecutor> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DebugApi").finish_non_exhaustive()
}
}
impl<Provider, Eth> Clone for DebugApi<Provider, Eth> {
impl<Provider, Eth, BlockExecutor> Clone for DebugApi<Provider, Eth, BlockExecutor> {
fn clone(&self) -> Self {
Self { inner: Arc::clone(&self.inner) }
}
}
struct DebugApiInner<Provider, Eth> {
struct DebugApiInner<Provider, Eth, BlockExecutor> {
/// The provider that can interact with the chain.
provider: Provider,
/// The implementation of `eth` API
eth_api: Eth,
// restrict the number of concurrent calls to blocking calls
blocking_task_guard: BlockingTaskGuard,
/// block executor for debug & trace apis
block_executor: BlockExecutor,
}

View File

@ -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,8 @@ 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()));
// Pick which namespaces to expose.
let config = TransportRpcModuleConfig::default().with_http([RethRpcModule::Eth]);