node: revise NodeTypes trait (#10665)

This commit is contained in:
Thomas Coratger
2024-09-03 05:52:53 -07:00
committed by GitHub
parent 020597da32
commit d30e3a4888
11 changed files with 140 additions and 62 deletions

View File

@@ -17,55 +17,99 @@ use reth_transaction_pool::TransactionPool;
use crate::{primitives::NodePrimitives, ConfigureEvm, EngineTypes};
/// 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
/// consensus layer.
/// This includes the primitive types of a node.
///
/// This trait is intended to be stateless and only define the types of the node.
pub trait NodeTypes: Send + Sync + Unpin + 'static {
/// The node's primitive types, defining basic operations and structures.
type Primitives: NodePrimitives;
/// The node's engine types, defining the interaction with the consensus engine.
type Engine: EngineTypes;
/// The type used for configuration of the EVM.
type ChainSpec: EthChainSpec;
}
/// A [`NodeTypes`] type builder
#[derive(Default, Debug)]
pub struct AnyNodeTypes<P = (), E = (), C = ()>(PhantomData<P>, PhantomData<E>, PhantomData<C>);
/// The type that configures an Ethereum-like node with an engine for consensus.
pub trait NodeTypesWithEngine: NodeTypes {
/// The node's engine types, defining the interaction with the consensus engine.
type Engine: EngineTypes;
}
impl<P, E, C> AnyNodeTypes<P, E, C> {
/// A [`NodeTypes`] type builder.
#[derive(Default, Debug)]
pub struct AnyNodeTypes<P = (), C = ()>(PhantomData<P>, PhantomData<C>);
impl<P, C> AnyNodeTypes<P, C> {
/// Sets the `Primitives` associated type.
pub const fn primitives<T>(self) -> AnyNodeTypes<T, E, C> {
AnyNodeTypes::<T, E, C>(PhantomData::<T>, PhantomData::<E>, PhantomData::<C>)
pub const fn primitives<T>(self) -> AnyNodeTypes<T, C> {
AnyNodeTypes::<T, C>(PhantomData::<T>, PhantomData::<C>)
}
/// Sets the `Engine` associated type.
pub const fn engine<T>(self) -> AnyNodeTypes<P, T, C> {
AnyNodeTypes::<P, T, C>(PhantomData::<P>, PhantomData::<T>, PhantomData::<C>)
/// Sets the `ChainSpec` associated type.
pub const fn chain_spec<T>(self) -> AnyNodeTypes<P, T> {
AnyNodeTypes::<P, T>(PhantomData::<P>, PhantomData::<T>)
}
}
impl<P, E, C> NodeTypes for AnyNodeTypes<P, E, C>
impl<P, C> NodeTypes for AnyNodeTypes<P, C>
where
P: NodePrimitives + Send + Sync + Unpin + 'static,
C: EthChainSpec,
{
type Primitives = P;
type ChainSpec = C;
}
/// A [`NodeTypesWithEngine`] type builder.
#[derive(Default, Debug)]
pub struct AnyNodeTypesWithEngine<P = (), E = (), C = ()> {
/// Embedding the basic node types.
base: AnyNodeTypes<P, C>,
/// Phantom data for the engine.
_engine: PhantomData<E>,
}
impl<P, E, C> AnyNodeTypesWithEngine<P, E, C> {
/// Sets the `Primitives` associated type.
pub const fn primitives<T>(self) -> AnyNodeTypesWithEngine<T, E, C> {
AnyNodeTypesWithEngine { base: self.base.primitives::<T>(), _engine: PhantomData }
}
/// Sets the `Engine` associated type.
pub const fn engine<T>(self) -> AnyNodeTypesWithEngine<P, T, C> {
AnyNodeTypesWithEngine { base: self.base, _engine: PhantomData::<T> }
}
/// Sets the `ChainSpec` associated type.
pub const fn chain_spec<T>(self) -> AnyNodeTypesWithEngine<P, E, T> {
AnyNodeTypesWithEngine { base: self.base.chain_spec::<T>(), _engine: PhantomData }
}
}
impl<P, E, C> NodeTypes for AnyNodeTypesWithEngine<P, E, C>
where
P: NodePrimitives + Send + Sync + Unpin + 'static,
E: EngineTypes + Send + Sync + Unpin,
C: EthChainSpec,
{
type Primitives = P;
type Engine = E;
type ChainSpec = C;
}
/// A helper trait that is downstream of the [`NodeTypes`] trait and adds stateful components to the
/// node.
impl<P, E, C> NodeTypesWithEngine for AnyNodeTypesWithEngine<P, E, C>
where
P: NodePrimitives + Send + Sync + Unpin + 'static,
E: EngineTypes + Send + Sync + Unpin,
C: EthChainSpec,
{
type Engine = E;
}
/// A helper trait that is downstream of the [`NodeTypesWithEngine`] trait and adds stateful
/// components to the node.
///
/// Its types are configured by node internally and are not intended to be user configurable.
pub trait FullNodeTypes: NodeTypes<ChainSpec = ChainSpec> + 'static {
pub trait FullNodeTypes: NodeTypesWithEngine<ChainSpec = ChainSpec> + 'static {
/// Underlying database type used by the node to store and retrieve data.
type DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static;
/// The provider type used to interact with the node.
@@ -104,18 +148,26 @@ impl<Types, DB, Provider> Clone for FullNodeTypesAdapter<Types, DB, Provider> {
impl<Types, DB, Provider> NodeTypes for FullNodeTypesAdapter<Types, DB, Provider>
where
Types: NodeTypes,
Types: NodeTypesWithEngine,
DB: Send + Sync + Unpin + 'static,
Provider: Send + Sync + Unpin + 'static,
{
type Primitives = Types::Primitives;
type Engine = Types::Engine;
type ChainSpec = Types::ChainSpec;
}
impl<Types, DB, Provider> NodeTypesWithEngine for FullNodeTypesAdapter<Types, DB, Provider>
where
Types: NodeTypesWithEngine,
DB: Send + Sync + Unpin + 'static,
Provider: Send + Sync + Unpin + 'static,
{
type Engine = Types::Engine;
}
impl<Types, DB, Provider> FullNodeTypes for FullNodeTypesAdapter<Types, DB, Provider>
where
Types: NodeTypes<ChainSpec = ChainSpec>,
Types: NodeTypesWithEngine<ChainSpec = ChainSpec>,
Provider: FullProvider<DB, Types::ChainSpec>,
DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static,
{

View File

@@ -21,7 +21,7 @@ use reth_exex::ExExContext;
use reth_network::{
NetworkBuilder, NetworkConfig, NetworkConfigBuilder, NetworkHandle, NetworkManager,
};
use reth_node_api::{FullNodeTypes, FullNodeTypesAdapter, NodeAddOns, NodeTypes};
use reth_node_api::{FullNodeTypes, FullNodeTypesAdapter, NodeAddOns, NodeTypesWithEngine};
use reth_node_core::{
cli::config::{PayloadBuilderConfig, RethTransactionPoolConfig},
dirs::{ChainPath, DataDirPath},
@@ -58,8 +58,8 @@ pub type RethFullAdapter<DB, Types> = FullNodeTypesAdapter<Types, DB, Blockchain
/// ## Order
///
/// Configuring a node starts out with a [`NodeConfig`] (this can be obtained from cli arguments for
/// 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.
/// example) and then proceeds to configure the core static types of the node:
/// [`NodeTypesWithEngine`], these include the node's primitive types and the node's engine types.
///
/// Next all stateful components of the node are configured, these include all the
/// components of the node that are downstream of those types, these include:
@@ -125,10 +125,10 @@ pub type RethFullAdapter<DB, Types> = FullNodeTypesAdapter<Types, DB, Blockchain
///
/// ## Internals
///
/// The node builder is fully type safe, it uses the [`NodeTypes`] trait to enforce that all
/// components are configured with the correct types. However the database types and with that the
/// provider trait implementations are currently created by the builder itself during the launch
/// process, hence the database type is not part of the [`NodeTypes`] trait and the node's
/// The node builder is fully type safe, it uses the [`NodeTypesWithEngine`] trait to enforce that
/// all components are configured with the correct types. However the database types and with that
/// the provider trait implementations are currently created by the builder itself during the launch
/// process, hence the database type is not part of the [`NodeTypesWithEngine`] trait and the node's
/// components, that depend on the database, are configured separately. In order to have a nice
/// trait that encapsulates the entire node the
/// [`FullNodeComponents`](reth_node_api::FullNodeComponents) trait was introduced. This
@@ -208,7 +208,7 @@ where
/// Configures the types of the node.
pub fn with_types<T>(self) -> NodeBuilderWithTypes<RethFullAdapter<DB, T>>
where
T: NodeTypes<ChainSpec = ChainSpec>,
T: NodeTypesWithEngine<ChainSpec = ChainSpec>,
{
self.with_types_and_provider()
}
@@ -218,7 +218,7 @@ where
self,
) -> NodeBuilderWithTypes<FullNodeTypesAdapter<T, DB, P>>
where
T: NodeTypes<ChainSpec = ChainSpec>,
T: NodeTypesWithEngine<ChainSpec = ChainSpec>,
P: FullProvider<DB, T::ChainSpec>,
{
NodeBuilderWithTypes::new(self.config, self.database)
@@ -266,7 +266,7 @@ where
/// Configures the types of the node.
pub fn with_types<T>(self) -> WithLaunchContext<NodeBuilderWithTypes<RethFullAdapter<DB, T>>>
where
T: NodeTypes<ChainSpec = ChainSpec>,
T: NodeTypesWithEngine<ChainSpec = ChainSpec>,
{
WithLaunchContext { builder: self.builder.with_types(), task_executor: self.task_executor }
}
@@ -276,7 +276,7 @@ where
self,
) -> WithLaunchContext<NodeBuilderWithTypes<FullNodeTypesAdapter<T, DB, P>>>
where
T: NodeTypes<ChainSpec = ChainSpec>,
T: NodeTypesWithEngine<ChainSpec = ChainSpec>,
P: FullProvider<DB, T::ChainSpec>,
{
WithLaunchContext {
@@ -475,7 +475,7 @@ where
impl<T, DB, CB, AO> WithLaunchContext<NodeBuilderWithComponents<RethFullAdapter<DB, T>, CB, AO>>
where
DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static,
T: NodeTypes<ChainSpec = ChainSpec>,
T: NodeTypesWithEngine<ChainSpec = ChainSpec>,
CB: NodeComponentsBuilder<RethFullAdapter<DB, T>>,
AO: NodeAddOns<
NodeAdapter<RethFullAdapter<DB, T>, CB::Components>,

View File

@@ -8,7 +8,9 @@
use std::{fmt, future::Future, marker::PhantomData};
use reth_exex::ExExContext;
use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeAddOns, NodeTypes};
use reth_node_api::{
FullNodeComponents, FullNodeTypes, NodeAddOns, NodeTypes, NodeTypesWithEngine,
};
use reth_node_core::{
node_config::NodeConfig,
rpc::eth::{helpers::AddDevSigners, FullEthApiServer},
@@ -90,10 +92,13 @@ pub struct NodeAdapter<T: FullNodeTypes, C: NodeComponents<T>> {
impl<T: FullNodeTypes, C: NodeComponents<T>> NodeTypes for NodeAdapter<T, C> {
type Primitives = T::Primitives;
type Engine = T::Engine;
type ChainSpec = T::ChainSpec;
}
impl<T: FullNodeTypes, C: NodeComponents<T>> NodeTypesWithEngine for NodeAdapter<T, C> {
type Engine = T::Engine;
}
impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeTypes for NodeAdapter<T, C> {
type DB = T::DB;
type Provider = T::Provider;

View File

@@ -35,7 +35,9 @@ use crate::{ConfigureEvm, FullNodeTypes};
/// - transaction pool
/// - network
/// - payload builder.
pub trait NodeComponents<NodeTypes: FullNodeTypes>: Clone + Unpin + Send + Sync + 'static {
pub trait NodeComponents<NodeTypesWithEngine: FullNodeTypes>:
Clone + Unpin + Send + Sync + 'static
{
/// The transaction pool of the node.
type Pool: TransactionPool + Unpin;
@@ -67,7 +69,7 @@ pub trait NodeComponents<NodeTypes: FullNodeTypes>: Clone + Unpin + Send + Sync
fn network(&self) -> &Self::Network;
/// Returns the handle to the payload builder service.
fn payload_builder(&self) -> &PayloadBuilderHandle<NodeTypes::Engine>;
fn payload_builder(&self) -> &PayloadBuilderHandle<NodeTypesWithEngine::Engine>;
}
/// All the components of the node.

View File

@@ -1,5 +1,5 @@
// re-export the node api types
pub use reth_node_api::{FullNodeTypes, NodeTypes};
pub use reth_node_api::{FullNodeTypes, NodeTypes, NodeTypesWithEngine};
use std::{marker::PhantomData, sync::Arc};
@@ -20,10 +20,10 @@ use crate::{
NodeAdapter, NodeAddOns,
};
/// A [`crate::Node`] is a [`NodeTypes`] that comes with preconfigured components.
/// A [`crate::Node`] is a [`NodeTypesWithEngine`] that comes with preconfigured components.
///
/// This can be used to configure the builder with a preset of components.
pub trait Node<N: FullNodeTypes>: NodeTypes + Clone {
pub trait Node<N: FullNodeTypes>: NodeTypesWithEngine + Clone {
/// The type that builds the node's components.
type ComponentsBuilder: NodeComponentsBuilder<N>;
@@ -60,11 +60,18 @@ where
{
type Primitives = N::Primitives;
type Engine = N::Engine;
type ChainSpec = N::ChainSpec;
}
impl<N, C, AO> NodeTypesWithEngine for AnyNode<N, C, AO>
where
N: FullNodeTypes,
C: Send + Sync + Unpin + 'static,
AO: Send + Sync + Unpin + Clone + 'static,
{
type Engine = N::Engine;
}
impl<N, C, AO> Node<N> for AnyNode<N, C, AO>
where
N: FullNodeTypes + Clone,