reth_node_builder/components/
builder.rs

1//! A generic [`NodeComponentsBuilder`]
2
3use crate::{
4    components::{
5        Components, ConsensusBuilder, ExecutorBuilder, NetworkBuilder, NodeComponents,
6        PayloadServiceBuilder, PoolBuilder,
7    },
8    BuilderContext, ConfigureEvm, FullNodeTypes,
9};
10use reth_consensus::{ConsensusError, FullConsensus};
11use reth_network::types::NetPrimitivesFor;
12use reth_network_api::FullNetwork;
13use reth_node_api::{PrimitivesTy, TxTy};
14use reth_transaction_pool::{PoolPooledTx, PoolTransaction, TransactionPool};
15use std::{future::Future, marker::PhantomData};
16
17/// A generic, general purpose and customizable [`NodeComponentsBuilder`] implementation.
18///
19/// This type is stateful and captures the configuration of the node's components.
20///
21/// ## Component dependencies:
22///
23/// The components of the node depend on each other:
24/// - The payload builder service depends on the transaction pool.
25/// - The network depends on the transaction pool.
26///
27/// We distinguish between different kind of components:
28/// - Components that are standalone, such as the transaction pool.
29/// - Components that are spawned as a service, such as the payload builder service or the network.
30///
31/// ## Builder lifecycle:
32///
33/// First all standalone components are built. Then the service components are spawned.
34/// All component builders are captured in the builder state and will be consumed once the node is
35/// launched.
36#[derive(Debug)]
37pub struct ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB> {
38    pool_builder: PoolB,
39    payload_builder: PayloadB,
40    network_builder: NetworkB,
41    executor_builder: ExecB,
42    consensus_builder: ConsB,
43    _marker: PhantomData<Node>,
44}
45
46impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
47    ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
48{
49    /// Configures the node types.
50    pub fn node_types<Types>(
51        self,
52    ) -> ComponentsBuilder<Types, PoolB, PayloadB, NetworkB, ExecB, ConsB>
53    where
54        Types: FullNodeTypes,
55    {
56        let Self {
57            pool_builder,
58            payload_builder,
59            network_builder,
60            executor_builder: evm_builder,
61            consensus_builder,
62            _marker,
63        } = self;
64        ComponentsBuilder {
65            executor_builder: evm_builder,
66            pool_builder,
67            payload_builder,
68            network_builder,
69            consensus_builder,
70            _marker: Default::default(),
71        }
72    }
73
74    /// Apply a function to the pool builder.
75    pub fn map_pool(self, f: impl FnOnce(PoolB) -> PoolB) -> Self {
76        Self {
77            pool_builder: f(self.pool_builder),
78            payload_builder: self.payload_builder,
79            network_builder: self.network_builder,
80            executor_builder: self.executor_builder,
81            consensus_builder: self.consensus_builder,
82            _marker: self._marker,
83        }
84    }
85
86    /// Apply a function to the payload builder.
87    pub fn map_payload(self, f: impl FnOnce(PayloadB) -> PayloadB) -> Self {
88        Self {
89            pool_builder: self.pool_builder,
90            payload_builder: f(self.payload_builder),
91            network_builder: self.network_builder,
92            executor_builder: self.executor_builder,
93            consensus_builder: self.consensus_builder,
94            _marker: self._marker,
95        }
96    }
97
98    /// Apply a function to the network builder.
99    pub fn map_network(self, f: impl FnOnce(NetworkB) -> NetworkB) -> Self {
100        Self {
101            pool_builder: self.pool_builder,
102            payload_builder: self.payload_builder,
103            network_builder: f(self.network_builder),
104            executor_builder: self.executor_builder,
105            consensus_builder: self.consensus_builder,
106            _marker: self._marker,
107        }
108    }
109
110    /// Apply a function to the executor builder.
111    pub fn map_executor(self, f: impl FnOnce(ExecB) -> ExecB) -> Self {
112        Self {
113            pool_builder: self.pool_builder,
114            payload_builder: self.payload_builder,
115            network_builder: self.network_builder,
116            executor_builder: f(self.executor_builder),
117            consensus_builder: self.consensus_builder,
118            _marker: self._marker,
119        }
120    }
121
122    /// Apply a function to the consensus builder.
123    pub fn map_consensus(self, f: impl FnOnce(ConsB) -> ConsB) -> Self {
124        Self {
125            pool_builder: self.pool_builder,
126            payload_builder: self.payload_builder,
127            network_builder: self.network_builder,
128            executor_builder: self.executor_builder,
129            consensus_builder: f(self.consensus_builder),
130            _marker: self._marker,
131        }
132    }
133}
134
135impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
136    ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
137where
138    Node: FullNodeTypes,
139{
140    /// Configures the pool builder.
141    ///
142    /// This accepts a [`PoolBuilder`] instance that will be used to create the node's transaction
143    /// pool.
144    pub fn pool<PB>(
145        self,
146        pool_builder: PB,
147    ) -> ComponentsBuilder<Node, PB, PayloadB, NetworkB, ExecB, ConsB>
148    where
149        PB: PoolBuilder<Node>,
150    {
151        let Self {
152            pool_builder: _,
153            payload_builder,
154            network_builder,
155            executor_builder: evm_builder,
156            consensus_builder,
157            _marker,
158        } = self;
159        ComponentsBuilder {
160            pool_builder,
161            payload_builder,
162            network_builder,
163            executor_builder: evm_builder,
164            consensus_builder,
165            _marker,
166        }
167    }
168}
169
170impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
171    ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
172where
173    Node: FullNodeTypes,
174    PoolB: PoolBuilder<Node>,
175{
176    /// Configures the network builder.
177    ///
178    /// This accepts a [`NetworkBuilder`] instance that will be used to create the node's network
179    /// stack.
180    pub fn network<NB>(
181        self,
182        network_builder: NB,
183    ) -> ComponentsBuilder<Node, PoolB, PayloadB, NB, ExecB, ConsB>
184    where
185        NB: NetworkBuilder<Node, PoolB::Pool>,
186    {
187        let Self {
188            pool_builder,
189            payload_builder,
190            network_builder: _,
191            executor_builder: evm_builder,
192            consensus_builder,
193            _marker,
194        } = self;
195        ComponentsBuilder {
196            pool_builder,
197            payload_builder,
198            network_builder,
199            executor_builder: evm_builder,
200            consensus_builder,
201            _marker,
202        }
203    }
204
205    /// Configures the payload builder.
206    ///
207    /// This accepts a [`PayloadServiceBuilder`] instance that will be used to create the node's
208    /// payload builder service.
209    pub fn payload<PB>(
210        self,
211        payload_builder: PB,
212    ) -> ComponentsBuilder<Node, PoolB, PB, NetworkB, ExecB, ConsB>
213    where
214        ExecB: ExecutorBuilder<Node>,
215        PB: PayloadServiceBuilder<Node, PoolB::Pool, ExecB::EVM>,
216    {
217        let Self {
218            pool_builder,
219            payload_builder: _,
220            network_builder,
221            executor_builder: evm_builder,
222            consensus_builder,
223            _marker,
224        } = self;
225        ComponentsBuilder {
226            pool_builder,
227            payload_builder,
228            network_builder,
229            executor_builder: evm_builder,
230            consensus_builder,
231            _marker,
232        }
233    }
234
235    /// Configures the executor builder.
236    ///
237    /// This accepts a [`ExecutorBuilder`] instance that will be used to create the node's
238    /// components for execution.
239    pub fn executor<EB>(
240        self,
241        executor_builder: EB,
242    ) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, EB, ConsB>
243    where
244        EB: ExecutorBuilder<Node>,
245    {
246        let Self {
247            pool_builder,
248            payload_builder,
249            network_builder,
250            executor_builder: _,
251            consensus_builder,
252            _marker,
253        } = self;
254        ComponentsBuilder {
255            pool_builder,
256            payload_builder,
257            network_builder,
258            executor_builder,
259            consensus_builder,
260            _marker,
261        }
262    }
263
264    /// Configures the consensus builder.
265    ///
266    /// This accepts a [`ConsensusBuilder`] instance that will be used to create the node's
267    /// components for consensus.
268    pub fn consensus<CB>(
269        self,
270        consensus_builder: CB,
271    ) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, CB>
272    where
273        CB: ConsensusBuilder<Node>,
274    {
275        let Self {
276            pool_builder,
277            payload_builder,
278            network_builder,
279            executor_builder,
280            consensus_builder: _,
281
282            _marker,
283        } = self;
284        ComponentsBuilder {
285            pool_builder,
286            payload_builder,
287            network_builder,
288            executor_builder,
289            consensus_builder,
290            _marker,
291        }
292    }
293}
294
295impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB> NodeComponentsBuilder<Node>
296    for ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
297where
298    Node: FullNodeTypes,
299    PoolB: PoolBuilder<Node, Pool: TransactionPool>,
300    NetworkB: NetworkBuilder<
301        Node,
302        PoolB::Pool,
303        Network: FullNetwork<
304            Primitives: NetPrimitivesFor<
305                PrimitivesTy<Node::Types>,
306                PooledTransaction = PoolPooledTx<PoolB::Pool>,
307            >,
308        >,
309    >,
310    PayloadB: PayloadServiceBuilder<Node, PoolB::Pool, ExecB::EVM>,
311    ExecB: ExecutorBuilder<Node>,
312    ConsB: ConsensusBuilder<Node>,
313{
314    type Components =
315        Components<Node, NetworkB::Network, PoolB::Pool, ExecB::EVM, ConsB::Consensus>;
316
317    async fn build_components(
318        self,
319        context: &BuilderContext<Node>,
320    ) -> eyre::Result<Self::Components> {
321        let Self {
322            pool_builder,
323            payload_builder,
324            network_builder,
325            executor_builder: evm_builder,
326            consensus_builder,
327            _marker,
328        } = self;
329
330        let evm_config = evm_builder.build_evm(context).await?;
331        let pool = pool_builder.build_pool(context).await?;
332        let network = network_builder.build_network(context, pool.clone()).await?;
333        let payload_builder_handle = payload_builder
334            .spawn_payload_builder_service(context, pool.clone(), evm_config.clone())
335            .await?;
336        let consensus = consensus_builder.build_consensus(context).await?;
337
338        Ok(Components {
339            transaction_pool: pool,
340            evm_config,
341            network,
342            payload_builder_handle,
343            consensus,
344        })
345    }
346}
347
348impl Default for ComponentsBuilder<(), (), (), (), (), ()> {
349    fn default() -> Self {
350        Self {
351            pool_builder: (),
352            payload_builder: (),
353            network_builder: (),
354            executor_builder: (),
355            consensus_builder: (),
356            _marker: Default::default(),
357        }
358    }
359}
360
361/// A type that configures all the customizable components of the node and knows how to build them.
362///
363/// Implementers of this trait are responsible for building all the components of the node: See
364/// [`NodeComponents`].
365///
366/// The [`ComponentsBuilder`] is a generic, general purpose implementation of this trait that can be
367/// used to customize certain components of the node using the builder pattern and defaults, e.g.
368/// Ethereum and Optimism.
369/// A type that's responsible for building the components of the node.
370pub trait NodeComponentsBuilder<Node: FullNodeTypes>: Send {
371    /// The components for the node with the given types
372    type Components: NodeComponents<Node>;
373
374    /// Consumes the type and returns the created components.
375    fn build_components(
376        self,
377        ctx: &BuilderContext<Node>,
378    ) -> impl Future<Output = eyre::Result<Self::Components>> + Send;
379}
380
381impl<Node, Net, F, Fut, Pool, EVM, Cons> NodeComponentsBuilder<Node> for F
382where
383    Net: FullNetwork<
384        Primitives: NetPrimitivesFor<
385            PrimitivesTy<Node::Types>,
386            PooledTransaction = PoolPooledTx<Pool>,
387        >,
388    >,
389    Node: FullNodeTypes,
390    F: FnOnce(&BuilderContext<Node>) -> Fut + Send,
391    Fut: Future<Output = eyre::Result<Components<Node, Net, Pool, EVM, Cons>>> + Send,
392    Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
393        + Unpin
394        + 'static,
395    EVM: ConfigureEvm<Primitives = PrimitivesTy<Node::Types>> + 'static,
396    Cons:
397        FullConsensus<PrimitivesTy<Node::Types>, Error = ConsensusError> + Clone + Unpin + 'static,
398{
399    type Components = Components<Node, Net, Pool, EVM, Cons>;
400
401    fn build_components(
402        self,
403        ctx: &BuilderContext<Node>,
404    ) -> impl Future<Output = eyre::Result<Self::Components>> + Send {
405        self(ctx)
406    }
407}