Skip to main content

reth_e2e_test_utils/
lib.rs

1//! Utilities for end-to-end tests.
2
3use alloy_primitives::{Address, B256};
4use alloy_rpc_types_engine::PayloadAttributes;
5use node::NodeTestContext;
6use reth_chainspec::{ChainSpec, EthereumHardfork};
7use reth_db::{test_utils::TempDatabase, DatabaseEnv};
8use reth_network_api::test_utils::PeersHandleProvider;
9use reth_node_builder::{
10    components::NodeComponentsBuilder,
11    rpc::{EngineValidatorAddOn, RethRpcAddOns},
12    FullNodeTypesAdapter, Node, NodeAdapter, NodeComponents, NodeTypes, NodeTypesWithDBAdapter,
13    PayloadTypes,
14};
15use reth_provider::providers::{BlockchainProvider, NodeTypesForProvider};
16use std::sync::Arc;
17use wallet::Wallet;
18
19/// Wrapper type to create test nodes
20pub mod node;
21pub mod testsuite;
22
23/// Helper for transaction operations
24pub mod transaction;
25
26/// Helper type to yield accounts from mnemonic
27pub mod wallet;
28
29/// Helper for payload operations
30mod payload;
31
32/// Helper for setting up nodes with pre-imported chain data
33pub mod setup_import;
34
35/// Helper for network operations
36mod network;
37
38/// Helper for rpc operations
39mod rpc;
40
41/// Utilities for creating and writing RLP test data
42pub mod test_rlp_utils;
43
44/// Helpers for verifying the persisted state and trie representation
45pub mod trie;
46
47/// Builder for configuring test node setups
48mod setup_builder;
49pub use setup_builder::E2ETestSetupBuilder;
50
51/// Creates the initial setup with `num_nodes` started and interconnected.
52pub async fn setup<N>(
53    num_nodes: usize,
54    chain_spec: Arc<N::ChainSpec>,
55    is_dev: bool,
56    attributes_generator: impl Fn(u64) -> <<N as NodeTypes>::Payload as PayloadTypes>::PayloadAttributes
57        + Send
58        + Sync
59        + Copy
60        + 'static,
61) -> eyre::Result<(Vec<NodeHelperType<N>>, Wallet)>
62where
63    N: NodeBuilderHelper,
64{
65    E2ETestSetupBuilder::new(num_nodes, chain_spec, attributes_generator)
66        .with_node_config_modifier(move |config| config.set_dev(is_dev))
67        .build()
68        .await
69}
70
71/// Creates the initial setup with `num_nodes` started and interconnected.
72pub async fn setup_engine<N>(
73    num_nodes: usize,
74    chain_spec: Arc<N::ChainSpec>,
75    is_dev: bool,
76    tree_config: reth_node_api::TreeConfig,
77    attributes_generator: impl Fn(u64) -> <<N as NodeTypes>::Payload as PayloadTypes>::PayloadAttributes
78        + Send
79        + Sync
80        + Copy
81        + 'static,
82) -> eyre::Result<(
83    Vec<NodeHelperType<N, BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>>>,
84    Wallet,
85)>
86where
87    N: NodeBuilderHelper,
88{
89    setup_engine_with_connection::<N>(
90        num_nodes,
91        chain_spec,
92        is_dev,
93        tree_config,
94        attributes_generator,
95        true,
96    )
97    .await
98}
99
100/// Creates the initial setup with `num_nodes` started and optionally interconnected.
101pub async fn setup_engine_with_connection<N>(
102    num_nodes: usize,
103    chain_spec: Arc<N::ChainSpec>,
104    is_dev: bool,
105    tree_config: reth_node_api::TreeConfig,
106    attributes_generator: impl Fn(u64) -> <<N as NodeTypes>::Payload as PayloadTypes>::PayloadAttributes
107        + Send
108        + Sync
109        + Copy
110        + 'static,
111    connect_nodes: bool,
112) -> eyre::Result<(
113    Vec<NodeHelperType<N, BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>>>,
114    Wallet,
115)>
116where
117    N: NodeBuilderHelper,
118{
119    E2ETestSetupBuilder::new(num_nodes, chain_spec, attributes_generator)
120        .with_tree_config_modifier(move |base| {
121            // Apply caller's tree_config but preserve the small cache size from base
122            tree_config.clone().with_cross_block_cache_size(base.cross_block_cache_size())
123        })
124        .with_node_config_modifier(move |config| config.set_dev(is_dev))
125        .with_connect_nodes(connect_nodes)
126        .build()
127        .await
128}
129
130/// Creates Ethereum [`PayloadAttributes`] valid for the given hardfork, allowing the same test
131/// to be run against multiple hardfork targets.
132///
133/// Withdrawals are set once Shanghai is active, the parent beacon block root once Cancun is
134/// active, and a slot number once Amsterdam is active. The payload builder requires a slot number
135/// for EIP-7843; tests use the timestamp as a deterministic dummy slot because the exact beacon
136/// slot is irrelevant for local e2e payloads.
137pub fn eth_payload_attributes_for_fork(
138    fork: EthereumHardfork,
139    timestamp: u64,
140) -> PayloadAttributes {
141    PayloadAttributes {
142        timestamp,
143        prev_randao: B256::ZERO,
144        suggested_fee_recipient: Address::ZERO,
145        withdrawals: (fork >= EthereumHardfork::Shanghai).then(Vec::new),
146        parent_beacon_block_root: (fork >= EthereumHardfork::Cancun).then_some(B256::ZERO),
147        slot_number: (fork >= EthereumHardfork::Amsterdam).then_some(timestamp),
148        ..Default::default()
149    }
150}
151
152// Type aliases
153
154/// Testing database
155pub type TmpDB = Arc<TempDatabase<DatabaseEnv>>;
156type TmpNodeAdapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
157    FullNodeTypesAdapter<N, TmpDB, Provider>;
158
159/// Type alias for a `NodeAdapter`
160pub type Adapter<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> = NodeAdapter<
161    TmpNodeAdapter<N, Provider>,
162    <<N as Node<TmpNodeAdapter<N, Provider>>>::ComponentsBuilder as NodeComponentsBuilder<
163        TmpNodeAdapter<N, Provider>,
164    >>::Components,
165>;
166
167/// Type alias for a type of `NodeHelper`
168pub type NodeHelperType<N, Provider = BlockchainProvider<NodeTypesWithDBAdapter<N, TmpDB>>> =
169    NodeTestContext<Adapter<N, Provider>, <N as Node<TmpNodeAdapter<N, Provider>>>::AddOns>;
170
171/// Helper trait to simplify bounds when calling setup functions.
172pub trait NodeBuilderHelper
173where
174    Self: Default
175        + NodeTypesForProvider<Payload: PayloadTypes<PayloadAttributes: From<PayloadAttributes>>>
176        + Node<
177            TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
178            ComponentsBuilder: NodeComponentsBuilder<
179                TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
180                Components: NodeComponents<
181                    TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
182                    Network: PeersHandleProvider,
183                >,
184            >,
185            AddOns: RethRpcAddOns<
186                Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
187            > + EngineValidatorAddOn<
188                Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
189            >,
190            ChainSpec: From<ChainSpec> + Clone,
191        >,
192{
193}
194
195impl<T> NodeBuilderHelper for T where
196    Self: Default
197        + NodeTypesForProvider<Payload: PayloadTypes<PayloadAttributes: From<PayloadAttributes>>>
198        + Node<
199            TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
200            ComponentsBuilder: NodeComponentsBuilder<
201                TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
202                Components: NodeComponents<
203                    TmpNodeAdapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
204                    Network: PeersHandleProvider,
205                >,
206            >,
207            AddOns: RethRpcAddOns<
208                Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
209            > + EngineValidatorAddOn<
210                Adapter<Self, BlockchainProvider<NodeTypesWithDBAdapter<Self, TmpDB>>>,
211            >,
212            ChainSpec: From<ChainSpec> + Clone,
213        >
214{
215}