mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-30 03:01:58 -04:00
feat: integrate builder (#6611)
This commit is contained in:
@@ -51,12 +51,6 @@ pub use dev_args::DevArgs;
|
||||
mod pruning_args;
|
||||
pub use pruning_args::PruningArgs;
|
||||
|
||||
/// RollupArgs for configuring the op-reth rollup
|
||||
#[cfg(feature = "optimism")]
|
||||
mod rollup_args;
|
||||
#[cfg(feature = "optimism")]
|
||||
pub use rollup_args::RollupArgs;
|
||||
|
||||
pub mod utils;
|
||||
|
||||
pub mod types;
|
||||
|
||||
@@ -34,18 +34,6 @@ pub struct PayloadBuilderArgs {
|
||||
/// Maximum number of tasks to spawn for building a payload.
|
||||
#[arg(long = "builder.max-tasks", default_value = "3", value_parser = RangedU64ValueParser::<usize>::new().range(1..))]
|
||||
pub max_payload_tasks: usize,
|
||||
|
||||
/// By default the pending block equals the latest block
|
||||
/// to save resources and not leak txs from the tx-pool,
|
||||
/// this flag enables computing of the pending block
|
||||
/// from the tx-pool instead.
|
||||
///
|
||||
/// If `compute_pending_block` is not enabled, the payload builder
|
||||
/// will use the payload attributes from the latest block. Note
|
||||
/// that this flag is not yet functional.
|
||||
#[cfg(feature = "optimism")]
|
||||
#[arg(long = "rollup.compute-pending-block")]
|
||||
pub compute_pending_block: bool,
|
||||
}
|
||||
|
||||
impl Default for PayloadBuilderArgs {
|
||||
@@ -56,8 +44,6 @@ impl Default for PayloadBuilderArgs {
|
||||
interval: Duration::from_secs(1),
|
||||
deadline: SLOT_DURATION,
|
||||
max_payload_tasks: 3,
|
||||
#[cfg(feature = "optimism")]
|
||||
compute_pending_block: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,11 +68,6 @@ impl PayloadBuilderConfig for PayloadBuilderArgs {
|
||||
fn max_payload_tasks(&self) -> usize {
|
||||
self.max_payload_tasks
|
||||
}
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
fn compute_pending_block(&self) -> bool {
|
||||
self.compute_pending_block
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
//! clap [Args](clap::Args) for op-reth rollup configuration
|
||||
|
||||
/// Parameters for rollup configuration
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, clap::Args)]
|
||||
#[command(next_help_heading = "Rollup")]
|
||||
pub struct RollupArgs {
|
||||
/// HTTP endpoint for the sequencer mempool
|
||||
#[arg(long = "rollup.sequencer-http", value_name = "HTTP_URL")]
|
||||
pub sequencer_http: Option<String>,
|
||||
|
||||
/// Disable transaction pool gossip
|
||||
#[arg(long = "rollup.disable-tx-pool-gossip")]
|
||||
pub disable_txpool_gossip: bool,
|
||||
|
||||
/// Enable walkback to genesis on startup. This is useful for re-validating the existing DB
|
||||
/// prior to beginning normal syncing.
|
||||
#[arg(long = "rollup.enable-genesis-walkback")]
|
||||
pub enable_genesis_walkback: bool,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use clap::{Args, Parser};
|
||||
|
||||
/// A helper type to parse Args more easily
|
||||
#[derive(Parser)]
|
||||
struct CommandParser<T: Args> {
|
||||
#[command(flatten)]
|
||||
args: T,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_database_args() {
|
||||
let default_args = RollupArgs::default();
|
||||
let args = CommandParser::<RollupArgs>::parse_from(["reth"]).args;
|
||||
assert_eq!(args, default_args);
|
||||
}
|
||||
}
|
||||
@@ -5,18 +5,13 @@ use crate::{
|
||||
types::{MaxU32, ZeroAsNoneU64},
|
||||
GasPriceOracleArgs, RpcStateCacheArgs,
|
||||
},
|
||||
cli::{
|
||||
components::{RethNodeComponents, RethRpcComponents, RethRpcServerHandles},
|
||||
config::RethRpcConfig,
|
||||
ext::RethNodeCommandConfig,
|
||||
},
|
||||
cli::config::RethRpcConfig,
|
||||
utils::get_or_create_jwt_secret_from_path,
|
||||
};
|
||||
use clap::{
|
||||
builder::{PossibleValue, RangedU64ValueParser, TypedValueParser},
|
||||
Arg, Args, Command,
|
||||
};
|
||||
use futures::TryFutureExt;
|
||||
use rand::Rng;
|
||||
use reth_network_api::{NetworkInfo, Peers};
|
||||
use reth_node_api::{ConfigureEvmEnv, EngineTypes};
|
||||
@@ -32,10 +27,10 @@ use reth_rpc_builder::{
|
||||
auth::{AuthServerConfig, AuthServerHandle},
|
||||
constants,
|
||||
error::RpcError,
|
||||
EthConfig, IpcServerBuilder, RethRpcModule, RpcModuleBuilder, RpcModuleConfig,
|
||||
RpcModuleSelection, RpcServerConfig, RpcServerHandle, ServerBuilder, TransportRpcModuleConfig,
|
||||
EthConfig, IpcServerBuilder, RethRpcModule, RpcModuleConfig, RpcModuleSelection,
|
||||
RpcServerConfig, RpcServerHandle, ServerBuilder, TransportRpcModuleConfig,
|
||||
};
|
||||
use reth_rpc_engine_api::{EngineApi, EngineApiServer};
|
||||
use reth_rpc_engine_api::EngineApi;
|
||||
use reth_tasks::TaskSpawner;
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
use std::{
|
||||
@@ -43,7 +38,7 @@ use std::{
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||
path::PathBuf,
|
||||
};
|
||||
use tracing::{debug, info};
|
||||
use tracing::debug;
|
||||
|
||||
/// Default max number of subscriptions per connection.
|
||||
pub(crate) const RPC_DEFAULT_MAX_SUBS_PER_CONN: u32 = 1024;
|
||||
@@ -268,81 +263,6 @@ impl RpcServerArgs {
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures and launches _all_ servers.
|
||||
///
|
||||
/// Returns the handles for the launched regular RPC server(s) (if any) and the server handle
|
||||
/// for the auth server that handles the `engine_` API that's accessed by the consensus
|
||||
/// layer.
|
||||
pub async fn start_servers<Reth, Engine, Conf, EngineT>(
|
||||
&self,
|
||||
components: &Reth,
|
||||
engine_api: Engine,
|
||||
jwt_secret: JwtSecret,
|
||||
conf: &mut Conf,
|
||||
) -> eyre::Result<RethRpcServerHandles>
|
||||
where
|
||||
EngineT: EngineTypes + 'static,
|
||||
Engine: EngineApiServer<EngineT>,
|
||||
Reth: RethNodeComponents,
|
||||
Conf: RethNodeCommandConfig,
|
||||
{
|
||||
let auth_config = self.auth_server_config(jwt_secret)?;
|
||||
|
||||
let module_config = self.transport_rpc_module_config();
|
||||
debug!(target: "reth::cli", http=?module_config.http(), ws=?module_config.ws(), "Using RPC module config");
|
||||
|
||||
let (mut modules, mut auth_module, mut registry) = RpcModuleBuilder::default()
|
||||
.with_provider(components.provider())
|
||||
.with_pool(components.pool())
|
||||
.with_network(components.network())
|
||||
.with_events(components.events())
|
||||
.with_executor(components.task_executor())
|
||||
.with_evm_config(components.evm_config())
|
||||
.build_with_auth_server(module_config, engine_api);
|
||||
|
||||
let rpc_components = RethRpcComponents {
|
||||
registry: &mut registry,
|
||||
modules: &mut modules,
|
||||
auth_module: &mut auth_module,
|
||||
};
|
||||
// apply configured customization
|
||||
conf.extend_rpc_modules(self, components, rpc_components)?;
|
||||
|
||||
let server_config = self.rpc_server_config();
|
||||
let launch_rpc = modules.clone().start_server(server_config).map_ok(|handle| {
|
||||
if let Some(url) = handle.ipc_endpoint() {
|
||||
info!(target: "reth::cli", url=%url, "RPC IPC server started");
|
||||
}
|
||||
if let Some(addr) = handle.http_local_addr() {
|
||||
info!(target: "reth::cli", url=%addr, "RPC HTTP server started");
|
||||
}
|
||||
if let Some(addr) = handle.ws_local_addr() {
|
||||
info!(target: "reth::cli", url=%addr, "RPC WS server started");
|
||||
}
|
||||
handle
|
||||
});
|
||||
|
||||
let launch_auth = auth_module.clone().start_server(auth_config).map_ok(|handle| {
|
||||
let addr = handle.local_addr();
|
||||
info!(target: "reth::cli", url=%addr, "RPC auth server started");
|
||||
handle
|
||||
});
|
||||
|
||||
// launch servers concurrently
|
||||
let (rpc, auth) = futures::future::try_join(launch_rpc, launch_auth).await?;
|
||||
let handles = RethRpcServerHandles { rpc, auth };
|
||||
|
||||
// call hook
|
||||
let rpc_components = RethRpcComponents {
|
||||
registry: &mut registry,
|
||||
modules: &mut modules,
|
||||
auth_module: &mut auth_module,
|
||||
};
|
||||
conf.on_rpc_server_started(self, components, rpc_components, handles.clone())?;
|
||||
|
||||
Ok(handles)
|
||||
}
|
||||
|
||||
/// Convenience function for starting a rpc server with configs which extracted from cli args.
|
||||
pub async fn start_rpc_server<Provider, Pool, Network, Tasks, Events, EvmConfig>(
|
||||
&self,
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
//! Components that are used by the node command.
|
||||
|
||||
use reth_db::database::Database;
|
||||
use reth_network::{NetworkEvents, NetworkProtocols};
|
||||
use reth_network_api::{NetworkInfo, Peers};
|
||||
use reth_node_api::ConfigureEvmEnv;
|
||||
use reth_primitives::ChainSpec;
|
||||
use reth_provider::{
|
||||
AccountReader, BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader,
|
||||
DatabaseProviderFactory, EvmEnvProvider, StateProviderFactory,
|
||||
};
|
||||
use reth_rpc_builder::{
|
||||
auth::{AuthRpcModule, AuthServerHandle},
|
||||
RethModuleRegistry, RpcServerHandle, TransportRpcModules,
|
||||
};
|
||||
use reth_tasks::TaskSpawner;
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
use std::{marker::PhantomData, sync::Arc};
|
||||
|
||||
/// Helper trait to unify all provider traits for simplicity.
|
||||
pub trait FullProvider<DB: Database>:
|
||||
DatabaseProviderFactory<DB>
|
||||
+ BlockReaderIdExt
|
||||
+ AccountReader
|
||||
+ StateProviderFactory
|
||||
+ EvmEnvProvider
|
||||
+ ChainSpecProvider
|
||||
+ ChangeSetReader
|
||||
+ CanonStateSubscriptions
|
||||
+ Clone
|
||||
+ Unpin
|
||||
+ 'static
|
||||
{
|
||||
}
|
||||
|
||||
impl<T, DB: Database> FullProvider<DB> for T where
|
||||
T: DatabaseProviderFactory<DB>
|
||||
+ BlockReaderIdExt
|
||||
+ AccountReader
|
||||
+ StateProviderFactory
|
||||
+ EvmEnvProvider
|
||||
+ ChainSpecProvider
|
||||
+ ChangeSetReader
|
||||
+ CanonStateSubscriptions
|
||||
+ Clone
|
||||
+ Unpin
|
||||
+ 'static
|
||||
{
|
||||
}
|
||||
|
||||
/// The trait that is implemented for the Node command.
|
||||
pub trait RethNodeComponents: Clone + Send + Sync + 'static {
|
||||
/// Underlying database type.
|
||||
type DB: Database + Clone + Unpin + 'static;
|
||||
/// The Provider type that is provided by the node itself
|
||||
type Provider: FullProvider<Self::DB>;
|
||||
/// The transaction pool type
|
||||
type Pool: TransactionPool + Clone + Unpin + 'static;
|
||||
/// The network type used to communicate with p2p.
|
||||
type Network: NetworkInfo + Peers + NetworkProtocols + NetworkEvents + Clone + Unpin + 'static;
|
||||
/// The events type used to create subscriptions.
|
||||
type Events: CanonStateSubscriptions + Clone + 'static;
|
||||
/// The type that is used to spawn tasks.
|
||||
type Tasks: TaskSpawner + Clone + Unpin + 'static;
|
||||
/// The type that defines how to configure the EVM before execution.
|
||||
type EvmConfig: ConfigureEvmEnv + 'static;
|
||||
|
||||
/// Returns the instance of the provider
|
||||
fn provider(&self) -> Self::Provider;
|
||||
|
||||
/// Returns the instance of the task executor.
|
||||
fn task_executor(&self) -> Self::Tasks;
|
||||
|
||||
/// Returns the instance of the transaction pool.
|
||||
fn pool(&self) -> Self::Pool;
|
||||
|
||||
/// Returns the instance of the network API.
|
||||
fn network(&self) -> Self::Network;
|
||||
|
||||
/// Returns the instance of the events subscription handler.
|
||||
fn events(&self) -> Self::Events;
|
||||
|
||||
/// Returns the instance of the EVM config.
|
||||
fn evm_config(&self) -> Self::EvmConfig;
|
||||
|
||||
/// Helper function to return the chain spec.
|
||||
fn chain_spec(&self) -> Arc<ChainSpec> {
|
||||
self.provider().chain_spec()
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper container to encapsulate [RethModuleRegistry],[TransportRpcModules] and [AuthRpcModule].
|
||||
///
|
||||
/// This can be used to access installed modules, or create commonly used handlers like
|
||||
/// [reth_rpc::EthApi], and ultimately merge additional rpc handler into the configured transport
|
||||
/// modules [TransportRpcModules] as well as configured authenticated methods [AuthRpcModule].
|
||||
#[derive(Debug)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub struct RethRpcComponents<'a, Reth: RethNodeComponents> {
|
||||
/// A Helper type the holds instances of the configured modules.
|
||||
///
|
||||
/// This provides easy access to rpc handlers, such as [RethModuleRegistry::eth_api].
|
||||
pub registry: &'a mut RethModuleRegistry<
|
||||
Reth::Provider,
|
||||
Reth::Pool,
|
||||
Reth::Network,
|
||||
Reth::Tasks,
|
||||
Reth::Events,
|
||||
Reth::EvmConfig,
|
||||
>,
|
||||
/// Holds installed modules per transport type.
|
||||
///
|
||||
/// This can be used to merge additional modules into the configured transports (http, ipc,
|
||||
/// ws). See [TransportRpcModules::merge_configured]
|
||||
pub modules: &'a mut TransportRpcModules,
|
||||
/// Holds jwt authenticated rpc module.
|
||||
///
|
||||
/// This can be used to merge additional modules into the configured authenticated methods
|
||||
pub auth_module: &'a mut AuthRpcModule,
|
||||
}
|
||||
|
||||
/// A Generic implementation of the RethNodeComponents trait.
|
||||
///
|
||||
/// Represents components required for the Reth node.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RethNodeComponentsImpl<DB, Provider, Pool, Network, Events, Tasks, EvmConfig> {
|
||||
/// Represents underlying database type.
|
||||
__phantom: PhantomData<DB>,
|
||||
/// Represents the provider instance.
|
||||
pub provider: Provider,
|
||||
/// Represents the transaction pool instance.
|
||||
pub pool: Pool,
|
||||
/// Represents the network instance used for communication.
|
||||
pub network: Network,
|
||||
/// Represents the task executor instance.
|
||||
pub task_executor: Tasks,
|
||||
/// Represents the events subscription handler instance.
|
||||
pub events: Events,
|
||||
/// Represents the type that is used to configure the EVM before execution.
|
||||
pub evm_config: EvmConfig,
|
||||
}
|
||||
|
||||
impl<DB, Provider, Pool, Network, Events, Tasks, EvmConfig>
|
||||
RethNodeComponentsImpl<DB, Provider, Pool, Network, Events, Tasks, EvmConfig>
|
||||
{
|
||||
/// Create new instance of the node components.
|
||||
pub fn new(
|
||||
provider: Provider,
|
||||
pool: Pool,
|
||||
network: Network,
|
||||
task_executor: Tasks,
|
||||
events: Events,
|
||||
evm_config: EvmConfig,
|
||||
) -> Self {
|
||||
Self {
|
||||
provider,
|
||||
pool,
|
||||
network,
|
||||
task_executor,
|
||||
events,
|
||||
evm_config,
|
||||
__phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB, Provider, Pool, Network, Events, Tasks, EvmConfig> RethNodeComponents
|
||||
for RethNodeComponentsImpl<DB, Provider, Pool, Network, Events, Tasks, EvmConfig>
|
||||
where
|
||||
DB: Database + Clone + Unpin + 'static,
|
||||
Provider: FullProvider<DB> + Clone + 'static,
|
||||
Tasks: TaskSpawner + Clone + Unpin + 'static,
|
||||
Pool: TransactionPool + Clone + Unpin + 'static,
|
||||
Network: NetworkInfo + Peers + NetworkProtocols + NetworkEvents + Clone + Unpin + 'static,
|
||||
Events: CanonStateSubscriptions + Clone + 'static,
|
||||
EvmConfig: ConfigureEvmEnv + 'static,
|
||||
{
|
||||
type DB = DB;
|
||||
type Provider = Provider;
|
||||
type Pool = Pool;
|
||||
type Network = Network;
|
||||
type Events = Events;
|
||||
type Tasks = Tasks;
|
||||
type EvmConfig = EvmConfig;
|
||||
|
||||
fn provider(&self) -> Self::Provider {
|
||||
self.provider.clone()
|
||||
}
|
||||
|
||||
fn task_executor(&self) -> Self::Tasks {
|
||||
self.task_executor.clone()
|
||||
}
|
||||
|
||||
fn pool(&self) -> Self::Pool {
|
||||
self.pool.clone()
|
||||
}
|
||||
|
||||
fn network(&self) -> Self::Network {
|
||||
self.network.clone()
|
||||
}
|
||||
|
||||
fn events(&self) -> Self::Events {
|
||||
self.events.clone()
|
||||
}
|
||||
|
||||
fn evm_config(&self) -> Self::EvmConfig {
|
||||
self.evm_config.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains the handles to the spawned RPC servers.
|
||||
///
|
||||
/// This can be used to access the endpoints of the servers.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use reth_node_core::{cli::components::RethRpcServerHandles, rpc::api::EthApiClient};
|
||||
/// # async fn t(handles: RethRpcServerHandles) {
|
||||
/// let client = handles.rpc.http_client().expect("http server not started");
|
||||
/// let block_number = client.block_number().await.unwrap();
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RethRpcServerHandles {
|
||||
/// The regular RPC server handle.
|
||||
pub rpc: RpcServerHandle,
|
||||
/// The handle to the auth server (engine API)
|
||||
pub auth: AuthServerHandle,
|
||||
}
|
||||
@@ -105,10 +105,6 @@ pub trait PayloadBuilderConfig {
|
||||
|
||||
/// Maximum number of tasks to spawn for building a payload.
|
||||
fn max_payload_tasks(&self) -> usize;
|
||||
|
||||
/// Returns whether or not to construct the pending block.
|
||||
#[cfg(feature = "optimism")]
|
||||
fn compute_pending_block(&self) -> bool;
|
||||
}
|
||||
|
||||
/// A trait that represents the configured network and can be used to apply additional configuration
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
//! A real or test database type
|
||||
|
||||
use crate::dirs::{ChainPath, DataDirPath, MaybePlatformPath};
|
||||
use alloy_chains::Chain;
|
||||
use reth_db::{
|
||||
init_db,
|
||||
mdbx::DatabaseArguments,
|
||||
test_utils::{create_test_rw_db, TempDatabase},
|
||||
DatabaseEnv,
|
||||
};
|
||||
use reth_interfaces::db::LogLevel;
|
||||
use std::{str::FromStr, sync::Arc};
|
||||
|
||||
/// A type that represents either a _real_ (represented by a path), or _test_ database, which will
|
||||
/// use a [TempDatabase].
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DatabaseBuilder {
|
||||
/// The real database type, with a specified data dir
|
||||
Real(MaybePlatformPath<DataDirPath>),
|
||||
/// The test database type
|
||||
Test,
|
||||
}
|
||||
|
||||
impl DatabaseBuilder {
|
||||
/// Creates a _test_ database
|
||||
pub fn test() -> Self {
|
||||
Self::Test
|
||||
}
|
||||
|
||||
/// Initializes and returns the [DatabaseInstance] depending on the current database type.
|
||||
///
|
||||
/// If the [DatabaseBuilder] is test, then the [ChainPath] constructed will be derived from the
|
||||
/// db path of the [TempDatabase] and the given chain. The [LogLevel] will not be used.
|
||||
///
|
||||
/// If the [DatabaseBuilder] is real, then the db will be initialized using the given log level
|
||||
/// and the [ChainPath] will be derived from the given path and chain. This database path is
|
||||
/// then passed into [init_db].
|
||||
pub fn init_db(
|
||||
self,
|
||||
log_level: Option<LogLevel>,
|
||||
chain: Chain,
|
||||
) -> eyre::Result<DatabaseInstance> {
|
||||
match self {
|
||||
DatabaseBuilder::Test => {
|
||||
let db = create_test_rw_db();
|
||||
let db_path_str = db.path().to_str().expect("Path is not valid unicode");
|
||||
let path = MaybePlatformPath::<DataDirPath>::from_str(db_path_str)
|
||||
.expect("Path is not valid");
|
||||
let data_dir = path.unwrap_or_chain_default(chain);
|
||||
|
||||
Ok(DatabaseInstance::Test { db, data_dir })
|
||||
}
|
||||
DatabaseBuilder::Real(path) => {
|
||||
let data_dir = path.unwrap_or_chain_default(chain);
|
||||
let db_path = data_dir.db_path();
|
||||
|
||||
tracing::info!(target: "reth::cli", path = ?db_path, "Opening database");
|
||||
let db = Arc::new(
|
||||
init_db(db_path.clone(), DatabaseArguments::default().log_level(log_level))?
|
||||
.with_metrics(),
|
||||
);
|
||||
Ok(DatabaseInstance::Real { db, data_dir })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The [Default] implementation for [DatabaseBuilder] uses the _real_ variant, using the default
|
||||
/// value for the inner [MaybePlatformPath].
|
||||
impl Default for DatabaseBuilder {
|
||||
fn default() -> Self {
|
||||
Self::Real(MaybePlatformPath::<DataDirPath>::default())
|
||||
}
|
||||
}
|
||||
|
||||
/// A constructed database type, with a [ChainPath].
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DatabaseInstance {
|
||||
/// The test database
|
||||
Test {
|
||||
/// The database
|
||||
db: Arc<TempDatabase<DatabaseEnv>>,
|
||||
/// The data dir
|
||||
data_dir: ChainPath<DataDirPath>,
|
||||
},
|
||||
/// The real database
|
||||
Real {
|
||||
/// The database
|
||||
db: Arc<DatabaseEnv>,
|
||||
/// The data dir
|
||||
data_dir: ChainPath<DataDirPath>,
|
||||
},
|
||||
}
|
||||
|
||||
impl DatabaseInstance {
|
||||
/// Returns the data dir for this database instance
|
||||
pub fn data_dir(&self) -> &ChainPath<DataDirPath> {
|
||||
match self {
|
||||
Self::Test { data_dir, .. } => data_dir,
|
||||
Self::Real { data_dir, .. } => data_dir,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_database_db_dir() {
|
||||
// create temp dir to test that the db path is correct
|
||||
let tempdir = tempfile::tempdir().unwrap();
|
||||
let expected_datadir_path = tempdir.path().to_path_buf();
|
||||
let expected_db_path = tempdir.path().join("db");
|
||||
let datadir_path = MaybePlatformPath::<DataDirPath>::from(tempdir.path().to_path_buf());
|
||||
let db = DatabaseBuilder::Real(datadir_path);
|
||||
let db = db.init_db(None, Chain::mainnet()).unwrap();
|
||||
|
||||
// ensure that the datadir path is correct
|
||||
assert_eq!(db.data_dir().data_dir_path(), expected_datadir_path);
|
||||
|
||||
// ensure that the db path is correct
|
||||
assert_eq!(db.data_dir().db_path(), expected_db_path);
|
||||
}
|
||||
}
|
||||
@@ -1,360 +0,0 @@
|
||||
//! Support for integrating customizations into the CLI.
|
||||
|
||||
use crate::cli::{
|
||||
components::{RethNodeComponents, RethRpcComponents, RethRpcServerHandles},
|
||||
config::{PayloadBuilderConfig, RethNetworkConfig, RethRpcConfig},
|
||||
};
|
||||
use clap::Args;
|
||||
use reth_basic_payload_builder::{
|
||||
BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig, PayloadBuilder,
|
||||
};
|
||||
use reth_node_api::EngineTypes;
|
||||
use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService};
|
||||
use reth_provider::CanonStateSubscriptions;
|
||||
use reth_tasks::TaskSpawner;
|
||||
use std::{fmt, marker::PhantomData};
|
||||
|
||||
/// A trait that allows for extending parts of the CLI with additional functionality.
|
||||
///
|
||||
/// This is intended as a way to allow to _extend_ the node command. For example, to register
|
||||
/// additional RPC namespaces.
|
||||
pub trait RethCliExt {
|
||||
/// Provides additional configuration for the node CLI command.
|
||||
///
|
||||
/// This supports additional CLI arguments that can be used to modify the node configuration.
|
||||
///
|
||||
/// If no additional CLI arguments are required, the [NoArgs] wrapper type can be used.
|
||||
type Node: RethNodeCommandExt;
|
||||
}
|
||||
|
||||
/// The default CLI extension.
|
||||
impl RethCliExt for () {
|
||||
type Node = DefaultRethNodeCommandConfig;
|
||||
}
|
||||
|
||||
/// A trait that allows for extending and customizing parts of the rethr node command.
|
||||
///
|
||||
/// The functions are invoked during the initialization of the node command in the following order:
|
||||
///
|
||||
/// 1. [configure_network](RethNodeCommandConfig::configure_network)
|
||||
/// 2. [on_components_initialized](RethNodeCommandConfig::on_components_initialized)
|
||||
/// 3. [spawn_payload_builder_service](RethNodeCommandConfig::spawn_payload_builder_service)
|
||||
/// 4. [extend_rpc_modules](RethNodeCommandConfig::extend_rpc_modules)
|
||||
/// 5. [on_rpc_server_started](RethNodeCommandConfig::on_rpc_server_started)
|
||||
/// 6. [on_node_started](RethNodeCommandConfig::on_node_started)
|
||||
pub trait RethNodeCommandConfig: fmt::Debug {
|
||||
/// Invoked with the network configuration before the network is configured.
|
||||
///
|
||||
/// This allows additional configuration of the network before it is launched.
|
||||
fn configure_network<Conf, Reth>(
|
||||
&mut self,
|
||||
config: &mut Conf,
|
||||
components: &Reth,
|
||||
) -> eyre::Result<()>
|
||||
where
|
||||
Conf: RethNetworkConfig,
|
||||
Reth: RethNodeComponents,
|
||||
{
|
||||
let _ = config;
|
||||
let _ = components;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Event hook called once all components have been initialized.
|
||||
///
|
||||
/// This is called as soon as the node components have been initialized.
|
||||
fn on_components_initialized<Reth: RethNodeComponents>(
|
||||
&mut self,
|
||||
components: &Reth,
|
||||
) -> eyre::Result<()> {
|
||||
let _ = components;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Event hook called once the node has been launched.
|
||||
///
|
||||
/// This is called last after the node has been launched.
|
||||
fn on_node_started<Reth: RethNodeComponents>(&mut self, components: &Reth) -> eyre::Result<()> {
|
||||
let _ = components;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Event hook called once the rpc servers has been started.
|
||||
///
|
||||
/// This is called after the rpc server has been started.
|
||||
fn on_rpc_server_started<Conf, Reth>(
|
||||
&mut self,
|
||||
config: &Conf,
|
||||
components: &Reth,
|
||||
rpc_components: RethRpcComponents<'_, Reth>,
|
||||
handles: RethRpcServerHandles,
|
||||
) -> eyre::Result<()>
|
||||
where
|
||||
Conf: RethRpcConfig,
|
||||
Reth: RethNodeComponents,
|
||||
{
|
||||
let _ = config;
|
||||
let _ = components;
|
||||
let _ = rpc_components;
|
||||
let _ = handles;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Allows for registering additional RPC modules for the transports.
|
||||
///
|
||||
/// This is expected to call the merge functions of [reth_rpc_builder::TransportRpcModules], for
|
||||
/// example [reth_rpc_builder::TransportRpcModules::merge_configured].
|
||||
///
|
||||
/// This is called before the rpc server will be started [Self::on_rpc_server_started].
|
||||
fn extend_rpc_modules<Conf, Reth>(
|
||||
&mut self,
|
||||
config: &Conf,
|
||||
components: &Reth,
|
||||
rpc_components: RethRpcComponents<'_, Reth>,
|
||||
) -> eyre::Result<()>
|
||||
where
|
||||
Conf: RethRpcConfig,
|
||||
Reth: RethNodeComponents,
|
||||
{
|
||||
let _ = config;
|
||||
let _ = components;
|
||||
let _ = rpc_components;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Configures the [PayloadBuilderService] for the node, spawns it and returns the
|
||||
/// [PayloadBuilderHandle].
|
||||
///
|
||||
/// By default this spawns a [BasicPayloadJobGenerator] with the default configuration
|
||||
/// [BasicPayloadJobGeneratorConfig].
|
||||
fn spawn_payload_builder_service<Conf, Reth, Builder, Engine>(
|
||||
&mut self,
|
||||
conf: &Conf,
|
||||
components: &Reth,
|
||||
payload_builder: Builder,
|
||||
) -> eyre::Result<PayloadBuilderHandle<Engine>>
|
||||
where
|
||||
Conf: PayloadBuilderConfig,
|
||||
Reth: RethNodeComponents,
|
||||
Engine: EngineTypes + 'static,
|
||||
Builder: PayloadBuilder<
|
||||
Reth::Pool,
|
||||
Reth::Provider,
|
||||
Attributes = Engine::PayloadBuilderAttributes,
|
||||
BuiltPayload = Engine::BuiltPayload,
|
||||
> + Unpin
|
||||
+ 'static,
|
||||
{
|
||||
let payload_job_config = BasicPayloadJobGeneratorConfig::default()
|
||||
.interval(conf.interval())
|
||||
.deadline(conf.deadline())
|
||||
.max_payload_tasks(conf.max_payload_tasks())
|
||||
.extradata(conf.extradata_rlp_bytes())
|
||||
.max_gas_limit(conf.max_gas_limit());
|
||||
|
||||
// no extradata for optimism
|
||||
#[cfg(feature = "optimism")]
|
||||
let payload_job_config = payload_job_config.extradata(Default::default());
|
||||
|
||||
let payload_generator = BasicPayloadJobGenerator::with_builder(
|
||||
components.provider(),
|
||||
components.pool(),
|
||||
components.task_executor(),
|
||||
payload_job_config,
|
||||
components.chain_spec(),
|
||||
payload_builder,
|
||||
);
|
||||
let (payload_service, payload_builder) = PayloadBuilderService::new(
|
||||
payload_generator,
|
||||
components.events().canonical_state_stream(),
|
||||
);
|
||||
|
||||
components
|
||||
.task_executor()
|
||||
.spawn_critical("payload builder service", Box::pin(payload_service));
|
||||
|
||||
Ok(payload_builder)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait that allows for extending parts of the CLI with additional functionality.
|
||||
pub trait RethNodeCommandExt: RethNodeCommandConfig + fmt::Debug + clap::Args {}
|
||||
|
||||
// blanket impl for all types that implement the required traits.
|
||||
impl<T> RethNodeCommandExt for T where T: RethNodeCommandConfig + fmt::Debug + clap::Args {}
|
||||
|
||||
/// The default configuration for the reth node command.
|
||||
///
|
||||
/// This is a convenience type for [NoArgs<()>].
|
||||
#[derive(Debug, Clone, Copy, Default, Args)]
|
||||
#[non_exhaustive]
|
||||
pub struct DefaultRethNodeCommandConfig;
|
||||
|
||||
impl RethNodeCommandConfig for DefaultRethNodeCommandConfig {}
|
||||
|
||||
impl RethNodeCommandConfig for () {}
|
||||
|
||||
/// A helper type for [RethCliExt] extension that don't require any additional clap Arguments.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct NoArgsCliExt<Conf>(PhantomData<Conf>);
|
||||
|
||||
impl<Conf: RethNodeCommandConfig> RethCliExt for NoArgsCliExt<Conf> {
|
||||
type Node = NoArgs<Conf>;
|
||||
}
|
||||
|
||||
/// A helper struct that allows for wrapping a [RethNodeCommandConfig] value without providing
|
||||
/// additional CLI arguments.
|
||||
///
|
||||
/// Note: This type must be manually filled with a [RethNodeCommandConfig] manually before executing
|
||||
/// the reth node command.
|
||||
#[derive(Debug, Clone, Copy, Default, Args)]
|
||||
pub struct NoArgs<T = ()> {
|
||||
#[arg(skip)]
|
||||
inner: Option<T>,
|
||||
}
|
||||
|
||||
impl<T> NoArgs<T> {
|
||||
/// Creates a new instance of the wrapper type.
|
||||
pub fn with(inner: T) -> Self {
|
||||
Self { inner: Some(inner) }
|
||||
}
|
||||
|
||||
/// Sets the inner value.
|
||||
pub fn set(&mut self, inner: T) {
|
||||
self.inner = Some(inner)
|
||||
}
|
||||
|
||||
/// Transforms the configured value.
|
||||
pub fn map<U>(self, inner: U) -> NoArgs<U> {
|
||||
NoArgs::with(inner)
|
||||
}
|
||||
|
||||
/// Returns the inner value if it exists.
|
||||
pub fn inner(&self) -> Option<&T> {
|
||||
self.inner.as_ref()
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner value if it exists.
|
||||
pub fn inner_mut(&mut self) -> Option<&mut T> {
|
||||
self.inner.as_mut()
|
||||
}
|
||||
|
||||
/// Consumes the wrapper and returns the inner value if it exists.
|
||||
pub fn into_inner(self) -> Option<T> {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: RethNodeCommandConfig> RethNodeCommandConfig for NoArgs<T> {
|
||||
fn configure_network<Conf, Reth>(
|
||||
&mut self,
|
||||
config: &mut Conf,
|
||||
components: &Reth,
|
||||
) -> eyre::Result<()>
|
||||
where
|
||||
Conf: RethNetworkConfig,
|
||||
Reth: RethNodeComponents,
|
||||
{
|
||||
if let Some(conf) = self.inner_mut() {
|
||||
conf.configure_network(config, components)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn on_components_initialized<Reth: RethNodeComponents>(
|
||||
&mut self,
|
||||
components: &Reth,
|
||||
) -> eyre::Result<()> {
|
||||
if let Some(conf) = self.inner_mut() {
|
||||
conf.on_components_initialized(components)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn on_node_started<Reth: RethNodeComponents>(&mut self, components: &Reth) -> eyre::Result<()> {
|
||||
if let Some(conf) = self.inner_mut() {
|
||||
conf.on_node_started(components)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn on_rpc_server_started<Conf, Reth>(
|
||||
&mut self,
|
||||
config: &Conf,
|
||||
components: &Reth,
|
||||
rpc_components: RethRpcComponents<'_, Reth>,
|
||||
handles: RethRpcServerHandles,
|
||||
) -> eyre::Result<()>
|
||||
where
|
||||
Conf: RethRpcConfig,
|
||||
Reth: RethNodeComponents,
|
||||
{
|
||||
if let Some(conf) = self.inner_mut() {
|
||||
conf.on_rpc_server_started(config, components, rpc_components, handles)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn extend_rpc_modules<Conf, Reth>(
|
||||
&mut self,
|
||||
config: &Conf,
|
||||
components: &Reth,
|
||||
rpc_components: RethRpcComponents<'_, Reth>,
|
||||
) -> eyre::Result<()>
|
||||
where
|
||||
Conf: RethRpcConfig,
|
||||
Reth: RethNodeComponents,
|
||||
{
|
||||
if let Some(conf) = self.inner_mut() {
|
||||
conf.extend_rpc_modules(config, components, rpc_components)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_payload_builder_service<Conf, Reth, Builder, Engine>(
|
||||
&mut self,
|
||||
conf: &Conf,
|
||||
components: &Reth,
|
||||
payload_builder: Builder,
|
||||
) -> eyre::Result<PayloadBuilderHandle<Engine>>
|
||||
where
|
||||
Conf: PayloadBuilderConfig,
|
||||
Reth: RethNodeComponents,
|
||||
Engine: EngineTypes + 'static,
|
||||
Builder: PayloadBuilder<
|
||||
Reth::Pool,
|
||||
Reth::Provider,
|
||||
Attributes = Engine::PayloadBuilderAttributes,
|
||||
BuiltPayload = Engine::BuiltPayload,
|
||||
> + Unpin
|
||||
+ 'static,
|
||||
{
|
||||
self.inner_mut()
|
||||
.ok_or_else(|| eyre::eyre!("config value must be set"))?
|
||||
.spawn_payload_builder_service(conf, components, payload_builder)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for NoArgs<T> {
|
||||
fn from(value: T) -> Self {
|
||||
Self::with(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn assert_ext<T: RethNodeCommandExt>() {}
|
||||
|
||||
#[test]
|
||||
fn ensure_ext() {
|
||||
assert_ext::<DefaultRethNodeCommandConfig>();
|
||||
assert_ext::<NoArgs<()>>();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
//! Types for the CLI.
|
||||
//! Additional CLI configuration support.
|
||||
|
||||
pub mod components;
|
||||
pub mod config;
|
||||
pub mod db_type;
|
||||
pub mod ext;
|
||||
pub mod runner;
|
||||
|
||||
130
crates/node-core/src/engine_api_store.rs
Normal file
130
crates/node-core/src/engine_api_store.rs
Normal file
@@ -0,0 +1,130 @@
|
||||
//! Stores engine API messages to disk for later inspection and replay.
|
||||
|
||||
use reth_beacon_consensus::BeaconEngineMessage;
|
||||
use reth_node_api::EngineTypes;
|
||||
use reth_primitives::fs::{self};
|
||||
use reth_rpc_types::{
|
||||
engine::{CancunPayloadFields, ForkchoiceState},
|
||||
ExecutionPayload,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::BTreeMap, path::PathBuf, time::SystemTime};
|
||||
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||
use tracing::*;
|
||||
|
||||
/// A message from the engine API that has been stored to disk.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum StoredEngineApiMessage<Attributes> {
|
||||
/// The on-disk representation of an `engine_forkchoiceUpdated` method call.
|
||||
ForkchoiceUpdated {
|
||||
/// The [ForkchoiceState] sent in the persisted call.
|
||||
state: ForkchoiceState,
|
||||
/// The payload attributes sent in the persisted call, if any.
|
||||
payload_attrs: Option<Attributes>,
|
||||
},
|
||||
/// The on-disk representation of an `engine_newPayload` method call.
|
||||
NewPayload {
|
||||
/// The [ExecutionPayload] sent in the persisted call.
|
||||
payload: ExecutionPayload,
|
||||
/// The Cancun-specific fields sent in the persisted call, if any.
|
||||
cancun_fields: Option<CancunPayloadFields>,
|
||||
},
|
||||
}
|
||||
|
||||
/// This can read and write engine API messages in a specific directory.
|
||||
#[derive(Debug)]
|
||||
pub struct EngineApiStore {
|
||||
/// The path to the directory that stores the engine API messages.
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl EngineApiStore {
|
||||
/// Creates a new [EngineApiStore] at the given path.
|
||||
///
|
||||
/// The path is expected to be a directory, where individual message JSON files will be stored.
|
||||
pub fn new(path: PathBuf) -> Self {
|
||||
Self { path }
|
||||
}
|
||||
|
||||
/// Stores the received [BeaconEngineMessage] to disk, appending the `received_at` time to the
|
||||
/// path.
|
||||
pub fn on_message<Engine>(
|
||||
&self,
|
||||
msg: &BeaconEngineMessage<Engine>,
|
||||
received_at: SystemTime,
|
||||
) -> eyre::Result<()>
|
||||
where
|
||||
Engine: EngineTypes,
|
||||
{
|
||||
fs::create_dir_all(&self.path)?; // ensure that store path had been created
|
||||
let timestamp = received_at.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis();
|
||||
match msg {
|
||||
BeaconEngineMessage::ForkchoiceUpdated { state, payload_attrs, tx: _tx } => {
|
||||
let filename = format!("{}-fcu-{}.json", timestamp, state.head_block_hash);
|
||||
fs::write(
|
||||
self.path.join(filename),
|
||||
serde_json::to_vec(&StoredEngineApiMessage::ForkchoiceUpdated {
|
||||
state: *state,
|
||||
payload_attrs: payload_attrs.clone(),
|
||||
})?,
|
||||
)?;
|
||||
}
|
||||
BeaconEngineMessage::NewPayload { payload, cancun_fields, tx: _tx } => {
|
||||
let filename = format!("{}-new_payload-{}.json", timestamp, payload.block_hash());
|
||||
fs::write(
|
||||
self.path.join(filename),
|
||||
serde_json::to_vec(
|
||||
&StoredEngineApiMessage::<Engine::PayloadAttributes>::NewPayload {
|
||||
payload: payload.clone(),
|
||||
cancun_fields: cancun_fields.clone(),
|
||||
},
|
||||
)?,
|
||||
)?;
|
||||
}
|
||||
// noop
|
||||
BeaconEngineMessage::TransitionConfigurationExchanged |
|
||||
BeaconEngineMessage::EventListener(_) => (),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Finds and iterates through any stored engine API message files, ordered by timestamp.
|
||||
pub fn engine_messages_iter(&self) -> eyre::Result<impl Iterator<Item = PathBuf>> {
|
||||
let mut filenames_by_ts = BTreeMap::<u64, Vec<PathBuf>>::default();
|
||||
for entry in fs::read_dir(&self.path)? {
|
||||
let entry = entry?;
|
||||
let filename = entry.file_name();
|
||||
if let Some(filename) = filename.to_str().filter(|n| n.ends_with(".json")) {
|
||||
if let Some(Ok(timestamp)) = filename.split('-').next().map(|n| n.parse::<u64>()) {
|
||||
filenames_by_ts.entry(timestamp).or_default().push(entry.path());
|
||||
tracing::debug!(target: "engine::store", timestamp, filename, "Queued engine API message");
|
||||
} else {
|
||||
tracing::warn!(target: "engine::store", %filename, "Could not parse timestamp from filename")
|
||||
}
|
||||
} else {
|
||||
tracing::warn!(target: "engine::store", ?filename, "Skipping non json file");
|
||||
}
|
||||
}
|
||||
Ok(filenames_by_ts.into_iter().flat_map(|(_, paths)| paths))
|
||||
}
|
||||
|
||||
/// Intercepts an incoming engine API message, storing it to disk and forwarding it to the
|
||||
/// engine channel.
|
||||
pub async fn intercept<Engine>(
|
||||
self,
|
||||
mut rx: UnboundedReceiver<BeaconEngineMessage<Engine>>,
|
||||
to_engine: UnboundedSender<BeaconEngineMessage<Engine>>,
|
||||
) where
|
||||
Engine: EngineTypes,
|
||||
BeaconEngineMessage<Engine>: std::fmt::Debug,
|
||||
{
|
||||
loop {
|
||||
let Some(msg) = rx.recv().await else { break };
|
||||
if let Err(error) = self.on_message(&msg, SystemTime::now()) {
|
||||
error!(target: "engine::intercept", ?msg, %error, "Error handling Engine API message");
|
||||
}
|
||||
let _ = to_engine.send(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
pub mod args;
|
||||
pub mod cli;
|
||||
pub mod dirs;
|
||||
pub mod engine_api_store;
|
||||
pub mod events;
|
||||
pub mod exit;
|
||||
pub mod init;
|
||||
|
||||
@@ -5,8 +5,8 @@ use crate::{
|
||||
get_secret_key, DatabaseArgs, DebugArgs, DevArgs, NetworkArgs, PayloadBuilderArgs,
|
||||
PruningArgs, RpcServerArgs, TxPoolArgs,
|
||||
},
|
||||
cli::{config::RethTransactionPoolConfig, db_type::DatabaseBuilder},
|
||||
dirs::{ChainPath, DataDirPath, MaybePlatformPath},
|
||||
cli::config::RethTransactionPoolConfig,
|
||||
dirs::{ChainPath, DataDirPath},
|
||||
metrics::prometheus_exporter,
|
||||
utils::{get_single_header, write_peers_to_file},
|
||||
};
|
||||
@@ -142,9 +142,6 @@ pub static PROMETHEUS_RECORDER_HANDLE: Lazy<PrometheusHandle> =
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NodeConfig {
|
||||
/// The test database
|
||||
pub database: DatabaseBuilder,
|
||||
|
||||
/// The path to the configuration file to use.
|
||||
pub config: Option<PathBuf>,
|
||||
|
||||
@@ -199,17 +196,12 @@ pub struct NodeConfig {
|
||||
|
||||
/// All pruning related arguments
|
||||
pub pruning: PruningArgs,
|
||||
|
||||
/// Rollup related arguments
|
||||
#[cfg(feature = "optimism")]
|
||||
pub rollup: crate::args::RollupArgs,
|
||||
}
|
||||
|
||||
impl NodeConfig {
|
||||
/// Creates a testing [NodeConfig], causing the database to be launched ephemerally.
|
||||
pub fn test() -> Self {
|
||||
let mut test = Self {
|
||||
database: DatabaseBuilder::test(),
|
||||
config: None,
|
||||
chain: MAINNET.clone(),
|
||||
metrics: None,
|
||||
@@ -223,8 +215,6 @@ impl NodeConfig {
|
||||
db: DatabaseArgs::default(),
|
||||
dev: DevArgs::default(),
|
||||
pruning: PruningArgs::default(),
|
||||
#[cfg(feature = "optimism")]
|
||||
rollup: crate::args::RollupArgs::default(),
|
||||
};
|
||||
|
||||
// set all ports to zero by default for test instances
|
||||
@@ -232,9 +222,9 @@ impl NodeConfig {
|
||||
test
|
||||
}
|
||||
|
||||
/// Set the datadir for the node
|
||||
pub fn with_datadir(mut self, datadir: MaybePlatformPath<DataDirPath>) -> Self {
|
||||
self.database = DatabaseBuilder::Real(datadir);
|
||||
/// Sets --dev mode for the node
|
||||
pub const fn dev(mut self) -> Self {
|
||||
self.dev.dev = true;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -316,13 +306,6 @@ impl NodeConfig {
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the rollup args for the node
|
||||
#[cfg(feature = "optimism")]
|
||||
pub fn with_rollup(mut self, rollup: crate::args::RollupArgs) -> Self {
|
||||
self.rollup = rollup;
|
||||
self
|
||||
}
|
||||
|
||||
/// Get the network secret from the given data dir
|
||||
pub fn network_secret(&self, data_dir: &ChainPath<DataDirPath>) -> eyre::Result<SecretKey> {
|
||||
let network_secret_path =
|
||||
@@ -392,6 +375,28 @@ impl NodeConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create the [NetworkConfig] for the node
|
||||
pub fn network_config<C>(
|
||||
&self,
|
||||
config: &Config,
|
||||
client: C,
|
||||
executor: TaskExecutor,
|
||||
head: Head,
|
||||
data_dir: &ChainPath<DataDirPath>,
|
||||
) -> eyre::Result<NetworkConfig<C>> {
|
||||
info!(target: "reth::cli", "Connecting to P2P network");
|
||||
let secret_key = self.network_secret(data_dir)?;
|
||||
let default_peers_path = data_dir.known_peers_path();
|
||||
Ok(self.load_network_config(
|
||||
config,
|
||||
client,
|
||||
executor.clone(),
|
||||
head,
|
||||
secret_key,
|
||||
default_peers_path.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Create the [NetworkBuilder].
|
||||
///
|
||||
/// This only configures it and does not spawn it.
|
||||
@@ -406,18 +411,7 @@ impl NodeConfig {
|
||||
where
|
||||
C: BlockNumReader,
|
||||
{
|
||||
info!(target: "reth::cli", "Connecting to P2P network");
|
||||
let secret_key = self.network_secret(data_dir)?;
|
||||
let default_peers_path = data_dir.known_peers_path();
|
||||
let network_config = self.load_network_config(
|
||||
config,
|
||||
client,
|
||||
executor.clone(),
|
||||
head,
|
||||
secret_key,
|
||||
default_peers_path.clone(),
|
||||
);
|
||||
|
||||
let network_config = self.network_config(config, client, executor, head, data_dir)?;
|
||||
let builder = NetworkManager::builder(network_config).await?;
|
||||
Ok(builder)
|
||||
}
|
||||
@@ -773,14 +767,6 @@ impl NodeConfig {
|
||||
self.network.port + self.instance - 1,
|
||||
)));
|
||||
|
||||
// When `sequencer_endpoint` is configured, the node will forward all transactions to a
|
||||
// Sequencer node for execution and inclusion on L1, and disable its own txpool
|
||||
// gossip to prevent other parties in the network from learning about them.
|
||||
#[cfg(feature = "optimism")]
|
||||
let cfg_builder = cfg_builder
|
||||
.sequencer_endpoint(self.rollup.sequencer_http.clone())
|
||||
.disable_tx_gossip(self.rollup.disable_txpool_gossip);
|
||||
|
||||
cfg_builder.build(client)
|
||||
}
|
||||
|
||||
@@ -914,7 +900,6 @@ impl NodeConfig {
|
||||
impl Default for NodeConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
database: DatabaseBuilder::default(),
|
||||
config: None,
|
||||
chain: MAINNET.clone(),
|
||||
metrics: None,
|
||||
@@ -928,8 +913,6 @@ impl Default for NodeConfig {
|
||||
db: DatabaseArgs::default(),
|
||||
dev: DevArgs::default(),
|
||||
pruning: PruningArgs::default(),
|
||||
#[cfg(feature = "optimism")]
|
||||
rollup: crate::args::RollupArgs::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user