mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
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:
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -6837,6 +6837,7 @@ dependencies = [
|
||||
"reth-db",
|
||||
"reth-network-peers",
|
||||
"reth-node-builder",
|
||||
"reth-node-ethereum",
|
||||
"reth-payload-builder",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
@ -7581,6 +7582,7 @@ dependencies = [
|
||||
"reth-rpc",
|
||||
"reth-rpc-builder",
|
||||
"reth-rpc-engine-api",
|
||||
"reth-rpc-eth-types",
|
||||
"reth-rpc-layer",
|
||||
"reth-rpc-types",
|
||||
"reth-stages",
|
||||
@ -7683,6 +7685,7 @@ dependencies = [
|
||||
"reth-node-core",
|
||||
"reth-payload-builder",
|
||||
"reth-provider",
|
||||
"reth-rpc",
|
||||
"reth-tracing",
|
||||
"reth-transaction-pool",
|
||||
"serde_json",
|
||||
@ -7740,6 +7743,7 @@ dependencies = [
|
||||
"reth-node-builder",
|
||||
"reth-optimism-consensus",
|
||||
"reth-optimism-payload-builder",
|
||||
"reth-optimism-rpc",
|
||||
"reth-payload-builder",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
@ -7749,6 +7753,7 @@ dependencies = [
|
||||
"reth-rpc-eth-types",
|
||||
"reth-rpc-types",
|
||||
"reth-rpc-types-compat",
|
||||
"reth-tasks",
|
||||
"reth-tracing",
|
||||
"reth-transaction-pool",
|
||||
"revm-primitives",
|
||||
@ -7848,8 +7853,10 @@ dependencies = [
|
||||
"reth-errors",
|
||||
"reth-evm",
|
||||
"reth-evm-optimism",
|
||||
"reth-node-api",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
"reth-rpc",
|
||||
"reth-rpc-eth-api",
|
||||
"reth-rpc-eth-types",
|
||||
"reth-rpc-server-types",
|
||||
@ -8119,6 +8126,7 @@ dependencies = [
|
||||
"reth-evm-optimism",
|
||||
"reth-network-api",
|
||||
"reth-network-peers",
|
||||
"reth-node-api",
|
||||
"reth-primitives",
|
||||
"reth-provider",
|
||||
"reth-revm",
|
||||
@ -8195,6 +8203,7 @@ dependencies = [
|
||||
"reth-metrics",
|
||||
"reth-network-api",
|
||||
"reth-network-peers",
|
||||
"reth-node-api",
|
||||
"reth-node-core",
|
||||
"reth-payload-builder",
|
||||
"reth-primitives",
|
||||
|
||||
@ -22,6 +22,7 @@ reth-node-builder = { workspace = true, features = ["test-utils"] }
|
||||
reth-tokio-util.workspace = true
|
||||
reth-stages-types.workspace = true
|
||||
reth-network-peers.workspace = true
|
||||
reth-node-ethereum.workspace = true
|
||||
|
||||
jsonrpsee.workspace = true
|
||||
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use node::NodeTestContext;
|
||||
use reth::{
|
||||
args::{DiscoveryArgs, NetworkArgs, RpcServerArgs},
|
||||
builder::{NodeBuilder, NodeConfig, NodeHandle},
|
||||
rpc::api::eth::{helpers::AddDevSigners, FullEthApiServer},
|
||||
tasks::TaskManager,
|
||||
};
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_db::{test_utils::TempDatabase, DatabaseEnv};
|
||||
use reth_node_builder::{
|
||||
components::NodeComponentsBuilder, FullNodeTypesAdapter, Node, NodeAdapter, RethFullAdapter,
|
||||
components::NodeComponentsBuilder, rpc::EthApiBuilderProvider, FullNodeTypesAdapter, Node,
|
||||
NodeAdapter, NodeAddOns, RethFullAdapter,
|
||||
};
|
||||
use reth_provider::providers::BlockchainProvider;
|
||||
use std::sync::Arc;
|
||||
use tracing::{span, Level};
|
||||
use wallet::Wallet;
|
||||
|
||||
@ -42,9 +45,11 @@ pub async fn setup<N>(
|
||||
num_nodes: usize,
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
is_dev: bool,
|
||||
) -> eyre::Result<(Vec<NodeHelperType<N>>, TaskManager, Wallet)>
|
||||
) -> eyre::Result<(Vec<NodeHelperType<N, N::AddOns>>, TaskManager, Wallet)>
|
||||
where
|
||||
N: Default + Node<TmpNodeAdapter<N>>,
|
||||
<N::AddOns as NodeAddOns<Adapter<N>>>::EthApi:
|
||||
FullEthApiServer + AddDevSigners + EthApiBuilderProvider<Adapter<N>>,
|
||||
{
|
||||
let tasks = TaskManager::current();
|
||||
let exec = tasks.executor();
|
||||
@ -55,7 +60,7 @@ where
|
||||
};
|
||||
|
||||
// Create nodes and peer them
|
||||
let mut nodes: Vec<NodeTestContext<_>> = Vec::with_capacity(num_nodes);
|
||||
let mut nodes: Vec<NodeTestContext<_, _>> = Vec::with_capacity(num_nodes);
|
||||
|
||||
for idx in 0..num_nodes {
|
||||
let node_config = NodeConfig::test()
|
||||
@ -106,4 +111,4 @@ type Adapter<N> = NodeAdapter<
|
||||
>;
|
||||
|
||||
/// Type alias for a type of NodeHelper
|
||||
pub type NodeHelperType<N> = NodeTestContext<Adapter<N>>;
|
||||
pub type NodeHelperType<N, AO> = NodeTestContext<Adapter<N>, AO>;
|
||||
|
||||
@ -1,7 +1,4 @@
|
||||
use crate::{
|
||||
engine_api::EngineApiTestContext, network::NetworkTestContext, payload::PayloadTestContext,
|
||||
rpc::RpcTestContext, traits::PayloadEnvelopeExt,
|
||||
};
|
||||
use std::{marker::PhantomData, pin::Pin};
|
||||
|
||||
use alloy_rpc_types::BlockNumberOrTag;
|
||||
use eyre::Ok;
|
||||
@ -11,32 +8,41 @@ use reth::{
|
||||
builder::FullNode,
|
||||
payload::PayloadTypes,
|
||||
providers::{BlockReader, BlockReaderIdExt, CanonStateSubscriptions, StageCheckpointReader},
|
||||
rpc::types::engine::PayloadStatusEnum,
|
||||
rpc::{
|
||||
api::eth::helpers::{EthApiSpec, EthTransactions, TraceExt},
|
||||
types::engine::PayloadStatusEnum,
|
||||
},
|
||||
};
|
||||
use reth_node_builder::NodeTypes;
|
||||
use reth_node_builder::{NodeAddOns, NodeTypes};
|
||||
use reth_primitives::{BlockHash, BlockNumber, Bytes, B256};
|
||||
use reth_stages_types::StageId;
|
||||
use std::{marker::PhantomData, pin::Pin};
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
use crate::{
|
||||
engine_api::EngineApiTestContext, network::NetworkTestContext, payload::PayloadTestContext,
|
||||
rpc::RpcTestContext, traits::PayloadEnvelopeExt,
|
||||
};
|
||||
|
||||
/// An helper struct to handle node actions
|
||||
pub struct NodeTestContext<Node>
|
||||
pub struct NodeTestContext<Node, AddOns>
|
||||
where
|
||||
Node: FullNodeComponents,
|
||||
AddOns: NodeAddOns<Node>,
|
||||
{
|
||||
pub inner: FullNode<Node>,
|
||||
pub inner: FullNode<Node, AddOns>,
|
||||
pub payload: PayloadTestContext<Node::Engine>,
|
||||
pub network: NetworkTestContext,
|
||||
pub engine_api: EngineApiTestContext<Node::Engine>,
|
||||
pub rpc: RpcTestContext<Node>,
|
||||
pub rpc: RpcTestContext<Node, AddOns::EthApi>,
|
||||
}
|
||||
|
||||
impl<Node> NodeTestContext<Node>
|
||||
impl<Node, AddOns> NodeTestContext<Node, AddOns>
|
||||
where
|
||||
Node: FullNodeComponents,
|
||||
AddOns: NodeAddOns<Node>,
|
||||
{
|
||||
/// Creates a new test node
|
||||
pub async fn new(node: FullNode<Node>) -> eyre::Result<Self> {
|
||||
pub async fn new(node: FullNode<Node, AddOns>) -> eyre::Result<Self> {
|
||||
let builder = node.payload_builder.clone();
|
||||
|
||||
Ok(Self {
|
||||
@ -53,7 +59,7 @@ where
|
||||
}
|
||||
|
||||
/// Establish a connection to the node
|
||||
pub async fn connect(&mut self, node: &mut NodeTestContext<Node>) {
|
||||
pub async fn connect(&mut self, node: &mut NodeTestContext<Node, AddOns>) {
|
||||
self.network.add_peer(node.network.record()).await;
|
||||
node.network.next_session_established().await;
|
||||
self.network.next_session_established().await;
|
||||
@ -77,6 +83,7 @@ where
|
||||
where
|
||||
<Node::Engine as EngineTypes>::ExecutionPayloadV3:
|
||||
From<<Node::Engine as PayloadTypes>::BuiltPayload> + PayloadEnvelopeExt,
|
||||
AddOns::EthApi: EthApiSpec + EthTransactions + TraceExt,
|
||||
{
|
||||
let mut chain = Vec::with_capacity(length as usize);
|
||||
for i in 0..length {
|
||||
|
||||
@ -3,17 +3,23 @@ use alloy_network::eip2718::Decodable2718;
|
||||
use reth::{
|
||||
builder::{rpc::RpcRegistry, FullNodeComponents},
|
||||
rpc::{
|
||||
api::{eth::helpers::EthTransactions, DebugApiServer},
|
||||
api::{
|
||||
eth::helpers::{EthApiSpec, EthTransactions, TraceExt},
|
||||
DebugApiServer,
|
||||
},
|
||||
server_types::eth::EthResult,
|
||||
},
|
||||
};
|
||||
use reth_primitives::{Bytes, B256};
|
||||
|
||||
pub struct RpcTestContext<Node: FullNodeComponents> {
|
||||
pub inner: RpcRegistry<Node>,
|
||||
pub struct RpcTestContext<Node: FullNodeComponents, EthApi> {
|
||||
pub inner: RpcRegistry<Node, EthApi>,
|
||||
}
|
||||
|
||||
impl<Node: FullNodeComponents> RpcTestContext<Node> {
|
||||
impl<Node: FullNodeComponents, EthApi> RpcTestContext<Node, EthApi>
|
||||
where
|
||||
EthApi: EthApiSpec + EthTransactions + TraceExt,
|
||||
{
|
||||
/// Injects a raw transaction into the node tx pool via RPC server
|
||||
pub async fn inject_tx(&mut self, raw_tx: Bytes) -> EthResult<B256> {
|
||||
let eth_api = self.inner.eth_api();
|
||||
|
||||
@ -25,6 +25,8 @@ reth-evm-ethereum.workspace = true
|
||||
reth-consensus.workspace = true
|
||||
reth-auto-seal-consensus.workspace = true
|
||||
reth-beacon-consensus.workspace = true
|
||||
reth-rpc.workspace = true
|
||||
reth-node-api.workspace = true
|
||||
|
||||
# misc
|
||||
eyre.workspace = true
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! Ethereum Node types config.
|
||||
|
||||
use crate::{EthEngineTypes, EthEvmConfig};
|
||||
use std::sync::Arc;
|
||||
|
||||
use reth_auto_seal_consensus::AutoSealConsensus;
|
||||
use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig};
|
||||
use reth_beacon_consensus::EthBeaconConsensus;
|
||||
@ -9,6 +10,7 @@ use reth_ethereum_engine_primitives::{
|
||||
};
|
||||
use reth_evm_ethereum::execute::EthExecutorProvider;
|
||||
use reth_network::NetworkHandle;
|
||||
use reth_node_api::{FullNodeComponents, NodeAddOns};
|
||||
use reth_node_builder::{
|
||||
components::{
|
||||
ComponentsBuilder, ConsensusBuilder, ExecutorBuilder, NetworkBuilder,
|
||||
@ -19,12 +21,14 @@ use reth_node_builder::{
|
||||
};
|
||||
use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService};
|
||||
use reth_provider::CanonStateSubscriptions;
|
||||
use reth_rpc::EthApi;
|
||||
use reth_tracing::tracing::{debug, info};
|
||||
use reth_transaction_pool::{
|
||||
blobstore::DiskFileBlobStore, EthTransactionPool, TransactionPool,
|
||||
TransactionValidationTaskExecutor,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{EthEngineTypes, EthEvmConfig};
|
||||
|
||||
/// Type configuration for a regular Ethereum node.
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
@ -64,6 +68,14 @@ impl NodeTypes for EthereumNode {
|
||||
type Engine = EthEngineTypes;
|
||||
}
|
||||
|
||||
/// Add-ons w.r.t. l1 ethereum.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EthereumAddOns;
|
||||
|
||||
impl<N: FullNodeComponents> NodeAddOns<N> for EthereumAddOns {
|
||||
type EthApi = EthApi<N::Provider, N::Pool, NetworkHandle, N::Evm>;
|
||||
}
|
||||
|
||||
impl<N> Node<N> for EthereumNode
|
||||
where
|
||||
N: FullNodeTypes<Engine = EthEngineTypes>,
|
||||
@ -77,7 +89,9 @@ where
|
||||
EthereumConsensusBuilder,
|
||||
>;
|
||||
|
||||
fn components_builder(self) -> Self::ComponentsBuilder {
|
||||
type AddOns = EthereumAddOns;
|
||||
|
||||
fn components_builder(&self) -> Self::ComponentsBuilder {
|
||||
Self::components()
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||
use alloy_genesis::Genesis;
|
||||
use alloy_primitives::{b256, hex};
|
||||
use futures::StreamExt;
|
||||
use reth::rpc::api::eth::helpers::EthTransactions;
|
||||
use reth::core::rpc::eth::helpers::EthTransactions;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_e2e_test_utils::setup;
|
||||
use reth_provider::CanonStateSubscriptions;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
use alloy_primitives::{Address, B256};
|
||||
use reth::rpc::types::engine::PayloadAttributes;
|
||||
use reth_e2e_test_utils::NodeHelperType;
|
||||
use reth_node_ethereum::EthereumNode;
|
||||
use reth_node_ethereum::{node::EthereumAddOns, EthereumNode};
|
||||
use reth_payload_builder::EthPayloadBuilderAttributes;
|
||||
|
||||
/// Ethereum Node Helper type
|
||||
pub(crate) type EthNode = NodeHelperType<EthereumNode>;
|
||||
pub(crate) type EthNode = NodeHelperType<EthereumNode, EthereumAddOns>;
|
||||
|
||||
/// Helper function to create a new eth payload attributes
|
||||
pub(crate) fn eth_payload_attributes(timestamp: u64) -> EthPayloadBuilderAttributes {
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
//! Node builder setup tests.
|
||||
|
||||
use reth_db::test_utils::create_test_rw_db;
|
||||
use reth_node_api::FullNodeComponents;
|
||||
use reth_node_builder::{NodeBuilder, NodeConfig};
|
||||
use reth_node_ethereum::node::EthereumNode;
|
||||
use reth_node_builder::{FullNodeComponents, NodeBuilder, NodeConfig};
|
||||
use reth_node_ethereum::node::{EthereumAddOns, EthereumNode};
|
||||
|
||||
#[test]
|
||||
fn test_basic_setup() {
|
||||
@ -15,6 +14,7 @@ fn test_basic_setup() {
|
||||
.with_database(db)
|
||||
.with_types::<EthereumNode>()
|
||||
.with_components(EthereumNode::components())
|
||||
.with_add_ons::<EthereumAddOns>()
|
||||
.on_component_initialized(move |ctx| {
|
||||
let _provider = ctx.provider();
|
||||
println!("{msg}");
|
||||
|
||||
@ -3,7 +3,7 @@ use reth_db::test_utils::create_test_rw_db;
|
||||
use reth_exex::ExExContext;
|
||||
use reth_node_api::FullNodeComponents;
|
||||
use reth_node_builder::{NodeBuilder, NodeConfig};
|
||||
use reth_node_ethereum::EthereumNode;
|
||||
use reth_node_ethereum::{node::EthereumAddOns, EthereumNode};
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
@ -33,6 +33,7 @@ fn basic_exex() {
|
||||
.with_database(db)
|
||||
.with_types::<EthereumNode>()
|
||||
.with_components(EthereumNode::components())
|
||||
.with_add_ons::<EthereumAddOns>()
|
||||
.install_exex("dummy", move |ctx| future::ok(DummyExEx { _ctx: ctx }))
|
||||
.check_launch();
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ use reth_node_builder::{
|
||||
};
|
||||
use reth_node_core::node_config::NodeConfig;
|
||||
use reth_node_ethereum::{
|
||||
node::{EthereumNetworkBuilder, EthereumPayloadBuilder},
|
||||
node::{EthereumAddOns, EthereumNetworkBuilder, EthereumPayloadBuilder},
|
||||
EthEngineTypes, EthEvmConfig,
|
||||
};
|
||||
use reth_payload_builder::noop::NoopPayloadBuilderService;
|
||||
@ -125,8 +125,9 @@ where
|
||||
TestExecutorBuilder,
|
||||
TestConsensusBuilder,
|
||||
>;
|
||||
type AddOns = EthereumAddOns;
|
||||
|
||||
fn components_builder(self) -> Self::ComponentsBuilder {
|
||||
fn components_builder(&self) -> Self::ComponentsBuilder {
|
||||
ComponentsBuilder::default()
|
||||
.node_types::<N>()
|
||||
.pool(TestPoolBuilder::default())
|
||||
|
||||
@ -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(_: ()) {}
|
||||
|
||||
@ -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
|
||||
|
||||
29
crates/node/builder/src/builder/add_ons.rs
Normal file
29
crates/node/builder/src/builder/add_ons.rs
Normal 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>,
|
||||
}
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
///
|
||||
|
||||
@ -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", &"...")
|
||||
|
||||
@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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::*;
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,8 @@ revm-primitives.workspace = true
|
||||
reth-discv5.workspace = true
|
||||
reth-rpc-eth-types.workspace = true
|
||||
reth-rpc-eth-api.workspace = true
|
||||
reth-optimism-rpc.workspace = true
|
||||
reth-tasks.workspace = true
|
||||
|
||||
# async
|
||||
async-trait.workspace = true
|
||||
@ -78,6 +80,7 @@ optimism = [
|
||||
"reth-beacon-consensus/optimism",
|
||||
"reth-revm/optimism",
|
||||
"reth-auto-seal-consensus/optimism",
|
||||
"reth-rpc-eth-types/optimism"
|
||||
"reth-rpc-eth-types/optimism",
|
||||
"reth-optimism-rpc/optimism"
|
||||
]
|
||||
test-utils = ["reth-node-builder/test-utils"]
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
//! Optimism Node types config.
|
||||
|
||||
use crate::{
|
||||
args::RollupArgs,
|
||||
txpool::{OpTransactionPool, OpTransactionValidator},
|
||||
OptimismEngineTypes,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig};
|
||||
use reth_evm::ConfigureEvm;
|
||||
use reth_evm_optimism::{OpExecutorProvider, OptimismEvmConfig};
|
||||
use reth_network::{NetworkHandle, NetworkManager};
|
||||
use reth_node_api::{FullNodeComponents, NodeAddOns};
|
||||
use reth_node_builder::{
|
||||
components::{
|
||||
ComponentsBuilder, ConsensusBuilder, ExecutorBuilder, NetworkBuilder,
|
||||
@ -18,14 +16,21 @@ use reth_node_builder::{
|
||||
BuilderContext, Node, PayloadBuilderConfig,
|
||||
};
|
||||
use reth_optimism_consensus::OptimismBeaconConsensus;
|
||||
use reth_optimism_rpc::OpEthApi;
|
||||
use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService};
|
||||
use reth_provider::CanonStateSubscriptions;
|
||||
use reth_rpc::EthApi;
|
||||
use reth_tracing::tracing::{debug, info};
|
||||
use reth_transaction_pool::{
|
||||
blobstore::DiskFileBlobStore, CoinbaseTipOrdering, TransactionPool,
|
||||
TransactionValidationTaskExecutor,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
args::RollupArgs,
|
||||
txpool::{OpTransactionPool, OpTransactionValidator},
|
||||
OptimismEngineTypes,
|
||||
};
|
||||
|
||||
/// Type configuration for a regular Optimism node.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
@ -82,9 +87,11 @@ where
|
||||
OptimismConsensusBuilder,
|
||||
>;
|
||||
|
||||
fn components_builder(self) -> Self::ComponentsBuilder {
|
||||
type AddOns = OptimismAddOns;
|
||||
|
||||
fn components_builder(&self) -> Self::ComponentsBuilder {
|
||||
let Self { args } = self;
|
||||
Self::components(args)
|
||||
Self::components(args.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,6 +100,14 @@ impl NodeTypes for OptimismNode {
|
||||
type Engine = OptimismEngineTypes;
|
||||
}
|
||||
|
||||
/// Add-ons w.r.t. optimism.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OptimismAddOns;
|
||||
|
||||
impl<N: FullNodeComponents> NodeAddOns<N> for OptimismAddOns {
|
||||
type EthApi = OpEthApi<EthApi<N::Provider, N::Pool, NetworkHandle, N::Evm>>;
|
||||
}
|
||||
|
||||
/// A regular optimism evm and executor builder.
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[non_exhaustive]
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use alloy_genesis::Genesis;
|
||||
use reth::{rpc::types::engine::PayloadAttributes, tasks::TaskManager};
|
||||
use reth_chainspec::{ChainSpecBuilder, BASE_MAINNET};
|
||||
use reth_e2e_test_utils::{transaction::TransactionTestContext, wallet::Wallet, NodeHelperType};
|
||||
use reth_node_optimism::{OptimismBuiltPayload, OptimismNode, OptimismPayloadBuilderAttributes};
|
||||
use reth_node_optimism::{
|
||||
node::OptimismAddOns, OptimismBuiltPayload, OptimismNode, OptimismPayloadBuilderAttributes,
|
||||
};
|
||||
use reth_payload_builder::EthPayloadBuilderAttributes;
|
||||
use reth_primitives::{Address, B256};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
/// Optimism Node Helper type
|
||||
pub(crate) type OpNode = NodeHelperType<OptimismNode>;
|
||||
pub(crate) type OpNode = NodeHelperType<OptimismNode, OptimismAddOns>;
|
||||
|
||||
pub(crate) async fn setup(num_nodes: usize) -> eyre::Result<(Vec<OpNode>, TaskManager, Wallet)> {
|
||||
let genesis: Genesis = serde_json::from_str(include_str!("../assets/genesis.json")).unwrap();
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
use reth_db::test_utils::create_test_rw_db;
|
||||
use reth_node_api::FullNodeComponents;
|
||||
use reth_node_builder::{NodeBuilder, NodeConfig};
|
||||
use reth_node_optimism::node::OptimismNode;
|
||||
use reth_node_optimism::node::{OptimismAddOns, OptimismNode};
|
||||
|
||||
#[test]
|
||||
fn test_basic_setup() {
|
||||
@ -14,6 +14,7 @@ fn test_basic_setup() {
|
||||
.with_database(db)
|
||||
.with_types::<OptimismNode>()
|
||||
.with_components(OptimismNode::components(Default::default()))
|
||||
.with_add_ons::<OptimismAddOns>()
|
||||
.on_component_initialized(move |ctx| {
|
||||
let _provider = ctx.provider();
|
||||
Ok(())
|
||||
|
||||
@ -25,6 +25,8 @@ reth-rpc-server-types.workspace = true
|
||||
reth-rpc-types.workspace = true
|
||||
reth-tasks = { workspace = true, features = ["rayon"] }
|
||||
reth-transaction-pool.workspace = true
|
||||
reth-rpc.workspace = true
|
||||
reth-node-api.workspace = true
|
||||
|
||||
# ethereum
|
||||
alloy-primitives.workspace = true
|
||||
|
||||
@ -12,9 +12,15 @@ use alloy_primitives::{Address, U64};
|
||||
use reth_chainspec::{ChainInfo, ChainSpec};
|
||||
use reth_errors::RethResult;
|
||||
use reth_evm::ConfigureEvm;
|
||||
use reth_node_api::{BuilderProvider, FullNodeComponents};
|
||||
use reth_provider::{BlockReaderIdExt, ChainSpecProvider, HeaderProvider, StateProviderFactory};
|
||||
use reth_rpc_eth_api::helpers::{
|
||||
Call, EthApiSpec, EthCall, EthFees, EthState, LoadFee, LoadState, SpawnBlocking, Trace,
|
||||
use reth_rpc::eth::DevSigner;
|
||||
use reth_rpc_eth_api::{
|
||||
helpers::{
|
||||
AddDevSigners, Call, EthApiSpec, EthCall, EthFees, EthSigner, EthState, LoadFee, LoadState,
|
||||
SpawnBlocking, Trace, UpdateRawTxForwarder,
|
||||
},
|
||||
RawTransactionForwarder,
|
||||
};
|
||||
use reth_rpc_eth_types::EthStateCache;
|
||||
use reth_rpc_types::SyncStatus;
|
||||
@ -154,3 +160,31 @@ impl<Eth: Trace> Trace for OpEthApi<Eth> {
|
||||
self.inner.evm_config()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Eth: AddDevSigners> AddDevSigners for OpEthApi<Eth> {
|
||||
fn signers(&self) -> &parking_lot::RwLock<Vec<Box<dyn EthSigner>>> {
|
||||
self.inner.signers()
|
||||
}
|
||||
|
||||
fn with_dev_accounts(&self) {
|
||||
*self.signers().write() = DevSigner::random_signers(20)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Eth: UpdateRawTxForwarder> UpdateRawTxForwarder for OpEthApi<Eth> {
|
||||
fn set_eth_raw_transaction_forwarder(&self, forwarder: Arc<dyn RawTransactionForwarder>) {
|
||||
self.inner.set_eth_raw_transaction_forwarder(forwarder);
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, Eth> BuilderProvider<N> for OpEthApi<Eth>
|
||||
where
|
||||
Eth: BuilderProvider<N>,
|
||||
N: FullNodeComponents,
|
||||
{
|
||||
type Ctx<'a> = <Eth as BuilderProvider<N>>::Ctx<'a>;
|
||||
|
||||
fn builder() -> Box<dyn for<'a> Fn(Self::Ctx<'a>) -> Self + Send> {
|
||||
Box::new(|ctx| Self { inner: Eth::builder()(ctx) })
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +61,7 @@ reth-rpc-types-compat.workspace = true
|
||||
reth-tracing.workspace = true
|
||||
reth-transaction-pool = { workspace = true, features = ["test-utils"] }
|
||||
reth-tokio-util.workspace = true
|
||||
reth-node-api.workspace = true
|
||||
|
||||
tokio = { workspace = true, features = ["rt", "rt-multi-thread"] }
|
||||
serde_json.workspace = true
|
||||
|
||||
@ -1,16 +1,18 @@
|
||||
use crate::{
|
||||
auth::AuthServerConfig, error::RpcError, EthConfig, IpcServerBuilder, RpcModuleConfig,
|
||||
RpcServerConfig, TransportRpcModuleConfig,
|
||||
};
|
||||
use std::{net::SocketAddr, path::PathBuf};
|
||||
|
||||
use jsonrpsee::server::ServerBuilder;
|
||||
use reth_node_core::{args::RpcServerArgs, utils::get_or_create_jwt_secret_from_path};
|
||||
use reth_rpc_eth_types::{EthStateCacheConfig, GasPriceOracleConfig};
|
||||
use reth_rpc_eth_types::{EthConfig, EthStateCacheConfig, GasPriceOracleConfig};
|
||||
use reth_rpc_layer::{JwtError, JwtSecret};
|
||||
use reth_rpc_server_types::RpcModuleSelection;
|
||||
use std::{net::SocketAddr, path::PathBuf};
|
||||
use tower::layer::util::Identity;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::{
|
||||
auth::AuthServerConfig, error::RpcError, IpcServerBuilder, RpcModuleConfig, RpcServerConfig,
|
||||
TransportRpcModuleConfig,
|
||||
};
|
||||
|
||||
/// A trait that provides a configured RPC server.
|
||||
///
|
||||
/// This provides all basic config values for the RPC server and is implemented by the
|
||||
|
||||
@ -1,31 +1,14 @@
|
||||
use std::{fmt::Debug, time::Duration};
|
||||
|
||||
use reth_evm::ConfigureEvm;
|
||||
use reth_network_api::NetworkInfo;
|
||||
use reth_provider::{
|
||||
BlockReader, BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider, EvmEnvProvider,
|
||||
FullRpcProvider, StateProviderFactory,
|
||||
};
|
||||
use reth_rpc::{eth::EthFilterConfig, EthApi, EthFilter, EthPubSub};
|
||||
use reth_provider::{BlockReader, CanonStateSubscriptions, EvmEnvProvider, StateProviderFactory};
|
||||
use reth_rpc::{EthFilter, EthPubSub};
|
||||
use reth_rpc_eth_types::{
|
||||
cache::cache_new_blocks_task, fee_history::fee_history_cache_new_blocks_task, EthStateCache,
|
||||
EthStateCacheConfig, FeeHistoryCache, FeeHistoryCacheConfig, GasPriceOracle,
|
||||
GasPriceOracleConfig, RPC_DEFAULT_GAS_CAP,
|
||||
cache::cache_new_blocks_task, EthApiBuilderCtx, EthConfig, EthStateCache,
|
||||
};
|
||||
use reth_rpc_server_types::constants::{
|
||||
default_max_tracing_requests, DEFAULT_ETH_PROOF_WINDOW, DEFAULT_MAX_BLOCKS_PER_FILTER,
|
||||
DEFAULT_MAX_LOGS_PER_RESPONSE, DEFAULT_PROOF_PERMITS,
|
||||
};
|
||||
use reth_tasks::{pool::BlockingTaskPool, TaskSpawner};
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use reth_tasks::TaskSpawner;
|
||||
|
||||
/// Default value for stale filter ttl
|
||||
const DEFAULT_STALE_FILTER_TTL: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
/// Alias for function that builds the core `eth` namespace API.
|
||||
pub type EthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi> =
|
||||
Box<dyn FnOnce(&EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>) -> EthApi>;
|
||||
/// Alias for `eth` namespace API builder.
|
||||
pub type DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi> =
|
||||
Box<dyn Fn(&EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>) -> EthApi>;
|
||||
|
||||
/// Handlers for core, filter and pubsub `eth` namespace APIs.
|
||||
#[derive(Debug, Clone)]
|
||||
@ -43,7 +26,7 @@ pub struct EthHandlers<Provider, Pool, Network, Events, EthApi> {
|
||||
impl<Provider, Pool, Network, Events, EthApi> EthHandlers<Provider, Pool, Network, Events, EthApi> {
|
||||
/// Returns a new [`EthHandlers`] builder.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn builder<EvmConfig, Tasks, EthApiB>(
|
||||
pub fn builder<EvmConfig, Tasks>(
|
||||
provider: Provider,
|
||||
pool: Pool,
|
||||
network: Network,
|
||||
@ -51,12 +34,16 @@ impl<Provider, Pool, Network, Events, EthApi> EthHandlers<Provider, Pool, Networ
|
||||
config: EthConfig,
|
||||
executor: Tasks,
|
||||
events: Events,
|
||||
eth_api_builder: EthApiB,
|
||||
) -> EthHandlersBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi>
|
||||
where
|
||||
EthApiB: FnOnce(&EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>) -> EthApi
|
||||
+ 'static,
|
||||
{
|
||||
eth_api_builder: DynEthApiBuilder<
|
||||
Provider,
|
||||
Pool,
|
||||
EvmConfig,
|
||||
Network,
|
||||
Tasks,
|
||||
Events,
|
||||
EthApi,
|
||||
>,
|
||||
) -> EthHandlersBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi> {
|
||||
EthHandlersBuilder {
|
||||
provider,
|
||||
pool,
|
||||
@ -65,7 +52,7 @@ impl<Provider, Pool, Network, Events, EthApi> EthHandlers<Provider, Pool, Networ
|
||||
config,
|
||||
executor,
|
||||
events,
|
||||
eth_api_builder: Box::new(eth_api_builder),
|
||||
eth_api_builder,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -80,7 +67,7 @@ pub struct EthHandlersBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig,
|
||||
config: EthConfig,
|
||||
executor: Tasks,
|
||||
events: Events,
|
||||
eth_api_builder: EthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
|
||||
eth_api_builder: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
|
||||
}
|
||||
|
||||
impl<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi>
|
||||
@ -89,9 +76,10 @@ where
|
||||
Provider: StateProviderFactory + BlockReader + EvmEnvProvider + Clone + Unpin + 'static,
|
||||
Pool: Send + Sync + Clone + 'static,
|
||||
EvmConfig: ConfigureEvm,
|
||||
Network: Clone,
|
||||
Network: Clone + 'static,
|
||||
Tasks: TaskSpawner + Clone + 'static,
|
||||
Events: CanonStateSubscriptions + Clone,
|
||||
Events: CanonStateSubscriptions + Clone + 'static,
|
||||
EthApi: 'static,
|
||||
{
|
||||
/// Returns a new instance with handlers for `eth` namespace.
|
||||
pub fn build(self) -> EthHandlers<Provider, Pool, Network, Events, EthApi> {
|
||||
@ -135,170 +123,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Additional config values for the eth namespace.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct EthConfig {
|
||||
/// Settings for the caching layer
|
||||
pub cache: EthStateCacheConfig,
|
||||
/// Settings for the gas price oracle
|
||||
pub gas_oracle: GasPriceOracleConfig,
|
||||
/// The maximum number of blocks into the past for generating state proofs.
|
||||
pub eth_proof_window: u64,
|
||||
/// The maximum number of tracing calls that can be executed in concurrently.
|
||||
pub max_tracing_requests: usize,
|
||||
/// Maximum number of blocks that could be scanned per filter request in `eth_getLogs` calls.
|
||||
pub max_blocks_per_filter: u64,
|
||||
/// Maximum number of logs that can be returned in a single response in `eth_getLogs` calls.
|
||||
pub max_logs_per_response: usize,
|
||||
/// Gas limit for `eth_call` and call tracing RPC methods.
|
||||
///
|
||||
/// Defaults to [`RPC_DEFAULT_GAS_CAP`]
|
||||
pub rpc_gas_cap: u64,
|
||||
///
|
||||
/// Sets TTL for stale filters
|
||||
pub stale_filter_ttl: Duration,
|
||||
/// Settings for the fee history cache
|
||||
pub fee_history_cache: FeeHistoryCacheConfig,
|
||||
/// The maximum number of getproof calls that can be executed concurrently.
|
||||
pub proof_permits: usize,
|
||||
}
|
||||
|
||||
impl EthConfig {
|
||||
/// Returns the filter config for the `eth_filter` handler.
|
||||
pub fn filter_config(&self) -> EthFilterConfig {
|
||||
EthFilterConfig::default()
|
||||
.max_blocks_per_filter(self.max_blocks_per_filter)
|
||||
.max_logs_per_response(self.max_logs_per_response)
|
||||
.stale_filter_ttl(self.stale_filter_ttl)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EthConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
cache: EthStateCacheConfig::default(),
|
||||
gas_oracle: GasPriceOracleConfig::default(),
|
||||
eth_proof_window: DEFAULT_ETH_PROOF_WINDOW,
|
||||
max_tracing_requests: default_max_tracing_requests(),
|
||||
max_blocks_per_filter: DEFAULT_MAX_BLOCKS_PER_FILTER,
|
||||
max_logs_per_response: DEFAULT_MAX_LOGS_PER_RESPONSE,
|
||||
rpc_gas_cap: RPC_DEFAULT_GAS_CAP.into(),
|
||||
stale_filter_ttl: DEFAULT_STALE_FILTER_TTL,
|
||||
fee_history_cache: FeeHistoryCacheConfig::default(),
|
||||
proof_permits: DEFAULT_PROOF_PERMITS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EthConfig {
|
||||
/// Configures the caching layer settings
|
||||
pub const fn state_cache(mut self, cache: EthStateCacheConfig) -> Self {
|
||||
self.cache = cache;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the gas price oracle settings
|
||||
pub const fn gpo_config(mut self, gas_oracle_config: GasPriceOracleConfig) -> Self {
|
||||
self.gas_oracle = gas_oracle_config;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum number of tracing requests
|
||||
pub const fn max_tracing_requests(mut self, max_requests: usize) -> Self {
|
||||
self.max_tracing_requests = max_requests;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum block length to scan per `eth_getLogs` request
|
||||
pub const fn max_blocks_per_filter(mut self, max_blocks: u64) -> Self {
|
||||
self.max_blocks_per_filter = max_blocks;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum number of logs per response
|
||||
pub const fn max_logs_per_response(mut self, max_logs: usize) -> Self {
|
||||
self.max_logs_per_response = max_logs;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum gas limit for `eth_call` and call tracing RPC methods
|
||||
pub const fn rpc_gas_cap(mut self, rpc_gas_cap: u64) -> Self {
|
||||
self.rpc_gas_cap = rpc_gas_cap;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum proof window for historical proof generation.
|
||||
pub const fn eth_proof_window(mut self, window: u64) -> Self {
|
||||
self.eth_proof_window = window;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the number of getproof requests
|
||||
pub const fn proof_permits(mut self, permits: usize) -> Self {
|
||||
self.proof_permits = permits;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Context for building the `eth` namespace API.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events> {
|
||||
/// Database handle.
|
||||
pub provider: Provider,
|
||||
/// Mempool handle.
|
||||
pub pool: Pool,
|
||||
/// Network handle.
|
||||
pub network: Network,
|
||||
/// EVM configuration.
|
||||
pub evm_config: EvmConfig,
|
||||
/// RPC config for `eth` namespace.
|
||||
pub config: EthConfig,
|
||||
/// Runtime handle.
|
||||
pub executor: Tasks,
|
||||
/// Events handle.
|
||||
pub events: Events,
|
||||
/// RPC cache handle.
|
||||
pub cache: EthStateCache,
|
||||
}
|
||||
|
||||
/// Ethereum layer one `eth` RPC server builder.
|
||||
#[derive(Default, Debug, Clone, Copy)]
|
||||
pub struct EthApiBuild;
|
||||
|
||||
impl EthApiBuild {
|
||||
/// Builds the [`EthApiServer`](reth_rpc_eth_api::EthApiServer), for given context.
|
||||
pub fn build<Provider, Pool, EvmConfig, Network, Tasks, Events>(
|
||||
ctx: &EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>,
|
||||
) -> EthApi<Provider, Pool, Network, EvmConfig>
|
||||
where
|
||||
Provider: FullRpcProvider,
|
||||
Pool: TransactionPool,
|
||||
Network: NetworkInfo + Clone,
|
||||
Tasks: TaskSpawner + Clone + 'static,
|
||||
Events: CanonStateSubscriptions,
|
||||
EvmConfig: ConfigureEvm,
|
||||
{
|
||||
let gas_oracle = GasPriceOracleBuilder::build(ctx);
|
||||
let fee_history_cache = FeeHistoryCacheBuilder::build(ctx);
|
||||
|
||||
EthApi::with_spawner(
|
||||
ctx.provider.clone(),
|
||||
ctx.pool.clone(),
|
||||
ctx.network.clone(),
|
||||
ctx.cache.clone(),
|
||||
gas_oracle,
|
||||
ctx.config.rpc_gas_cap,
|
||||
ctx.config.eth_proof_window,
|
||||
Box::new(ctx.executor.clone()),
|
||||
BlockingTaskPool::build().expect("failed to build blocking task pool"),
|
||||
fee_history_cache,
|
||||
ctx.evm_config.clone(),
|
||||
None,
|
||||
ctx.config.proof_permits,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds the `eth_` namespace API [`EthFilterApiServer`](reth_rpc_eth_api::EthFilterApiServer).
|
||||
#[derive(Debug)]
|
||||
pub struct EthFilterApiBuilder;
|
||||
@ -348,50 +172,3 @@ impl EthPubSubApiBuilder {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds `eth_` core api component [`GasPriceOracle`], for given context.
|
||||
#[derive(Debug)]
|
||||
pub struct GasPriceOracleBuilder;
|
||||
|
||||
impl GasPriceOracleBuilder {
|
||||
/// Builds a [`GasPriceOracle`], for given context.
|
||||
pub fn build<Provider, Pool, EvmConfig, Network, Tasks, Events>(
|
||||
ctx: &EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>,
|
||||
) -> GasPriceOracle<Provider>
|
||||
where
|
||||
Provider: BlockReaderIdExt + Clone,
|
||||
{
|
||||
GasPriceOracle::new(ctx.provider.clone(), ctx.config.gas_oracle, ctx.cache.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds `eth_` core api component [`FeeHistoryCache`], for given context.
|
||||
#[derive(Debug)]
|
||||
pub struct FeeHistoryCacheBuilder;
|
||||
|
||||
impl FeeHistoryCacheBuilder {
|
||||
/// Builds a [`FeeHistoryCache`], for given context.
|
||||
pub fn build<Provider, Pool, EvmConfig, Network, Tasks, Events>(
|
||||
ctx: &EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>,
|
||||
) -> FeeHistoryCache
|
||||
where
|
||||
Provider: ChainSpecProvider + BlockReaderIdExt + Clone + 'static,
|
||||
Tasks: TaskSpawner,
|
||||
Events: CanonStateSubscriptions,
|
||||
{
|
||||
let fee_history_cache =
|
||||
FeeHistoryCache::new(ctx.cache.clone(), ctx.config.fee_history_cache);
|
||||
|
||||
let new_canonical_blocks = ctx.events.canonical_state_stream();
|
||||
let fhc = fee_history_cache.clone();
|
||||
let provider = ctx.provider.clone();
|
||||
ctx.executor.spawn_critical(
|
||||
"cache canonical blocks for fee history task",
|
||||
Box::pin(async move {
|
||||
fee_history_cache_new_blocks_task(fhc, new_canonical_blocks, provider).await;
|
||||
}),
|
||||
);
|
||||
|
||||
fee_history_cache
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,13 +19,13 @@
|
||||
//! use reth_evm::ConfigureEvm;
|
||||
//! use reth_network_api::{NetworkInfo, Peers};
|
||||
//! use reth_provider::{AccountReader, CanonStateSubscriptions, ChangeSetReader, FullRpcProvider};
|
||||
//! use reth_rpc::EthApi;
|
||||
//! use reth_rpc_builder::{
|
||||
//! EthApiBuild, RethRpcModule, RpcModuleBuilder, RpcServerConfig, ServerBuilder,
|
||||
//! TransportRpcModuleConfig,
|
||||
//! RethRpcModule, RpcModuleBuilder, RpcServerConfig, ServerBuilder, TransportRpcModuleConfig,
|
||||
//! };
|
||||
//!
|
||||
//! use reth_tasks::TokioTaskExecutor;
|
||||
//! use reth_transaction_pool::TransactionPool;
|
||||
//!
|
||||
//! pub async fn launch<Provider, Pool, Network, Events, EvmConfig>(
|
||||
//! provider: Provider,
|
||||
//! pool: Pool,
|
||||
@ -54,7 +54,7 @@
|
||||
//! events,
|
||||
//! evm_config,
|
||||
//! )
|
||||
//! .build(transports, EthApiBuild::build);
|
||||
//! .build(transports, Box::new(EthApi::with_spawner));
|
||||
//! let handle = RpcServerConfig::default()
|
||||
//! .with_http(ServerBuilder::default())
|
||||
//! .start(&transport_modules)
|
||||
@ -70,9 +70,10 @@
|
||||
//! use reth_evm::ConfigureEvm;
|
||||
//! use reth_network_api::{NetworkInfo, Peers};
|
||||
//! use reth_provider::{AccountReader, CanonStateSubscriptions, ChangeSetReader, FullRpcProvider};
|
||||
//! use reth_rpc::EthApi;
|
||||
//! use reth_rpc_api::EngineApiServer;
|
||||
//! use reth_rpc_builder::{
|
||||
//! auth::AuthServerConfig, EthApiBuild, RethRpcModule, RpcModuleBuilder, RpcServerConfig,
|
||||
//! auth::AuthServerConfig, RethRpcModule, RpcModuleBuilder, RpcServerConfig,
|
||||
//! TransportRpcModuleConfig,
|
||||
//! };
|
||||
//! use reth_rpc_layer::JwtSecret;
|
||||
@ -113,7 +114,7 @@
|
||||
//!
|
||||
//! // configure the server modules
|
||||
//! let (modules, auth_module, _registry) =
|
||||
//! builder.build_with_auth_server(transports, engine_api, EthApiBuild::build);
|
||||
//! builder.build_with_auth_server(transports, engine_api, Box::new(EthApi::with_spawner));
|
||||
//!
|
||||
//! // start the servers
|
||||
//! let auth_config = AuthServerConfig::builder(JwtSecret::random()).build();
|
||||
@ -140,6 +141,7 @@ use std::{
|
||||
};
|
||||
|
||||
use error::{ConflictingModules, RpcError, ServerKind};
|
||||
use eth::DynEthApiBuilder;
|
||||
use http::{header::AUTHORIZATION, HeaderMap};
|
||||
use jsonrpsee::{
|
||||
core::RegisterMethodError,
|
||||
@ -167,7 +169,7 @@ use reth_rpc_eth_api::{
|
||||
},
|
||||
EthApiServer, FullEthApiServer, RawTransactionForwarder,
|
||||
};
|
||||
use reth_rpc_eth_types::{EthStateCache, EthSubscriptionIdProvider};
|
||||
use reth_rpc_eth_types::{EthConfig, EthStateCache, EthSubscriptionIdProvider};
|
||||
use reth_rpc_layer::{AuthLayer, Claims, JwtAuthValidator, JwtSecret};
|
||||
use reth_tasks::{pool::BlockingTaskGuard, TaskSpawner, TokioTaskExecutor};
|
||||
use reth_transaction_pool::{noop::NoopTransactionPool, TransactionPool};
|
||||
@ -202,17 +204,14 @@ pub mod error;
|
||||
|
||||
/// Eth utils
|
||||
pub mod eth;
|
||||
pub use eth::{
|
||||
EthApiBuild, EthApiBuilderCtx, EthConfig, EthHandlers, FeeHistoryCacheBuilder,
|
||||
GasPriceOracleBuilder,
|
||||
};
|
||||
pub use eth::EthHandlers;
|
||||
|
||||
// Rpc server metrics
|
||||
mod metrics;
|
||||
|
||||
/// Convenience function for starting a server in one step.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn launch<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi, EthApiB>(
|
||||
pub async fn launch<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi>(
|
||||
provider: Provider,
|
||||
pool: Pool,
|
||||
network: Network,
|
||||
@ -221,7 +220,7 @@ pub async fn launch<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi, E
|
||||
executor: Tasks,
|
||||
events: Events,
|
||||
evm_config: EvmConfig,
|
||||
eth: EthApiB,
|
||||
eth: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
|
||||
) -> Result<RpcServerHandle, RpcError>
|
||||
where
|
||||
Provider: FullRpcProvider + AccountReader + ChangeSetReader,
|
||||
@ -230,8 +229,6 @@ where
|
||||
Tasks: TaskSpawner + Clone + 'static,
|
||||
Events: CanonStateSubscriptions + Clone + 'static,
|
||||
EvmConfig: ConfigureEvm,
|
||||
EthApiB: FnOnce(&EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>) -> EthApi
|
||||
+ 'static,
|
||||
EthApi: FullEthApiServer,
|
||||
{
|
||||
let module_config = module_config.into();
|
||||
@ -426,11 +423,11 @@ where
|
||||
/// also configures the auth (engine api) server, which exposes a subset of the `eth_`
|
||||
/// namespace.
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn build_with_auth_server<EngineApi, EngineT, EthApi, EthApiB>(
|
||||
pub fn build_with_auth_server<EngineApi, EngineT, EthApi>(
|
||||
self,
|
||||
module_config: TransportRpcModuleConfig,
|
||||
engine: EngineApi,
|
||||
eth: EthApiB,
|
||||
eth: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
|
||||
) -> (
|
||||
TransportRpcModules,
|
||||
AuthRpcModule,
|
||||
@ -439,8 +436,6 @@ where
|
||||
where
|
||||
EngineT: EngineTypes + 'static,
|
||||
EngineApi: EngineApiServer<EngineT>,
|
||||
EthApiB: FnOnce(&EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>) -> EthApi
|
||||
+ 'static,
|
||||
EthApi: FullEthApiServer,
|
||||
{
|
||||
let Self { provider, pool, network, executor, events, evm_config } = self;
|
||||
@ -469,7 +464,8 @@ where
|
||||
/// use reth_evm::ConfigureEvm;
|
||||
/// use reth_network_api::noop::NoopNetwork;
|
||||
/// use reth_provider::test_utils::{NoopProvider, TestCanonStateSubscriptions};
|
||||
/// use reth_rpc_builder::{EthApiBuild, RpcModuleBuilder};
|
||||
/// use reth_rpc::EthApi;
|
||||
/// use reth_rpc_builder::RpcModuleBuilder;
|
||||
/// use reth_tasks::TokioTaskExecutor;
|
||||
/// use reth_transaction_pool::noop::NoopTransactionPool;
|
||||
///
|
||||
@ -481,19 +477,18 @@ where
|
||||
/// .with_executor(TokioTaskExecutor::default())
|
||||
/// .with_events(TestCanonStateSubscriptions::default())
|
||||
/// .with_evm_config(evm)
|
||||
/// .into_registry(Default::default(), EthApiBuild::build);
|
||||
/// .into_registry(Default::default(), Box::new(EthApi::with_spawner));
|
||||
///
|
||||
/// let eth_api = registry.eth_api();
|
||||
/// }
|
||||
/// ```
|
||||
pub fn into_registry<EthApi, EthApiB>(
|
||||
pub fn into_registry<EthApi>(
|
||||
self,
|
||||
config: RpcModuleConfig,
|
||||
eth: EthApiB,
|
||||
eth: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
|
||||
) -> RpcRegistryInner<Provider, Pool, Network, Tasks, Events, EthApi>
|
||||
where
|
||||
EthApiB: FnOnce(&EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>) -> EthApi
|
||||
+ 'static,
|
||||
EthApi: 'static,
|
||||
{
|
||||
let Self { provider, pool, network, executor, events, evm_config } = self;
|
||||
RpcRegistryInner::new(provider, pool, network, executor, events, config, evm_config, eth)
|
||||
@ -501,14 +496,12 @@ where
|
||||
|
||||
/// Configures all [`RpcModule`]s specific to the given [`TransportRpcModuleConfig`] which can
|
||||
/// be used to start the transport server(s).
|
||||
pub fn build<EthApi, EthApiB>(
|
||||
pub fn build<EthApi>(
|
||||
self,
|
||||
module_config: TransportRpcModuleConfig,
|
||||
eth: EthApiB,
|
||||
eth: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
|
||||
) -> TransportRpcModules<()>
|
||||
where
|
||||
EthApiB: FnOnce(&EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>) -> EthApi
|
||||
+ 'static,
|
||||
EthApi: FullEthApiServer,
|
||||
{
|
||||
let mut modules = TransportRpcModules::default();
|
||||
@ -636,13 +629,14 @@ impl<Provider, Pool, Network, Tasks, Events, EthApi>
|
||||
where
|
||||
Provider: StateProviderFactory + BlockReader + EvmEnvProvider + Clone + Unpin + 'static,
|
||||
Pool: Send + Sync + Clone + 'static,
|
||||
Network: Clone,
|
||||
Events: CanonStateSubscriptions + Clone,
|
||||
Network: Clone + 'static,
|
||||
Events: CanonStateSubscriptions + Clone + 'static,
|
||||
Tasks: TaskSpawner + Clone + 'static,
|
||||
EthApi: 'static,
|
||||
{
|
||||
/// Creates a new, empty instance.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new<EvmConfig, EthApiB>(
|
||||
pub fn new<EvmConfig>(
|
||||
provider: Provider,
|
||||
pool: Pool,
|
||||
network: Network,
|
||||
@ -650,12 +644,18 @@ where
|
||||
events: Events,
|
||||
config: RpcModuleConfig,
|
||||
evm_config: EvmConfig,
|
||||
eth_api_builder: EthApiB,
|
||||
eth_api_builder: DynEthApiBuilder<
|
||||
Provider,
|
||||
Pool,
|
||||
EvmConfig,
|
||||
Network,
|
||||
Tasks,
|
||||
Events,
|
||||
EthApi,
|
||||
>,
|
||||
) -> Self
|
||||
where
|
||||
EvmConfig: ConfigureEvm,
|
||||
EthApiB: FnOnce(&EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>) -> EthApi
|
||||
+ 'static,
|
||||
{
|
||||
let blocking_pool_guard = BlockingTaskGuard::new(config.eth.max_tracing_requests);
|
||||
|
||||
|
||||
@ -2,9 +2,10 @@
|
||||
|
||||
use std::io;
|
||||
|
||||
use reth_rpc::EthApi;
|
||||
use reth_rpc_builder::{
|
||||
error::{RpcError, ServerKind, WsHttpSamePortError},
|
||||
EthApiBuild, RpcServerConfig, TransportRpcModuleConfig,
|
||||
RpcServerConfig, TransportRpcModuleConfig,
|
||||
};
|
||||
use reth_rpc_server_types::RethRpcModule;
|
||||
|
||||
@ -26,8 +27,10 @@ async fn test_http_addr_in_use() {
|
||||
let handle = launch_http(vec![RethRpcModule::Admin]).await;
|
||||
let addr = handle.http_local_addr().unwrap();
|
||||
let builder = test_rpc_builder();
|
||||
let server = builder
|
||||
.build(TransportRpcModuleConfig::set_http(vec![RethRpcModule::Admin]), EthApiBuild::build);
|
||||
let server = builder.build(
|
||||
TransportRpcModuleConfig::set_http(vec![RethRpcModule::Admin]),
|
||||
Box::new(EthApi::with_spawner),
|
||||
);
|
||||
let result =
|
||||
RpcServerConfig::http(Default::default()).with_http_address(addr).start(&server).await;
|
||||
let err = result.unwrap_err();
|
||||
@ -39,8 +42,10 @@ async fn test_ws_addr_in_use() {
|
||||
let handle = launch_ws(vec![RethRpcModule::Admin]).await;
|
||||
let addr = handle.ws_local_addr().unwrap();
|
||||
let builder = test_rpc_builder();
|
||||
let server = builder
|
||||
.build(TransportRpcModuleConfig::set_ws(vec![RethRpcModule::Admin]), EthApiBuild::build);
|
||||
let server = builder.build(
|
||||
TransportRpcModuleConfig::set_ws(vec![RethRpcModule::Admin]),
|
||||
Box::new(EthApi::with_spawner),
|
||||
);
|
||||
let result = RpcServerConfig::ws(Default::default()).with_ws_address(addr).start(&server).await;
|
||||
let err = result.unwrap_err();
|
||||
assert!(is_addr_in_use_kind(&err, ServerKind::WS(addr)), "{err}");
|
||||
@ -60,7 +65,7 @@ async fn test_launch_same_port_different_modules() {
|
||||
let server = builder.build(
|
||||
TransportRpcModuleConfig::set_ws(vec![RethRpcModule::Admin])
|
||||
.with_http(vec![RethRpcModule::Eth]),
|
||||
EthApiBuild::build,
|
||||
Box::new(EthApi::with_spawner),
|
||||
);
|
||||
let addr = test_address();
|
||||
let res = RpcServerConfig::ws(Default::default())
|
||||
@ -82,7 +87,7 @@ async fn test_launch_same_port_same_cors() {
|
||||
let server = builder.build(
|
||||
TransportRpcModuleConfig::set_ws(vec![RethRpcModule::Eth])
|
||||
.with_http(vec![RethRpcModule::Eth]),
|
||||
EthApiBuild::build,
|
||||
Box::new(EthApi::with_spawner),
|
||||
);
|
||||
let addr = test_address();
|
||||
let res = RpcServerConfig::ws(Default::default())
|
||||
@ -102,7 +107,7 @@ async fn test_launch_same_port_different_cors() {
|
||||
let server = builder.build(
|
||||
TransportRpcModuleConfig::set_ws(vec![RethRpcModule::Eth])
|
||||
.with_http(vec![RethRpcModule::Eth]),
|
||||
EthApiBuild::build,
|
||||
Box::new(EthApi::with_spawner),
|
||||
);
|
||||
let addr = test_address();
|
||||
let res = RpcServerConfig::ws(Default::default())
|
||||
|
||||
@ -7,9 +7,10 @@ use reth_evm_ethereum::EthEvmConfig;
|
||||
use reth_network_api::noop::NoopNetwork;
|
||||
use reth_payload_builder::test_utils::spawn_test_payload_service;
|
||||
use reth_provider::test_utils::{NoopProvider, TestCanonStateSubscriptions};
|
||||
use reth_rpc::EthApi;
|
||||
use reth_rpc_builder::{
|
||||
auth::{AuthRpcModule, AuthServerConfig, AuthServerHandle},
|
||||
EthApiBuild, RpcModuleBuilder, RpcServerConfig, RpcServerHandle, TransportRpcModuleConfig,
|
||||
RpcModuleBuilder, RpcServerConfig, RpcServerHandle, TransportRpcModuleConfig,
|
||||
};
|
||||
use reth_rpc_engine_api::{capabilities::EngineCapabilities, EngineApi};
|
||||
use reth_rpc_layer::JwtSecret;
|
||||
@ -53,7 +54,8 @@ pub async fn launch_auth(secret: JwtSecret) -> AuthServerHandle {
|
||||
/// Launches a new server with http only with the given modules
|
||||
pub async fn launch_http(modules: impl Into<RpcModuleSelection>) -> RpcServerHandle {
|
||||
let builder = test_rpc_builder();
|
||||
let server = builder.build(TransportRpcModuleConfig::set_http(modules), EthApiBuild::build);
|
||||
let server =
|
||||
builder.build(TransportRpcModuleConfig::set_http(modules), Box::new(EthApi::with_spawner));
|
||||
RpcServerConfig::http(Default::default())
|
||||
.with_http_address(test_address())
|
||||
.start(&server)
|
||||
@ -64,7 +66,8 @@ pub async fn launch_http(modules: impl Into<RpcModuleSelection>) -> RpcServerHan
|
||||
/// Launches a new server with ws only with the given modules
|
||||
pub async fn launch_ws(modules: impl Into<RpcModuleSelection>) -> RpcServerHandle {
|
||||
let builder = test_rpc_builder();
|
||||
let server = builder.build(TransportRpcModuleConfig::set_ws(modules), EthApiBuild::build);
|
||||
let server =
|
||||
builder.build(TransportRpcModuleConfig::set_ws(modules), Box::new(EthApi::with_spawner));
|
||||
RpcServerConfig::ws(Default::default())
|
||||
.with_http_address(test_address())
|
||||
.start(&server)
|
||||
@ -78,7 +81,7 @@ pub async fn launch_http_ws(modules: impl Into<RpcModuleSelection>) -> RpcServer
|
||||
let modules = modules.into();
|
||||
let server = builder.build(
|
||||
TransportRpcModuleConfig::set_ws(modules.clone()).with_http(modules),
|
||||
EthApiBuild::build,
|
||||
Box::new(EthApi::with_spawner),
|
||||
);
|
||||
RpcServerConfig::ws(Default::default())
|
||||
.with_ws_address(test_address())
|
||||
@ -95,7 +98,7 @@ pub async fn launch_http_ws_same_port(modules: impl Into<RpcModuleSelection>) ->
|
||||
let modules = modules.into();
|
||||
let server = builder.build(
|
||||
TransportRpcModuleConfig::set_ws(modules.clone()).with_http(modules),
|
||||
EthApiBuild::build,
|
||||
Box::new(EthApi::with_spawner),
|
||||
);
|
||||
let addr = test_address();
|
||||
RpcServerConfig::ws(Default::default())
|
||||
|
||||
@ -32,7 +32,7 @@ pub use call::{Call, EthCall};
|
||||
pub use fee::{EthFees, LoadFee};
|
||||
pub use pending_block::LoadPendingBlock;
|
||||
pub use receipt::LoadReceipt;
|
||||
pub use signer::EthSigner;
|
||||
pub use signer::{AddDevSigners, EthSigner};
|
||||
pub use spec::EthApiSpec;
|
||||
pub use state::{EthState, LoadState};
|
||||
pub use trace::Trace;
|
||||
|
||||
@ -37,3 +37,14 @@ pub trait EthSigner: Send + Sync + DynClone {
|
||||
}
|
||||
|
||||
dyn_clone::clone_trait_object!(EthSigner);
|
||||
|
||||
/// Adds 20 random dev signers for access via the API. Used in dev mode.
|
||||
#[auto_impl::auto_impl(&)]
|
||||
pub trait AddDevSigners {
|
||||
/// Returns a handle to the signers.
|
||||
fn signers(&self) -> &parking_lot::RwLock<Vec<Box<dyn EthSigner>>>;
|
||||
|
||||
/// Generates 20 random developer accounts.
|
||||
/// Used in DEV mode.
|
||||
fn with_dev_accounts(&self);
|
||||
}
|
||||
|
||||
170
crates/rpc/rpc-eth-types/src/builder/config.rs
Normal file
170
crates/rpc/rpc-eth-types/src/builder/config.rs
Normal file
@ -0,0 +1,170 @@
|
||||
//! Configuration for `eth` namespace APIs.
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::{
|
||||
EthStateCacheConfig, FeeHistoryCacheConfig, GasPriceOracleConfig, RPC_DEFAULT_GAS_CAP,
|
||||
};
|
||||
use reth_rpc_server_types::constants::{
|
||||
default_max_tracing_requests, DEFAULT_ETH_PROOF_WINDOW, DEFAULT_MAX_BLOCKS_PER_FILTER,
|
||||
DEFAULT_MAX_LOGS_PER_RESPONSE, DEFAULT_PROOF_PERMITS,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Default value for stale filter ttl
|
||||
pub const DEFAULT_STALE_FILTER_TTL: Duration = Duration::from_secs(5 * 60);
|
||||
|
||||
/// Additional config values for the eth namespace.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct EthConfig {
|
||||
/// Settings for the caching layer
|
||||
pub cache: EthStateCacheConfig,
|
||||
/// Settings for the gas price oracle
|
||||
pub gas_oracle: GasPriceOracleConfig,
|
||||
/// The maximum number of blocks into the past for generating state proofs.
|
||||
pub eth_proof_window: u64,
|
||||
/// The maximum number of tracing calls that can be executed in concurrently.
|
||||
pub max_tracing_requests: usize,
|
||||
/// Maximum number of blocks that could be scanned per filter request in `eth_getLogs` calls.
|
||||
pub max_blocks_per_filter: u64,
|
||||
/// Maximum number of logs that can be returned in a single response in `eth_getLogs` calls.
|
||||
pub max_logs_per_response: usize,
|
||||
/// Gas limit for `eth_call` and call tracing RPC methods.
|
||||
///
|
||||
/// Defaults to [`RPC_DEFAULT_GAS_CAP`]
|
||||
pub rpc_gas_cap: u64,
|
||||
///
|
||||
/// Sets TTL for stale filters
|
||||
pub stale_filter_ttl: Duration,
|
||||
/// Settings for the fee history cache
|
||||
pub fee_history_cache: FeeHistoryCacheConfig,
|
||||
/// The maximum number of getproof calls that can be executed concurrently.
|
||||
pub proof_permits: usize,
|
||||
}
|
||||
|
||||
impl EthConfig {
|
||||
/// Returns the filter config for the `eth_filter` handler.
|
||||
pub fn filter_config(&self) -> EthFilterConfig {
|
||||
EthFilterConfig::default()
|
||||
.max_blocks_per_filter(self.max_blocks_per_filter)
|
||||
.max_logs_per_response(self.max_logs_per_response)
|
||||
.stale_filter_ttl(self.stale_filter_ttl)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EthConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
cache: EthStateCacheConfig::default(),
|
||||
gas_oracle: GasPriceOracleConfig::default(),
|
||||
eth_proof_window: DEFAULT_ETH_PROOF_WINDOW,
|
||||
max_tracing_requests: default_max_tracing_requests(),
|
||||
max_blocks_per_filter: DEFAULT_MAX_BLOCKS_PER_FILTER,
|
||||
max_logs_per_response: DEFAULT_MAX_LOGS_PER_RESPONSE,
|
||||
rpc_gas_cap: RPC_DEFAULT_GAS_CAP.into(),
|
||||
stale_filter_ttl: DEFAULT_STALE_FILTER_TTL,
|
||||
fee_history_cache: FeeHistoryCacheConfig::default(),
|
||||
proof_permits: DEFAULT_PROOF_PERMITS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EthConfig {
|
||||
/// Configures the caching layer settings
|
||||
pub const fn state_cache(mut self, cache: EthStateCacheConfig) -> Self {
|
||||
self.cache = cache;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the gas price oracle settings
|
||||
pub const fn gpo_config(mut self, gas_oracle_config: GasPriceOracleConfig) -> Self {
|
||||
self.gas_oracle = gas_oracle_config;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum number of tracing requests
|
||||
pub const fn max_tracing_requests(mut self, max_requests: usize) -> Self {
|
||||
self.max_tracing_requests = max_requests;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum block length to scan per `eth_getLogs` request
|
||||
pub const fn max_blocks_per_filter(mut self, max_blocks: u64) -> Self {
|
||||
self.max_blocks_per_filter = max_blocks;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum number of logs per response
|
||||
pub const fn max_logs_per_response(mut self, max_logs: usize) -> Self {
|
||||
self.max_logs_per_response = max_logs;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum gas limit for `eth_call` and call tracing RPC methods
|
||||
pub const fn rpc_gas_cap(mut self, rpc_gas_cap: u64) -> Self {
|
||||
self.rpc_gas_cap = rpc_gas_cap;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the maximum proof window for historical proof generation.
|
||||
pub const fn eth_proof_window(mut self, window: u64) -> Self {
|
||||
self.eth_proof_window = window;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the number of getproof requests
|
||||
pub const fn proof_permits(mut self, permits: usize) -> Self {
|
||||
self.proof_permits = permits;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Config for the filter
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct EthFilterConfig {
|
||||
/// Maximum number of blocks that a filter can scan for logs.
|
||||
///
|
||||
/// If `None` then no limit is enforced.
|
||||
pub max_blocks_per_filter: Option<u64>,
|
||||
/// Maximum number of logs that can be returned in a single response in `eth_getLogs` calls.
|
||||
///
|
||||
/// If `None` then no limit is enforced.
|
||||
pub max_logs_per_response: Option<usize>,
|
||||
/// How long a filter remains valid after the last poll.
|
||||
///
|
||||
/// A filter is considered stale if it has not been polled for longer than this duration and
|
||||
/// will be removed.
|
||||
pub stale_filter_ttl: Duration,
|
||||
}
|
||||
|
||||
impl EthFilterConfig {
|
||||
/// Sets the maximum number of blocks that a filter can scan for logs.
|
||||
pub const fn max_blocks_per_filter(mut self, num: u64) -> Self {
|
||||
self.max_blocks_per_filter = Some(num);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the maximum number of logs that can be returned in a single response in `eth_getLogs`
|
||||
/// calls.
|
||||
pub const fn max_logs_per_response(mut self, num: usize) -> Self {
|
||||
self.max_logs_per_response = Some(num);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets how long a filter remains valid after the last poll before it will be removed.
|
||||
pub const fn stale_filter_ttl(mut self, duration: Duration) -> Self {
|
||||
self.stale_filter_ttl = duration;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EthFilterConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
max_blocks_per_filter: None,
|
||||
max_logs_per_response: None,
|
||||
// 5min
|
||||
stale_filter_ttl: Duration::from_secs(5 * 60),
|
||||
}
|
||||
}
|
||||
}
|
||||
98
crates/rpc/rpc-eth-types/src/builder/ctx.rs
Normal file
98
crates/rpc/rpc-eth-types/src/builder/ctx.rs
Normal file
@ -0,0 +1,98 @@
|
||||
//! Context required for building `eth` namespace APIs.
|
||||
|
||||
use reth_provider::{BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider};
|
||||
use reth_tasks::TaskSpawner;
|
||||
|
||||
use crate::{
|
||||
fee_history::fee_history_cache_new_blocks_task, EthConfig, EthStateCache, FeeHistoryCache,
|
||||
GasPriceOracle,
|
||||
};
|
||||
|
||||
/// Context for building the `eth` namespace API.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events> {
|
||||
/// Database handle.
|
||||
pub provider: Provider,
|
||||
/// Mempool handle.
|
||||
pub pool: Pool,
|
||||
/// Network handle.
|
||||
pub network: Network,
|
||||
/// EVM configuration.
|
||||
pub evm_config: EvmConfig,
|
||||
/// RPC config for `eth` namespace.
|
||||
pub config: EthConfig,
|
||||
/// Runtime handle.
|
||||
pub executor: Tasks,
|
||||
/// Events handle.
|
||||
pub events: Events,
|
||||
/// RPC cache handle.
|
||||
pub cache: EthStateCache,
|
||||
}
|
||||
|
||||
impl<Provider, Pool, EvmConfig, Network, Tasks, Events>
|
||||
EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>
|
||||
where
|
||||
Provider: BlockReaderIdExt + Clone,
|
||||
{
|
||||
/// Returns a new [`FeeHistoryCache`] for the context.
|
||||
pub fn new_fee_history_cache(&self) -> FeeHistoryCache
|
||||
where
|
||||
Provider: ChainSpecProvider + 'static,
|
||||
Tasks: TaskSpawner,
|
||||
Events: CanonStateSubscriptions,
|
||||
{
|
||||
FeeHistoryCacheBuilder::build(self)
|
||||
}
|
||||
|
||||
/// Returns a new [`GasPriceOracle`] for the context.
|
||||
pub fn new_gas_price_oracle(&self) -> GasPriceOracle<Provider> {
|
||||
GasPriceOracleBuilder::build(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds `eth_` core api component [`GasPriceOracle`], for given context.
|
||||
#[derive(Debug)]
|
||||
pub struct GasPriceOracleBuilder;
|
||||
|
||||
impl GasPriceOracleBuilder {
|
||||
/// Builds a [`GasPriceOracle`], for given context.
|
||||
pub fn build<Provider, Pool, EvmConfig, Network, Tasks, Events>(
|
||||
ctx: &EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>,
|
||||
) -> GasPriceOracle<Provider>
|
||||
where
|
||||
Provider: BlockReaderIdExt + Clone,
|
||||
{
|
||||
GasPriceOracle::new(ctx.provider.clone(), ctx.config.gas_oracle, ctx.cache.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds `eth_` core api component [`FeeHistoryCache`], for given context.
|
||||
#[derive(Debug)]
|
||||
pub struct FeeHistoryCacheBuilder;
|
||||
|
||||
impl FeeHistoryCacheBuilder {
|
||||
/// Builds a [`FeeHistoryCache`], for given context.
|
||||
pub fn build<Provider, Pool, EvmConfig, Network, Tasks, Events>(
|
||||
ctx: &EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>,
|
||||
) -> FeeHistoryCache
|
||||
where
|
||||
Provider: ChainSpecProvider + BlockReaderIdExt + Clone + 'static,
|
||||
Tasks: TaskSpawner,
|
||||
Events: CanonStateSubscriptions,
|
||||
{
|
||||
let fee_history_cache =
|
||||
FeeHistoryCache::new(ctx.cache.clone(), ctx.config.fee_history_cache);
|
||||
|
||||
let new_canonical_blocks = ctx.events.canonical_state_stream();
|
||||
let fhc = fee_history_cache.clone();
|
||||
let provider = ctx.provider.clone();
|
||||
ctx.executor.spawn_critical(
|
||||
"cache canonical blocks for fee history task",
|
||||
Box::pin(async move {
|
||||
fee_history_cache_new_blocks_task(fhc, new_canonical_blocks, provider).await;
|
||||
}),
|
||||
);
|
||||
|
||||
fee_history_cache
|
||||
}
|
||||
}
|
||||
4
crates/rpc/rpc-eth-types/src/builder/mod.rs
Normal file
4
crates/rpc/rpc-eth-types/src/builder/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
//! `eth` namespace API builder types.
|
||||
|
||||
pub mod config;
|
||||
pub mod ctx;
|
||||
@ -8,6 +8,7 @@
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
|
||||
pub mod builder;
|
||||
pub mod cache;
|
||||
pub mod error;
|
||||
pub mod fee_history;
|
||||
@ -20,6 +21,10 @@ pub mod revm_utils;
|
||||
pub mod transaction;
|
||||
pub mod utils;
|
||||
|
||||
pub use builder::{
|
||||
config::{EthConfig, EthFilterConfig},
|
||||
ctx::EthApiBuilderCtx,
|
||||
};
|
||||
pub use cache::{
|
||||
config::EthStateCacheConfig, db::StateCacheDb, multi_consumer::MultiConsumerLruCache,
|
||||
EthStateCache,
|
||||
|
||||
@ -33,6 +33,7 @@ reth-evm.workspace = true
|
||||
reth-rpc-eth-types.workspace = true
|
||||
reth-rpc-server-types.workspace = true
|
||||
reth-evm-optimism = { workspace = true, optional = true }
|
||||
reth-node-api.workspace = true
|
||||
|
||||
# eth
|
||||
alloy-dyn-abi.workspace = true
|
||||
|
||||
@ -1,25 +1,26 @@
|
||||
//! Implementation of the [`jsonrpsee`] generated [`EthApiServer`](crate::EthApi) trait
|
||||
//! Handles RPC requests for the `eth_` namespace.
|
||||
|
||||
use futures::Future;
|
||||
use std::sync::Arc;
|
||||
|
||||
use derive_more::Deref;
|
||||
use futures::Future;
|
||||
use reth_node_api::{BuilderProvider, FullNodeComponents};
|
||||
use reth_primitives::{BlockNumberOrTag, U256};
|
||||
use reth_provider::BlockReaderIdExt;
|
||||
use reth_provider::{BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider};
|
||||
use reth_rpc_eth_api::{
|
||||
helpers::{transaction::UpdateRawTxForwarder, EthSigner, SpawnBlocking},
|
||||
RawTransactionForwarder,
|
||||
};
|
||||
use reth_rpc_eth_types::{EthStateCache, FeeHistoryCache, GasCap, GasPriceOracle, PendingBlock};
|
||||
use reth_rpc_eth_types::{
|
||||
EthApiBuilderCtx, EthStateCache, FeeHistoryCache, GasCap, GasPriceOracle, PendingBlock,
|
||||
};
|
||||
use reth_tasks::{
|
||||
pool::{BlockingTaskGuard, BlockingTaskPool},
|
||||
TaskSpawner, TokioTaskExecutor,
|
||||
TaskExecutor, TaskSpawner, TokioTaskExecutor,
|
||||
};
|
||||
use tokio::sync::{AcquireError, Mutex, OwnedSemaphorePermit};
|
||||
|
||||
use crate::eth::DevSigner;
|
||||
|
||||
/// `Eth` API implementation.
|
||||
///
|
||||
/// This type provides the functionality for handling `eth_` related requests.
|
||||
@ -55,66 +56,59 @@ where
|
||||
raw_transaction_forwarder: Option<Arc<dyn RawTransactionForwarder>>,
|
||||
proof_permits: usize,
|
||||
) -> Self {
|
||||
Self::with_spawner(
|
||||
let inner = EthApiInner::new(
|
||||
provider,
|
||||
pool,
|
||||
network,
|
||||
eth_cache,
|
||||
gas_oracle,
|
||||
gas_cap.into().into(),
|
||||
eth_proof_window,
|
||||
Box::<TokioTaskExecutor>::default(),
|
||||
blocking_task_pool,
|
||||
fee_history_cache,
|
||||
evm_config,
|
||||
raw_transaction_forwarder,
|
||||
proof_permits,
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a new, shareable instance.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn with_spawner(
|
||||
provider: Provider,
|
||||
pool: Pool,
|
||||
network: Network,
|
||||
eth_cache: EthStateCache,
|
||||
gas_oracle: GasPriceOracle<Provider>,
|
||||
gas_cap: u64,
|
||||
eth_proof_window: u64,
|
||||
task_spawner: Box<dyn TaskSpawner>,
|
||||
blocking_task_pool: BlockingTaskPool,
|
||||
fee_history_cache: FeeHistoryCache,
|
||||
evm_config: EvmConfig,
|
||||
raw_transaction_forwarder: Option<Arc<dyn RawTransactionForwarder>>,
|
||||
proof_permits: usize,
|
||||
) -> Self {
|
||||
// get the block number of the latest block
|
||||
let latest_block = provider
|
||||
.header_by_number_or_tag(BlockNumberOrTag::Latest)
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|header| header.number)
|
||||
.unwrap_or_default();
|
||||
|
||||
let inner = EthApiInner {
|
||||
provider,
|
||||
pool,
|
||||
network,
|
||||
signers: parking_lot::RwLock::new(Default::default()),
|
||||
eth_cache,
|
||||
gas_oracle,
|
||||
gas_cap,
|
||||
eth_proof_window,
|
||||
starting_block: U256::from(latest_block),
|
||||
task_spawner,
|
||||
pending_block: Default::default(),
|
||||
blocking_task_pool,
|
||||
fee_history_cache,
|
||||
evm_config,
|
||||
raw_transaction_forwarder: parking_lot::RwLock::new(raw_transaction_forwarder),
|
||||
blocking_task_guard: BlockingTaskGuard::new(proof_permits),
|
||||
};
|
||||
TokioTaskExecutor::default(),
|
||||
raw_transaction_forwarder,
|
||||
proof_permits,
|
||||
);
|
||||
|
||||
Self { inner: Arc::new(inner) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Provider, Pool, EvmConfig, Network> EthApi<Provider, Pool, Network, EvmConfig>
|
||||
where
|
||||
Provider: ChainSpecProvider + BlockReaderIdExt + Clone + 'static,
|
||||
Pool: Clone,
|
||||
EvmConfig: Clone,
|
||||
Network: Clone,
|
||||
{
|
||||
/// Creates a new, shareable instance.
|
||||
pub fn with_spawner<Tasks, Events>(
|
||||
ctx: &EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>,
|
||||
) -> Self
|
||||
where
|
||||
Tasks: TaskSpawner + Clone + 'static,
|
||||
Events: CanonStateSubscriptions,
|
||||
{
|
||||
let blocking_task_pool =
|
||||
BlockingTaskPool::build().expect("failed to build blocking task pool");
|
||||
|
||||
let inner = EthApiInner::new(
|
||||
ctx.provider.clone(),
|
||||
ctx.pool.clone(),
|
||||
ctx.network.clone(),
|
||||
ctx.cache.clone(),
|
||||
ctx.new_gas_price_oracle(),
|
||||
ctx.config.rpc_gas_cap,
|
||||
ctx.config.eth_proof_window,
|
||||
blocking_task_pool,
|
||||
ctx.new_fee_history_cache(),
|
||||
ctx.evm_config.clone(),
|
||||
ctx.executor.clone(),
|
||||
None,
|
||||
ctx.config.proof_permits,
|
||||
);
|
||||
|
||||
Self { inner: Arc::new(inner) }
|
||||
}
|
||||
@ -163,12 +157,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<Provider, Pool, Network, EvmConfig> EthApi<Provider, Pool, Network, EvmConfig> {
|
||||
/// Generates 20 random developer accounts.
|
||||
/// Used in DEV mode.
|
||||
pub fn with_dev_accounts(&self) {
|
||||
let mut signers = self.inner.signers.write();
|
||||
*signers = DevSigner::random_signers(20);
|
||||
impl<N, Network> BuilderProvider<N> for EthApi<N::Provider, N::Pool, Network, N::Evm>
|
||||
where
|
||||
N: FullNodeComponents,
|
||||
Network: Send + Sync + Clone + 'static,
|
||||
{
|
||||
type Ctx<'a> =
|
||||
&'a EthApiBuilderCtx<N::Provider, N::Pool, N::Evm, Network, TaskExecutor, N::Provider>;
|
||||
|
||||
fn builder() -> Box<dyn for<'a> Fn(Self::Ctx<'a>) -> Self + Send> {
|
||||
Box::new(|ctx| Self::with_spawner(ctx))
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,6 +207,59 @@ pub struct EthApiInner<Provider, Pool, Network, EvmConfig> {
|
||||
blocking_task_guard: BlockingTaskGuard,
|
||||
}
|
||||
|
||||
impl<Provider, Pool, Network, EvmConfig> EthApiInner<Provider, Pool, Network, EvmConfig>
|
||||
where
|
||||
Provider: BlockReaderIdExt,
|
||||
{
|
||||
/// Creates a new, shareable instance using the default tokio task spawner.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
provider: Provider,
|
||||
pool: Pool,
|
||||
network: Network,
|
||||
eth_cache: EthStateCache,
|
||||
gas_oracle: GasPriceOracle<Provider>,
|
||||
gas_cap: impl Into<GasCap>,
|
||||
eth_proof_window: u64,
|
||||
blocking_task_pool: BlockingTaskPool,
|
||||
fee_history_cache: FeeHistoryCache,
|
||||
evm_config: EvmConfig,
|
||||
task_spawner: impl TaskSpawner + 'static,
|
||||
raw_transaction_forwarder: Option<Arc<dyn RawTransactionForwarder>>,
|
||||
proof_permits: usize,
|
||||
) -> Self {
|
||||
let signers = parking_lot::RwLock::new(Default::default());
|
||||
// get the block number of the latest block
|
||||
let starting_block = U256::from(
|
||||
provider
|
||||
.header_by_number_or_tag(BlockNumberOrTag::Latest)
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|header| header.number)
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
|
||||
Self {
|
||||
provider,
|
||||
pool,
|
||||
network,
|
||||
signers,
|
||||
eth_cache,
|
||||
gas_oracle,
|
||||
gas_cap: gas_cap.into().into(),
|
||||
eth_proof_window,
|
||||
starting_block,
|
||||
task_spawner: Box::new(task_spawner),
|
||||
pending_block: Default::default(),
|
||||
blocking_task_pool,
|
||||
fee_history_cache,
|
||||
evm_config,
|
||||
raw_transaction_forwarder: parking_lot::RwLock::new(raw_transaction_forwarder),
|
||||
blocking_task_guard: BlockingTaskGuard::new(proof_permits),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Provider, Pool, Network, EvmConfig> EthApiInner<Provider, Pool, Network, EvmConfig> {
|
||||
/// Returns a handle to data on disk.
|
||||
#[inline]
|
||||
|
||||
@ -17,7 +17,7 @@ use reth_provider::{BlockIdReader, BlockReader, EvmEnvProvider, ProviderError};
|
||||
use reth_rpc_eth_api::EthFilterApiServer;
|
||||
use reth_rpc_eth_types::{
|
||||
logs_utils::{self, append_matching_block_logs},
|
||||
EthApiError, EthFilterError, EthStateCache, EthSubscriptionIdProvider,
|
||||
EthApiError, EthFilterConfig, EthFilterError, EthStateCache, EthSubscriptionIdProvider,
|
||||
};
|
||||
use reth_rpc_server_types::ToRpcResult;
|
||||
use reth_rpc_types::{
|
||||
@ -515,56 +515,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Config for the filter
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct EthFilterConfig {
|
||||
/// Maximum number of blocks that a filter can scan for logs.
|
||||
///
|
||||
/// If `None` then no limit is enforced.
|
||||
pub max_blocks_per_filter: Option<u64>,
|
||||
/// Maximum number of logs that can be returned in a single response in `eth_getLogs` calls.
|
||||
///
|
||||
/// If `None` then no limit is enforced.
|
||||
pub max_logs_per_response: Option<usize>,
|
||||
/// How long a filter remains valid after the last poll.
|
||||
///
|
||||
/// A filter is considered stale if it has not been polled for longer than this duration and
|
||||
/// will be removed.
|
||||
pub stale_filter_ttl: Duration,
|
||||
}
|
||||
|
||||
impl EthFilterConfig {
|
||||
/// Sets the maximum number of blocks that a filter can scan for logs.
|
||||
pub const fn max_blocks_per_filter(mut self, num: u64) -> Self {
|
||||
self.max_blocks_per_filter = Some(num);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the maximum number of logs that can be returned in a single response in `eth_getLogs`
|
||||
/// calls.
|
||||
pub const fn max_logs_per_response(mut self, num: usize) -> Self {
|
||||
self.max_logs_per_response = Some(num);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets how long a filter remains valid after the last poll before it will be removed.
|
||||
pub const fn stale_filter_ttl(mut self, duration: Duration) -> Self {
|
||||
self.stale_filter_ttl = duration;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EthFilterConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
max_blocks_per_filter: None,
|
||||
max_logs_per_response: None,
|
||||
// 5min
|
||||
stale_filter_ttl: Duration::from_secs(5 * 60),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// All active filters
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ActiveFilters {
|
||||
|
||||
@ -6,12 +6,26 @@ use alloy_dyn_abi::TypedData;
|
||||
use reth_primitives::{
|
||||
eip191_hash_message, sign_message, Address, Signature, TransactionSigned, B256,
|
||||
};
|
||||
use reth_rpc_eth_api::helpers::{signer::Result, EthSigner};
|
||||
use reth_rpc_eth_api::helpers::{signer::Result, AddDevSigners, EthSigner};
|
||||
use reth_rpc_eth_types::SignError;
|
||||
use reth_rpc_types::TypedTransactionRequest;
|
||||
use reth_rpc_types_compat::transaction::to_primitive_transaction;
|
||||
use secp256k1::SecretKey;
|
||||
|
||||
use crate::EthApi;
|
||||
|
||||
impl<Provider, Pool, Network, EvmConfig> AddDevSigners
|
||||
for EthApi<Provider, Pool, Network, EvmConfig>
|
||||
{
|
||||
fn signers(&self) -> &parking_lot::RwLock<Vec<Box<dyn EthSigner>>> {
|
||||
self.inner.signers()
|
||||
}
|
||||
|
||||
fn with_dev_accounts(&self) {
|
||||
*self.signers().write() = DevSigner::random_signers(20)
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds developer keys
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DevSigner {
|
||||
@ -22,14 +36,14 @@ pub struct DevSigner {
|
||||
#[allow(dead_code)]
|
||||
impl DevSigner {
|
||||
/// Generates a random dev signer which satisfies [`EthSigner`] trait
|
||||
pub(crate) fn random() -> Box<dyn EthSigner> {
|
||||
pub fn random() -> Box<dyn EthSigner> {
|
||||
let mut signers = Self::random_signers(1);
|
||||
signers.pop().expect("expect to generate at least one signer")
|
||||
}
|
||||
|
||||
/// Generates provided number of random dev signers
|
||||
/// which satisfy [`EthSigner`] trait
|
||||
pub(crate) fn random_signers(num: u32) -> Vec<Box<dyn EthSigner + 'static>> {
|
||||
pub fn random_signers(num: u32) -> Vec<Box<dyn EthSigner + 'static>> {
|
||||
let mut signers = Vec::new();
|
||||
for _ in 0..num {
|
||||
let (sk, pk) = secp256k1::generate_keypair(&mut rand::thread_rng());
|
||||
|
||||
@ -9,9 +9,9 @@ pub mod pubsub;
|
||||
/// Implementation of `eth` namespace API.
|
||||
pub use bundle::EthBundle;
|
||||
pub use core::EthApi;
|
||||
pub use filter::{EthFilter, EthFilterConfig};
|
||||
pub use filter::EthFilter;
|
||||
pub use pubsub::EthPubSub;
|
||||
|
||||
pub use helpers::signer::DevSigner;
|
||||
|
||||
pub use reth_rpc_eth_api::RawTransactionForwarder;
|
||||
pub use reth_rpc_eth_api::{EthApiServer, RawTransactionForwarder};
|
||||
|
||||
@ -46,7 +46,8 @@ use reth_node_api::{
|
||||
};
|
||||
use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};
|
||||
use reth_node_ethereum::node::{
|
||||
EthereumConsensusBuilder, EthereumExecutorBuilder, EthereumNetworkBuilder, EthereumPoolBuilder,
|
||||
EthereumAddOns, EthereumConsensusBuilder, EthereumExecutorBuilder, EthereumNetworkBuilder,
|
||||
EthereumPoolBuilder,
|
||||
};
|
||||
use reth_payload_builder::{
|
||||
error::PayloadBuilderError, EthBuiltPayload, EthPayloadBuilderAttributes, PayloadBuilderHandle,
|
||||
@ -212,8 +213,9 @@ where
|
||||
EthereumExecutorBuilder,
|
||||
EthereumConsensusBuilder,
|
||||
>;
|
||||
type AddOns = EthereumAddOns;
|
||||
|
||||
fn components_builder(self) -> Self::ComponentsBuilder {
|
||||
fn components_builder(&self) -> Self::ComponentsBuilder {
|
||||
ComponentsBuilder::default()
|
||||
.node_types::<N>()
|
||||
.pool(EthereumPoolBuilder::default())
|
||||
|
||||
@ -22,7 +22,7 @@ use reth_chainspec::{Chain, ChainSpec, Head};
|
||||
use reth_evm_ethereum::EthEvmConfig;
|
||||
use reth_node_api::{ConfigureEvm, ConfigureEvmEnv, FullNodeTypes};
|
||||
use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};
|
||||
use reth_node_ethereum::{EthExecutorProvider, EthereumNode};
|
||||
use reth_node_ethereum::{node::EthereumAddOns, EthExecutorProvider, EthereumNode};
|
||||
use reth_primitives::{
|
||||
revm_primitives::{AnalysisKind, CfgEnvWithHandlerCfg, TxEnv},
|
||||
Address, Header, TransactionSigned, U256,
|
||||
@ -180,6 +180,7 @@ async fn main() -> eyre::Result<()> {
|
||||
.with_types::<EthereumNode>()
|
||||
// use default ethereum components but with our executor
|
||||
.with_components(EthereumNode::components().executor(MyExecutorBuilder::default()))
|
||||
.with_add_ons::<EthereumAddOns>()
|
||||
.launch()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@ -10,7 +10,7 @@ use reth::{
|
||||
blobstore::InMemoryBlobStore, EthTransactionPool, TransactionValidationTaskExecutor,
|
||||
},
|
||||
};
|
||||
use reth_node_ethereum::EthereumNode;
|
||||
use reth_node_ethereum::{node::EthereumAddOns, EthereumNode};
|
||||
use reth_tracing::tracing::{debug, info};
|
||||
use reth_transaction_pool::PoolConfig;
|
||||
|
||||
@ -23,6 +23,7 @@ fn main() {
|
||||
// Configure the components of the node
|
||||
// use default ethereum components but use our custom pool
|
||||
.with_components(EthereumNode::components().pool(CustomPoolBuilder::default()))
|
||||
.with_add_ons::<EthereumAddOns>()
|
||||
.launch()
|
||||
.await?;
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ use reth::{
|
||||
transaction_pool::TransactionPool,
|
||||
};
|
||||
use reth_basic_payload_builder::BasicPayloadJobGeneratorConfig;
|
||||
use reth_node_ethereum::{EthEngineTypes, EthereumNode};
|
||||
use reth_node_ethereum::{node::EthereumAddOns, EthEngineTypes, EthereumNode};
|
||||
use reth_payload_builder::PayloadBuilderService;
|
||||
|
||||
pub mod generator;
|
||||
@ -78,6 +78,7 @@ fn main() {
|
||||
.with_components(
|
||||
EthereumNode::components().payload(CustomPayloadBuilder::default()),
|
||||
)
|
||||
.with_add_ons::<EthereumAddOns>()
|
||||
.launch()
|
||||
.await?;
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ use reth::{
|
||||
providers::{BlockchainProvider, StaticFileProvider},
|
||||
ProviderFactory,
|
||||
},
|
||||
rpc::eth::EthApi,
|
||||
utils::open_db_read_only,
|
||||
};
|
||||
use reth_chainspec::ChainSpecBuilder;
|
||||
@ -27,7 +28,7 @@ use reth_db_api::models::ClientVersion;
|
||||
|
||||
// Bringing up the RPC
|
||||
use reth::rpc::builder::{
|
||||
EthApiBuild, RethRpcModule, RpcModuleBuilder, RpcServerConfig, TransportRpcModuleConfig,
|
||||
RethRpcModule, RpcModuleBuilder, RpcServerConfig, TransportRpcModuleConfig,
|
||||
};
|
||||
// Configuring the network parts, ideally also wouldn't need to think about this.
|
||||
use myrpc_ext::{MyRpcExt, MyRpcExtApiServer};
|
||||
@ -70,7 +71,7 @@ async fn main() -> eyre::Result<()> {
|
||||
|
||||
// Pick which namespaces to expose.
|
||||
let config = TransportRpcModuleConfig::default().with_http([RethRpcModule::Eth]);
|
||||
let mut server = rpc_builder.build(config, EthApiBuild::build);
|
||||
let mut server = rpc_builder.build(config, Box::new(EthApi::with_spawner));
|
||||
|
||||
// Add a custom rpc namespace
|
||||
let custom_rpc = MyRpcExt { provider };
|
||||
|
||||
@ -21,7 +21,7 @@ use reth::{
|
||||
use reth_chainspec::{Chain, ChainSpec};
|
||||
use reth_node_api::{ConfigureEvm, ConfigureEvmEnv, FullNodeTypes};
|
||||
use reth_node_core::{args::RpcServerArgs, node_config::NodeConfig};
|
||||
use reth_node_ethereum::{EthEvmConfig, EthExecutorProvider, EthereumNode};
|
||||
use reth_node_ethereum::{node::EthereumAddOns, EthEvmConfig, EthExecutorProvider, EthereumNode};
|
||||
use reth_primitives::{
|
||||
revm_primitives::{SpecId, StatefulPrecompileMut},
|
||||
Header, TransactionSigned,
|
||||
@ -244,6 +244,7 @@ async fn main() -> eyre::Result<()> {
|
||||
.with_types::<EthereumNode>()
|
||||
// use default ethereum components but with our executor
|
||||
.with_components(EthereumNode::components().executor(MyExecutorBuilder::default()))
|
||||
.with_add_ons::<EthereumAddOns>()
|
||||
.launch()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user