//! Utilities for end-to-end tests. use node::NodeTestContext; use reth_chainspec::EthChainSpec; use reth_db::{test_utils::TempDatabase, DatabaseEnv}; use reth_engine_local::LocalPayloadAttributesBuilder; use reth_network_api::test_utils::PeersHandleProvider; use reth_node_builder::{ components::NodeComponentsBuilder, rpc::{EngineValidatorAddOn, RethRpcAddOns}, EngineNodeLauncher, FullNodeTypesAdapter, Node, NodeAdapter, NodeBuilder, NodeComponents, NodeConfig, NodeHandle, NodeTypesWithDBAdapter, NodeTypesWithEngine, PayloadAttributesBuilder, PayloadTypes, }; use reth_node_core::args::{DiscoveryArgs, NetworkArgs, RpcServerArgs}; use reth_provider::providers::{BlockchainProvider2, NodeTypesForProvider, NodeTypesForTree}; use reth_rpc_server_types::RpcModuleSelection; use reth_tasks::TaskManager; use std::sync::Arc; use tracing::{span, Level}; use wallet::Wallet; /// Wrapper type to create test nodes pub mod node; /// Helper for transaction operations pub mod transaction; /// Helper type to yield accounts from mnemonic pub mod wallet; /// Helper for payload operations mod payload; /// Helper for network operations mod network; /// Helper for engine api operations mod engine_api; /// Helper for rpc operations mod rpc; /// Helper traits mod traits; /// Creates the initial setup with `num_nodes` started and interconnected. pub async fn setup( num_nodes: usize, chain_spec: Arc, is_dev: bool, attributes_generator: impl Fn(u64) -> <::Engine as PayloadTypes>::PayloadBuilderAttributes + Copy + 'static, ) -> eyre::Result<(Vec>, TaskManager, Wallet)> where N: Default + Node> + NodeTypesForTree + NodeTypesWithEngine, N::ComponentsBuilder: NodeComponentsBuilder< TmpNodeAdapter, Components: NodeComponents, Network: PeersHandleProvider>, >, N::AddOns: RethRpcAddOns> + EngineValidatorAddOn>, LocalPayloadAttributesBuilder: PayloadAttributesBuilder< <::Engine as PayloadTypes>::PayloadAttributes, >, { let tasks = TaskManager::current(); let exec = tasks.executor(); let network_config = NetworkArgs { discovery: DiscoveryArgs { disable_discovery: true, ..DiscoveryArgs::default() }, ..NetworkArgs::default() }; // Create nodes and peer them let mut nodes: Vec> = Vec::with_capacity(num_nodes); for idx in 0..num_nodes { let node_config = NodeConfig::new(chain_spec.clone()) .with_network(network_config.clone()) .with_unused_ports() .with_rpc(RpcServerArgs::default().with_unused_ports().with_http()) .set_dev(is_dev); let span = span!(Level::INFO, "node", idx); let _enter = span.enter(); let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone()) .testing_node(exec.clone()) .node(Default::default()) .launch() .await?; let mut node = NodeTestContext::new(node, attributes_generator).await?; // Connect each node in a chain. if let Some(previous_node) = nodes.last_mut() { previous_node.connect(&mut node).await; } // Connect last node with the first if there are more than two if idx + 1 == num_nodes && num_nodes > 2 { if let Some(first_node) = nodes.first_mut() { node.connect(first_node).await; } } nodes.push(node); } Ok((nodes, tasks, Wallet::default().with_chain_id(chain_spec.chain().into()))) } /// Creates the initial setup with `num_nodes` started and interconnected. pub async fn setup_engine( num_nodes: usize, chain_spec: Arc, is_dev: bool, attributes_generator: impl Fn(u64) -> <::Engine as PayloadTypes>::PayloadBuilderAttributes + Copy + 'static, ) -> eyre::Result<( Vec>>>, TaskManager, Wallet, )> where N: Default + Node>>> + NodeTypesWithEngine + NodeTypesForProvider, N::ComponentsBuilder: NodeComponentsBuilder< TmpNodeAdapter>>, Components: NodeComponents< TmpNodeAdapter>>, Network: PeersHandleProvider, >, >, N::AddOns: RethRpcAddOns>>> + EngineValidatorAddOn>>>, LocalPayloadAttributesBuilder: PayloadAttributesBuilder< <::Engine as PayloadTypes>::PayloadAttributes, >, { let tasks = TaskManager::current(); let exec = tasks.executor(); let network_config = NetworkArgs { discovery: DiscoveryArgs { disable_discovery: true, ..DiscoveryArgs::default() }, ..NetworkArgs::default() }; // Create nodes and peer them let mut nodes: Vec> = Vec::with_capacity(num_nodes); for idx in 0..num_nodes { let node_config = NodeConfig::new(chain_spec.clone()) .with_network(network_config.clone()) .with_unused_ports() .with_rpc( RpcServerArgs::default() .with_unused_ports() .with_http() .with_http_api(RpcModuleSelection::All), ) .set_dev(is_dev); let span = span!(Level::INFO, "node", idx); let _enter = span.enter(); let node = N::default(); let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone()) .testing_node(exec.clone()) .with_types_and_provider::>() .with_components(node.components_builder()) .with_add_ons(node.add_ons()) .launch_with_fn(|builder| { let launcher = EngineNodeLauncher::new( builder.task_executor().clone(), builder.config().datadir(), Default::default(), ); builder.launch_with(launcher) }) .await?; let mut node = NodeTestContext::new(node, attributes_generator).await?; let genesis = node.block_hash(0); node.engine_api.update_forkchoice(genesis, genesis).await?; // Connect each node in a chain. if let Some(previous_node) = nodes.last_mut() { previous_node.connect(&mut node).await; } // Connect last node with the first if there are more than two if idx + 1 == num_nodes && num_nodes > 2 { if let Some(first_node) = nodes.first_mut() { node.connect(first_node).await; } } nodes.push(node); } Ok((nodes, tasks, Wallet::default().with_chain_id(chain_spec.chain().into()))) } // Type aliases /// Testing database pub type TmpDB = Arc>; type TmpNodeAdapter>> = FullNodeTypesAdapter; /// Type alias for a `NodeAdapter` pub type Adapter>> = NodeAdapter< TmpNodeAdapter, <>>::ComponentsBuilder as NodeComponentsBuilder< TmpNodeAdapter, >>::Components, >; /// Type alias for a type of `NodeHelper` pub type NodeHelperType>> = NodeTestContext, >>::AddOns>;