1use node::NodeTestContext;
4use reth_chainspec::EthChainSpec;
5use reth_db::{test_utils::TempDatabase, DatabaseEnv};
6use reth_engine_local::LocalPayloadAttributesBuilder;
7use reth_network_api::test_utils::PeersHandleProvider;
8use reth_node_api::EngineValidator;
9use reth_node_builder::{
10 components::NodeComponentsBuilder,
11 rpc::{EngineValidatorAddOn, RethRpcAddOns},
12 EngineNodeLauncher, FullNodeTypesAdapter, Node, NodeAdapter, NodeBuilder, NodeComponents,
13 NodeConfig, NodeHandle, NodeTypesWithDBAdapter, NodeTypesWithEngine, PayloadAttributesBuilder,
14 PayloadTypes,
15};
16use reth_node_core::args::{DiscoveryArgs, NetworkArgs, RpcServerArgs};
17use reth_primitives::EthPrimitives;
18use reth_provider::providers::{
19 BlockchainProvider, BlockchainProvider2, NodeTypesForProvider, NodeTypesForTree,
20};
21use reth_rpc_server_types::RpcModuleSelection;
22use reth_tasks::TaskManager;
23use std::sync::Arc;
24use tracing::{span, Level};
25use wallet::Wallet;
26
27pub mod node;
29
30pub mod transaction;
32
33pub mod wallet;
35
36mod payload;
38
39mod network;
41
42mod engine_api;
44mod rpc;
46
47mod traits;
49
50pub async fn setup<N>(
52 num_nodes: usize,
53 chain_spec: Arc<N::ChainSpec>,
54 is_dev: bool,
55 attributes_generator: impl Fn(u64) -> <<N as NodeTypesWithEngine>::Engine as PayloadTypes>::PayloadBuilderAttributes + Copy + 'static,
56) -> eyre::Result<(Vec<NodeHelperType<N>>, TaskManager, Wallet)>
57where
58 N: Default + Node<TmpNodeAdapter<N>> + NodeTypesForTree + NodeTypesWithEngine,
59 N::ComponentsBuilder: NodeComponentsBuilder<
60 TmpNodeAdapter<N>,
61 Components: NodeComponents<TmpNodeAdapter<N>, Network: PeersHandleProvider>,
62 >,
63 N::AddOns: RethRpcAddOns<Adapter<N>>,
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 attributes_generator: impl Fn(u64) -> <<N as NodeTypesWithEngine>::Engine as PayloadTypes>::PayloadBuilderAttributes + Copy + 'static,
117) -> eyre::Result<(
118 Vec<NodeHelperType<N, BlockchainProvider2<NodeTypesWithDBAdapter<N, TmpDB>>>>,
119 TaskManager,
120 Wallet,
121)>
122where
123 N: Default
124 + Node<TmpNodeAdapter<N, BlockchainProvider2<NodeTypesWithDBAdapter<N, TmpDB>>>>
125 + NodeTypesWithEngine<Primitives = EthPrimitives>
126 + NodeTypesForProvider,
127 N::ComponentsBuilder: NodeComponentsBuilder<
128 TmpNodeAdapter<N, BlockchainProvider2<NodeTypesWithDBAdapter<N, TmpDB>>>,
129 Components: NodeComponents<
130 TmpNodeAdapter<N, BlockchainProvider2<NodeTypesWithDBAdapter<N, TmpDB>>>,
131 Network: PeersHandleProvider,
132 >,
133 >,
134 N::AddOns: RethRpcAddOns<Adapter<N, BlockchainProvider2<NodeTypesWithDBAdapter<N, TmpDB>>>>
135 + EngineValidatorAddOn<
136 Adapter<N, BlockchainProvider2<NodeTypesWithDBAdapter<N, TmpDB>>>,
137 Validator: EngineValidator<N::Engine, Block = reth_primitives::Block>,
138 >,
139 LocalPayloadAttributesBuilder<N::ChainSpec>: PayloadAttributesBuilder<
140 <<N as NodeTypesWithEngine>::Engine as PayloadTypes>::PayloadAttributes,
141 >,
142{
143 let tasks = TaskManager::current();
144 let exec = tasks.executor();
145
146 let network_config = NetworkArgs {
147 discovery: DiscoveryArgs { disable_discovery: true, ..DiscoveryArgs::default() },
148 ..NetworkArgs::default()
149 };
150
151 let mut nodes: Vec<NodeTestContext<_, _>> = Vec::with_capacity(num_nodes);
153
154 for idx in 0..num_nodes {
155 let node_config = NodeConfig::new(chain_spec.clone())
156 .with_network(network_config.clone())
157 .with_unused_ports()
158 .with_rpc(
159 RpcServerArgs::default()
160 .with_unused_ports()
161 .with_http()
162 .with_http_api(RpcModuleSelection::All),
163 )
164 .set_dev(is_dev);
165
166 let span = span!(Level::INFO, "node", idx);
167 let _enter = span.enter();
168 let node = N::default();
169 let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone())
170 .testing_node(exec.clone())
171 .with_types_and_provider::<N, BlockchainProvider2<_>>()
172 .with_components(node.components_builder())
173 .with_add_ons(node.add_ons())
174 .launch_with_fn(|builder| {
175 let launcher = EngineNodeLauncher::new(
176 builder.task_executor().clone(),
177 builder.config().datadir(),
178 Default::default(),
179 );
180 builder.launch_with(launcher)
181 })
182 .await?;
183
184 let mut node = NodeTestContext::new(node, attributes_generator).await?;
185
186 let genesis = node.block_hash(0);
187 node.engine_api.update_forkchoice(genesis, genesis).await?;
188
189 if let Some(previous_node) = nodes.last_mut() {
191 previous_node.connect(&mut node).await;
192 }
193
194 if idx + 1 == num_nodes && num_nodes > 2 {
196 if let Some(first_node) = nodes.first_mut() {
197 node.connect(first_node).await;
198 }
199 }
200
201 nodes.push(node);
202 }
203
204 Ok((nodes, tasks, Wallet::default().with_chain_id(chain_spec.chain().into())))
205}
206
207pub type TmpDB = Arc<TempDatabase<DatabaseEnv>>;
211type TmpNodeAdapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
212 FullNodeTypesAdapter<NodeTypesWithDBAdapter<N, TmpDB>, Provider>;
213
214pub type Adapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> = NodeAdapter<
216 TmpNodeAdapter<N, Provider>,
217 <<N as Node<TmpNodeAdapter<N, Provider>>>::ComponentsBuilder as NodeComponentsBuilder<
218 TmpNodeAdapter<N, Provider>,
219 >>::Components,
220>;
221
222pub type NodeHelperType<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
224 NodeTestContext<Adapter<N, Provider>, <N as Node<TmpNodeAdapter<N, Provider>>>::AddOns>;