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
36mod network;
38
39mod rpc;
41
42pub async fn setup<N>(
44 num_nodes: usize,
45 chain_spec: Arc<N::ChainSpec>,
46 is_dev: bool,
47 attributes_generator: impl Fn(u64) -> <<N as NodeTypes>::Payload as PayloadTypes>::PayloadBuilderAttributes + Send + Sync + Copy + 'static,
48) -> eyre::Result<(Vec<NodeHelperType<N>>, TaskManager, Wallet)>
49where
50 N: Default + Node<TmpNodeAdapter<N>> + NodeTypesForProvider + NodeTypes,
51 N::ComponentsBuilder: NodeComponentsBuilder<
52 TmpNodeAdapter<N>,
53 Components: NodeComponents<TmpNodeAdapter<N>, Network: PeersHandleProvider>,
54 >,
55 N::AddOns: RethRpcAddOns<Adapter<N>> + EngineValidatorAddOn<Adapter<N>>,
56 LocalPayloadAttributesBuilder<N::ChainSpec>:
57 PayloadAttributesBuilder<<<N as NodeTypes>::Payload as PayloadTypes>::PayloadAttributes>,
58{
59 let tasks = TaskManager::current();
60 let exec = tasks.executor();
61
62 let network_config = NetworkArgs {
63 discovery: DiscoveryArgs { disable_discovery: true, ..DiscoveryArgs::default() },
64 ..NetworkArgs::default()
65 };
66
67 let mut nodes: Vec<NodeTestContext<_, _>> = Vec::with_capacity(num_nodes);
69
70 for idx in 0..num_nodes {
71 let node_config = NodeConfig::new(chain_spec.clone())
72 .with_network(network_config.clone())
73 .with_unused_ports()
74 .with_rpc(RpcServerArgs::default().with_unused_ports().with_http())
75 .set_dev(is_dev);
76
77 let span = span!(Level::INFO, "node", idx);
78 let _enter = span.enter();
79 let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone())
80 .testing_node(exec.clone())
81 .node(Default::default())
82 .launch()
83 .await?;
84
85 let mut node = NodeTestContext::new(node, attributes_generator).await?;
86
87 if let Some(previous_node) = nodes.last_mut() {
89 previous_node.connect(&mut node).await;
90 }
91
92 if idx + 1 == num_nodes && num_nodes > 2 {
94 if let Some(first_node) = nodes.first_mut() {
95 node.connect(first_node).await;
96 }
97 }
98
99 nodes.push(node);
100 }
101
102 Ok((nodes, tasks, Wallet::default().with_chain_id(chain_spec.chain().into())))
103}
104
105pub async fn setup_engine<N>(
107 num_nodes: usize,
108 chain_spec: Arc<N::ChainSpec>,
109 is_dev: bool,
110 attributes_generator: impl Fn(u64) -> <<N as NodeTypes>::Payload as PayloadTypes>::PayloadBuilderAttributes + Send + Sync + Copy + 'static,
111) -> eyre::Result<(
112 Vec<NodeHelperType<N, BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>>>,
113 TaskManager,
114 Wallet,
115)>
116where
117 N: NodeBuilderHelper,
118 LocalPayloadAttributesBuilder<N::ChainSpec>:
119 PayloadAttributesBuilder<<N::Payload as PayloadTypes>::PayloadAttributes>,
120{
121 let tasks = TaskManager::current();
122 let exec = tasks.executor();
123
124 let network_config = NetworkArgs {
125 discovery: DiscoveryArgs { disable_discovery: true, ..DiscoveryArgs::default() },
126 ..NetworkArgs::default()
127 };
128
129 let mut nodes: Vec<NodeTestContext<_, _>> = Vec::with_capacity(num_nodes);
131
132 for idx in 0..num_nodes {
133 let node_config = NodeConfig::new(chain_spec.clone())
134 .with_network(network_config.clone())
135 .with_unused_ports()
136 .with_rpc(
137 RpcServerArgs::default()
138 .with_unused_ports()
139 .with_http()
140 .with_http_api(RpcModuleSelection::All),
141 )
142 .set_dev(is_dev);
143
144 let span = span!(Level::INFO, "node", idx);
145 let _enter = span.enter();
146 let node = N::default();
147 let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone())
148 .testing_node(exec.clone())
149 .with_types_and_provider::<N, BlockchainProvider<_>>()
150 .with_components(node.components_builder())
151 .with_add_ons(node.add_ons())
152 .launch_with_fn(|builder| {
153 let launcher = EngineNodeLauncher::new(
154 builder.task_executor().clone(),
155 builder.config().datadir(),
156 Default::default(),
157 );
158 builder.launch_with(launcher)
159 })
160 .await?;
161
162 let mut node = NodeTestContext::new(node, attributes_generator).await?;
163
164 let genesis = node.block_hash(0);
165 node.update_forkchoice(genesis, genesis).await?;
166
167 if let Some(previous_node) = nodes.last_mut() {
169 previous_node.connect(&mut node).await;
170 }
171
172 if idx + 1 == num_nodes && num_nodes > 2 {
174 if let Some(first_node) = nodes.first_mut() {
175 node.connect(first_node).await;
176 }
177 }
178
179 nodes.push(node);
180 }
181
182 Ok((nodes, tasks, Wallet::default().with_chain_id(chain_spec.chain().into())))
183}
184
185pub type TmpDB = Arc<TempDatabase<DatabaseEnv>>;
189type TmpNodeAdapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
190 FullNodeTypesAdapter<N, TmpDB, Provider>;
191
192pub type Adapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> = NodeAdapter<
194 TmpNodeAdapter<N, Provider>,
195 <<N as Node<TmpNodeAdapter<N, Provider>>>::ComponentsBuilder as NodeComponentsBuilder<
196 TmpNodeAdapter<N, Provider>,
197 >>::Components,
198>;
199
200pub type NodeHelperType<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
202 NodeTestContext<Adapter<N, Provider>, <N as Node<TmpNodeAdapter<N, Provider>>>::AddOns>;
203
204pub trait NodeBuilderHelper
206where
207 Self: Default
208 + NodeTypesForProvider
209 + NodeTypes<
210 Payload: PayloadTypes<
211 PayloadBuilderAttributes: From<reth_payload_builder::EthPayloadBuilderAttributes>,
212 >,
213 > + Node<
214 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
215 Primitives: NodePrimitives<
216 BlockHeader = alloy_consensus::Header,
217 BlockBody = alloy_consensus::BlockBody<
218 <Self::Primitives as NodePrimitives>::SignedTx,
219 >,
220 >,
221 ComponentsBuilder: NodeComponentsBuilder<
222 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
223 Components: NodeComponents<
224 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
225 Network: PeersHandleProvider,
226 >,
227 >,
228 AddOns: RethRpcAddOns<
229 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
230 > + EngineValidatorAddOn<
231 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
232 >,
233 ChainSpec: From<ChainSpec> + Clone,
234 >,
235 LocalPayloadAttributesBuilder<Self::ChainSpec>:
236 PayloadAttributesBuilder<<Self::Payload as PayloadTypes>::PayloadAttributes>,
237{
238}
239
240impl<T> NodeBuilderHelper for T
241where
242 Self: Default
243 + NodeTypesForProvider
244 + NodeTypes<
245 Payload: PayloadTypes<
246 PayloadBuilderAttributes: From<reth_payload_builder::EthPayloadBuilderAttributes>,
247 >,
248 > + Node<
249 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
250 Primitives: NodePrimitives<
251 BlockHeader = alloy_consensus::Header,
252 BlockBody = alloy_consensus::BlockBody<
253 <Self::Primitives as NodePrimitives>::SignedTx,
254 >,
255 >,
256 ComponentsBuilder: NodeComponentsBuilder<
257 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
258 Components: NodeComponents<
259 TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
260 Network: PeersHandleProvider,
261 >,
262 >,
263 AddOns: RethRpcAddOns<
264 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
265 > + EngineValidatorAddOn<
266 Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
267 >,
268 ChainSpec: From<ChainSpec> + Clone,
269 >,
270 LocalPayloadAttributesBuilder<Self::ChainSpec>:
271 PayloadAttributesBuilder<<Self::Payload as PayloadTypes>::PayloadAttributes>,
272{
273}