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_evm::execute::BlockExecutorProvider;
12use reth_network::NetworkPrimitives;
13use reth_node_api::{BlockTy, BodyTy, HeaderTy, PrimitivesTy, TxTy};
14use reth_transaction_pool::{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        PB: PayloadServiceBuilder<Node, PoolB::Pool>,
215    {
216        let Self {
217            pool_builder,
218            payload_builder: _,
219            network_builder,
220            executor_builder: evm_builder,
221            consensus_builder,
222            _marker,
223        } = self;
224        ComponentsBuilder {
225            pool_builder,
226            payload_builder,
227            network_builder,
228            executor_builder: evm_builder,
229            consensus_builder,
230            _marker,
231        }
232    }
233
234    /// Configures the executor builder.
235    ///
236    /// This accepts a [`ExecutorBuilder`] instance that will be used to create the node's
237    /// components for execution.
238    pub fn executor<EB>(
239        self,
240        executor_builder: EB,
241    ) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, EB, ConsB>
242    where
243        EB: ExecutorBuilder<Node>,
244    {
245        let Self {
246            pool_builder,
247            payload_builder,
248            network_builder,
249            executor_builder: _,
250            consensus_builder,
251            _marker,
252        } = self;
253        ComponentsBuilder {
254            pool_builder,
255            payload_builder,
256            network_builder,
257            executor_builder,
258            consensus_builder,
259            _marker,
260        }
261    }
262
263    /// Configures the consensus builder.
264    ///
265    /// This accepts a [`ConsensusBuilder`] instance that will be used to create the node's
266    /// components for consensus.
267    pub fn consensus<CB>(
268        self,
269        consensus_builder: CB,
270    ) -> ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, CB>
271    where
272        CB: ConsensusBuilder<Node>,
273    {
274        let Self {
275            pool_builder,
276            payload_builder,
277            network_builder,
278            executor_builder,
279            consensus_builder: _,
280
281            _marker,
282        } = self;
283        ComponentsBuilder {
284            pool_builder,
285            payload_builder,
286            network_builder,
287            executor_builder,
288            consensus_builder,
289            _marker,
290        }
291    }
292}
293
294impl<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB> NodeComponentsBuilder<Node>
295    for ComponentsBuilder<Node, PoolB, PayloadB, NetworkB, ExecB, ConsB>
296where
297    Node: FullNodeTypes,
298    PoolB: PoolBuilder<
299        Node,
300        Pool: TransactionPool<
301            Transaction: PoolTransaction<
302                Pooled = <NetworkB::Primitives as NetworkPrimitives>::PooledTransaction,
303            >,
304        >,
305    >,
306    NetworkB: NetworkBuilder<
307        Node,
308        PoolB::Pool,
309        Primitives: NetworkPrimitives<
310            BlockHeader = HeaderTy<Node::Types>,
311            BlockBody = BodyTy<Node::Types>,
312            Block = BlockTy<Node::Types>,
313        >,
314    >,
315    PayloadB: PayloadServiceBuilder<Node, PoolB::Pool>,
316    ExecB: ExecutorBuilder<Node>,
317    ConsB: ConsensusBuilder<Node>,
318{
319    type Components = Components<
320        Node,
321        NetworkB::Primitives,
322        PoolB::Pool,
323        ExecB::EVM,
324        ExecB::Executor,
325        ConsB::Consensus,
326    >;
327
328    async fn build_components(
329        self,
330        context: &BuilderContext<Node>,
331    ) -> eyre::Result<Self::Components> {
332        let Self {
333            pool_builder,
334            payload_builder,
335            network_builder,
336            executor_builder: evm_builder,
337            consensus_builder,
338            _marker,
339        } = self;
340
341        let (evm_config, executor) = evm_builder.build_evm(context).await?;
342        let pool = pool_builder.build_pool(context).await?;
343        let network = network_builder.build_network(context, pool.clone()).await?;
344        let payload_builder_handle =
345            payload_builder.spawn_payload_builder_service(context, pool.clone()).await?;
346        let consensus = consensus_builder.build_consensus(context).await?;
347
348        Ok(Components {
349            transaction_pool: pool,
350            evm_config,
351            network,
352            payload_builder_handle,
353            executor,
354            consensus,
355        })
356    }
357}
358
359impl Default for ComponentsBuilder<(), (), (), (), (), ()> {
360    fn default() -> Self {
361        Self {
362            pool_builder: (),
363            payload_builder: (),
364            network_builder: (),
365            executor_builder: (),
366            consensus_builder: (),
367            _marker: Default::default(),
368        }
369    }
370}
371
372/// A type that configures all the customizable components of the node and knows how to build them.
373///
374/// Implementers of this trait are responsible for building all the components of the node: See
375/// [`NodeComponents`].
376///
377/// The [`ComponentsBuilder`] is a generic, general purpose implementation of this trait that can be
378/// used to customize certain components of the node using the builder pattern and defaults, e.g.
379/// Ethereum and Optimism.
380/// A type that's responsible for building the components of the node.
381pub trait NodeComponentsBuilder<Node: FullNodeTypes>: Send {
382    /// The components for the node with the given types
383    type Components: NodeComponents<Node>;
384
385    /// Consumes the type and returns the created components.
386    fn build_components(
387        self,
388        ctx: &BuilderContext<Node>,
389    ) -> impl Future<Output = eyre::Result<Self::Components>> + Send;
390}
391
392impl<Node, N, F, Fut, Pool, EVM, Executor, Cons> NodeComponentsBuilder<Node> for F
393where
394    N: NetworkPrimitives<
395        BlockHeader = HeaderTy<Node::Types>,
396        BlockBody = BodyTy<Node::Types>,
397        Block = BlockTy<Node::Types>,
398    >,
399    Node: FullNodeTypes,
400    F: FnOnce(&BuilderContext<Node>) -> Fut + Send,
401    Fut: Future<Output = eyre::Result<Components<Node, N, Pool, EVM, Executor, Cons>>> + Send,
402    Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
403        + Unpin
404        + 'static,
405    EVM: ConfigureEvm<Primitives = PrimitivesTy<Node::Types>> + 'static,
406    Executor: BlockExecutorProvider<Primitives = PrimitivesTy<Node::Types>>,
407    Cons:
408        FullConsensus<PrimitivesTy<Node::Types>, Error = ConsensusError> + Clone + Unpin + 'static,
409{
410    type Components = Components<Node, N, Pool, EVM, Executor, Cons>;
411
412    fn build_components(
413        self,
414        ctx: &BuilderContext<Node>,
415    ) -> impl Future<Output = eyre::Result<Self::Components>> + Send {
416        self(ctx)
417    }
418}