feat: integrate ExecutorProvider (#7798)

This commit is contained in:
Matthias Seitz
2024-05-03 13:39:46 +02:00
committed by GitHub
parent ec45ae679f
commit 067b0ff420
74 changed files with 1087 additions and 2027 deletions

View File

@ -5,6 +5,7 @@ use reth_db::{
database::Database,
database_metrics::{DatabaseMetadata, DatabaseMetrics},
};
use reth_evm::execute::BlockExecutorProvider;
use reth_network::NetworkHandle;
use reth_payload_builder::PayloadBuilderHandle;
use reth_provider::FullProvider;
@ -88,12 +89,18 @@ pub trait FullNodeComponents: FullNodeTypes + 'static {
/// The node's EVM configuration, defining settings for the Ethereum Virtual Machine.
type Evm: ConfigureEvm;
/// The type that knows how to execute blocks.
type Executor: BlockExecutorProvider;
/// Returns the transaction pool of the node.
fn pool(&self) -> &Self::Pool;
/// Returns the node's evm config.
fn evm_config(&self) -> &Self::Evm;
/// Returns the node's executor type.
fn block_executor(&self) -> &Self::Executor;
/// Returns the provider of the node.
fn provider(&self) -> &Self::Provider;

View File

@ -17,6 +17,7 @@ reth-auto-seal-consensus.workspace = true
reth-beacon-consensus.workspace = true
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

View File

@ -27,6 +27,7 @@ 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::*;
@ -460,6 +461,28 @@ 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

@ -98,6 +98,7 @@ impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeTypes for NodeAdapter<T, C>
impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeComponents for NodeAdapter<T, C> {
type Pool = C::Pool;
type Evm = C::Evm;
type Executor = C::Executor;
fn pool(&self) -> &Self::Pool {
self.components.pool()
@ -107,6 +108,10 @@ impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeComponents for NodeAdapter<
self.components.evm_config()
}
fn block_executor(&self) -> &Self::Executor {
self.components.block_executor()
}
fn provider(&self) -> &Self::Provider {
&self.provider
}

View File

@ -7,6 +7,7 @@ use crate::{
},
BuilderContext, ConfigureEvm, FullNodeTypes,
};
use reth_evm::execute::BlockExecutorProvider;
use reth_transaction_pool::TransactionPool;
use std::{future::Future, marker::PhantomData};
@ -232,7 +233,7 @@ where
PayloadB: PayloadServiceBuilder<Node, PoolB::Pool>,
ExecB: ExecutorBuilder<Node>,
{
type Components = Components<Node, PoolB::Pool, ExecB::EVM>;
type Components = Components<Node, PoolB::Pool, ExecB::EVM, ExecB::Executor>;
async fn build_components(
self,
@ -246,12 +247,12 @@ where
_marker,
} = self;
let evm_config = evm_builder.build_evm(context).await?;
let (evm_config, executor) = evm_builder.build_evm(context).await?;
let pool = pool_builder.build_pool(context).await?;
let network = network_builder.build_network(context, pool.clone()).await?;
let payload_builder = payload_builder.spawn_payload_service(context, pool.clone()).await?;
Ok(Components { transaction_pool: pool, evm_config, network, payload_builder })
Ok(Components { transaction_pool: pool, evm_config, network, payload_builder, executor })
}
}
@ -287,15 +288,16 @@ pub trait NodeComponentsBuilder<Node: FullNodeTypes>: Send {
) -> impl Future<Output = eyre::Result<Self::Components>> + Send;
}
impl<Node, F, Fut, Pool, EVM> NodeComponentsBuilder<Node> for F
impl<Node, F, Fut, Pool, EVM, Executor> NodeComponentsBuilder<Node> for F
where
Node: FullNodeTypes,
F: FnOnce(&BuilderContext<Node>) -> Fut + Send,
Fut: Future<Output = eyre::Result<Components<Node, Pool, EVM>>> + Send,
Fut: Future<Output = eyre::Result<Components<Node, Pool, EVM, Executor>>> + Send,
Pool: TransactionPool + Unpin + 'static,
EVM: ConfigureEvm,
Executor: BlockExecutorProvider,
{
type Components = Components<Node, Pool, EVM>;
type Components = Components<Node, Pool, EVM, Executor>;
fn build_components(
self,

View File

@ -1,34 +1,41 @@
//! EVM component for the node builder.
use crate::{BuilderContext, FullNodeTypes};
use reth_evm::execute::BlockExecutorProvider;
use reth_node_api::ConfigureEvm;
use std::future::Future;
/// A type that knows how to build the executor types.
pub trait ExecutorBuilder<Node: FullNodeTypes>: Send {
/// The EVM config to build.
/// The EVM config to use.
///
/// This provides the node with the necessary configuration to configure an EVM.
type EVM: ConfigureEvm;
// TODO(mattsse): integrate `Executor`
/// The type that knows how to execute blocks.
type Executor: BlockExecutorProvider;
/// Creates the EVM config.
fn build_evm(
self,
ctx: &BuilderContext<Node>,
) -> impl Future<Output = eyre::Result<Self::EVM>> + Send;
) -> impl Future<Output = eyre::Result<(Self::EVM, Self::Executor)>> + Send;
}
impl<Node, F, Fut, EVM> ExecutorBuilder<Node> for F
impl<Node, F, Fut, EVM, Executor> ExecutorBuilder<Node> for F
where
Node: FullNodeTypes,
EVM: ConfigureEvm,
Executor: BlockExecutorProvider,
F: FnOnce(&BuilderContext<Node>) -> Fut + Send,
Fut: Future<Output = eyre::Result<EVM>> + Send,
Fut: Future<Output = eyre::Result<(EVM, Executor)>> + Send,
{
type EVM = EVM;
type Executor = Executor;
fn build_evm(
self,
ctx: &BuilderContext<Node>,
) -> impl Future<Output = eyre::Result<Self::EVM>> {
) -> impl Future<Output = eyre::Result<(Self::EVM, Self::Executor)>> {
self(ctx)
}
}

View File

@ -13,6 +13,7 @@ pub use execute::*;
pub use network::*;
pub use payload::*;
pub use pool::*;
use reth_evm::execute::BlockExecutorProvider;
use reth_network::NetworkHandle;
use reth_payload_builder::PayloadBuilderHandle;
use reth_transaction_pool::TransactionPool;
@ -35,12 +36,18 @@ pub trait NodeComponents<NodeTypes: FullNodeTypes>: Clone + Send + Sync + 'stati
/// The node's EVM configuration, defining settings for the Ethereum Virtual Machine.
type Evm: ConfigureEvm;
/// The type that knows how to execute blocks.
type Executor: BlockExecutorProvider;
/// Returns the transaction pool of the node.
fn pool(&self) -> &Self::Pool;
/// Returns the node's evm config.
fn evm_config(&self) -> &Self::Evm;
/// Returns the node's executor type.
fn block_executor(&self) -> &Self::Executor;
/// Returns the handle to the network
fn network(&self) -> &NetworkHandle;
@ -52,25 +59,29 @@ pub trait NodeComponents<NodeTypes: FullNodeTypes>: Clone + Send + Sync + 'stati
///
/// This provides access to all the components of the node.
#[derive(Debug)]
pub struct Components<Node: FullNodeTypes, Pool, EVM> {
pub struct Components<Node: FullNodeTypes, Pool, EVM, Executor> {
/// The transaction pool of the node.
pub transaction_pool: Pool,
/// The node's EVM configuration, defining settings for the Ethereum Virtual Machine.
pub evm_config: EVM,
/// The node's executor type used to execute individual blocks and batches of blocks.
pub executor: Executor,
/// The network implementation of the node.
pub network: NetworkHandle,
/// The handle to the payload builder service.
pub payload_builder: PayloadBuilderHandle<Node::Engine>,
}
impl<Node, Pool, EVM> NodeComponents<Node> for Components<Node, Pool, EVM>
impl<Node, Pool, EVM, Executor> NodeComponents<Node> for Components<Node, Pool, EVM, Executor>
where
Node: FullNodeTypes,
Pool: TransactionPool + Unpin + 'static,
EVM: ConfigureEvm,
Executor: BlockExecutorProvider,
{
type Pool = Pool;
type Evm = EVM;
type Executor = Executor;
fn pool(&self) -> &Self::Pool {
&self.transaction_pool
@ -80,6 +91,10 @@ where
&self.evm_config
}
fn block_executor(&self) -> &Self::Executor {
&self.executor
}
fn network(&self) -> &NetworkHandle {
&self.network
}
@ -89,16 +104,18 @@ where
}
}
impl<Node, Pool, EVM> Clone for Components<Node, Pool, EVM>
impl<Node, Pool, EVM, Executor> Clone for Components<Node, Pool, EVM, Executor>
where
Node: FullNodeTypes,
Pool: TransactionPool,
EVM: ConfigureEvm,
Executor: BlockExecutorProvider,
{
fn clone(&self) -> Self {
Self {
transaction_pool: self.transaction_pool.clone(),
evm_config: self.evm_config.clone(),
executor: self.executor.clone(),
network: self.network.clone(),
payload_builder: self.payload_builder.clone(),
}

View File

@ -30,7 +30,6 @@ use reth_node_core::{
use reth_node_events::{cl::ConsensusLayerHealthEvents, node};
use reth_primitives::format_ether;
use reth_provider::{providers::BlockchainProvider, CanonStateSubscriptions};
use reth_revm::EvmProcessorFactory;
use reth_rpc_engine_api::EngineApi;
use reth_tasks::TaskExecutor;
use reth_tracing::tracing::{debug, info};
@ -157,7 +156,7 @@ where
let tree_externals = TreeExternals::new(
ctx.provider_factory().clone(),
consensus.clone(),
EvmProcessorFactory::new(ctx.chain_spec(), components.evm_config().clone()),
components.block_executor().clone(),
);
let tree = BlockchainTree::new(tree_externals, tree_config, ctx.prune_modes())?
.with_sync_metrics_tx(sync_metrics_tx.clone())
@ -303,7 +302,7 @@ where
consensus_engine_tx.clone(),
canon_state_notification_sender,
mining_mode,
node_adapter.components.evm_config().clone(),
node_adapter.components.block_executor().clone(),
)
.build();
@ -318,7 +317,7 @@ where
ctx.prune_config(),
max_block,
static_file_producer,
node_adapter.components.evm_config().clone(),
node_adapter.components.block_executor().clone(),
pipeline_exex_handle,
)
.await?;
@ -341,7 +340,7 @@ where
ctx.prune_config(),
max_block,
static_file_producer,
node_adapter.components.evm_config().clone(),
node_adapter.components.block_executor().clone(),
pipeline_exex_handle,
)
.await?;

View File

@ -1,6 +1,5 @@
//! Helpers for setting up parts of the node.
use crate::ConfigureEvm;
use reth_config::{config::StageConfig, PruneConfig};
use reth_consensus::Consensus;
use reth_db::database::Database;
@ -8,6 +7,7 @@ use reth_downloaders::{
bodies::bodies::BodiesDownloaderBuilder,
headers::reverse_headers::ReverseHeadersDownloaderBuilder,
};
use reth_evm::execute::BlockExecutorProvider;
use reth_exex::ExExManagerHandle;
use reth_interfaces::p2p::{
bodies::{client::BodiesClient, downloader::BodyDownloader},
@ -18,7 +18,6 @@ use reth_node_core::{
primitives::{BlockNumber, B256},
};
use reth_provider::{HeaderSyncMode, ProviderFactory};
use reth_revm::stack::{Hook, InspectorStackConfig};
use reth_stages::{
prelude::DefaultStages,
stages::{
@ -36,7 +35,7 @@ use tokio::sync::watch;
/// Constructs a [Pipeline] that's wired to the network
#[allow(clippy::too_many_arguments)]
pub async fn build_networked_pipeline<DB, Client, EvmConfig>(
pub async fn build_networked_pipeline<DB, Client, Executor>(
node_config: &NodeConfig,
config: &StageConfig,
client: Client,
@ -47,13 +46,13 @@ pub async fn build_networked_pipeline<DB, Client, EvmConfig>(
prune_config: Option<PruneConfig>,
max_block: Option<BlockNumber>,
static_file_producer: StaticFileProducer<DB>,
evm_config: EvmConfig,
executor: Executor,
exex_manager_handle: ExExManagerHandle,
) -> eyre::Result<Pipeline<DB>>
where
DB: Database + Unpin + Clone + 'static,
Client: HeadersClient + BodiesClient + Clone + 'static,
EvmConfig: ConfigureEvm + Clone + 'static,
Executor: BlockExecutorProvider,
{
// building network downloaders using the fetch client
let header_downloader = ReverseHeadersDownloaderBuilder::new(config.headers)
@ -75,7 +74,7 @@ where
metrics_tx,
prune_config,
static_file_producer,
evm_config,
executor,
exex_manager_handle,
)
.await?;
@ -85,7 +84,7 @@ where
/// Builds the [Pipeline] with the given [ProviderFactory] and downloaders.
#[allow(clippy::too_many_arguments)]
pub async fn build_pipeline<DB, H, B, EvmConfig>(
pub async fn build_pipeline<DB, H, B, Executor>(
node_config: &NodeConfig,
provider_factory: ProviderFactory<DB>,
stage_config: &StageConfig,
@ -96,14 +95,14 @@ pub async fn build_pipeline<DB, H, B, EvmConfig>(
metrics_tx: reth_stages::MetricEventsSender,
prune_config: Option<PruneConfig>,
static_file_producer: StaticFileProducer<DB>,
evm_config: EvmConfig,
executor: Executor,
exex_manager_handle: ExExManagerHandle,
) -> eyre::Result<Pipeline<DB>>
where
DB: Database + Clone + 'static,
H: HeaderDownloader + 'static,
B: BodyDownloader + 'static,
EvmConfig: ConfigureEvm + Clone + 'static,
Executor: BlockExecutorProvider,
{
let mut builder = Pipeline::builder();
@ -113,22 +112,6 @@ where
}
let (tip_tx, tip_rx) = watch::channel(B256::ZERO);
let factory = reth_revm::EvmProcessorFactory::new(node_config.chain.clone(), evm_config);
let stack_config = InspectorStackConfig {
use_printer_tracer: node_config.debug.print_inspector,
hook: if let Some(hook_block) = node_config.debug.hook_block {
Hook::Block(hook_block)
} else if let Some(tx) = node_config.debug.hook_transaction {
Hook::Transaction(tx)
} else if node_config.debug.hook_all {
Hook::All
} else {
Hook::None
},
};
let factory = factory.with_stack_config(stack_config);
let prune_modes = prune_config.map(|prune| prune.segments).unwrap_or_default();
@ -147,7 +130,7 @@ where
Arc::clone(&consensus),
header_downloader,
body_downloader,
factory.clone(),
executor.clone(),
stage_config.etl.clone(),
)
.set(SenderRecoveryStage {
@ -155,7 +138,7 @@ where
})
.set(
ExecutionStage::new(
factory,
executor,
ExecutionStageThresholds {
max_blocks: stage_config.execution.max_blocks,
max_changes: stage_config.execution.max_changes,