feat: make nodetypes stateless and move evm to components (#7992)

This commit is contained in:
Matthias Seitz
2024-04-30 18:56:34 +02:00
committed by GitHub
parent 581682605c
commit d04d9556fa
20 changed files with 402 additions and 171 deletions

View File

@ -27,6 +27,15 @@ pub struct NoopBlockchainTree {
pub canon_state_notification_sender: Option<CanonStateNotificationSender>, pub canon_state_notification_sender: Option<CanonStateNotificationSender>,
} }
impl NoopBlockchainTree {
/// Create a new NoopBlockchainTree with a canon state notification sender.
pub fn with_canon_state_notifications(
canon_state_notification_sender: CanonStateNotificationSender,
) -> Self {
Self { canon_state_notification_sender: Some(canon_state_notification_sender) }
}
}
impl BlockchainTreeEngine for NoopBlockchainTree { impl BlockchainTreeEngine for NoopBlockchainTree {
fn buffer_block(&self, _block: SealedBlockWithSenders) -> Result<(), InsertBlockError> { fn buffer_block(&self, _block: SealedBlockWithSenders) -> Result<(), InsertBlockError> {
Ok(()) Ok(())

View File

@ -80,7 +80,7 @@ pub trait ConfigureEvm: ConfigureEvmEnv {
/// This represents the set of methods used to configure the EVM's environment before block /// This represents the set of methods used to configure the EVM's environment before block
/// execution. /// execution.
pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone { pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static {
/// The type of the transaction metadata that should be used to fill fields in the transaction /// The type of the transaction metadata that should be used to fill fields in the transaction
/// environment. /// environment.
/// ///

View File

@ -4,7 +4,9 @@ use crate::{EthEngineTypes, EthEvmConfig};
use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig}; use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig};
use reth_network::NetworkHandle; use reth_network::NetworkHandle;
use reth_node_builder::{ use reth_node_builder::{
components::{ComponentsBuilder, NetworkBuilder, PayloadServiceBuilder, PoolBuilder}, components::{
ComponentsBuilder, ExecutorBuilder, NetworkBuilder, PayloadServiceBuilder, PoolBuilder,
},
node::{FullNodeTypes, NodeTypes}, node::{FullNodeTypes, NodeTypes},
BuilderContext, Node, PayloadBuilderConfig, BuilderContext, Node, PayloadBuilderConfig,
}; };
@ -23,8 +25,13 @@ pub struct EthereumNode;
impl EthereumNode { impl EthereumNode {
/// Returns a [ComponentsBuilder] configured for a regular Ethereum node. /// Returns a [ComponentsBuilder] configured for a regular Ethereum node.
pub fn components<Node>( pub fn components<Node>() -> ComponentsBuilder<
) -> ComponentsBuilder<Node, EthereumPoolBuilder, EthereumPayloadBuilder, EthereumNetworkBuilder> Node,
EthereumPoolBuilder,
EthereumPayloadBuilder,
EthereumNetworkBuilder,
EthereumExecutorBuilder,
>
where where
Node: FullNodeTypes<Engine = EthEngineTypes>, Node: FullNodeTypes<Engine = EthEngineTypes>,
{ {
@ -33,31 +40,48 @@ impl EthereumNode {
.pool(EthereumPoolBuilder::default()) .pool(EthereumPoolBuilder::default())
.payload(EthereumPayloadBuilder::default()) .payload(EthereumPayloadBuilder::default())
.network(EthereumNetworkBuilder::default()) .network(EthereumNetworkBuilder::default())
.executor(EthereumExecutorBuilder::default())
} }
} }
impl NodeTypes for EthereumNode { impl NodeTypes for EthereumNode {
type Primitives = (); type Primitives = ();
type Engine = EthEngineTypes; type Engine = EthEngineTypes;
type Evm = EthEvmConfig;
fn evm_config(&self) -> Self::Evm {
EthEvmConfig::default()
}
} }
impl<N> Node<N> for EthereumNode impl<N> Node<N> for EthereumNode
where where
N: FullNodeTypes<Engine = EthEngineTypes>, N: FullNodeTypes<Engine = EthEngineTypes>,
{ {
type ComponentsBuilder = type ComponentsBuilder = ComponentsBuilder<
ComponentsBuilder<N, EthereumPoolBuilder, EthereumPayloadBuilder, EthereumNetworkBuilder>; N,
EthereumPoolBuilder,
EthereumPayloadBuilder,
EthereumNetworkBuilder,
EthereumExecutorBuilder,
>;
fn components_builder(self) -> Self::ComponentsBuilder { fn components_builder(self) -> Self::ComponentsBuilder {
Self::components() Self::components()
} }
} }
/// A regular ethereum evm and executor builder.
#[derive(Debug, Default, Clone, Copy)]
#[non_exhaustive]
pub struct EthereumExecutorBuilder;
impl<Node> ExecutorBuilder<Node> for EthereumExecutorBuilder
where
Node: FullNodeTypes,
{
type EVM = EthEvmConfig;
async fn build_evm(self, _ctx: &BuilderContext<Node>) -> eyre::Result<Self::EVM> {
Ok(EthEvmConfig::default())
}
}
/// A basic ethereum transaction pool. /// A basic ethereum transaction pool.
/// ///
/// This contains various settings that can be configured and take precedence over the node's /// This contains various settings that can be configured and take precedence over the node's

View File

@ -13,7 +13,7 @@ fn test_basic_setup() {
let msg = "On components".to_string(); let msg = "On components".to_string();
let _builder = NodeBuilder::new(config) let _builder = NodeBuilder::new(config)
.with_database(db) .with_database(db)
.with_types(EthereumNode::default()) .with_types::<EthereumNode>()
.with_components(EthereumNode::components()) .with_components(EthereumNode::components())
.on_component_initialized(move |ctx| { .on_component_initialized(move |ctx| {
let _provider = ctx.provider(); let _provider = ctx.provider();

View File

@ -31,7 +31,7 @@ fn basic_exex() {
let db = create_test_rw_db(); let db = create_test_rw_db();
let _builder = NodeBuilder::new(config) let _builder = NodeBuilder::new(config)
.with_database(db) .with_database(db)
.with_types(EthereumNode::default()) .with_types::<EthereumNode>()
.with_components(EthereumNode::components()) .with_components(EthereumNode::components())
.install_exex("dummy", move |ctx| future::ok(DummyExEx { _ctx: ctx })) .install_exex("dummy", move |ctx| future::ok(DummyExEx { _ctx: ctx }))
.check_launch(); .check_launch();

View File

@ -1,4 +1,4 @@
//! Traits for configuring a node //! Traits for configuring a node.
use crate::{primitives::NodePrimitives, ConfigureEvm, EngineTypes}; use crate::{primitives::NodePrimitives, ConfigureEvm, EngineTypes};
use reth_db::{ use reth_db::{
@ -15,21 +15,20 @@ use std::marker::PhantomData;
/// The type that configures the essential types of an ethereum like node. /// The type that configures the essential types of an ethereum like node.
/// ///
/// This includes the primitive types of a node, the engine API types for communication with the /// This includes the primitive types of a node, the engine API types for communication with the
/// consensus layer, and the EVM configuration type for setting up the Ethereum Virtual Machine. /// consensus layer.
///
/// This trait is intended to be stateless and only define the types of the node.
pub trait NodeTypes: Send + Sync + 'static { pub trait NodeTypes: Send + Sync + 'static {
/// The node's primitive types, defining basic operations and structures. /// The node's primitive types, defining basic operations and structures.
type Primitives: NodePrimitives; type Primitives: NodePrimitives;
/// The node's engine types, defining the interaction with the consensus engine. /// The node's engine types, defining the interaction with the consensus engine.
type Engine: EngineTypes; type Engine: EngineTypes;
/// The node's EVM configuration, defining settings for the Ethereum Virtual Machine.
type Evm: ConfigureEvm;
/// Returns the node's evm config.
fn evm_config(&self) -> Self::Evm;
} }
/// A helper trait that is downstream of the [NodeTypes] trait and adds stateful components to the /// A helper trait that is downstream of the [NodeTypes] trait and adds stateful components to the
/// node. /// node.
///
/// Its types are configured by node internally and are not intended to be user configurable.
pub trait FullNodeTypes: NodeTypes + 'static { pub trait FullNodeTypes: NodeTypes + 'static {
/// Underlying database type used by the node to store and retrieve data. /// Underlying database type used by the node to store and retrieve data.
type DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static; type DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static;
@ -41,7 +40,7 @@ pub trait FullNodeTypes: NodeTypes + 'static {
#[derive(Debug)] #[derive(Debug)]
pub struct FullNodeTypesAdapter<Types, DB, Provider> { pub struct FullNodeTypesAdapter<Types, DB, Provider> {
/// An instance of the user configured node types. /// An instance of the user configured node types.
pub types: Types, pub types: PhantomData<Types>,
/// The database type used by the node. /// The database type used by the node.
pub db: PhantomData<DB>, pub db: PhantomData<DB>,
/// The provider type used by the node. /// The provider type used by the node.
@ -49,9 +48,15 @@ pub struct FullNodeTypesAdapter<Types, DB, Provider> {
} }
impl<Types, DB, Provider> FullNodeTypesAdapter<Types, DB, Provider> { impl<Types, DB, Provider> FullNodeTypesAdapter<Types, DB, Provider> {
/// Create a new adapter from the given node types. /// Create a new adapter with the configured types.
pub fn new(types: Types) -> Self { pub fn new() -> Self {
Self { types, db: Default::default(), provider: Default::default() } Self { types: Default::default(), db: Default::default(), provider: Default::default() }
}
}
impl<Types, DB, Provider> Default for FullNodeTypesAdapter<Types, DB, Provider> {
fn default() -> Self {
Self::new()
} }
} }
@ -63,11 +68,6 @@ where
{ {
type Primitives = Types::Primitives; type Primitives = Types::Primitives;
type Engine = Types::Engine; type Engine = Types::Engine;
type Evm = Types::Evm;
fn evm_config(&self) -> Self::Evm {
self.types.evm_config()
}
} }
impl<Types, DB, Provider> FullNodeTypes for FullNodeTypesAdapter<Types, DB, Provider> impl<Types, DB, Provider> FullNodeTypes for FullNodeTypesAdapter<Types, DB, Provider>
@ -85,9 +85,15 @@ pub trait FullNodeComponents: FullNodeTypes + 'static {
/// The transaction pool of the node. /// The transaction pool of the node.
type Pool: TransactionPool + Unpin; type Pool: TransactionPool + Unpin;
/// The node's EVM configuration, defining settings for the Ethereum Virtual Machine.
type Evm: ConfigureEvm;
/// Returns the transaction pool of the node. /// Returns the transaction pool of the node.
fn pool(&self) -> &Self::Pool; fn pool(&self) -> &Self::Pool;
/// Returns the node's evm config.
fn evm_config(&self) -> &Self::Evm;
/// Returns the provider of the node. /// Returns the provider of the node.
fn provider(&self) -> &Self::Provider; fn provider(&self) -> &Self::Provider;

View File

@ -50,10 +50,10 @@ pub type RethFullAdapter<DB, Types> = FullNodeTypesAdapter<Types, DB, Blockchain
/// example) and then proceeds to configure the core static types of the node: [NodeTypes], these /// example) and then proceeds to configure the core static types of the node: [NodeTypes], these
/// include the node's primitive types and the node's engine types. /// include the node's primitive types and the node's engine types.
/// ///
/// Next all stateful components of the node are configured, these include the /// Next all stateful components of the node are configured, these include all the
/// [ConfigureEvm](reth_node_api::evm::ConfigureEvm), the database [Database] and all the
/// components of the node that are downstream of those types, these include: /// components of the node that are downstream of those types, these include:
/// ///
/// - The EVM and Executor configuration: [ExecutorBuilder](crate::components::ExecutorBuilder)
/// - The transaction pool: [PoolBuilder] /// - The transaction pool: [PoolBuilder]
/// - The network: [NetworkBuilder](crate::components::NetworkBuilder) /// - The network: [NetworkBuilder](crate::components::NetworkBuilder)
/// - The payload builder: [PayloadBuilder](crate::components::PayloadServiceBuilder) /// - The payload builder: [PayloadBuilder](crate::components::PayloadServiceBuilder)
@ -71,9 +71,10 @@ pub type RethFullAdapter<DB, Types> = FullNodeTypesAdapter<Types, DB, Blockchain
/// ## Components /// ## Components
/// ///
/// All components are configured with a [NodeComponentsBuilder] that is responsible for actually /// All components are configured with a [NodeComponentsBuilder] that is responsible for actually
/// creating the node components during the launch process. The [ComponentsBuilder] is a general /// creating the node components during the launch process. The
/// purpose implementation of the [NodeComponentsBuilder] trait that can be used to configure the /// [ComponentsBuilder](crate::components::ComponentsBuilder) is a general purpose implementation of
/// network, transaction pool and payload builder of the node. It enforces the correct order of /// the [NodeComponentsBuilder] trait that can be used to configure the executor, network,
/// transaction pool and payload builder of the node. It enforces the correct order of
/// configuration, for example the network and the payload builder depend on the transaction pool /// configuration, for example the network and the payload builder depend on the transaction pool
/// type that is configured first. /// type that is configured first.
/// ///
@ -127,8 +128,8 @@ pub type RethFullAdapter<DB, Types> = FullNodeTypesAdapter<Types, DB, Blockchain
/// ### Limitations /// ### Limitations
/// ///
/// Currently the launch process is limited to ethereum nodes and requires all the components /// Currently the launch process is limited to ethereum nodes and requires all the components
/// specified above. It also expect beacon consensus with the ethereum engine API that is configured /// specified above. It also expects beacon consensus with the ethereum engine API that is
/// by the builder itself during launch. This might change in the future. /// configured by the builder itself during launch. This might change in the future.
/// ///
/// [builder]: https://doc.rust-lang.org/1.0.0/style/ownership/builders.html /// [builder]: https://doc.rust-lang.org/1.0.0/style/ownership/builders.html
pub struct NodeBuilder<DB> { pub struct NodeBuilder<DB> {
@ -187,12 +188,11 @@ where
DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static, DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static,
{ {
/// Configures the types of the node. /// Configures the types of the node.
pub fn with_types<T>(self, types: T) -> NodeBuilderWithTypes<RethFullAdapter<DB, T>> pub fn with_types<T>(self) -> NodeBuilderWithTypes<RethFullAdapter<DB, T>>
where where
T: NodeTypes, T: NodeTypes,
{ {
let types = FullNodeTypesAdapter::new(types); NodeBuilderWithTypes::new(self.config, self.database)
NodeBuilderWithTypes::new(self.config, types, self.database)
} }
/// Preconfigures the node with a specific node implementation. /// Preconfigures the node with a specific node implementation.
@ -205,7 +205,7 @@ where
where where
N: Node<RethFullAdapter<DB, N>>, N: Node<RethFullAdapter<DB, N>>,
{ {
self.with_types(node.clone()).with_components(node.components_builder()) self.with_types().with_components(node.components_builder())
} }
} }
@ -236,15 +236,12 @@ where
DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static, DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static,
{ {
/// Configures the types of the node. /// Configures the types of the node.
pub fn with_types<T>( pub fn with_types<T>(self) -> WithLaunchContext<NodeBuilderWithTypes<RethFullAdapter<DB, T>>>
self,
types: T,
) -> WithLaunchContext<NodeBuilderWithTypes<RethFullAdapter<DB, T>>>
where where
T: NodeTypes, T: NodeTypes,
{ {
WithLaunchContext { WithLaunchContext {
builder: self.builder.with_types(types), builder: self.builder.with_types(),
task_executor: self.task_executor, task_executor: self.task_executor,
data_dir: self.data_dir, data_dir: self.data_dir,
} }
@ -260,7 +257,7 @@ where
where where
N: Node<RethFullAdapter<DB, N>>, N: Node<RethFullAdapter<DB, N>>,
{ {
self.with_types(node.clone()).with_components(node.components_builder()) self.with_types().with_components(node.components_builder())
} }
/// Launches a preconfigured [Node] /// Launches a preconfigured [Node]
@ -428,8 +425,6 @@ pub struct BuilderContext<Node: FullNodeTypes> {
pub(crate) config: NodeConfig, pub(crate) config: NodeConfig,
/// loaded config /// loaded config
pub(crate) reth_config: reth_config::Config, pub(crate) reth_config: reth_config::Config,
/// EVM config of the node
pub(crate) evm_config: Node::Evm,
} }
impl<Node: FullNodeTypes> BuilderContext<Node> { impl<Node: FullNodeTypes> BuilderContext<Node> {
@ -441,9 +436,8 @@ impl<Node: FullNodeTypes> BuilderContext<Node> {
data_dir: ChainPath<DataDirPath>, data_dir: ChainPath<DataDirPath>,
config: NodeConfig, config: NodeConfig,
reth_config: reth_config::Config, reth_config: reth_config::Config,
evm_config: Node::Evm,
) -> Self { ) -> Self {
Self { head, provider, executor, data_dir, config, reth_config, evm_config } Self { head, provider, executor, data_dir, config, reth_config }
} }
/// Returns the configured provider to interact with the blockchain. /// Returns the configured provider to interact with the blockchain.
@ -451,11 +445,6 @@ impl<Node: FullNodeTypes> BuilderContext<Node> {
&self.provider &self.provider
} }
/// Returns the configured evm.
pub fn evm_config(&self) -> &Node::Evm {
&self.evm_config
}
/// Returns the current head of the blockchain at launch. /// Returns the current head of the blockchain at launch.
pub fn head(&self) -> Head { pub fn head(&self) -> Head {
self.head self.head

View File

@ -31,8 +31,8 @@ pub struct NodeBuilderWithTypes<T: FullNodeTypes> {
impl<T: FullNodeTypes> NodeBuilderWithTypes<T> { impl<T: FullNodeTypes> NodeBuilderWithTypes<T> {
/// Creates a new instance of the node builder with the given configuration and types. /// Creates a new instance of the node builder with the given configuration and types.
pub fn new(config: NodeConfig, types: T, database: T::DB) -> Self { pub fn new(config: NodeConfig, database: T::DB) -> Self {
Self { config, adapter: NodeTypesAdapter::new(types, database) } Self { config, adapter: NodeTypesAdapter::new(database) }
} }
/// Advances the state of the node builder to the next state where all components are configured /// Advances the state of the node builder to the next state where all components are configured
@ -59,14 +59,12 @@ impl<T: FullNodeTypes> NodeBuilderWithTypes<T> {
pub(crate) struct NodeTypesAdapter<T: FullNodeTypes> { pub(crate) struct NodeTypesAdapter<T: FullNodeTypes> {
/// The database type used by the node. /// The database type used by the node.
pub(crate) database: T::DB, pub(crate) database: T::DB,
// TODO(mattsse): make this stateless
pub(crate) types: T,
} }
impl<T: FullNodeTypes> NodeTypesAdapter<T> { impl<T: FullNodeTypes> NodeTypesAdapter<T> {
/// Create a new adapter from the given node types. /// Create a new adapter from the given node types.
pub(crate) fn new(types: T, database: T::DB) -> Self { pub(crate) fn new(database: T::DB) -> Self {
Self { types, database } Self { database }
} }
} }
@ -85,18 +83,11 @@ pub struct NodeAdapter<T: FullNodeTypes, C: NodeComponents<T>> {
pub task_executor: TaskExecutor, pub task_executor: TaskExecutor,
/// The provider of the node. /// The provider of the node.
pub provider: T::Provider, pub provider: T::Provider,
/// EVM config
pub evm: T::Evm,
} }
impl<T: FullNodeTypes, C: NodeComponents<T>> NodeTypes for NodeAdapter<T, C> { impl<T: FullNodeTypes, C: NodeComponents<T>> NodeTypes for NodeAdapter<T, C> {
type Primitives = T::Primitives; type Primitives = T::Primitives;
type Engine = T::Engine; type Engine = T::Engine;
type Evm = T::Evm;
fn evm_config(&self) -> Self::Evm {
self.evm.clone()
}
} }
impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeTypes for NodeAdapter<T, C> { impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeTypes for NodeAdapter<T, C> {
@ -106,11 +97,16 @@ impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeTypes for NodeAdapter<T, C>
impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeComponents for NodeAdapter<T, C> { impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeComponents for NodeAdapter<T, C> {
type Pool = C::Pool; type Pool = C::Pool;
type Evm = C::Evm;
fn pool(&self) -> &Self::Pool { fn pool(&self) -> &Self::Pool {
self.components.pool() self.components.pool()
} }
fn evm_config(&self) -> &Self::Evm {
self.components.evm_config()
}
fn provider(&self) -> &Self::Provider { fn provider(&self) -> &Self::Provider {
&self.provider &self.provider
} }
@ -134,7 +130,6 @@ impl<T: FullNodeTypes, C: NodeComponents<T>> Clone for NodeAdapter<T, C> {
components: self.components.clone(), components: self.components.clone(),
task_executor: self.task_executor.clone(), task_executor: self.task_executor.clone(),
provider: self.provider.clone(), provider: self.provider.clone(),
evm: self.evm.clone(),
} }
} }
} }

View File

@ -1,13 +1,16 @@
//! A generic [NodeComponentsBuilder] //! A generic [NodeComponentsBuilder]
use crate::{ use crate::{
components::{Components, NetworkBuilder, NodeComponents, PayloadServiceBuilder, PoolBuilder}, components::{
BuilderContext, FullNodeTypes, Components, ExecutorBuilder, NetworkBuilder, NodeComponents, PayloadServiceBuilder,
PoolBuilder,
},
BuilderContext, ConfigureEvm, FullNodeTypes,
}; };
use reth_transaction_pool::TransactionPool; use reth_transaction_pool::TransactionPool;
use std::{future::Future, marker::PhantomData}; use std::{future::Future, marker::PhantomData};
/// A generic, customizable [`NodeComponentsBuilder`]. /// A generic, general purpose and customizable [`NodeComponentsBuilder`] implementation.
/// ///
/// This type is stateful and captures the configuration of the node's components. /// This type is stateful and captures the configuration of the node's components.
/// ///
@ -27,21 +30,31 @@ use std::{future::Future, marker::PhantomData};
/// All component builders are captured in the builder state and will be consumed once the node is /// All component builders are captured in the builder state and will be consumed once the node is
/// launched. /// launched.
#[derive(Debug)] #[derive(Debug)]
pub struct ComponentsBuilder<Node, PoolB, PayloadB, NetworkB> { pub struct ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB> {
pool_builder: PoolB, pool_builder: PoolB,
payload_builder: PayloadB, payload_builder: PayloadB,
network_builder: NetworkB, network_builder: NetworkB,
executor_builder: ExecB,
_marker: PhantomData<Node>, _marker: PhantomData<Node>,
} }
impl<Node, PoolB, PayloadB, NetworkB> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB> { impl<Node, PoolB, PayloadB, NetworkB, ExecB>
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB>
{
/// Configures the node types. /// Configures the node types.
pub fn node_types<Types>(self) -> ComponentsBuilder<Types, PoolB, PayloadB, NetworkB> pub fn node_types<Types>(self) -> ComponentsBuilder<Types, PoolB, PayloadB, NetworkB, ExecB>
where where
Types: FullNodeTypes, Types: FullNodeTypes,
{ {
let Self { pool_builder, payload_builder, network_builder, _marker } = self; let Self {
pool_builder,
payload_builder,
network_builder,
executor_builder: evm_builder,
_marker,
} = self;
ComponentsBuilder { ComponentsBuilder {
executor_builder: evm_builder,
pool_builder, pool_builder,
payload_builder, payload_builder,
network_builder, network_builder,
@ -55,6 +68,7 @@ impl<Node, PoolB, PayloadB, NetworkB> ComponentsBuilder<Node, PoolB, PayloadB, N
pool_builder: f(self.pool_builder), pool_builder: f(self.pool_builder),
payload_builder: self.payload_builder, payload_builder: self.payload_builder,
network_builder: self.network_builder, network_builder: self.network_builder,
executor_builder: self.executor_builder,
_marker: self._marker, _marker: self._marker,
} }
} }
@ -65,6 +79,7 @@ impl<Node, PoolB, PayloadB, NetworkB> ComponentsBuilder<Node, PoolB, PayloadB, N
pool_builder: self.pool_builder, pool_builder: self.pool_builder,
payload_builder: f(self.payload_builder), payload_builder: f(self.payload_builder),
network_builder: self.network_builder, network_builder: self.network_builder,
executor_builder: self.executor_builder,
_marker: self._marker, _marker: self._marker,
} }
} }
@ -75,12 +90,25 @@ impl<Node, PoolB, PayloadB, NetworkB> ComponentsBuilder<Node, PoolB, PayloadB, N
pool_builder: self.pool_builder, pool_builder: self.pool_builder,
payload_builder: self.payload_builder, payload_builder: self.payload_builder,
network_builder: f(self.network_builder), network_builder: f(self.network_builder),
executor_builder: self.executor_builder,
_marker: self._marker,
}
}
/// Apply a function to the executor builder.
pub fn map_executor(self, f: impl FnOnce(ExecB) -> ExecB) -> Self {
Self {
pool_builder: self.pool_builder,
payload_builder: self.payload_builder,
network_builder: self.network_builder,
executor_builder: f(self.executor_builder),
_marker: self._marker, _marker: self._marker,
} }
} }
} }
impl<Node, PoolB, PayloadB, NetworkB> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB> impl<Node, PoolB, PayloadB, NetworkB, ExecB>
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB>
where where
Node: FullNodeTypes, Node: FullNodeTypes,
{ {
@ -88,16 +116,32 @@ where
/// ///
/// This accepts a [PoolBuilder] instance that will be used to create the node's transaction /// This accepts a [PoolBuilder] instance that will be used to create the node's transaction
/// pool. /// pool.
pub fn pool<PB>(self, pool_builder: PB) -> ComponentsBuilder<Node, PB, PayloadB, NetworkB> pub fn pool<PB>(
self,
pool_builder: PB,
) -> ComponentsBuilder<Node, PB, PayloadB, NetworkB, ExecB>
where where
PB: PoolBuilder<Node>, PB: PoolBuilder<Node>,
{ {
let Self { pool_builder: _, payload_builder, network_builder, _marker } = self; let Self {
ComponentsBuilder { pool_builder, payload_builder, network_builder, _marker } pool_builder: _,
payload_builder,
network_builder,
executor_builder: evm_builder,
_marker,
} = self;
ComponentsBuilder {
pool_builder,
payload_builder,
network_builder,
executor_builder: evm_builder,
_marker,
}
} }
} }
impl<Node, PoolB, PayloadB, NetworkB> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB> impl<Node, PoolB, PayloadB, NetworkB, ExecB>
ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB>
where where
Node: FullNodeTypes, Node: FullNodeTypes,
PoolB: PoolBuilder<Node>, PoolB: PoolBuilder<Node>,
@ -106,57 +150,118 @@ where
/// ///
/// This accepts a [NetworkBuilder] instance that will be used to create the node's network /// This accepts a [NetworkBuilder] instance that will be used to create the node's network
/// stack. /// stack.
pub fn network<NB>(self, network_builder: NB) -> ComponentsBuilder<Node, PoolB, PayloadB, NB> pub fn network<NB>(
self,
network_builder: NB,
) -> ComponentsBuilder<Node, PoolB, PayloadB, NB, ExecB>
where where
NB: NetworkBuilder<Node, PoolB::Pool>, NB: NetworkBuilder<Node, PoolB::Pool>,
{ {
let Self { pool_builder, payload_builder, network_builder: _, _marker } = self; let Self {
ComponentsBuilder { pool_builder, payload_builder, network_builder, _marker } pool_builder,
payload_builder,
network_builder: _,
executor_builder: evm_builder,
_marker,
} = self;
ComponentsBuilder {
pool_builder,
payload_builder,
network_builder,
executor_builder: evm_builder,
_marker,
}
} }
/// Configures the payload builder. /// Configures the payload builder.
/// ///
/// This accepts a [PayloadServiceBuilder] instance that will be used to create the node's /// This accepts a [PayloadServiceBuilder] instance that will be used to create the node's
/// payload builder service. /// payload builder service.
pub fn payload<PB>(self, payload_builder: PB) -> ComponentsBuilder<Node, PoolB, PB, NetworkB> pub fn payload<PB>(
self,
payload_builder: PB,
) -> ComponentsBuilder<Node, PoolB, PB, NetworkB, ExecB>
where where
PB: PayloadServiceBuilder<Node, PoolB::Pool>, PB: PayloadServiceBuilder<Node, PoolB::Pool>,
{ {
let Self { pool_builder, payload_builder: _, network_builder, _marker } = self; let Self {
ComponentsBuilder { pool_builder, payload_builder, network_builder, _marker } pool_builder,
payload_builder: _,
network_builder,
executor_builder: evm_builder,
_marker,
} = self;
ComponentsBuilder {
pool_builder,
payload_builder,
network_builder,
executor_builder: evm_builder,
_marker,
}
}
/// Configures the executor builder.
///
/// This accepts a [ExecutorBuilder] instance that will be used to create the node's components
/// for execution.
pub fn executor<EB>(
self,
executor_builder: EB,
) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, EB>
where
EB: ExecutorBuilder<Node>,
{
let Self { pool_builder, payload_builder, network_builder, executor_builder: _, _marker } =
self;
ComponentsBuilder {
pool_builder,
payload_builder,
network_builder,
executor_builder,
_marker,
}
} }
} }
impl<Node, PoolB, PayloadB, NetworkB> NodeComponentsBuilder<Node> impl<Node, PoolB, PayloadB, NetworkB, ExecB> NodeComponentsBuilder<Node>
for ComponentsBuilder<Node, PoolB, PayloadB, NetworkB> for ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB>
where where
Node: FullNodeTypes, Node: FullNodeTypes,
PoolB: PoolBuilder<Node>, PoolB: PoolBuilder<Node>,
NetworkB: NetworkBuilder<Node, PoolB::Pool>, NetworkB: NetworkBuilder<Node, PoolB::Pool>,
PayloadB: PayloadServiceBuilder<Node, PoolB::Pool>, PayloadB: PayloadServiceBuilder<Node, PoolB::Pool>,
ExecB: ExecutorBuilder<Node>,
{ {
type Components = Components<Node, PoolB::Pool>; type Components = Components<Node, PoolB::Pool, ExecB::EVM>;
async fn build_components( async fn build_components(
self, self,
context: &BuilderContext<Node>, context: &BuilderContext<Node>,
) -> eyre::Result<Self::Components> { ) -> eyre::Result<Self::Components> {
let Self { pool_builder, payload_builder, network_builder, _marker } = self; let Self {
pool_builder,
payload_builder,
network_builder,
executor_builder: evm_builder,
_marker,
} = self;
let evm_config = evm_builder.build_evm(context).await?;
let pool = pool_builder.build_pool(context).await?; let pool = pool_builder.build_pool(context).await?;
let network = network_builder.build_network(context, pool.clone()).await?; let network = network_builder.build_network(context, pool.clone()).await?;
let payload_builder = payload_builder.spawn_payload_service(context, pool.clone()).await?; let payload_builder = payload_builder.spawn_payload_service(context, pool.clone()).await?;
Ok(Components { transaction_pool: pool, network, payload_builder }) Ok(Components { transaction_pool: pool, evm_config, network, payload_builder })
} }
} }
impl Default for ComponentsBuilder<(), (), (), ()> { impl Default for ComponentsBuilder<(), (), (), (), ()> {
fn default() -> Self { fn default() -> Self {
Self { Self {
pool_builder: (), pool_builder: (),
payload_builder: (), payload_builder: (),
network_builder: (), network_builder: (),
executor_builder: (),
_marker: Default::default(), _marker: Default::default(),
} }
} }
@ -167,9 +272,9 @@ impl Default for ComponentsBuilder<(), (), (), ()> {
/// Implementers of this trait are responsible for building all the components of the node: See /// Implementers of this trait are responsible for building all the components of the node: See
/// [NodeComponents]. /// [NodeComponents].
/// ///
/// The [ComponentsBuilder] is a generic implementation of this trait that can be used to customize /// The [ComponentsBuilder] is a generic, general purpose implementation of this trait that can be
/// certain components of the node using the builder pattern and defaults, e.g. Ethereum and /// used to customize certain components of the node using the builder pattern and defaults, e.g.
/// Optimism. /// Ethereum and Optimism.
/// A type that's responsible for building the components of the node. /// A type that's responsible for building the components of the node.
pub trait NodeComponentsBuilder<Node: FullNodeTypes>: Send { pub trait NodeComponentsBuilder<Node: FullNodeTypes>: Send {
/// The components for the node with the given types /// The components for the node with the given types
@ -182,14 +287,15 @@ pub trait NodeComponentsBuilder<Node: FullNodeTypes>: Send {
) -> impl Future<Output = eyre::Result<Self::Components>> + Send; ) -> impl Future<Output = eyre::Result<Self::Components>> + Send;
} }
impl<Node, F, Fut, Pool> NodeComponentsBuilder<Node> for F impl<Node, F, Fut, Pool, EVM> NodeComponentsBuilder<Node> for F
where where
Node: FullNodeTypes, Node: FullNodeTypes,
F: FnOnce(&BuilderContext<Node>) -> Fut + Send, F: FnOnce(&BuilderContext<Node>) -> Fut + Send,
Fut: Future<Output = eyre::Result<Components<Node, Pool>>> + Send, Fut: Future<Output = eyre::Result<Components<Node, Pool, EVM>>> + Send,
Pool: TransactionPool + Unpin + 'static, Pool: TransactionPool + Unpin + 'static,
EVM: ConfigureEvm,
{ {
type Components = Components<Node, Pool>; type Components = Components<Node, Pool, EVM>;
fn build_components( fn build_components(
self, self,

View File

@ -0,0 +1,34 @@
//! EVM component for the node builder.
use crate::{BuilderContext, FullNodeTypes};
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.
type EVM: ConfigureEvm;
// TODO(mattsse): integrate `Executor`
/// Creates the transaction pool.
fn build_evm(
self,
ctx: &BuilderContext<Node>,
) -> impl Future<Output = eyre::Result<Self::EVM>> + Send;
}
impl<Node, F, Fut, EVM> ExecutorBuilder<Node> for F
where
Node: FullNodeTypes,
EVM: ConfigureEvm,
F: FnOnce(&BuilderContext<Node>) -> Fut + Send,
Fut: Future<Output = eyre::Result<EVM>> + Send,
{
type EVM = EVM;
fn build_evm(
self,
ctx: &BuilderContext<Node>,
) -> impl Future<Output = eyre::Result<Self::EVM>> {
self(ctx)
}
}

View File

@ -7,8 +7,9 @@
//! //!
//! Components depend on a fully type configured node: [FullNodeTypes](crate::node::FullNodeTypes). //! Components depend on a fully type configured node: [FullNodeTypes](crate::node::FullNodeTypes).
use crate::FullNodeTypes; use crate::{ConfigureEvm, FullNodeTypes};
pub use builder::*; pub use builder::*;
pub use execute::*;
pub use network::*; pub use network::*;
pub use payload::*; pub use payload::*;
pub use pool::*; pub use pool::*;
@ -17,11 +18,13 @@ use reth_payload_builder::PayloadBuilderHandle;
use reth_transaction_pool::TransactionPool; use reth_transaction_pool::TransactionPool;
mod builder; mod builder;
mod execute;
mod network; mod network;
mod payload; mod payload;
mod pool; mod pool;
/// An abstraction over the components of a node, consisting of: /// An abstraction over the components of a node, consisting of:
/// - evm and executor
/// - transaction pool /// - transaction pool
/// - network /// - network
/// - payload builder. /// - payload builder.
@ -29,9 +32,15 @@ pub trait NodeComponents<NodeTypes: FullNodeTypes>: Clone + Send + Sync + 'stati
/// The transaction pool of the node. /// The transaction pool of the node.
type Pool: TransactionPool + Unpin; type Pool: TransactionPool + Unpin;
/// The node's EVM configuration, defining settings for the Ethereum Virtual Machine.
type Evm: ConfigureEvm;
/// Returns the transaction pool of the node. /// Returns the transaction pool of the node.
fn pool(&self) -> &Self::Pool; fn pool(&self) -> &Self::Pool;
/// Returns the node's evm config.
fn evm_config(&self) -> &Self::Evm;
/// Returns the handle to the network /// Returns the handle to the network
fn network(&self) -> &NetworkHandle; fn network(&self) -> &NetworkHandle;
@ -43,26 +52,34 @@ pub trait NodeComponents<NodeTypes: FullNodeTypes>: Clone + Send + Sync + 'stati
/// ///
/// This provides access to all the components of the node. /// This provides access to all the components of the node.
#[derive(Debug)] #[derive(Debug)]
pub struct Components<Node: FullNodeTypes, Pool> { pub struct Components<Node: FullNodeTypes, Pool, EVM> {
/// The transaction pool of the node. /// The transaction pool of the node.
pub transaction_pool: Pool, pub transaction_pool: Pool,
/// The node's EVM configuration, defining settings for the Ethereum Virtual Machine.
pub evm_config: EVM,
/// The network implementation of the node. /// The network implementation of the node.
pub network: NetworkHandle, pub network: NetworkHandle,
/// The handle to the payload builder service. /// The handle to the payload builder service.
pub payload_builder: PayloadBuilderHandle<Node::Engine>, pub payload_builder: PayloadBuilderHandle<Node::Engine>,
} }
impl<Node, Pool> NodeComponents<Node> for Components<Node, Pool> impl<Node, Pool, EVM> NodeComponents<Node> for Components<Node, Pool, EVM>
where where
Node: FullNodeTypes, Node: FullNodeTypes,
Pool: TransactionPool + Unpin + 'static, Pool: TransactionPool + Unpin + 'static,
EVM: ConfigureEvm,
{ {
type Pool = Pool; type Pool = Pool;
type Evm = EVM;
fn pool(&self) -> &Self::Pool { fn pool(&self) -> &Self::Pool {
&self.transaction_pool &self.transaction_pool
} }
fn evm_config(&self) -> &Self::Evm {
&self.evm_config
}
fn network(&self) -> &NetworkHandle { fn network(&self) -> &NetworkHandle {
&self.network &self.network
} }
@ -72,14 +89,16 @@ where
} }
} }
impl<Node, Pool> Clone for Components<Node, Pool> impl<Node, Pool, EVM> Clone for Components<Node, Pool, EVM>
where where
Node: FullNodeTypes, Node: FullNodeTypes,
Pool: TransactionPool, Pool: TransactionPool,
EVM: ConfigureEvm,
{ {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
transaction_pool: self.transaction_pool.clone(), transaction_pool: self.transaction_pool.clone(),
evm_config: self.evm_config.clone(),
network: self.network.clone(), network: self.network.clone(),
payload_builder: self.payload_builder.clone(), payload_builder: self.payload_builder.clone(),
} }

View File

@ -40,6 +40,7 @@ use tokio::sync::{mpsc::unbounded_channel, oneshot};
pub mod common; pub mod common;
pub use common::LaunchContext; pub use common::LaunchContext;
use reth_blockchain_tree::noop::NoopBlockchainTree;
/// A general purpose trait that launches a new node of any kind. /// A general purpose trait that launches a new node of any kind.
/// ///
@ -83,7 +84,7 @@ where
) -> eyre::Result<Self::Node> { ) -> eyre::Result<Self::Node> {
let Self { ctx } = self; let Self { ctx } = self;
let NodeBuilderWithComponents { let NodeBuilderWithComponents {
adapter: NodeTypesAdapter { types, database }, adapter: NodeTypesAdapter { database },
components_builder, components_builder,
add_ons: NodeAddOns { hooks, rpc, exexs: installed_exex }, add_ons: NodeAddOns { hooks, rpc, exexs: installed_exex },
config, config,
@ -124,27 +125,22 @@ where
let sync_metrics_listener = reth_stages::MetricsListener::new(sync_metrics_rx); let sync_metrics_listener = reth_stages::MetricsListener::new(sync_metrics_rx);
ctx.task_executor().spawn_critical("stages metrics listener task", sync_metrics_listener); ctx.task_executor().spawn_critical("stages metrics listener task", sync_metrics_listener);
// Configure the blockchain tree for the node
let evm_config = types.evm_config();
let tree_config = BlockchainTreeConfig::default();
let tree_externals = TreeExternals::new(
ctx.provider_factory().clone(),
consensus.clone(),
EvmProcessorFactory::new(ctx.chain_spec(), evm_config.clone()),
);
let tree = BlockchainTree::new(tree_externals, tree_config, ctx.prune_modes())?
.with_sync_metrics_tx(sync_metrics_tx.clone());
let canon_state_notification_sender = tree.canon_state_notification_sender();
let blockchain_tree = Arc::new(ShareableBlockchainTree::new(tree));
debug!(target: "reth::cli", "configured blockchain tree");
// fetch the head block from the database // fetch the head block from the database
let head = ctx.lookup_head()?; let head = ctx.lookup_head()?;
// setup the blockchain provider // Configure the blockchain tree for the node
let blockchain_db = let tree_config = BlockchainTreeConfig::default();
BlockchainProvider::new(ctx.provider_factory().clone(), blockchain_tree.clone())?;
// NOTE: This is a temporary workaround to provide the canon state notification sender to the components builder because there's a cyclic dependency between the blockchain provider and the tree component. This will be removed once the Blockchain provider no longer depends on an instance of the tree: <https://github.com/paradigmxyz/reth/issues/7154>
let (canon_state_notification_sender, _receiver) =
tokio::sync::broadcast::channel(tree_config.max_reorg_depth() as usize * 2);
let blockchain_db = BlockchainProvider::new(
ctx.provider_factory().clone(),
Arc::new(NoopBlockchainTree::with_canon_state_notifications(
canon_state_notification_sender.clone(),
)),
)?;
let builder_ctx = BuilderContext::new( let builder_ctx = BuilderContext::new(
head, head,
@ -153,19 +149,37 @@ where
ctx.data_dir().clone(), ctx.data_dir().clone(),
ctx.node_config().clone(), ctx.node_config().clone(),
ctx.toml_config().clone(), ctx.toml_config().clone(),
evm_config.clone(),
); );
debug!(target: "reth::cli", "creating components"); debug!(target: "reth::cli", "creating components");
let components = components_builder.build_components(&builder_ctx).await?; let components = components_builder.build_components(&builder_ctx).await?;
let tree_externals = TreeExternals::new(
ctx.provider_factory().clone(),
consensus.clone(),
EvmProcessorFactory::new(ctx.chain_spec(), components.evm_config().clone()),
);
let tree = BlockchainTree::new(tree_externals, tree_config, ctx.prune_modes())?
.with_sync_metrics_tx(sync_metrics_tx.clone())
// Note: This is required because we need to ensure that both the components and the
// tree are using the same channel for canon state notifications. This will be removed
// once the Blockchain provider no longer depends on an instance of the tree
.with_canon_state_notification_sender(canon_state_notification_sender);
let canon_state_notification_sender = tree.canon_state_notification_sender();
let blockchain_tree = Arc::new(ShareableBlockchainTree::new(tree));
// Replace the tree component with the actual tree
let blockchain_db = blockchain_db.with_tree(blockchain_tree);
debug!(target: "reth::cli", "configured blockchain tree");
let NodeHooks { on_component_initialized, on_node_started, .. } = hooks; let NodeHooks { on_component_initialized, on_node_started, .. } = hooks;
let node_adapter = NodeAdapter { let node_adapter = NodeAdapter {
components, components,
task_executor: ctx.task_executor().clone(), task_executor: ctx.task_executor().clone(),
provider: blockchain_db.clone(), provider: blockchain_db.clone(),
evm: evm_config.clone(),
}; };
debug!(target: "reth::cli", "calling on_component_initialized hook"); debug!(target: "reth::cli", "calling on_component_initialized hook");
@ -225,7 +239,7 @@ where
}); });
// send notifications from the blockchain tree to exex manager // send notifications from the blockchain tree to exex manager
let mut canon_state_notifications = blockchain_tree.subscribe_to_canonical_state(); let mut canon_state_notifications = blockchain_db.subscribe_to_canonical_state();
let mut handle = exex_manager_handle.clone(); let mut handle = exex_manager_handle.clone();
ctx.task_executor().spawn_critical( ctx.task_executor().spawn_critical(
"exex manager blockchain tree notifications", "exex manager blockchain tree notifications",
@ -305,7 +319,7 @@ address.to_string(), format_ether(alloc.balance));
consensus_engine_tx.clone(), consensus_engine_tx.clone(),
canon_state_notification_sender, canon_state_notification_sender,
mining_mode, mining_mode,
evm_config.clone(), node_adapter.components.evm_config().clone(),
) )
.build(); .build();
@ -320,7 +334,7 @@ address.to_string(), format_ether(alloc.balance));
ctx.prune_config(), ctx.prune_config(),
max_block, max_block,
static_file_producer, static_file_producer,
evm_config, node_adapter.components.evm_config().clone(),
pipeline_exex_handle, pipeline_exex_handle,
) )
.await?; .await?;
@ -343,7 +357,7 @@ address.to_string(), format_ether(alloc.balance));
ctx.prune_config(), ctx.prune_config(),
max_block, max_block,
static_file_producer, static_file_producer,
evm_config, node_adapter.components.evm_config().clone(),
pipeline_exex_handle, pipeline_exex_handle,
) )
.await?; .await?;
@ -447,7 +461,7 @@ address.to_string(), format_ether(alloc.balance));
}); });
let full_node = FullNode { let full_node = FullNode {
evm_config: node_adapter.evm.clone(), evm_config: node_adapter.components.evm_config().clone(),
pool: node_adapter.components.pool().clone(), pool: node_adapter.components.pool().clone(),
network: node_adapter.components.network().clone(), network: node_adapter.components.network().clone(),
provider: node_adapter.provider.clone(), provider: node_adapter.provider.clone(),

View File

@ -274,7 +274,7 @@ where
.with_network(node.network().clone()) .with_network(node.network().clone())
.with_events(node.provider().clone()) .with_events(node.provider().clone())
.with_executor(node.task_executor().clone()) .with_executor(node.task_executor().clone())
.with_evm_config(node.evm_config()) .with_evm_config(node.evm_config().clone())
.build_with_auth_server(module_config, engine_api); .build_with_auth_server(module_config, engine_api);
let mut registry = RpcRegistry { registry }; let mut registry = RpcRegistry { registry };

View File

@ -6,10 +6,13 @@ use crate::{
OptimismEngineTypes, OptimismEngineTypes,
}; };
use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig}; use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig};
use reth_evm::ConfigureEvm;
use reth_evm_optimism::OptimismEvmConfig; use reth_evm_optimism::OptimismEvmConfig;
use reth_network::{NetworkHandle, NetworkManager}; use reth_network::{NetworkHandle, NetworkManager};
use reth_node_builder::{ use reth_node_builder::{
components::{ComponentsBuilder, NetworkBuilder, PayloadServiceBuilder, PoolBuilder}, components::{
ComponentsBuilder, ExecutorBuilder, NetworkBuilder, PayloadServiceBuilder, PoolBuilder,
},
node::{FullNodeTypes, NodeTypes}, node::{FullNodeTypes, NodeTypes},
BuilderContext, Node, PayloadBuilderConfig, BuilderContext, Node, PayloadBuilderConfig,
}; };
@ -38,7 +41,13 @@ impl OptimismNode {
/// Returns the components for the given [RollupArgs]. /// Returns the components for the given [RollupArgs].
pub fn components<Node>( pub fn components<Node>(
args: RollupArgs, args: RollupArgs,
) -> ComponentsBuilder<Node, OptimismPoolBuilder, OptimismPayloadBuilder, OptimismNetworkBuilder> ) -> ComponentsBuilder<
Node,
OptimismPoolBuilder,
OptimismPayloadBuilder,
OptimismNetworkBuilder,
OptimismExecutorBuilder,
>
where where
Node: FullNodeTypes<Engine = OptimismEngineTypes>, Node: FullNodeTypes<Engine = OptimismEngineTypes>,
{ {
@ -46,8 +55,12 @@ impl OptimismNode {
ComponentsBuilder::default() ComponentsBuilder::default()
.node_types::<Node>() .node_types::<Node>()
.pool(OptimismPoolBuilder::default()) .pool(OptimismPoolBuilder::default())
.payload(OptimismPayloadBuilder::new(compute_pending_block)) .payload(OptimismPayloadBuilder::new(
compute_pending_block,
OptimismEvmConfig::default(),
))
.network(OptimismNetworkBuilder { disable_txpool_gossip }) .network(OptimismNetworkBuilder { disable_txpool_gossip })
.executor(OptimismExecutorBuilder::default())
} }
} }
@ -55,8 +68,13 @@ impl<N> Node<N> for OptimismNode
where where
N: FullNodeTypes<Engine = OptimismEngineTypes>, N: FullNodeTypes<Engine = OptimismEngineTypes>,
{ {
type ComponentsBuilder = type ComponentsBuilder = ComponentsBuilder<
ComponentsBuilder<N, OptimismPoolBuilder, OptimismPayloadBuilder, OptimismNetworkBuilder>; N,
OptimismPoolBuilder,
OptimismPayloadBuilder,
OptimismNetworkBuilder,
OptimismExecutorBuilder,
>;
fn components_builder(self) -> Self::ComponentsBuilder { fn components_builder(self) -> Self::ComponentsBuilder {
let Self { args } = self; let Self { args } = self;
@ -67,10 +85,21 @@ where
impl NodeTypes for OptimismNode { impl NodeTypes for OptimismNode {
type Primitives = (); type Primitives = ();
type Engine = OptimismEngineTypes; type Engine = OptimismEngineTypes;
type Evm = OptimismEvmConfig; }
fn evm_config(&self) -> Self::Evm { /// A regular optimism evm and executor builder.
OptimismEvmConfig::default() #[derive(Debug, Default, Clone, Copy)]
#[non_exhaustive]
pub struct OptimismExecutorBuilder;
impl<Node> ExecutorBuilder<Node> for OptimismExecutorBuilder
where
Node: FullNodeTypes,
{
type EVM = OptimismEvmConfig;
async fn build_evm(self, _ctx: &BuilderContext<Node>) -> eyre::Result<Self::EVM> {
Ok(OptimismEvmConfig::default())
} }
} }
@ -151,7 +180,7 @@ where
/// A basic optimism payload service builder /// A basic optimism payload service builder
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct OptimismPayloadBuilder { pub struct OptimismPayloadBuilder<EVM = OptimismEvmConfig> {
/// By default the pending block equals the latest block /// By default the pending block equals the latest block
/// to save resources and not leak txs from the tx-pool, /// to save resources and not leak txs from the tx-pool,
/// this flag enables computing of the pending block /// this flag enables computing of the pending block
@ -161,19 +190,22 @@ pub struct OptimismPayloadBuilder {
/// will use the payload attributes from the latest block. Note /// will use the payload attributes from the latest block. Note
/// that this flag is not yet functional. /// that this flag is not yet functional.
pub compute_pending_block: bool, pub compute_pending_block: bool,
/// The EVM configuration to use for the payload builder.
pub evm_config: EVM,
} }
impl OptimismPayloadBuilder { impl<EVM> OptimismPayloadBuilder<EVM> {
/// Create a new instance with the given `compute_pending_block` flag. /// Create a new instance with the given `compute_pending_block` flag and evm config.
pub const fn new(compute_pending_block: bool) -> Self { pub const fn new(compute_pending_block: bool, evm_config: EVM) -> Self {
Self { compute_pending_block } Self { compute_pending_block, evm_config }
} }
} }
impl<Node, Pool> PayloadServiceBuilder<Node, Pool> for OptimismPayloadBuilder impl<Node, EVM, Pool> PayloadServiceBuilder<Node, Pool> for OptimismPayloadBuilder<EVM>
where where
Node: FullNodeTypes<Engine = OptimismEngineTypes>, Node: FullNodeTypes<Engine = OptimismEngineTypes>,
Pool: TransactionPool + Unpin + 'static, Pool: TransactionPool + Unpin + 'static,
EVM: ConfigureEvm,
{ {
async fn spawn_payload_service( async fn spawn_payload_service(
self, self,
@ -182,7 +214,7 @@ where
) -> eyre::Result<PayloadBuilderHandle<Node::Engine>> { ) -> eyre::Result<PayloadBuilderHandle<Node::Engine>> {
let payload_builder = reth_optimism_payload_builder::OptimismPayloadBuilder::new( let payload_builder = reth_optimism_payload_builder::OptimismPayloadBuilder::new(
ctx.chain_spec(), ctx.chain_spec(),
ctx.evm_config().clone(), self.evm_config,
) )
.set_compute_pending_block(self.compute_pending_block); .set_compute_pending_block(self.compute_pending_block);
let conf = ctx.payload_builder_config(); let conf = ctx.payload_builder_config();

View File

@ -12,7 +12,7 @@ fn test_basic_setup() {
let db = create_test_rw_db(); let db = create_test_rw_db();
let _builder = NodeBuilder::new(config) let _builder = NodeBuilder::new(config)
.with_database(db) .with_database(db)
.with_types(OptimismNode::default()) .with_types::<OptimismNode>()
.with_components(OptimismNode::components(Default::default())) .with_components(OptimismNode::components(Default::default()))
.on_component_initialized(move |ctx| { .on_component_initialized(move |ctx| {
let _provider = ctx.provider(); let _provider = ctx.provider();

View File

@ -89,6 +89,13 @@ impl<DB> BlockchainProvider<DB> {
) -> Self { ) -> Self {
Self { database, tree, chain_info: ChainInfoTracker::new(latest) } Self { database, tree, chain_info: ChainInfoTracker::new(latest) }
} }
/// Sets the treeviewer for the provider.
#[doc(hidden)]
pub fn with_tree(mut self, tree: Arc<dyn TreeViewer>) -> Self {
self.tree = tree;
self
}
} }
impl<DB> BlockchainProvider<DB> impl<DB> BlockchainProvider<DB>

View File

@ -37,9 +37,8 @@ use reth_node_api::{
EngineTypes, PayloadAttributes, PayloadBuilderAttributes, PayloadOrAttributes, EngineTypes, PayloadAttributes, PayloadBuilderAttributes, PayloadOrAttributes,
}; };
use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig}; use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};
use reth_node_ethereum::{ use reth_node_ethereum::node::{
node::{EthereumNetworkBuilder, EthereumPoolBuilder}, EthereumExecutorBuilder, EthereumNetworkBuilder, EthereumPoolBuilder,
EthEvmConfig,
}; };
use reth_payload_builder::{ use reth_payload_builder::{
error::PayloadBuilderError, EthBuiltPayload, EthPayloadBuilderAttributes, PayloadBuilderHandle, error::PayloadBuilderError, EthBuiltPayload, EthPayloadBuilderAttributes, PayloadBuilderHandle,
@ -187,12 +186,6 @@ impl NodeTypes for MyCustomNode {
type Primitives = (); type Primitives = ();
// use the custom engine types // use the custom engine types
type Engine = CustomEngineTypes; type Engine = CustomEngineTypes;
// use the default ethereum EVM config
type Evm = EthEvmConfig;
fn evm_config(&self) -> Self::Evm {
Self::Evm::default()
}
} }
/// Implement the Node trait for the custom node /// Implement the Node trait for the custom node
@ -207,6 +200,7 @@ where
EthereumPoolBuilder, EthereumPoolBuilder,
CustomPayloadServiceBuilder, CustomPayloadServiceBuilder,
EthereumNetworkBuilder, EthereumNetworkBuilder,
EthereumExecutorBuilder,
>; >;
fn components_builder(self) -> Self::ComponentsBuilder { fn components_builder(self) -> Self::ComponentsBuilder {
@ -215,6 +209,7 @@ where
.pool(EthereumPoolBuilder::default()) .pool(EthereumPoolBuilder::default())
.payload(CustomPayloadServiceBuilder::default()) .payload(CustomPayloadServiceBuilder::default())
.network(EthereumNetworkBuilder::default()) .network(EthereumNetworkBuilder::default())
.executor(EthereumExecutorBuilder::default())
} }
} }

View File

@ -3,7 +3,7 @@
#![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(not(test), warn(unused_crate_dependencies))]
use reth::{ use reth::{
builder::{node::NodeTypes, NodeBuilder}, builder::{components::ExecutorBuilder, BuilderContext, NodeBuilder},
primitives::{ primitives::{
address, address,
revm_primitives::{CfgEnvWithHandlerCfg, Env, PrecompileResult, TxEnv}, revm_primitives::{CfgEnvWithHandlerCfg, Env, PrecompileResult, TxEnv},
@ -17,9 +17,9 @@ use reth::{
}, },
tasks::TaskManager, tasks::TaskManager,
}; };
use reth_node_api::{ConfigureEvm, ConfigureEvmEnv}; use reth_node_api::{ConfigureEvm, ConfigureEvmEnv, FullNodeTypes};
use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig}; use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};
use reth_node_ethereum::{EthEngineTypes, EthEvmConfig, EthereumNode}; use reth_node_ethereum::{EthEvmConfig, EthereumNode};
use reth_primitives::{Chain, ChainSpec, Genesis, Header, Transaction}; use reth_primitives::{Chain, ChainSpec, Genesis, Header, Transaction};
use reth_tracing::{RethTracer, Tracer}; use reth_tracing::{RethTracer, Tracer};
use std::sync::Arc; use std::sync::Arc;
@ -104,18 +104,19 @@ impl ConfigureEvm for MyEvmConfig {
} }
} }
#[derive(Debug, Clone, Default)] /// A regular ethereum evm and executor builder.
#[derive(Debug, Default, Clone, Copy)]
#[non_exhaustive] #[non_exhaustive]
struct MyCustomNode; pub struct MyExecutorBuilder;
/// Configure the node types impl<Node> ExecutorBuilder<Node> for MyExecutorBuilder
impl NodeTypes for MyCustomNode { where
type Primitives = (); Node: FullNodeTypes,
type Engine = EthEngineTypes; {
type Evm = MyEvmConfig; type EVM = MyEvmConfig;
fn evm_config(&self) -> Self::Evm { async fn build_evm(self, _ctx: &BuilderContext<Node>) -> eyre::Result<Self::EVM> {
Self::Evm::default() Ok(MyEvmConfig::default())
} }
} }
@ -140,8 +141,8 @@ async fn main() -> eyre::Result<()> {
let handle = NodeBuilder::new(node_config) let handle = NodeBuilder::new(node_config)
.testing_node(tasks.executor()) .testing_node(tasks.executor())
.with_types(MyCustomNode::default()) .with_types::<EthereumNode>()
.with_components(EthereumNode::components()) .with_components(EthereumNode::components().executor(MyExecutorBuilder::default()))
.launch() .launch()
.await .await
.unwrap(); .unwrap();

View File

@ -19,7 +19,7 @@ fn main() {
.run(|builder, _| async move { .run(|builder, _| async move {
let handle = builder let handle = builder
// use the default ethereum node types // use the default ethereum node types
.with_types(EthereumNode::default()) .with_types::<EthereumNode>()
// Configure the components of the node // Configure the components of the node
// use default ethereum components but use our custom pool // use default ethereum components but use our custom pool
.with_components(EthereumNode::components().pool(CustomPoolBuilder::default())) .with_components(EthereumNode::components().pool(CustomPoolBuilder::default()))

View File

@ -73,7 +73,7 @@ fn main() {
Cli::parse_args() Cli::parse_args()
.run(|builder, _| async move { .run(|builder, _| async move {
let handle = builder let handle = builder
.with_types(EthereumNode::default()) .with_types::<EthereumNode>()
// Configure the components of the node // Configure the components of the node
// use default ethereum components but use our custom payload builder // use default ethereum components but use our custom payload builder
.with_components( .with_components(