//! This example shows how to configure custom components for a reth node. #![warn(unused_crate_dependencies)] use reth_ethereum::{ chainspec::ChainSpec, cli::interface::Cli, node::{ api::{FullNodeTypes, NodeTypes}, builder::{components::PoolBuilder, BuilderContext}, node::EthereumAddOns, EthereumNode, }, pool::{ blobstore::InMemoryBlobStore, EthTransactionPool, PoolConfig, TransactionValidationTaskExecutor, }, provider::CanonStateSubscriptions, EthPrimitives, }; use reth_tracing::tracing::{debug, info}; fn main() { Cli::parse_args() .run(|builder, _| async move { let handle = builder // use the default ethereum node types .with_types::() // 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::default()) .launch() .await?; handle.wait_for_node_exit().await }) .unwrap(); } /// A custom pool builder #[derive(Debug, Clone, Default)] #[non_exhaustive] pub struct CustomPoolBuilder { /// Use custom pool config pool_config: PoolConfig, } /// Implement the [`PoolBuilder`] trait for the custom pool builder /// /// This will be used to build the transaction pool and its maintenance tasks during launch. impl PoolBuilder for CustomPoolBuilder where Node: FullNodeTypes>, { type Pool = EthTransactionPool; async fn build_pool(self, ctx: &BuilderContext) -> eyre::Result { let data_dir = ctx.config().datadir(); let blob_store = InMemoryBlobStore::default(); let validator = TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone()) .with_head_timestamp(ctx.head().timestamp) .kzg_settings(ctx.kzg_settings()?) .with_additional_tasks(ctx.config().txpool.additional_validation_tasks) .build_with_tasks(ctx.task_executor().clone(), blob_store.clone()); let transaction_pool = reth_ethereum::pool::Pool::eth_pool(validator, blob_store, self.pool_config); info!(target: "reth::cli", "Transaction pool initialized"); let transactions_path = data_dir.txpool_transactions(); // spawn txpool maintenance task { let pool = transaction_pool.clone(); let chain_events = ctx.provider().canonical_state_stream(); let client = ctx.provider().clone(); let transactions_backup_config = reth_ethereum::pool::maintain::LocalTransactionBackupConfig::with_local_txs_backup( transactions_path, ); ctx.task_executor().spawn_critical_with_graceful_shutdown_signal( "local transactions backup task", |shutdown| { reth_ethereum::pool::maintain::backup_local_transactions_task( shutdown, pool.clone(), transactions_backup_config, ) }, ); // spawn the maintenance task ctx.task_executor().spawn_critical( "txpool maintenance task", reth_ethereum::pool::maintain::maintain_transaction_pool_future( client, pool, chain_events, ctx.task_executor().clone(), reth_ethereum::pool::maintain::MaintainPoolConfig { max_tx_lifetime: transaction_pool.config().max_queued_lifetime, ..Default::default() }, ), ); debug!(target: "reth::cli", "Spawned txpool maintenance task"); } Ok(transaction_pool) } }