reth_node_builder/builder/
states.rs1use crate::{
9 components::{NodeComponents, NodeComponentsBuilder},
10 hooks::NodeHooks,
11 launch::LaunchNode,
12 rpc::{RethRpcAddOns, RethRpcServerHandles, RpcContext},
13 AddOns, ComponentsFor, FullNode,
14};
15
16use reth_exex::ExExContext;
17use reth_node_api::{FullNodeComponents, FullNodeTypes, NodeAddOns, NodeTypes};
18use reth_node_core::node_config::NodeConfig;
19use reth_provider::providers::RocksDBProvider;
20use reth_tasks::TaskExecutor;
21use std::{fmt, fmt::Debug, future::Future};
22
23pub struct NodeBuilderWithTypes<T: FullNodeTypes> {
25 config: NodeConfig<<T::Types as NodeTypes>::ChainSpec>,
27 adapter: NodeTypesAdapter<T>,
29 rocksdb_provider: Option<RocksDBProvider>,
31}
32
33impl<T: FullNodeTypes> NodeBuilderWithTypes<T> {
34 pub const fn new(
36 config: NodeConfig<<T::Types as NodeTypes>::ChainSpec>,
37 database: T::DB,
38 rocksdb_provider: Option<RocksDBProvider>,
39 ) -> Self {
40 Self { config, adapter: NodeTypesAdapter::new(database), rocksdb_provider }
41 }
42
43 pub fn with_components<CB>(self, components_builder: CB) -> NodeBuilderWithComponents<T, CB, ()>
45 where
46 CB: NodeComponentsBuilder<T>,
47 {
48 let Self { config, adapter, rocksdb_provider } = self;
49
50 NodeBuilderWithComponents {
51 config,
52 adapter,
53 rocksdb_provider,
54 components_builder,
55 add_ons: AddOns { hooks: NodeHooks::default(), exexs: Vec::new(), add_ons: () },
56 }
57 }
58}
59
60pub struct NodeTypesAdapter<T: FullNodeTypes> {
62 pub database: T::DB,
64}
65
66impl<T: FullNodeTypes> NodeTypesAdapter<T> {
67 pub(crate) const fn new(database: T::DB) -> Self {
69 Self { database }
70 }
71}
72
73impl<T: FullNodeTypes> fmt::Debug for NodeTypesAdapter<T> {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 f.debug_struct("NodeTypesAdapter").field("db", &"...").field("types", &"...").finish()
76 }
77}
78
79#[derive(Debug)]
82pub struct NodeAdapter<T: FullNodeTypes, C: NodeComponents<T> = ComponentsFor<T>> {
83 pub components: C,
85 pub task_executor: TaskExecutor,
87 pub provider: T::Provider,
89}
90
91impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeTypes for NodeAdapter<T, C> {
92 type Types = T::Types;
93 type DB = T::DB;
94 type Provider = T::Provider;
95}
96
97impl<T: FullNodeTypes, C: NodeComponents<T>> FullNodeComponents for NodeAdapter<T, C> {
98 type Pool = C::Pool;
99 type Evm = C::Evm;
100 type Consensus = C::Consensus;
101 type Network = C::Network;
102
103 fn pool(&self) -> &Self::Pool {
104 self.components.pool()
105 }
106
107 fn evm_config(&self) -> &Self::Evm {
108 self.components.evm_config()
109 }
110
111 fn consensus(&self) -> &Self::Consensus {
112 self.components.consensus()
113 }
114
115 fn network(&self) -> &Self::Network {
116 self.components.network()
117 }
118
119 fn payload_builder_handle(
120 &self,
121 ) -> &reth_payload_builder::PayloadBuilderHandle<
122 <Self::Types as reth_node_api::NodeTypes>::Payload,
123 > {
124 self.components.payload_builder_handle()
125 }
126
127 fn provider(&self) -> &Self::Provider {
128 &self.provider
129 }
130
131 fn task_executor(&self) -> &TaskExecutor {
132 &self.task_executor
133 }
134}
135
136impl<T: FullNodeTypes, C: NodeComponents<T>> Clone for NodeAdapter<T, C> {
137 fn clone(&self) -> Self {
138 Self {
139 components: self.components.clone(),
140 task_executor: self.task_executor.clone(),
141 provider: self.provider.clone(),
142 }
143 }
144}
145
146pub struct NodeBuilderWithComponents<
150 T: FullNodeTypes,
151 CB: NodeComponentsBuilder<T>,
152 AO: NodeAddOns<NodeAdapter<T, CB::Components>>,
153> {
154 pub config: NodeConfig<<T::Types as NodeTypes>::ChainSpec>,
156 pub adapter: NodeTypesAdapter<T>,
158 pub rocksdb_provider: Option<RocksDBProvider>,
160 pub components_builder: CB,
162 pub add_ons: AddOns<NodeAdapter<T, CB::Components>, AO>,
164}
165
166impl<T, CB> NodeBuilderWithComponents<T, CB, ()>
167where
168 T: FullNodeTypes,
169 CB: NodeComponentsBuilder<T>,
170{
171 pub fn with_add_ons<AO>(self, add_ons: AO) -> NodeBuilderWithComponents<T, CB, AO>
174 where
175 AO: NodeAddOns<NodeAdapter<T, CB::Components>>,
176 {
177 let Self { config, adapter, rocksdb_provider, components_builder, .. } = self;
178
179 NodeBuilderWithComponents {
180 config,
181 adapter,
182 rocksdb_provider,
183 components_builder,
184 add_ons: AddOns { hooks: NodeHooks::default(), exexs: Vec::new(), add_ons },
185 }
186 }
187}
188
189impl<T, CB, AO> NodeBuilderWithComponents<T, CB, AO>
190where
191 T: FullNodeTypes,
192 CB: NodeComponentsBuilder<T>,
193 AO: NodeAddOns<NodeAdapter<T, CB::Components>>,
194{
195 pub fn on_component_initialized<F>(mut self, hook: F) -> Self
197 where
198 F: FnOnce(NodeAdapter<T, CB::Components>) -> eyre::Result<()> + Send + 'static,
199 {
200 self.add_ons.hooks.set_on_component_initialized(hook);
201 self
202 }
203
204 pub fn on_node_started<F>(mut self, hook: F) -> Self
206 where
207 F: FnOnce(FullNode<NodeAdapter<T, CB::Components>, AO>) -> eyre::Result<()>
208 + Send
209 + 'static,
210 {
211 self.add_ons.hooks.set_on_node_started(hook);
212 self
213 }
214
215 pub fn install_exex<F, R, E>(mut self, exex_id: impl Into<String>, exex: F) -> Self
221 where
222 F: FnOnce(ExExContext<NodeAdapter<T, CB::Components>>) -> R + Send + 'static,
223 R: Future<Output = eyre::Result<E>> + Send,
224 E: Future<Output = eyre::Result<()>> + Send,
225 {
226 self.add_ons.exexs.push((exex_id.into(), Box::new(exex)));
227 self
228 }
229
230 pub fn launch_with_fn<L, R>(self, launcher: L) -> R
232 where
233 L: FnOnce(Self) -> R,
234 {
235 launcher(self)
236 }
237
238 pub const fn check_launch(self) -> Self {
242 self
243 }
244
245 pub fn map_add_ons<F>(mut self, f: F) -> Self
268 where
269 F: FnOnce(AO) -> AO,
270 {
271 self.add_ons.add_ons = f(self.add_ons.add_ons);
272 self
273 }
274}
275
276impl<T, CB, AO> NodeBuilderWithComponents<T, CB, AO>
277where
278 T: FullNodeTypes,
279 CB: NodeComponentsBuilder<T>,
280 AO: RethRpcAddOns<NodeAdapter<T, CB::Components>>,
281{
282 pub fn launch_with<L>(self, launcher: L) -> L::Future
284 where
285 L: LaunchNode<Self>,
286 {
287 launcher.launch_node(self)
288 }
289
290 pub fn on_rpc_started<F>(self, hook: F) -> Self
292 where
293 F: FnOnce(
294 RpcContext<'_, NodeAdapter<T, CB::Components>, AO::EthApi>,
295 RethRpcServerHandles,
296 ) -> eyre::Result<()>
297 + Send
298 + 'static,
299 {
300 self.map_add_ons(|mut add_ons| {
301 add_ons.hooks_mut().set_on_rpc_started(hook);
302 add_ons
303 })
304 }
305
306 pub fn extend_rpc_modules<F>(self, hook: F) -> Self
308 where
309 F: FnOnce(RpcContext<'_, NodeAdapter<T, CB::Components>, AO::EthApi>) -> eyre::Result<()>
310 + Send
311 + 'static,
312 {
313 self.map_add_ons(|mut add_ons| {
314 add_ons.hooks_mut().set_extend_rpc_modules(hook);
315 add_ons
316 })
317 }
318}
319
320#[cfg(test)]
321mod test {
322 use super::*;
323 use crate::components::Components;
324 use reth_consensus::noop::NoopConsensus;
325 use reth_db_api::mock::DatabaseMock;
326 use reth_ethereum_engine_primitives::EthEngineTypes;
327 use reth_evm::noop::NoopEvmConfig;
328 use reth_evm_ethereum::MockEvmConfig;
329 use reth_network::EthNetworkPrimitives;
330 use reth_network_api::noop::NoopNetwork;
331 use reth_node_api::FullNodeTypesAdapter;
332 use reth_node_ethereum::EthereumNode;
333 use reth_payload_builder::PayloadBuilderHandle;
334 use reth_provider::noop::NoopProvider;
335 use reth_tasks::Runtime;
336 use reth_transaction_pool::noop::NoopTransactionPool;
337
338 #[test]
339 fn test_noop_components() {
340 let components = Components::<
341 FullNodeTypesAdapter<EthereumNode, DatabaseMock, NoopProvider>,
342 NoopNetwork<EthNetworkPrimitives>,
343 _,
344 NoopEvmConfig<MockEvmConfig>,
345 _,
346 > {
347 transaction_pool: NoopTransactionPool::default(),
348 evm_config: NoopEvmConfig::default(),
349 consensus: NoopConsensus::default(),
350 network: NoopNetwork::default(),
351 payload_builder_handle: PayloadBuilderHandle::<EthEngineTypes>::noop(),
352 };
353
354 let task_executor = Runtime::test();
355
356 let node = NodeAdapter { components, task_executor, provider: NoopProvider::default() };
357
358 <NodeAdapter<_, _> as FullNodeComponents>::pool(&node);
360 }
361}