reth_node_ethereum/
node.rs

1//! Ethereum Node types config.
2
3use std::sync::Arc;
4
5use reth_basic_payload_builder::{BasicPayloadJobGenerator, BasicPayloadJobGeneratorConfig};
6use reth_beacon_consensus::EthBeaconConsensus;
7use reth_chainspec::ChainSpec;
8use reth_ethereum_engine_primitives::{
9    EthBuiltPayload, EthPayloadAttributes, EthPayloadBuilderAttributes,
10};
11use reth_ethereum_payload_builder::EthereumBuilderConfig;
12use reth_evm::execute::BasicBlockExecutorProvider;
13use reth_evm_ethereum::execute::EthExecutionStrategyFactory;
14use reth_network::{EthNetworkPrimitives, NetworkHandle, PeersInfo};
15use reth_node_api::{
16    AddOnsContext, ConfigureEvm, FullNodeComponents, HeaderTy, NodeTypesWithDB, TxTy,
17};
18use reth_node_builder::{
19    components::{
20        ComponentsBuilder, ConsensusBuilder, ExecutorBuilder, NetworkBuilder,
21        PayloadServiceBuilder, PoolBuilder,
22    },
23    node::{FullNodeTypes, NodeTypes, NodeTypesWithEngine},
24    rpc::{EngineValidatorBuilder, RpcAddOns},
25    BuilderContext, Node, NodeAdapter, NodeComponentsBuilder, PayloadBuilderConfig, PayloadTypes,
26};
27use reth_node_core::version::default_extra_data_bytes;
28use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService};
29use reth_primitives::{EthPrimitives, PooledTransactionsElement};
30use reth_provider::{CanonStateSubscriptions, EthStorage};
31use reth_rpc::EthApi;
32use reth_tracing::tracing::{debug, info};
33use reth_transaction_pool::{
34    blobstore::DiskFileBlobStore, EthTransactionPool, PoolTransaction, TransactionPool,
35    TransactionValidationTaskExecutor,
36};
37use reth_trie_db::MerklePatriciaTrie;
38
39use crate::{EthEngineTypes, EthEvmConfig};
40
41pub use reth_ethereum_engine_primitives::EthereumEngineValidator;
42
43/// Type configuration for a regular Ethereum node.
44#[derive(Debug, Default, Clone, Copy)]
45#[non_exhaustive]
46pub struct EthereumNode;
47
48impl EthereumNode {
49    /// Returns a [`ComponentsBuilder`] configured for a regular Ethereum node.
50    pub fn components<Node>() -> ComponentsBuilder<
51        Node,
52        EthereumPoolBuilder,
53        EthereumPayloadBuilder,
54        EthereumNetworkBuilder,
55        EthereumExecutorBuilder,
56        EthereumConsensusBuilder,
57    >
58    where
59        Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = EthPrimitives>>,
60        <Node::Types as NodeTypesWithEngine>::Engine: PayloadTypes<
61            BuiltPayload = EthBuiltPayload,
62            PayloadAttributes = EthPayloadAttributes,
63            PayloadBuilderAttributes = EthPayloadBuilderAttributes,
64        >,
65    {
66        ComponentsBuilder::default()
67            .node_types::<Node>()
68            .pool(EthereumPoolBuilder::default())
69            .payload(EthereumPayloadBuilder::default())
70            .network(EthereumNetworkBuilder::default())
71            .executor(EthereumExecutorBuilder::default())
72            .consensus(EthereumConsensusBuilder::default())
73    }
74}
75
76impl NodeTypes for EthereumNode {
77    type Primitives = EthPrimitives;
78    type ChainSpec = ChainSpec;
79    type StateCommitment = MerklePatriciaTrie;
80    type Storage = EthStorage;
81}
82
83impl NodeTypesWithEngine for EthereumNode {
84    type Engine = EthEngineTypes;
85}
86
87/// Add-ons w.r.t. l1 ethereum.
88pub type EthereumAddOns<N> = RpcAddOns<
89    N,
90    EthApi<
91        <N as FullNodeTypes>::Provider,
92        <N as FullNodeComponents>::Pool,
93        NetworkHandle,
94        <N as FullNodeComponents>::Evm,
95    >,
96    EthereumEngineValidatorBuilder,
97>;
98
99impl<Types, N> Node<N> for EthereumNode
100where
101    Types: NodeTypesWithDB
102        + NodeTypesWithEngine<
103            Engine = EthEngineTypes,
104            ChainSpec = ChainSpec,
105            Primitives = EthPrimitives,
106            Storage = EthStorage,
107        >,
108    N: FullNodeTypes<Types = Types>,
109{
110    type ComponentsBuilder = ComponentsBuilder<
111        N,
112        EthereumPoolBuilder,
113        EthereumPayloadBuilder,
114        EthereumNetworkBuilder,
115        EthereumExecutorBuilder,
116        EthereumConsensusBuilder,
117    >;
118
119    type AddOns = EthereumAddOns<
120        NodeAdapter<N, <Self::ComponentsBuilder as NodeComponentsBuilder<N>>::Components>,
121    >;
122
123    fn components_builder(&self) -> Self::ComponentsBuilder {
124        Self::components()
125    }
126
127    fn add_ons(&self) -> Self::AddOns {
128        EthereumAddOns::default()
129    }
130}
131
132/// A regular ethereum evm and executor builder.
133#[derive(Debug, Default, Clone, Copy)]
134#[non_exhaustive]
135pub struct EthereumExecutorBuilder;
136
137impl<Types, Node> ExecutorBuilder<Node> for EthereumExecutorBuilder
138where
139    Types: NodeTypesWithEngine<ChainSpec = ChainSpec, Primitives = EthPrimitives>,
140    Node: FullNodeTypes<Types = Types>,
141{
142    type EVM = EthEvmConfig;
143    type Executor = BasicBlockExecutorProvider<EthExecutionStrategyFactory>;
144
145    async fn build_evm(
146        self,
147        ctx: &BuilderContext<Node>,
148    ) -> eyre::Result<(Self::EVM, Self::Executor)> {
149        let chain_spec = ctx.chain_spec();
150        let enclave_args = ctx.config().enclave;
151        let evm_config = EthEvmConfig::new_with_enclave_addr_port(
152            ctx.chain_spec(),
153            enclave_args.enclave_server_addr,
154            enclave_args.enclave_server_port,
155            enclave_args.enclave_timeout,
156        );
157        let strategy_factory = EthExecutionStrategyFactory::new(chain_spec, evm_config.clone());
158        let executor = BasicBlockExecutorProvider::new(strategy_factory);
159
160        Ok((evm_config, executor))
161    }
162}
163
164/// A basic ethereum transaction pool.
165///
166/// This contains various settings that can be configured and take precedence over the node's
167/// config.
168#[derive(Debug, Default, Clone, Copy)]
169#[non_exhaustive]
170pub struct EthereumPoolBuilder {
171    // TODO add options for txpool args
172}
173
174impl<Types, Node> PoolBuilder<Node> for EthereumPoolBuilder
175where
176    Types: NodeTypesWithEngine<ChainSpec = ChainSpec, Primitives = EthPrimitives>,
177    Node: FullNodeTypes<Types = Types>,
178{
179    type Pool = EthTransactionPool<Node::Provider, DiskFileBlobStore>;
180
181    async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {
182        let data_dir = ctx.config().datadir();
183        let pool_config = ctx.pool_config();
184        let blob_store = DiskFileBlobStore::open(data_dir.blobstore(), Default::default())?;
185        let validator = TransactionValidationTaskExecutor::eth_builder(ctx.chain_spec())
186            .with_head_timestamp(ctx.head().timestamp)
187            .kzg_settings(ctx.kzg_settings()?)
188            .with_local_transactions_config(pool_config.local_transactions_config.clone())
189            .with_additional_tasks(ctx.config().txpool.additional_validation_tasks)
190            .build_with_tasks(
191                ctx.provider().clone(),
192                ctx.task_executor().clone(),
193                blob_store.clone(),
194            );
195
196        let transaction_pool =
197            reth_transaction_pool::Pool::eth_pool(validator, blob_store, pool_config);
198        info!(target: "reth::cli", "Transaction pool initialized");
199        let transactions_path = data_dir.txpool_transactions();
200
201        // spawn txpool maintenance task
202        {
203            let pool = transaction_pool.clone();
204            let chain_events = ctx.provider().canonical_state_stream();
205            let client = ctx.provider().clone();
206            let transactions_backup_config =
207                reth_transaction_pool::maintain::LocalTransactionBackupConfig::with_local_txs_backup(transactions_path);
208
209            ctx.task_executor().spawn_critical_with_graceful_shutdown_signal(
210                "local transactions backup task",
211                |shutdown| {
212                    reth_transaction_pool::maintain::backup_local_transactions_task(
213                        shutdown,
214                        pool.clone(),
215                        transactions_backup_config,
216                    )
217                },
218            );
219
220            // spawn the maintenance task
221            ctx.task_executor().spawn_critical(
222                "txpool maintenance task",
223                reth_transaction_pool::maintain::maintain_transaction_pool_future(
224                    client,
225                    pool,
226                    chain_events,
227                    ctx.task_executor().clone(),
228                    Default::default(),
229                ),
230            );
231            debug!(target: "reth::cli", "Spawned txpool maintenance task");
232        }
233
234        Ok(transaction_pool)
235    }
236}
237
238/// A basic ethereum payload service.
239#[derive(Clone, Debug)]
240pub struct EthereumPayloadBuilder {
241    /// Payload builder configuration.
242    config: EthereumBuilderConfig,
243}
244
245impl Default for EthereumPayloadBuilder {
246    fn default() -> Self {
247        Self { config: EthereumBuilderConfig::new(default_extra_data_bytes()) }
248    }
249}
250
251impl EthereumPayloadBuilder {
252    /// Create new ethereum payload builder.
253    pub const fn new(config: EthereumBuilderConfig) -> Self {
254        Self { config }
255    }
256}
257
258impl EthereumPayloadBuilder {
259    /// A helper method initializing [`PayloadBuilderService`] with the given EVM config.
260    pub fn spawn<Types, Node, Evm, Pool>(
261        self,
262        evm_config: Evm,
263        ctx: &BuilderContext<Node>,
264        pool: Pool,
265    ) -> eyre::Result<PayloadBuilderHandle<Types::Engine>>
266    where
267        Types: NodeTypesWithEngine<ChainSpec = ChainSpec, Primitives = EthPrimitives>,
268        Node: FullNodeTypes<Types = Types>,
269        Evm: ConfigureEvm<Header = HeaderTy<Types>, Transaction = TxTy<Node::Types>>,
270        Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
271            + Unpin
272            + 'static,
273        Types::Engine: PayloadTypes<
274            BuiltPayload = EthBuiltPayload,
275            PayloadAttributes = EthPayloadAttributes,
276            PayloadBuilderAttributes = EthPayloadBuilderAttributes,
277        >,
278    {
279        let payload_builder =
280            reth_ethereum_payload_builder::EthereumPayloadBuilder::new(evm_config, self.config);
281        let conf = ctx.payload_builder_config();
282
283        let payload_job_config = BasicPayloadJobGeneratorConfig::default()
284            .interval(conf.interval())
285            .deadline(conf.deadline())
286            .max_payload_tasks(conf.max_payload_tasks())
287            .extradata(conf.extradata_bytes());
288
289        let payload_generator = BasicPayloadJobGenerator::with_builder(
290            ctx.provider().clone(),
291            pool,
292            ctx.task_executor().clone(),
293            payload_job_config,
294            payload_builder,
295        );
296        let (payload_service, payload_builder) =
297            PayloadBuilderService::new(payload_generator, ctx.provider().canonical_state_stream());
298
299        ctx.task_executor().spawn_critical("payload builder service", Box::pin(payload_service));
300
301        Ok(payload_builder)
302    }
303}
304
305impl<Types, Node, Pool> PayloadServiceBuilder<Node, Pool> for EthereumPayloadBuilder
306where
307    Types: NodeTypesWithEngine<ChainSpec = ChainSpec, Primitives = EthPrimitives>,
308    Node: FullNodeTypes<Types = Types>,
309    Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
310        + Unpin
311        + 'static,
312    Types::Engine: PayloadTypes<
313        BuiltPayload = EthBuiltPayload,
314        PayloadAttributes = EthPayloadAttributes,
315        PayloadBuilderAttributes = EthPayloadBuilderAttributes,
316    >,
317{
318    async fn spawn_payload_service(
319        self,
320        ctx: &BuilderContext<Node>,
321        pool: Pool,
322    ) -> eyre::Result<PayloadBuilderHandle<Types::Engine>> {
323        let enclave_args = ctx.config().enclave;
324        self.spawn(
325            EthEvmConfig::new_with_enclave_addr_port(
326                ctx.chain_spec(),
327                enclave_args.enclave_server_addr,
328                enclave_args.enclave_server_port,
329                enclave_args.enclave_timeout,
330            ),
331            ctx,
332            pool,
333        )
334    }
335}
336
337/// A basic ethereum payload service.
338#[derive(Debug, Default, Clone, Copy)]
339pub struct EthereumNetworkBuilder {
340    // TODO add closure to modify network
341}
342
343impl<Node, Pool> NetworkBuilder<Node, Pool> for EthereumNetworkBuilder
344where
345    Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = EthPrimitives>>,
346    Pool: TransactionPool<
347            Transaction: PoolTransaction<
348                Consensus = TxTy<Node::Types>,
349                Pooled = PooledTransactionsElement,
350            >,
351        > + Unpin
352        + 'static,
353{
354    type Primitives = EthNetworkPrimitives;
355
356    async fn build_network(
357        self,
358        ctx: &BuilderContext<Node>,
359        pool: Pool,
360    ) -> eyre::Result<NetworkHandle> {
361        let network = ctx.network_builder().await?;
362        let handle = ctx.start_network(network, pool);
363        info!(target: "reth::cli", enode=%handle.local_node_record(), "P2P networking initialized");
364        Ok(handle)
365    }
366}
367
368/// A basic ethereum consensus builder.
369#[derive(Debug, Default, Clone, Copy)]
370pub struct EthereumConsensusBuilder {
371    // TODO add closure to modify consensus
372}
373
374impl<Node> ConsensusBuilder<Node> for EthereumConsensusBuilder
375where
376    Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = EthPrimitives>>,
377{
378    type Consensus = Arc<dyn reth_consensus::FullConsensus>;
379
380    async fn build_consensus(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Consensus> {
381        Ok(Arc::new(EthBeaconConsensus::new(ctx.chain_spec())))
382    }
383}
384
385/// Builder for [`EthereumEngineValidator`].
386#[derive(Debug, Default, Clone)]
387#[non_exhaustive]
388pub struct EthereumEngineValidatorBuilder;
389
390impl<Node, Types> EngineValidatorBuilder<Node> for EthereumEngineValidatorBuilder
391where
392    Types: NodeTypesWithEngine<
393        ChainSpec = ChainSpec,
394        Engine = EthEngineTypes,
395        Primitives = EthPrimitives,
396    >,
397    Node: FullNodeComponents<Types = Types>,
398{
399    type Validator = EthereumEngineValidator;
400
401    async fn build(self, ctx: &AddOnsContext<'_, Node>) -> eyre::Result<Self::Validator> {
402        Ok(EthereumEngineValidator::new(ctx.config.chain.clone()))
403    }
404}