1use node::NodeTestContext;
4use reth_chainspec::{ChainSpec, EthChainSpec};
5use reth_db::{test_utils::TempDatabase, DatabaseEnv};
6use reth_engine_local::LocalPayloadAttributesBuilder;
7use reth_network_api::test_utils::PeersHandleProvider;
8use reth_node_builder::{
9 components::NodeComponentsBuilder,
10 rpc::{EngineValidatorAddOn, RethRpcAddOns},
11 EngineNodeLauncher, FullNodeTypesAdapter, Node, NodeAdapter, NodeBuilder, NodeComponents,
12 NodeConfig, NodeHandle, NodePrimitives, NodeTypes, NodeTypesWithDBAdapter,
13 PayloadAttributesBuilder, PayloadTypes,
14};
15use reth_node_core::args::{DiscoveryArgs, NetworkArgs, RpcServerArgs};
16use reth_provider::providers::{BlockchainProvider, NodeTypesForProvider};
17use reth_rpc_server_types::RpcModuleSelection;
18use reth_tasks::TaskManager;
19use std::sync::Arc;
20use tracing::{span, Level};
21use wallet::Wallet;
22
23pub mod node;
25pub mod testsuite;
26
27pub mod transaction;
29
30pub mod wallet;
32
33mod payload;
35
36pub mod setup_import;
38
39mod network;
41
42mod rpc;
44
45pub mod test_rlp_utils;
47
48pub async fn setup<N>(
50 num_nodes: usize,
51 chain_spec: Arc<N::ChainSpec>,
52 is_dev: bool,
53 attributes_generator: impl Fn(u64) -> <<N as NodeTypes>::Payload as PayloadTypes>::PayloadBuilderAttributes + Send + Sync + Copy + 'static,
54) -> eyre::Result<(Vec<NodeHelperType<N>>, TaskManager, Wallet)>
55where
56 N: Default + Node<TmpNodeAdapter<N>> + NodeTypesForProvider,
57 N::ComponentsBuilder: NodeComponentsBuilder<
58 TmpNodeAdapter<N>,
59 Components: NodeComponents<TmpNodeAdapter<N>, Network: PeersHandleProvider>,
60 >,
61 N::AddOns: RethRpcAddOns<Adapter<N>> + EngineValidatorAddOn<Adapter<N>>,
62 LocalPayloadAttributesBuilder<N::ChainSpec>:
63 PayloadAttributesBuilder<<<N as NodeTypes>::Payload as PayloadTypes>::PayloadAttributes>,
64{
65 let tasks = TaskManager::current();
66 let exec = tasks.executor();
67
68 let network_config = NetworkArgs {
69 discovery: DiscoveryArgs { disable_discovery: true, ..DiscoveryArgs::default() },
70 ..NetworkArgs::default()
71 };
72
73 let mut nodes: Vec<NodeTestContext<_, _>> = Vec::with_capacity(num_nodes);
75
76 for idx in 0..num_nodes {
77 let node_config = NodeConfig::new(chain_spec.clone())
78 .with_network(network_config.clone())
79 .with_unused_ports()
80 .with_rpc(RpcServerArgs::default().with_unused_ports().with_http())
81 .set_dev(is_dev);
82
83 let span = span!(Level::INFO, "node", idx);
84 let _enter = span.enter();
85 let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone())
86 .testing_node(exec.clone())
87 .node(Default::default())
88 .launch()
89 .await?;
90
91 let mut node = NodeTestContext::new(node, attributes_generator).await?;
92
93 if let Some(previous_node) = nodes.last_mut() {
95 previous_node.connect(&mut node).await;
96 }
97
98 if idx + 1 == num_nodes && num_nodes > 2 {
100 if let Some(first_node) = nodes.first_mut() {
101 node.connect(first_node).await;
102 }
103 }
104
105 nodes.push(node);
106 }
107
108 Ok((nodes, tasks, Wallet::default().with_chain_id(chain_spec.chain().into())))
109}
110
111pub async fn setup_engine<N>(
113 num_nodes: usize,
114 chain_spec: Arc<N::ChainSpec>,
115 is_dev: bool,
116 tree_config: reth_node_api::TreeConfig,
117 attributes_generator: impl Fn(u64) -> <<N as NodeTypes>::Payload as PayloadTypes>::PayloadBuilderAttributes + Send + Sync + Copy + 'static,
118) -> eyre::Result<(
119 Vec<NodeHelperType<N, BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>>>,
120 TaskManager,
121 Wallet,
122)>
123where
124 N: NodeBuilderHelper,
125 LocalPayloadAttributesBuilder<N::ChainSpec>:
126 PayloadAttributesBuilder<<N::Payload as PayloadTypes>::PayloadAttributes>,
127{
128 setup_engine_with_connection::<N>(
129 num_nodes,
130 chain_spec,
131 is_dev,
132 tree_config,
133 attributes_generator,
134 true,
135 )
136 .await
137}
138
139pub async fn setup_engine_with_connection<N>(
141 num_nodes: usize,
142 chain_spec: Arc<N::ChainSpec>,
143 is_dev: bool,
144 tree_config: reth_node_api::TreeConfig,
145 attributes_generator: impl Fn(u64) -> <<N as NodeTypes>::Payload as PayloadTypes>::PayloadBuilderAttributes + Send + Sync + Copy + 'static,
146 connect_nodes: bool,
147) -> eyre::Result<(
148 Vec<NodeHelperType<N, BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>>>,
149 TaskManager,
150 Wallet,
151)>
152where
153 N: NodeBuilderHelper,
154 LocalPayloadAttributesBuilder<N::ChainSpec>:
155 PayloadAttributesBuilder<<N::Payload as PayloadTypes>::PayloadAttributes>,
156{
157 let tasks = TaskManager::current();
158 let exec = tasks.executor();
159
160 let network_config = NetworkArgs {
161 discovery: DiscoveryArgs { disable_discovery: true, ..DiscoveryArgs::default() },
162 ..NetworkArgs::default()
163 };
164
165 let mut nodes: Vec<NodeTestContext<_, _>> = Vec::with_capacity(num_nodes);
167
168 for idx in 0..num_nodes {
169 let node_config = NodeConfig::new(chain_spec.clone())
170 .with_network(network_config.clone())
171 .with_unused_ports()
172 .with_rpc(
173 RpcServerArgs::default()
174 .with_unused_ports()
175 .with_http()
176 .with_http_api(RpcModuleSelection::All),
177 )
178 .set_dev(is_dev);
179
180 let span = span!(Level::INFO, "node", idx);
181 let _enter = span.enter();
182 let node = N::default();
183 let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone())
184 .testing_node(exec.clone())
185 .with_types_and_provider::<N, BlockchainProvider<_>>()
186 .with_components(node.components_builder())
187 .with_add_ons(node.add_ons())
188 .launch_with_fn(|builder| {
189 let launcher = EngineNodeLauncher::new(
190 builder.task_executor().clone(),
191 builder.config().datadir(),
192 tree_config.clone(),
193 );
194 builder.launch_with(launcher)
195 })
196 .await?;
197
198 let mut node = NodeTestContext::new(node, attributes_generator).await?;
199
200 let genesis = node.block_hash(0);
201 node.update_forkchoice(genesis, genesis).await?;
202
203 if connect_nodes {
205 if let Some(previous_node) = nodes.last_mut() {
206 previous_node.connect(&mut node).await;
207 }
208
209 if idx + 1 == num_nodes && num_nodes > 2 {
211 if let Some(first_node) = nodes.first_mut() {
212 node.connect(first_node).await;
213 }
214 }
215 }
216
217 nodes.push(node);
218 }
219
220 Ok((nodes, tasks, Wallet::default().with_chain_id(chain_spec.chain().into())))
221}
222
223pub type TmpDB = Arc<TempDatabase<DatabaseEnv>>;
227type TmpNodeAdapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
228 FullNodeTypesAdapter<N, TmpDB, Provider>;
229
230pub type Adapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> = NodeAdapter<
232 TmpNodeAdapter<N, Provider>,
233 <<N as Node<TmpNodeAdapter<N, Provider>>>::ComponentsBuilder as NodeComponentsBuilder<
234 TmpNodeAdapter<N, Provider>,
235 >>::Components,
236>;
237
238pub type NodeHelperType<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
240 NodeTestContext<Adapter<N, Provider>, <N as Node<TmpNodeAdapter<N, Provider>>>::AddOns>;
241
242pub trait NodeBuilderHelper
244where
245 Self: Default
246 + NodeTypesForProvider<
247 Payload: PayloadTypes<
248 PayloadBuilderAttributes: From<reth_payload_builder::EthPayloadBuilderAttributes>,
249 >,
250 > + Node<
251 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
252 Primitives: NodePrimitives<
253 BlockHeader = alloy_consensus::Header,
254 BlockBody = alloy_consensus::BlockBody<
255 <Self::Primitives as NodePrimitives>::SignedTx,
256 >,
257 >,
258 ComponentsBuilder: NodeComponentsBuilder<
259 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
260 Components: NodeComponents<
261 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
262 Network: PeersHandleProvider,
263 >,
264 >,
265 AddOns: RethRpcAddOns<
266 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
267 > + EngineValidatorAddOn<
268 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
269 >,
270 ChainSpec: From<ChainSpec> + Clone,
271 >,
272 LocalPayloadAttributesBuilder<Self::ChainSpec>:
273 PayloadAttributesBuilder<<Self::Payload as PayloadTypes>::PayloadAttributes>,
274{
275}
276
277impl<T> NodeBuilderHelper for T
278where
279 Self: Default
280 + NodeTypesForProvider<
281 Payload: PayloadTypes<
282 PayloadBuilderAttributes: From<reth_payload_builder::EthPayloadBuilderAttributes>,
283 >,
284 > + Node<
285 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
286 Primitives: NodePrimitives<
287 BlockHeader = alloy_consensus::Header,
288 BlockBody = alloy_consensus::BlockBody<
289 <Self::Primitives as NodePrimitives>::SignedTx,
290 >,
291 >,
292 ComponentsBuilder: NodeComponentsBuilder<
293 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
294 Components: NodeComponents<
295 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
296 Network: PeersHandleProvider,
297 >,
298 >,
299 AddOns: RethRpcAddOns<
300 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
301 > + EngineValidatorAddOn<
302 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
303 >,
304 ChainSpec: From<ChainSpec> + Clone,
305 >,
306 LocalPayloadAttributesBuilder<Self::ChainSpec>:
307 PayloadAttributesBuilder<<Self::Payload as PayloadTypes>::PayloadAttributes>,
308{
309}