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 &&
100 num_nodes > 2 &&
101 let Some(first_node) = nodes.first_mut()
102 {
103 node.connect(first_node).await;
104 }
105
106 nodes.push(node);
107 }
108
109 Ok((nodes, tasks, Wallet::default().with_chain_id(chain_spec.chain().into())))
110}
111
112pub async fn setup_engine<N>(
114 num_nodes: usize,
115 chain_spec: Arc<N::ChainSpec>,
116 is_dev: bool,
117 tree_config: reth_node_api::TreeConfig,
118 attributes_generator: impl Fn(u64) -> <<N as NodeTypes>::Payload as PayloadTypes>::PayloadBuilderAttributes + Send + Sync + Copy + 'static,
119) -> eyre::Result<(
120 Vec<NodeHelperType<N, BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>>>,
121 TaskManager,
122 Wallet,
123)>
124where
125 N: NodeBuilderHelper,
126 LocalPayloadAttributesBuilder<N::ChainSpec>:
127 PayloadAttributesBuilder<<N::Payload as PayloadTypes>::PayloadAttributes>,
128{
129 setup_engine_with_connection::<N>(
130 num_nodes,
131 chain_spec,
132 is_dev,
133 tree_config,
134 attributes_generator,
135 true,
136 )
137 .await
138}
139
140pub async fn setup_engine_with_connection<N>(
142 num_nodes: usize,
143 chain_spec: Arc<N::ChainSpec>,
144 is_dev: bool,
145 tree_config: reth_node_api::TreeConfig,
146 attributes_generator: impl Fn(u64) -> <<N as NodeTypes>::Payload as PayloadTypes>::PayloadBuilderAttributes + Send + Sync + Copy + 'static,
147 connect_nodes: bool,
148) -> eyre::Result<(
149 Vec<NodeHelperType<N, BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>>>,
150 TaskManager,
151 Wallet,
152)>
153where
154 N: NodeBuilderHelper,
155 LocalPayloadAttributesBuilder<N::ChainSpec>:
156 PayloadAttributesBuilder<<N::Payload as PayloadTypes>::PayloadAttributes>,
157{
158 let tasks = TaskManager::current();
159 let exec = tasks.executor();
160
161 let network_config = NetworkArgs {
162 discovery: DiscoveryArgs { disable_discovery: true, ..DiscoveryArgs::default() },
163 ..NetworkArgs::default()
164 };
165
166 let mut nodes: Vec<NodeTestContext<_, _>> = Vec::with_capacity(num_nodes);
168
169 for idx in 0..num_nodes {
170 let node_config = NodeConfig::new(chain_spec.clone())
171 .with_network(network_config.clone())
172 .with_unused_ports()
173 .with_rpc(
174 RpcServerArgs::default()
175 .with_unused_ports()
176 .with_http()
177 .with_http_api(RpcModuleSelection::All),
178 )
179 .set_dev(is_dev);
180
181 let span = span!(Level::INFO, "node", idx);
182 let _enter = span.enter();
183 let node = N::default();
184 let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone())
185 .testing_node(exec.clone())
186 .with_types_and_provider::<N, BlockchainProvider<_>>()
187 .with_components(node.components_builder())
188 .with_add_ons(node.add_ons())
189 .launch_with_fn(|builder| {
190 let launcher = EngineNodeLauncher::new(
191 builder.task_executor().clone(),
192 builder.config().datadir(),
193 tree_config.clone(),
194 );
195 builder.launch_with(launcher)
196 })
197 .await?;
198
199 let mut node = NodeTestContext::new(node, attributes_generator).await?;
200
201 let genesis = node.block_hash(0);
202 node.update_forkchoice(genesis, genesis).await?;
203
204 if connect_nodes {
206 if let Some(previous_node) = nodes.last_mut() {
207 previous_node.connect(&mut node).await;
208 }
209
210 if idx + 1 == num_nodes &&
212 num_nodes > 2 &&
213 let Some(first_node) = nodes.first_mut()
214 {
215 node.connect(first_node).await;
216 }
217 }
218
219 nodes.push(node);
220 }
221
222 Ok((nodes, tasks, Wallet::default().with_chain_id(chain_spec.chain().into())))
223}
224
225pub type TmpDB = Arc<TempDatabase<DatabaseEnv>>;
229type TmpNodeAdapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
230 FullNodeTypesAdapter<N, TmpDB, Provider>;
231
232pub type Adapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> = NodeAdapter<
234 TmpNodeAdapter<N, Provider>,
235 <<N as Node<TmpNodeAdapter<N, Provider>>>::ComponentsBuilder as NodeComponentsBuilder<
236 TmpNodeAdapter<N, Provider>,
237 >>::Components,
238>;
239
240pub type NodeHelperType<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
242 NodeTestContext<Adapter<N, Provider>, <N as Node<TmpNodeAdapter<N, Provider>>>::AddOns>;
243
244pub trait NodeBuilderHelper
246where
247 Self: Default
248 + NodeTypesForProvider<
249 Payload: PayloadTypes<
250 PayloadBuilderAttributes: From<reth_payload_builder::EthPayloadBuilderAttributes>,
251 >,
252 > + Node<
253 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
254 Primitives: NodePrimitives<
255 BlockHeader = alloy_consensus::Header,
256 BlockBody = alloy_consensus::BlockBody<
257 <Self::Primitives as NodePrimitives>::SignedTx,
258 >,
259 >,
260 ComponentsBuilder: NodeComponentsBuilder<
261 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
262 Components: NodeComponents<
263 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
264 Network: PeersHandleProvider,
265 >,
266 >,
267 AddOns: RethRpcAddOns<
268 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
269 > + EngineValidatorAddOn<
270 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
271 >,
272 ChainSpec: From<ChainSpec> + Clone,
273 >,
274 LocalPayloadAttributesBuilder<Self::ChainSpec>:
275 PayloadAttributesBuilder<<Self::Payload as PayloadTypes>::PayloadAttributes>,
276{
277}
278
279impl<T> NodeBuilderHelper for T
280where
281 Self: Default
282 + NodeTypesForProvider<
283 Payload: PayloadTypes<
284 PayloadBuilderAttributes: From<reth_payload_builder::EthPayloadBuilderAttributes>,
285 >,
286 > + Node<
287 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
288 Primitives: NodePrimitives<
289 BlockHeader = alloy_consensus::Header,
290 BlockBody = alloy_consensus::BlockBody<
291 <Self::Primitives as NodePrimitives>::SignedTx,
292 >,
293 >,
294 ComponentsBuilder: NodeComponentsBuilder<
295 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
296 Components: NodeComponents<
297 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
298 Network: PeersHandleProvider,
299 >,
300 >,
301 AddOns: RethRpcAddOns<
302 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
303 > + EngineValidatorAddOn<
304 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
305 >,
306 ChainSpec: From<ChainSpec> + Clone,
307 >,
308 LocalPayloadAttributesBuilder<Self::ChainSpec>:
309 PayloadAttributesBuilder<<Self::Payload as PayloadTypes>::PayloadAttributes>,
310{
311}