chore(rpc): expose ethapi in node builder for op customisation (#9444)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
Emilia Hane
2024-07-16 15:53:03 +02:00
committed by GitHub
parent fcc6307ada
commit 2aa94e9aee
53 changed files with 1117 additions and 664 deletions

View File

@ -1,6 +1,7 @@
//! Traits for configuring a node.
use crate::{primitives::NodePrimitives, ConfigureEvm, EngineTypes};
use std::marker::PhantomData;
use reth_db_api::{
database::Database,
database_metrics::{DatabaseMetadata, DatabaseMetrics},
@ -11,7 +12,8 @@ use reth_payload_builder::PayloadBuilderHandle;
use reth_provider::FullProvider;
use reth_tasks::TaskExecutor;
use reth_transaction_pool::TransactionPool;
use std::marker::PhantomData;
use crate::{primitives::NodePrimitives, ConfigureEvm, EngineTypes};
/// The type that configures the essential types of an ethereum like node.
///
@ -145,3 +147,34 @@ pub trait FullNodeComponents: FullNodeTypes + Clone + 'static {
/// Returns the task executor.
fn task_executor(&self) -> &TaskExecutor;
}
/// Customizable node add-on types.
pub trait NodeAddOns<N: FullNodeComponents>: Send + Sync + Unpin + Clone + 'static {
/// The core `eth` namespace API type to install on the RPC server (see
/// `reth_rpc_eth_api::EthApiServer`).
type EthApi: Send + Clone;
}
impl<N: FullNodeComponents> NodeAddOns<N> for () {
type EthApi = ();
}
/// Returns the builder for type.
pub trait BuilderProvider<N: FullNodeComponents>: Send {
/// Context required to build type.
type Ctx<'a>;
/// Returns builder for type.
#[allow(clippy::type_complexity)]
fn builder() -> Box<dyn for<'a> Fn(Self::Ctx<'a>) -> Self + Send>;
}
impl<N: FullNodeComponents> BuilderProvider<N> for () {
type Ctx<'a> = ();
fn builder() -> Box<dyn for<'a> Fn(Self::Ctx<'a>) -> Self + Send> {
Box::new(noop_builder)
}
}
const fn noop_builder(_: ()) {}

View File

@ -47,6 +47,7 @@ reth-consensus-debug-client.workspace = true
reth-rpc-types.workspace = true
reth-engine-util.workspace = true
reth-cli-util.workspace = true
reth-rpc-eth-types.workspace = true
## async
futures.workspace = true

View File

@ -0,0 +1,29 @@
//! Node add-ons. Depend on core [`NodeComponents`](crate::NodeComponents).
use std::marker::PhantomData;
use reth_node_api::{FullNodeComponents, NodeAddOns};
use crate::{exex::BoxedLaunchExEx, hooks::NodeHooks, rpc::RpcHooks};
/// Additional node extensions.
///
/// At this point we consider all necessary components defined.
pub struct AddOns<Node: FullNodeComponents, AddOns: NodeAddOns<Node>> {
/// Additional `NodeHooks` that are called at specific points in the node's launch lifecycle.
pub hooks: NodeHooks<Node, AddOns>,
/// The `ExExs` (execution extensions) of the node.
pub exexs: Vec<(String, Box<dyn BoxedLaunchExEx<Node>>)>,
/// Additional RPC add-ons.
pub rpc: RpcAddOns<Node, AddOns::EthApi>,
}
/// Captures node specific addons that can be installed on top of the type configured node and are
/// required for launching the node, such as RPC.
#[derive(Default)]
pub struct RpcAddOns<Node: FullNodeComponents, EthApi> {
/// Core `eth` API type to install on the RPC server, configured w.r.t. network.
pub _eth_api: PhantomData<EthApi>,
/// Additional RPC hooks.
pub hooks: RpcHooks<Node, EthApi>,
}

View File

@ -2,13 +2,13 @@
#![allow(clippy::type_complexity, missing_debug_implementations)]
use crate::{
common::WithConfigs,
components::NodeComponentsBuilder,
node::FullNode,
rpc::{RethRpcServerHandles, RpcContext},
DefaultNodeLauncher, Node, NodeHandle,
};
pub mod add_ons;
mod states;
pub use states::*;
use std::sync::Arc;
use futures::Future;
use reth_chainspec::ChainSpec;
use reth_cli_util::get_secret_key;
@ -20,23 +20,28 @@ use reth_exex::ExExContext;
use reth_network::{
NetworkBuilder, NetworkConfig, NetworkConfigBuilder, NetworkHandle, NetworkManager,
};
use reth_node_api::{FullNodeTypes, FullNodeTypesAdapter, NodeTypes};
use reth_node_api::{FullNodeTypes, FullNodeTypesAdapter, NodeAddOns, NodeTypes};
use reth_node_core::{
cli::config::{PayloadBuilderConfig, RethTransactionPoolConfig},
dirs::{ChainPath, DataDirPath},
node_config::NodeConfig,
primitives::Head,
rpc::eth::{helpers::AddDevSigners, FullEthApiServer},
};
use reth_primitives::revm_primitives::EnvKzgSettings;
use reth_provider::{providers::BlockchainProvider, ChainSpecProvider};
use reth_tasks::TaskExecutor;
use reth_transaction_pool::{PoolConfig, TransactionPool};
use secp256k1::SecretKey;
pub use states::*;
use std::sync::Arc;
use tracing::{info, trace, warn};
mod states;
use crate::{
common::WithConfigs,
components::NodeComponentsBuilder,
node::FullNode,
rpc::{EthApiBuilderProvider, RethRpcServerHandles, RpcContext},
DefaultNodeLauncher, Node, NodeHandle,
};
/// The adapter type for a reth node with the builtin provider type
// Note: we need to hardcode this because custom components might depend on it in associated types.
@ -212,11 +217,11 @@ where
pub fn node<N>(
self,
node: N,
) -> NodeBuilderWithComponents<RethFullAdapter<DB, N>, N::ComponentsBuilder>
) -> NodeBuilderWithComponents<RethFullAdapter<DB, N>, N::ComponentsBuilder, N::AddOns>
where
N: Node<RethFullAdapter<DB, N>>,
{
self.with_types().with_components(node.components_builder())
self.with_types().with_components(node.components_builder()).with_add_ons::<N::AddOns>()
}
}
@ -259,11 +264,13 @@ where
pub fn node<N>(
self,
node: N,
) -> WithLaunchContext<NodeBuilderWithComponents<RethFullAdapter<DB, N>, N::ComponentsBuilder>>
) -> WithLaunchContext<
NodeBuilderWithComponents<RethFullAdapter<DB, N>, N::ComponentsBuilder, N::AddOns>,
>
where
N: Node<RethFullAdapter<DB, N>>,
{
self.with_types().with_components(node.components_builder())
self.with_types().with_components(node.components_builder()).with_add_ons::<N::AddOns>()
}
/// Launches a preconfigured [Node]
@ -280,10 +287,22 @@ where
RethFullAdapter<DB, N>,
<N::ComponentsBuilder as NodeComponentsBuilder<RethFullAdapter<DB, N>>>::Components,
>,
N::AddOns,
>,
>
where
N: Node<RethFullAdapter<DB, N>>,
<N::AddOns as NodeAddOns<
NodeAdapter<
RethFullAdapter<DB, N>,
<N::ComponentsBuilder as NodeComponentsBuilder<RethFullAdapter<DB, N>>>::Components,
>,
>>::EthApi: EthApiBuilderProvider<
NodeAdapter<
RethFullAdapter<DB, N>,
<N::ComponentsBuilder as NodeComponentsBuilder<RethFullAdapter<DB, N>>>::Components,
>,
> + FullEthApiServer + AddDevSigners,
{
self.node(node).launch().await
}
@ -298,7 +317,7 @@ where
pub fn with_components<CB>(
self,
components_builder: CB,
) -> WithLaunchContext<NodeBuilderWithComponents<RethFullAdapter<DB, T>, CB>>
) -> WithLaunchContext<NodeBuilderWithComponents<RethFullAdapter<DB, T>, CB, ()>>
where
CB: NodeComponentsBuilder<RethFullAdapter<DB, T>>,
{
@ -309,11 +328,35 @@ where
}
}
impl<T, DB, CB> WithLaunchContext<NodeBuilderWithComponents<RethFullAdapter<DB, T>, CB>>
impl<T, DB, CB> WithLaunchContext<NodeBuilderWithComponents<RethFullAdapter<DB, T>, CB, ()>>
where
DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static,
T: NodeTypes,
CB: NodeComponentsBuilder<RethFullAdapter<DB, T>>,
{
/// Advances the state of the node builder to the next state where all customizable
/// [`NodeAddOns`] types are configured.
pub fn with_add_ons<AO>(
self,
) -> WithLaunchContext<NodeBuilderWithComponents<RethFullAdapter<DB, T>, CB, AO>>
where
CB: NodeComponentsBuilder<RethFullAdapter<DB, T>>,
AO: NodeAddOns<NodeAdapter<RethFullAdapter<DB, T>, CB::Components>>,
{
WithLaunchContext {
builder: self.builder.with_add_ons::<AO>(),
task_executor: self.task_executor,
}
}
}
impl<T, DB, CB, AO> WithLaunchContext<NodeBuilderWithComponents<RethFullAdapter<DB, T>, CB, AO>>
where
DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static,
T: NodeTypes,
CB: NodeComponentsBuilder<RethFullAdapter<DB, T>>,
AO: NodeAddOns<NodeAdapter<RethFullAdapter<DB, T>, CB::Components>>,
AO::EthApi: FullEthApiServer + AddDevSigners,
{
/// Sets the hook that is run once the node's components are initialized.
pub fn on_component_initialized<F>(self, hook: F) -> Self
@ -332,7 +375,7 @@ where
pub fn on_node_started<F>(self, hook: F) -> Self
where
F: FnOnce(
FullNode<NodeAdapter<RethFullAdapter<DB, T>, CB::Components>>,
FullNode<NodeAdapter<RethFullAdapter<DB, T>, CB::Components>, AO>,
) -> eyre::Result<()>
+ Send
+ 'static,
@ -344,7 +387,7 @@ where
pub fn on_rpc_started<F>(self, hook: F) -> Self
where
F: FnOnce(
RpcContext<'_, NodeAdapter<RethFullAdapter<DB, T>, CB::Components>>,
RpcContext<'_, NodeAdapter<RethFullAdapter<DB, T>, CB::Components>, AO::EthApi>,
RethRpcServerHandles,
) -> eyre::Result<()>
+ Send
@ -357,7 +400,7 @@ where
pub fn extend_rpc_modules<F>(self, hook: F) -> Self
where
F: FnOnce(
RpcContext<'_, NodeAdapter<RethFullAdapter<DB, T>, CB::Components>>,
RpcContext<'_, NodeAdapter<RethFullAdapter<DB, T>, CB::Components>, AO::EthApi>,
) -> eyre::Result<()>
+ Send
+ 'static,
@ -384,16 +427,6 @@ where
}
}
/// Launches the node and returns a handle to it.
pub async fn launch(
self,
) -> eyre::Result<NodeHandle<NodeAdapter<RethFullAdapter<DB, T>, CB::Components>>> {
let Self { builder, task_executor } = self;
let launcher = DefaultNodeLauncher::new(task_executor, builder.config.datadir());
builder.launch_with(launcher).await
}
/// Check that the builder can be launched
///
/// This is useful when writing tests to ensure that the builder is configured correctly.
@ -402,6 +435,27 @@ where
}
}
impl<T, DB, CB, AO> WithLaunchContext<NodeBuilderWithComponents<RethFullAdapter<DB, T>, CB, AO>>
where
DB: Database + DatabaseMetrics + DatabaseMetadata + Clone + Unpin + 'static,
T: NodeTypes,
CB: NodeComponentsBuilder<RethFullAdapter<DB, T>>,
AO: NodeAddOns<NodeAdapter<RethFullAdapter<DB, T>, CB::Components>>,
AO::EthApi: EthApiBuilderProvider<NodeAdapter<RethFullAdapter<DB, T>, CB::Components>>
+ FullEthApiServer
+ AddDevSigners,
{
/// Launches the node with the [`DefaultNodeLauncher`] that sets up engine API consensus and rpc
pub async fn launch(
self,
) -> eyre::Result<NodeHandle<NodeAdapter<RethFullAdapter<DB, T>, CB::Components>, AO>> {
let Self { builder, task_executor } = self;
let launcher = DefaultNodeLauncher::new(task_executor, builder.config.datadir());
builder.launch_with(launcher).await
}
}
/// Captures the necessary context for building the components of the node.
pub struct BuilderContext<Node: FullNodeTypes> {
/// The current head of the blockchain at launch.

View File

@ -5,21 +5,25 @@
//! The node builder process is essentially a state machine that transitions through various states
//! before the node can be launched.
use crate::{
components::{NodeComponents, NodeComponentsBuilder},
exex::BoxedLaunchExEx,
hooks::NodeHooks,
launch::LaunchNode,
rpc::{RethRpcServerHandles, RpcContext, RpcHooks},
FullNode,
};
use std::{fmt, future::Future, marker::PhantomData};
use reth_exex::ExExContext;
use reth_network::NetworkHandle;
use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeTypes};
use reth_node_core::node_config::NodeConfig;
use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeAddOns, NodeTypes};
use reth_node_core::{
node_config::NodeConfig,
rpc::eth::{helpers::AddDevSigners, FullEthApiServer},
};
use reth_payload_builder::PayloadBuilderHandle;
use reth_tasks::TaskExecutor;
use std::{fmt, future::Future};
use crate::{
components::{NodeComponents, NodeComponentsBuilder},
hooks::NodeHooks,
launch::LaunchNode,
rpc::{EthApiBuilderProvider, RethRpcServerHandles, RpcContext, RpcHooks},
AddOns, FullNode, RpcAddOns,
};
/// A node builder that also has the configured types.
pub struct NodeBuilderWithTypes<T: FullNodeTypes> {
@ -36,7 +40,7 @@ impl<T: FullNodeTypes> NodeBuilderWithTypes<T> {
}
/// Advances the state of the node builder to the next state where all components are configured
pub fn with_components<CB>(self, components_builder: CB) -> NodeBuilderWithComponents<T, CB>
pub fn with_components<CB>(self, components_builder: CB) -> NodeBuilderWithComponents<T, CB, ()>
where
CB: NodeComponentsBuilder<T>,
{
@ -46,9 +50,9 @@ impl<T: FullNodeTypes> NodeBuilderWithTypes<T> {
config,
adapter,
components_builder,
add_ons: NodeAddOns {
add_ons: AddOns {
hooks: NodeHooks::default(),
rpc: RpcHooks::new(),
rpc: RpcAddOns { _eth_api: PhantomData::<()>, hooks: RpcHooks::default() },
exexs: Vec::new(),
},
}
@ -142,7 +146,11 @@ impl<T: FullNodeTypes, C: NodeComponents<T>> Clone for NodeAdapter<T, C> {
/// A fully type configured node builder.
///
/// Supports adding additional addons to the node.
pub struct NodeBuilderWithComponents<T: FullNodeTypes, CB: NodeComponentsBuilder<T>> {
pub struct NodeBuilderWithComponents<
T: FullNodeTypes,
CB: NodeComponentsBuilder<T>,
AO: NodeAddOns<NodeAdapter<T, CB::Components>>,
> {
/// All settings for how the node should be configured.
pub(crate) config: NodeConfig,
/// Adapter for the underlying node types and database
@ -150,10 +158,41 @@ pub struct NodeBuilderWithComponents<T: FullNodeTypes, CB: NodeComponentsBuilder
/// container for type specific components
pub(crate) components_builder: CB,
/// Additional node extensions.
pub(crate) add_ons: NodeAddOns<NodeAdapter<T, CB::Components>>,
pub(crate) add_ons: AddOns<NodeAdapter<T, CB::Components>, AO>,
}
impl<T: FullNodeTypes, CB: NodeComponentsBuilder<T>> NodeBuilderWithComponents<T, CB> {
impl<T, CB> NodeBuilderWithComponents<T, CB, ()>
where
T: FullNodeTypes,
CB: NodeComponentsBuilder<T>,
{
/// Advances the state of the node builder to the next state where all customizable
/// [`NodeAddOns`] types are configured.
pub fn with_add_ons<AO>(self) -> NodeBuilderWithComponents<T, CB, AO>
where
AO: NodeAddOns<NodeAdapter<T, CB::Components>>,
{
let Self { config, adapter, components_builder, .. } = self;
NodeBuilderWithComponents {
config,
adapter,
components_builder,
add_ons: AddOns {
hooks: NodeHooks::default(),
rpc: RpcAddOns { _eth_api: PhantomData::<AO::EthApi>, hooks: RpcHooks::default() },
exexs: Vec::new(),
},
}
}
}
impl<T, CB, AO> NodeBuilderWithComponents<T, CB, AO>
where
T: FullNodeTypes,
CB: NodeComponentsBuilder<T>,
AO: NodeAddOns<NodeAdapter<T, CB::Components>>,
{
/// Sets the hook that is run once the node's components are initialized.
pub fn on_component_initialized<F>(mut self, hook: F) -> Self
where
@ -166,7 +205,9 @@ impl<T: FullNodeTypes, CB: NodeComponentsBuilder<T>> NodeBuilderWithComponents<T
/// Sets the hook that is run once the node has started.
pub fn on_node_started<F>(mut self, hook: F) -> Self
where
F: FnOnce(FullNode<NodeAdapter<T, CB::Components>>) -> eyre::Result<()> + Send + 'static,
F: FnOnce(FullNode<NodeAdapter<T, CB::Components>, AO>) -> eyre::Result<()>
+ Send
+ 'static,
{
self.add_ons.hooks.set_on_node_started(hook);
self
@ -176,24 +217,24 @@ impl<T: FullNodeTypes, CB: NodeComponentsBuilder<T>> NodeBuilderWithComponents<T
pub fn on_rpc_started<F>(mut self, hook: F) -> Self
where
F: FnOnce(
RpcContext<'_, NodeAdapter<T, CB::Components>>,
RpcContext<'_, NodeAdapter<T, CB::Components>, AO::EthApi>,
RethRpcServerHandles,
) -> eyre::Result<()>
+ Send
+ 'static,
{
self.add_ons.rpc.set_on_rpc_started(hook);
self.add_ons.rpc.hooks.set_on_rpc_started(hook);
self
}
/// Sets the hook that is run to configure the rpc modules.
pub fn extend_rpc_modules<F>(mut self, hook: F) -> Self
where
F: FnOnce(RpcContext<'_, NodeAdapter<T, CB::Components>>) -> eyre::Result<()>
F: FnOnce(RpcContext<'_, NodeAdapter<T, CB::Components>, AO::EthApi>) -> eyre::Result<()>
+ Send
+ 'static,
{
self.add_ons.rpc.set_extend_rpc_modules(hook);
self.add_ons.rpc.hooks.set_extend_rpc_modules(hook);
self
}
@ -212,14 +253,6 @@ impl<T: FullNodeTypes, CB: NodeComponentsBuilder<T>> NodeBuilderWithComponents<T
self
}
/// Launches the node with the given launcher.
pub async fn launch_with<L>(self, launcher: L) -> eyre::Result<L::Node>
where
L: LaunchNode<Self>,
{
launcher.launch_node(self).await
}
/// Launches the node with the given closure.
pub fn launch_with_fn<L, R>(self, launcher: L) -> R
where
@ -236,12 +269,19 @@ impl<T: FullNodeTypes, CB: NodeComponentsBuilder<T>> NodeBuilderWithComponents<T
}
}
/// Additional node extensions.
pub(crate) struct NodeAddOns<Node: FullNodeComponents> {
/// Additional `NodeHooks` that are called at specific points in the node's launch lifecycle.
pub(crate) hooks: NodeHooks<Node>,
/// Additional RPC hooks.
pub(crate) rpc: RpcHooks<Node>,
/// The `ExExs` (execution extensions) of the node.
pub(crate) exexs: Vec<(String, Box<dyn BoxedLaunchExEx<Node>>)>,
impl<T, CB, AO> NodeBuilderWithComponents<T, CB, AO>
where
T: FullNodeTypes,
CB: NodeComponentsBuilder<T>,
AO: NodeAddOns<NodeAdapter<T, CB::Components>>,
AO::EthApi:
EthApiBuilderProvider<NodeAdapter<T, CB::Components>> + FullEthApiServer + AddDevSigners,
{
/// Launches the node with the given launcher.
pub async fn launch_with<L>(self, launcher: L) -> eyre::Result<L::Node>
where
L: LaunchNode<Self>,
{
launcher.launch_node(self).await
}
}

View File

@ -1,5 +1,11 @@
//! A generic [`NodeComponentsBuilder`]
use std::{future::Future, marker::PhantomData};
use reth_consensus::Consensus;
use reth_evm::execute::BlockExecutorProvider;
use reth_transaction_pool::TransactionPool;
use crate::{
components::{
Components, ConsensusBuilder, ExecutorBuilder, NetworkBuilder, NodeComponents,
@ -7,10 +13,6 @@ use crate::{
},
BuilderContext, ConfigureEvm, FullNodeTypes,
};
use reth_consensus::Consensus;
use reth_evm::execute::BlockExecutorProvider;
use reth_transaction_pool::TransactionPool;
use std::{future::Future, marker::PhantomData};
/// A generic, general purpose and customizable [`NodeComponentsBuilder`] implementation.
///

View File

@ -1,25 +1,35 @@
use crate::node::FullNode;
use reth_node_api::FullNodeComponents;
use reth_node_core::exit::NodeExitFuture;
use std::fmt;
use reth_node_api::{FullNodeComponents, NodeAddOns};
use reth_node_core::exit::NodeExitFuture;
use crate::node::FullNode;
/// A Handle to the launched node.
#[must_use = "Needs to await the node exit future"]
pub struct NodeHandle<Node: FullNodeComponents> {
pub struct NodeHandle<Node: FullNodeComponents, AddOns: NodeAddOns<Node>> {
/// All node components.
pub node: FullNode<Node>,
pub node: FullNode<Node, AddOns>,
/// The exit future of the node.
pub node_exit_future: NodeExitFuture,
}
impl<Node: FullNodeComponents> NodeHandle<Node> {
impl<Node, AddOns> NodeHandle<Node, AddOns>
where
Node: FullNodeComponents,
AddOns: NodeAddOns<Node>,
{
/// Waits for the node to exit, if it was configured to exit.
pub async fn wait_for_node_exit(self) -> eyre::Result<()> {
self.node_exit_future.await
}
}
impl<Node: FullNodeComponents> fmt::Debug for NodeHandle<Node> {
impl<Node, AddOns> fmt::Debug for NodeHandle<Node, AddOns>
where
Node: FullNodeComponents,
AddOns: NodeAddOns<Node>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NodeHandle")
.field("node", &"...")

View File

@ -1,17 +1,25 @@
use crate::node::FullNode;
use reth_node_api::FullNodeComponents;
use std::fmt;
use reth_node_api::{FullNodeComponents, NodeAddOns};
use crate::node::FullNode;
/// Container for all the configurable hook functions.
pub(crate) struct NodeHooks<Node: FullNodeComponents> {
pub(crate) on_component_initialized: Box<dyn OnComponentInitializedHook<Node>>,
pub(crate) on_node_started: Box<dyn OnNodeStartedHook<Node>>,
pub(crate) _marker: std::marker::PhantomData<Node>,
pub struct NodeHooks<Node: FullNodeComponents, AddOns: NodeAddOns<Node>> {
/// Hook to run once core components are initialized.
pub on_component_initialized: Box<dyn OnComponentInitializedHook<Node>>,
/// Hook to run once the node is started.
pub on_node_started: Box<dyn OnNodeStartedHook<Node, AddOns>>,
_marker: std::marker::PhantomData<Node>,
}
impl<Node: FullNodeComponents> NodeHooks<Node> {
impl<Node, AddOns> NodeHooks<Node, AddOns>
where
Node: FullNodeComponents,
AddOns: NodeAddOns<Node>,
{
/// Creates a new, empty [`NodeHooks`] instance for the given node type.
pub(crate) fn new() -> Self {
pub fn new() -> Self {
Self {
on_component_initialized: Box::<()>::default(),
on_node_started: Box::<()>::default(),
@ -41,7 +49,7 @@ impl<Node: FullNodeComponents> NodeHooks<Node> {
/// Sets the hook that is run once the node has started.
pub(crate) fn set_on_node_started<F>(&mut self, hook: F) -> &mut Self
where
F: OnNodeStartedHook<Node> + 'static,
F: OnNodeStartedHook<Node, AddOns> + 'static,
{
self.on_node_started = Box::new(hook);
self
@ -51,19 +59,27 @@ impl<Node: FullNodeComponents> NodeHooks<Node> {
#[allow(unused)]
pub(crate) fn on_node_started<F>(mut self, hook: F) -> Self
where
F: OnNodeStartedHook<Node> + 'static,
F: OnNodeStartedHook<Node, AddOns> + 'static,
{
self.set_on_node_started(hook);
self
}
}
impl<Node: FullNodeComponents> Default for NodeHooks<Node> {
impl<Node, AddOns> Default for NodeHooks<Node, AddOns>
where
Node: FullNodeComponents,
AddOns: NodeAddOns<Node>,
{
fn default() -> Self {
Self::new()
}
}
impl<Node: FullNodeComponents> fmt::Debug for NodeHooks<Node> {
impl<Node, AddOns> fmt::Debug for NodeHooks<Node, AddOns>
where
Node: FullNodeComponents,
AddOns: NodeAddOns<Node>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NodeHooks")
.field("on_component_initialized", &"...")
@ -90,19 +106,20 @@ where
}
/// A helper trait that is run once the node is started.
pub trait OnNodeStartedHook<Node: FullNodeComponents>: Send {
pub trait OnNodeStartedHook<Node: FullNodeComponents, AddOns: NodeAddOns<Node>>: Send {
/// Consumes the event hook and runs it.
///
/// If this returns an error, the node launch will be aborted.
fn on_event(self: Box<Self>, node: FullNode<Node>) -> eyre::Result<()>;
fn on_event(self: Box<Self>, node: FullNode<Node, AddOns>) -> eyre::Result<()>;
}
impl<Node, F> OnNodeStartedHook<Node> for F
impl<Node, AddOns, F> OnNodeStartedHook<Node, AddOns> for F
where
Node: FullNodeComponents,
F: FnOnce(FullNode<Node>) -> eyre::Result<()> + Send,
AddOns: NodeAddOns<Node>,
F: FnOnce(FullNode<Node, AddOns>) -> eyre::Result<()> + Send,
{
fn on_event(self: Box<Self>, node: FullNode<Node>) -> eyre::Result<()> {
fn on_event(self: Box<Self>, node: FullNode<Node, AddOns>) -> eyre::Result<()> {
(*self)(node)
}
}
@ -113,8 +130,12 @@ impl<Node> OnComponentInitializedHook<Node> for () {
}
}
impl<Node: FullNodeComponents> OnNodeStartedHook<Node> for () {
fn on_event(self: Box<Self>, _node: FullNode<Node>) -> eyre::Result<()> {
impl<Node, AddOns> OnNodeStartedHook<Node, AddOns> for ()
where
Node: FullNodeComponents,
AddOns: NodeAddOns<Node>,
{
fn on_event(self: Box<Self>, _node: FullNode<Node, AddOns>) -> eyre::Result<()> {
Ok(())
}
}

View File

@ -1,12 +1,13 @@
//! Abstraction for launching a node.
use crate::{
builder::{NodeAdapter, NodeAddOns, NodeTypesAdapter},
components::{NodeComponents, NodeComponentsBuilder},
hooks::NodeHooks,
node::FullNode,
NodeBuilderWithComponents, NodeHandle,
};
pub mod common;
mod exex;
pub use common::LaunchContext;
pub use exex::ExExLauncher;
use std::{future::Future, sync::Arc};
use futures::{future::Either, stream, stream_select, StreamExt};
use reth_beacon_consensus::{
hooks::{EngineHooks, PruneHook, StaticFileHook},
@ -15,11 +16,12 @@ use reth_beacon_consensus::{
use reth_consensus_debug_client::{DebugConsensusClient, EtherscanBlockProvider, RpcBlockProvider};
use reth_engine_util::EngineMessageStreamExt;
use reth_exex::ExExManagerHandle;
use reth_network::NetworkEvents;
use reth_node_api::FullNodeTypes;
use reth_network::{NetworkEvents, NetworkHandle};
use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeAddOns};
use reth_node_core::{
dirs::{ChainPath, DataDirPath},
exit::NodeExitFuture,
rpc::eth::{helpers::AddDevSigners, FullEthApiServer},
version::{CARGO_PKG_VERSION, CLIENT_CODE, NAME_CLIENT, VERGEN_GIT_SHA},
};
use reth_node_events::{cl::ConsensusLayerHealthEvents, node};
@ -30,18 +32,32 @@ use reth_rpc_types::engine::ClientVersionV1;
use reth_tasks::TaskExecutor;
use reth_tracing::tracing::{debug, info};
use reth_transaction_pool::TransactionPool;
use std::{future::Future, sync::Arc};
use tokio::sync::{mpsc::unbounded_channel, oneshot};
use tokio_stream::wrappers::UnboundedReceiverStream;
pub mod common;
pub use common::LaunchContext;
mod exex;
pub use exex::ExExLauncher;
use crate::{
builder::{NodeAdapter, NodeTypesAdapter},
components::{NodeComponents, NodeComponentsBuilder},
hooks::NodeHooks,
node::FullNode,
rpc::EthApiBuilderProvider,
AddOns, NodeBuilderWithComponents, NodeHandle,
};
/// Alias for [`reth_rpc_eth_types::EthApiBuilderCtx`], adapter for [`FullNodeComponents`].
pub type EthApiBuilderCtx<N> = reth_rpc_eth_types::EthApiBuilderCtx<
<N as FullNodeTypes>::Provider,
<N as FullNodeComponents>::Pool,
<N as FullNodeComponents>::Evm,
NetworkHandle,
TaskExecutor,
<N as FullNodeTypes>::Provider,
>;
/// A general purpose trait that launches a new node of any kind.
///
/// Acts as a node factory.
/// Acts as a node factory that targets a certain node configuration and returns a handle to the
/// node.
///
/// This is essentially the launch logic for a node.
///
@ -80,22 +96,25 @@ impl DefaultNodeLauncher {
}
}
impl<T, CB> LaunchNode<NodeBuilderWithComponents<T, CB>> for DefaultNodeLauncher
impl<T, CB, AO> LaunchNode<NodeBuilderWithComponents<T, CB, AO>> for DefaultNodeLauncher
where
T: FullNodeTypes<Provider = BlockchainProvider<<T as FullNodeTypes>::DB>>,
CB: NodeComponentsBuilder<T>,
AO: NodeAddOns<NodeAdapter<T, CB::Components>>,
AO::EthApi:
EthApiBuilderProvider<NodeAdapter<T, CB::Components>> + FullEthApiServer + AddDevSigners,
{
type Node = NodeHandle<NodeAdapter<T, CB::Components>>;
type Node = NodeHandle<NodeAdapter<T, CB::Components>, AO>;
async fn launch_node(
self,
target: NodeBuilderWithComponents<T, CB>,
target: NodeBuilderWithComponents<T, CB, AO>,
) -> eyre::Result<Self::Node> {
let Self { ctx } = self;
let NodeBuilderWithComponents {
adapter: NodeTypesAdapter { database },
components_builder,
add_ons: NodeAddOns { hooks, rpc, exexs: installed_exex },
add_ons: AddOns { hooks, rpc, exexs: installed_exex },
config,
} = target;
let NodeHooks { on_component_initialized, on_node_started, .. } = hooks;

View File

@ -17,9 +17,13 @@ pub use node::*;
/// Support for configuring the components of a node.
pub mod components;
pub use components::{NodeComponents, NodeComponentsBuilder};
mod builder;
pub use builder::*;
pub use builder::{
add_ons::{AddOns, RpcAddOns},
*,
};
mod launch;
pub use launch::*;

View File

@ -1,4 +1,8 @@
use crate::rpc::{RethRpcServerHandles, RpcRegistry};
// re-export the node api types
pub use reth_node_api::{FullNodeTypes, NodeTypes};
use std::{marker::PhantomData, sync::Arc};
use reth_chainspec::ChainSpec;
use reth_network::NetworkHandle;
use reth_node_api::FullNodeComponents;
@ -11,11 +15,12 @@ use reth_payload_builder::PayloadBuilderHandle;
use reth_provider::ChainSpecProvider;
use reth_rpc_builder::{auth::AuthServerHandle, RpcServerHandle};
use reth_tasks::TaskExecutor;
use std::{marker::PhantomData, sync::Arc};
// re-export the node api types
use crate::components::NodeComponentsBuilder;
pub use reth_node_api::{FullNodeTypes, NodeTypes};
use crate::{
components::NodeComponentsBuilder,
rpc::{RethRpcServerHandles, RpcRegistry},
NodeAdapter, NodeAddOns,
};
/// A [`crate::Node`] is a [`NodeTypes`] that comes with preconfigured components.
///
@ -24,45 +29,53 @@ pub trait Node<N: FullNodeTypes>: NodeTypes + Clone {
/// The type that builds the node's components.
type ComponentsBuilder: NodeComponentsBuilder<N>;
/// Exposes the customizable node add-on types.
type AddOns: NodeAddOns<
NodeAdapter<N, <Self::ComponentsBuilder as NodeComponentsBuilder<N>>::Components>,
>;
/// Returns a [`NodeComponentsBuilder`] for the node.
fn components_builder(self) -> Self::ComponentsBuilder;
fn components_builder(&self) -> Self::ComponentsBuilder;
}
/// A [`Node`] type builder
#[derive(Clone, Default, Debug)]
pub struct AnyNode<N = (), C = ()>(PhantomData<N>, C);
pub struct AnyNode<N = (), C = (), AO = ()>(PhantomData<(N, AO)>, C);
impl<N, C> AnyNode<N, C> {
/// Configures the types of the node.
pub fn types<T>(self) -> AnyNode<T, C> {
AnyNode::<T, C>(PhantomData::<T>, self.1)
AnyNode::<T, C>(PhantomData::<(T, ())>, self.1)
}
/// Sets the node components builder.
pub fn components_builder<T>(self, value: T) -> AnyNode<N, T> {
AnyNode::<N, T>(PhantomData::<N>, value)
pub const fn components_builder<T>(&self, value: T) -> AnyNode<N, T> {
AnyNode::<N, T>(PhantomData::<(N, ())>, value)
}
}
impl<N, C> NodeTypes for AnyNode<N, C>
impl<N, C, AO> NodeTypes for AnyNode<N, C, AO>
where
N: FullNodeTypes,
C: NodeComponentsBuilder<N> + Sync + Unpin + 'static,
C: Send + Sync + Unpin + 'static,
AO: Send + Sync + Unpin + Clone + 'static,
{
type Primitives = N::Primitives;
type Engine = N::Engine;
}
impl<N, C> Node<N> for AnyNode<N, C>
impl<N, C, AO> Node<N> for AnyNode<N, C, AO>
where
N: FullNodeTypes + Clone,
C: NodeComponentsBuilder<N> + Clone + Sync + Unpin + 'static,
AO: NodeAddOns<NodeAdapter<N, C::Components>>,
{
type ComponentsBuilder = C;
type AddOns = AO;
fn components_builder(self) -> Self::ComponentsBuilder {
self.1
fn components_builder(&self) -> Self::ComponentsBuilder {
self.1.clone()
}
}
@ -70,7 +83,7 @@ where
///
/// This can be used to interact with the launched node.
#[derive(Debug, Clone)]
pub struct FullNode<Node: FullNodeComponents> {
pub struct FullNode<Node: FullNodeComponents, AddOns: NodeAddOns<Node>> {
/// The evm configuration.
pub evm_config: Node::Evm,
/// The executor of the node.
@ -88,14 +101,18 @@ pub struct FullNode<Node: FullNodeComponents> {
/// Handles to the node's rpc servers
pub rpc_server_handles: RethRpcServerHandles,
/// The configured rpc namespaces
pub rpc_registry: RpcRegistry<Node>,
pub rpc_registry: RpcRegistry<Node, AddOns::EthApi>,
/// The initial node config.
pub config: NodeConfig,
/// The data dir of the node.
pub data_dir: ChainPath<DataDirPath>,
}
impl<Node: FullNodeComponents> FullNode<Node> {
impl<Node, AddOns> FullNode<Node, AddOns>
where
Node: FullNodeComponents,
AddOns: NodeAddOns<Node>,
{
/// Returns the [`ChainSpec`] of the node.
pub fn chain_spec(&self) -> Arc<ChainSpec> {
self.provider.chain_spec()

View File

@ -7,19 +7,23 @@ use std::{
use futures::TryFutureExt;
use reth_network::NetworkHandle;
use reth_node_api::FullNodeComponents;
use reth_node_core::{node_config::NodeConfig, rpc::api::EngineApiServer};
use reth_node_api::{BuilderProvider, FullNodeComponents};
use reth_node_core::{
node_config::NodeConfig,
rpc::{api::EngineApiServer, eth::FullEthApiServer},
};
use reth_payload_builder::PayloadBuilderHandle;
use reth_rpc::eth::EthApi;
use reth_rpc_builder::{
auth::{AuthRpcModule, AuthServerHandle},
config::RethRpcServerConfig,
EthApiBuild, RpcModuleBuilder, RpcRegistryInner, RpcServerHandle, TransportRpcModules,
RpcModuleBuilder, RpcRegistryInner, RpcServerHandle, TransportRpcModules,
};
use reth_rpc_layer::JwtSecret;
use reth_tasks::TaskExecutor;
use reth_tracing::tracing::{debug, info};
use crate::{EthApiBuilderCtx, RpcAddOns};
/// Contains the handles to the spawned RPC servers.
///
/// This can be used to access the endpoints of the servers.
@ -32,21 +36,24 @@ pub struct RethRpcServerHandles {
}
/// Contains hooks that are called during the rpc setup.
pub(crate) struct RpcHooks<Node: FullNodeComponents> {
pub(crate) on_rpc_started: Box<dyn OnRpcStarted<Node>>,
pub(crate) extend_rpc_modules: Box<dyn ExtendRpcModules<Node>>,
pub struct RpcHooks<Node: FullNodeComponents, EthApi> {
/// Hooks to run once RPC server is running.
pub on_rpc_started: Box<dyn OnRpcStarted<Node, EthApi>>,
/// Hooks to run to configure RPC server API.
pub extend_rpc_modules: Box<dyn ExtendRpcModules<Node, EthApi>>,
}
impl<Node: FullNodeComponents> RpcHooks<Node> {
/// Creates a new, empty [`RpcHooks`] instance for the given node type.
pub(crate) fn new() -> Self {
impl<Node: FullNodeComponents, EthApi> Default for RpcHooks<Node, EthApi> {
fn default() -> Self {
Self { on_rpc_started: Box::<()>::default(), extend_rpc_modules: Box::<()>::default() }
}
}
impl<Node: FullNodeComponents, EthApi> RpcHooks<Node, EthApi> {
/// Sets the hook that is run once the rpc server is started.
pub(crate) fn set_on_rpc_started<F>(&mut self, hook: F) -> &mut Self
where
F: OnRpcStarted<Node> + 'static,
F: OnRpcStarted<Node, EthApi> + 'static,
{
self.on_rpc_started = Box::new(hook);
self
@ -56,7 +63,7 @@ impl<Node: FullNodeComponents> RpcHooks<Node> {
#[allow(unused)]
pub(crate) fn on_rpc_started<F>(mut self, hook: F) -> Self
where
F: OnRpcStarted<Node> + 'static,
F: OnRpcStarted<Node, EthApi> + 'static,
{
self.set_on_rpc_started(hook);
self
@ -65,7 +72,7 @@ impl<Node: FullNodeComponents> RpcHooks<Node> {
/// Sets the hook that is run to configure the rpc modules.
pub(crate) fn set_extend_rpc_modules<F>(&mut self, hook: F) -> &mut Self
where
F: ExtendRpcModules<Node> + 'static,
F: ExtendRpcModules<Node, EthApi> + 'static,
{
self.extend_rpc_modules = Box::new(hook);
self
@ -75,14 +82,14 @@ impl<Node: FullNodeComponents> RpcHooks<Node> {
#[allow(unused)]
pub(crate) fn extend_rpc_modules<F>(mut self, hook: F) -> Self
where
F: ExtendRpcModules<Node> + 'static,
F: ExtendRpcModules<Node, EthApi> + 'static,
{
self.set_extend_rpc_modules(hook);
self
}
}
impl<Node: FullNodeComponents> fmt::Debug for RpcHooks<Node> {
impl<Node: FullNodeComponents, EthApi> fmt::Debug for RpcHooks<Node, EthApi> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RpcHooks")
.field("on_rpc_started", &"...")
@ -92,33 +99,33 @@ impl<Node: FullNodeComponents> fmt::Debug for RpcHooks<Node> {
}
/// Event hook that is called once the rpc server is started.
pub trait OnRpcStarted<Node: FullNodeComponents>: Send {
pub trait OnRpcStarted<Node: FullNodeComponents, EthApi>: Send {
/// The hook that is called once the rpc server is started.
fn on_rpc_started(
self: Box<Self>,
ctx: RpcContext<'_, Node>,
ctx: RpcContext<'_, Node, EthApi>,
handles: RethRpcServerHandles,
) -> eyre::Result<()>;
}
impl<Node, F> OnRpcStarted<Node> for F
impl<Node, EthApi, F> OnRpcStarted<Node, EthApi> for F
where
F: FnOnce(RpcContext<'_, Node>, RethRpcServerHandles) -> eyre::Result<()> + Send,
F: FnOnce(RpcContext<'_, Node, EthApi>, RethRpcServerHandles) -> eyre::Result<()> + Send,
Node: FullNodeComponents,
{
fn on_rpc_started(
self: Box<Self>,
ctx: RpcContext<'_, Node>,
ctx: RpcContext<'_, Node, EthApi>,
handles: RethRpcServerHandles,
) -> eyre::Result<()> {
(*self)(ctx, handles)
}
}
impl<Node: FullNodeComponents> OnRpcStarted<Node> for () {
impl<Node: FullNodeComponents, EthApi> OnRpcStarted<Node, EthApi> for () {
fn on_rpc_started(
self: Box<Self>,
_: RpcContext<'_, Node>,
_: RpcContext<'_, Node, EthApi>,
_: RethRpcServerHandles,
) -> eyre::Result<()> {
Ok(())
@ -126,49 +133,49 @@ impl<Node: FullNodeComponents> OnRpcStarted<Node> for () {
}
/// Event hook that is called when the rpc server is started.
pub trait ExtendRpcModules<Node: FullNodeComponents>: Send {
pub trait ExtendRpcModules<Node: FullNodeComponents, EthApi>: Send {
/// The hook that is called once the rpc server is started.
fn extend_rpc_modules(self: Box<Self>, ctx: RpcContext<'_, Node>) -> eyre::Result<()>;
fn extend_rpc_modules(self: Box<Self>, ctx: RpcContext<'_, Node, EthApi>) -> eyre::Result<()>;
}
impl<Node, F> ExtendRpcModules<Node> for F
impl<Node, EthApi, F> ExtendRpcModules<Node, EthApi> for F
where
F: FnOnce(RpcContext<'_, Node>) -> eyre::Result<()> + Send,
F: FnOnce(RpcContext<'_, Node, EthApi>) -> eyre::Result<()> + Send,
Node: FullNodeComponents,
{
fn extend_rpc_modules(self: Box<Self>, ctx: RpcContext<'_, Node>) -> eyre::Result<()> {
fn extend_rpc_modules(self: Box<Self>, ctx: RpcContext<'_, Node, EthApi>) -> eyre::Result<()> {
(*self)(ctx)
}
}
impl<Node: FullNodeComponents> ExtendRpcModules<Node> for () {
fn extend_rpc_modules(self: Box<Self>, _: RpcContext<'_, Node>) -> eyre::Result<()> {
impl<Node: FullNodeComponents, EthApi> ExtendRpcModules<Node, EthApi> for () {
fn extend_rpc_modules(self: Box<Self>, _: RpcContext<'_, Node, EthApi>) -> eyre::Result<()> {
Ok(())
}
}
/// Helper wrapper type to encapsulate the [`RpcRegistryInner`] over components trait.
#[derive(Debug)]
#[derive(Debug, Clone)]
#[allow(clippy::type_complexity)]
pub struct RpcRegistry<Node: FullNodeComponents> {
pub struct RpcRegistry<Node: FullNodeComponents, EthApi> {
pub(crate) registry: RpcRegistryInner<
Node::Provider,
Node::Pool,
NetworkHandle,
TaskExecutor,
Node::Provider,
EthApi<Node::Provider, Node::Pool, NetworkHandle, Node::Evm>,
EthApi,
>,
}
impl<Node: FullNodeComponents> Deref for RpcRegistry<Node> {
impl<Node: FullNodeComponents, EthApi> Deref for RpcRegistry<Node, EthApi> {
type Target = RpcRegistryInner<
Node::Provider,
Node::Pool,
NetworkHandle,
TaskExecutor,
Node::Provider,
EthApi<Node::Provider, Node::Pool, NetworkHandle, Node::Evm>,
EthApi,
>;
fn deref(&self) -> &Self::Target {
@ -176,18 +183,12 @@ impl<Node: FullNodeComponents> Deref for RpcRegistry<Node> {
}
}
impl<Node: FullNodeComponents> DerefMut for RpcRegistry<Node> {
impl<Node: FullNodeComponents, EthApi> DerefMut for RpcRegistry<Node, EthApi> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.registry
}
}
impl<Node: FullNodeComponents> Clone for RpcRegistry<Node> {
fn clone(&self) -> Self {
Self { registry: self.registry.clone() }
}
}
/// Helper container to encapsulate [`RpcRegistryInner`], [`TransportRpcModules`] and
/// [`AuthRpcModule`].
///
@ -196,7 +197,7 @@ impl<Node: FullNodeComponents> Clone for RpcRegistry<Node> {
/// transport modules [`TransportRpcModules`] as well as configured authenticated methods
/// [`AuthRpcModule`].
#[allow(missing_debug_implementations)]
pub struct RpcContext<'a, Node: FullNodeComponents> {
pub struct RpcContext<'a, Node: FullNodeComponents, EthApi> {
/// The node components.
pub(crate) node: Node,
@ -206,7 +207,7 @@ pub struct RpcContext<'a, Node: FullNodeComponents> {
/// A Helper type the holds instances of the configured modules.
///
/// This provides easy access to rpc handlers, such as [`RpcRegistryInner::eth_api`].
pub registry: &'a mut RpcRegistry<Node>,
pub registry: &'a mut RpcRegistry<Node, EthApi>,
/// Holds installed modules per transport type.
///
/// This can be used to merge additional modules into the configured transports (http, ipc,
@ -218,7 +219,7 @@ pub struct RpcContext<'a, Node: FullNodeComponents> {
pub auth_module: &'a mut AuthRpcModule,
}
impl<'a, Node: FullNodeComponents> RpcContext<'a, Node> {
impl<'a, Node: FullNodeComponents, EthApi> RpcContext<'a, Node, EthApi> {
/// Returns the config of the node.
pub const fn config(&self) -> &NodeConfig {
self.config
@ -251,19 +252,18 @@ impl<'a, Node: FullNodeComponents> RpcContext<'a, Node> {
}
/// Launch the rpc servers.
pub(crate) async fn launch_rpc_servers<Node, Engine>(
pub(crate) async fn launch_rpc_servers<Node, Engine, EthApi>(
node: Node,
engine_api: Engine,
config: &NodeConfig,
jwt_secret: JwtSecret,
hooks: RpcHooks<Node>,
) -> eyre::Result<(RethRpcServerHandles, RpcRegistry<Node>)>
add_ons: RpcAddOns<Node, EthApi>,
) -> eyre::Result<(RethRpcServerHandles, RpcRegistry<Node, EthApi>)>
where
EthApi: EthApiBuilderProvider<Node> + FullEthApiServer,
Node: FullNodeComponents + Clone,
Engine: EngineApiServer<Node::Engine>,
{
let RpcHooks { on_rpc_started, extend_rpc_modules } = hooks;
let auth_config = config.rpc.auth_server_config(jwt_secret)?;
let module_config = config.rpc.transport_rpc_module_config();
debug!(target: "reth::cli", http=?module_config.http(), ws=?module_config.ws(), "Using RPC module config");
@ -275,7 +275,7 @@ where
.with_events(node.provider().clone())
.with_executor(node.task_executor().clone())
.with_evm_config(node.evm_config().clone())
.build_with_auth_server(module_config, engine_api, EthApiBuild::build);
.build_with_auth_server(module_config, engine_api, EthApi::eth_api_builder());
let mut registry = RpcRegistry { registry };
let ctx = RpcContext {
@ -286,6 +286,9 @@ where
auth_module: &mut auth_module,
};
let RpcAddOns { hooks, .. } = add_ons;
let RpcHooks { on_rpc_started, extend_rpc_modules } = hooks;
extend_rpc_modules.extend_rpc_modules(ctx)?;
let server_config = config.rpc.rpc_server_config();
@ -329,3 +332,20 @@ where
Ok((handles, registry))
}
/// Provides builder for the core `eth` API type.
pub trait EthApiBuilderProvider<N: FullNodeComponents>: BuilderProvider<N> {
/// Returns the eth api builder.
#[allow(clippy::type_complexity)]
fn eth_api_builder() -> Box<dyn Fn(&EthApiBuilderCtx<N>) -> Self + Send>;
}
impl<N, F> EthApiBuilderProvider<N> for F
where
N: FullNodeComponents,
for<'a> F: BuilderProvider<N, Ctx<'a> = &'a EthApiBuilderCtx<N>>,
{
fn eth_api_builder() -> Box<dyn Fn(&EthApiBuilderCtx<N>) -> Self + Send> {
F::builder()
}
}