Files
2025-05-24 08:35:40 +00:00

113 lines
4.1 KiB
Rust

//! 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::<EthereumNode>()
// 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<Node> PoolBuilder<Node> for CustomPoolBuilder
where
Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = EthPrimitives>>,
{
type Pool = EthTransactionPool<Node::Provider, InMemoryBlobStore>;
async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {
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)
}
}