Skip to main content

reth_e2e_test_utils/
chain_spec.rs

1//! Chain specifications and payload attributes for test nodes.
2
3use alloy_genesis::Genesis;
4use alloy_primitives::{Address, B256};
5use alloy_rpc_types_engine::PayloadAttributes;
6use reth_chainspec::{ChainSpec, ChainSpecBuilder, EthereumHardfork, EthereumHardforks, MAINNET};
7use std::sync::Arc;
8
9/// Returns the genesis of the test chain.
10///
11/// The genesis funds the first 20 accounts derived from the test mnemonic, see
12/// [`Wallet`](crate::wallet::Wallet).
13pub fn test_genesis() -> Genesis {
14    serde_json::from_str(include_str!("testsuite/assets/genesis.json"))
15        .expect("failed to parse test genesis")
16}
17
18/// Returns a [`ChainSpecBuilder`] for the mainnet chain id with the [`test_genesis`] and no
19/// hardforks activated.
20///
21/// Use this to schedule hardforks at non-genesis timestamps, otherwise prefer
22/// [`test_chain_spec`].
23pub fn test_chain_spec_builder() -> ChainSpecBuilder {
24    ChainSpecBuilder::default().chain(MAINNET.chain).genesis(test_genesis())
25}
26
27/// Returns the test chain spec with every hardfork up to and including `fork` active at genesis.
28///
29/// # Panics
30///
31/// If `fork` can not be activated at genesis via [`ChainSpecBuilder`].
32pub fn test_chain_spec(fork: EthereumHardfork) -> Arc<ChainSpec> {
33    let builder = test_chain_spec_builder();
34    let builder = match fork {
35        EthereumHardfork::Frontier => builder.frontier_activated(),
36        EthereumHardfork::Homestead => builder.homestead_activated(),
37        EthereumHardfork::Dao => builder.dao_activated(),
38        EthereumHardfork::Tangerine => builder.tangerine_whistle_activated(),
39        EthereumHardfork::SpuriousDragon => builder.spurious_dragon_activated(),
40        EthereumHardfork::Byzantium => builder.byzantium_activated(),
41        EthereumHardfork::Constantinople => builder.constantinople_activated(),
42        EthereumHardfork::Petersburg => builder.petersburg_activated(),
43        EthereumHardfork::Istanbul => builder.istanbul_activated(),
44        EthereumHardfork::MuirGlacier => builder.muirglacier_activated(),
45        EthereumHardfork::Berlin => builder.berlin_activated(),
46        EthereumHardfork::London => builder.london_activated(),
47        EthereumHardfork::ArrowGlacier => builder.arrowglacier_activated(),
48        EthereumHardfork::GrayGlacier => builder.grayglacier_activated(),
49        EthereumHardfork::Paris => builder.paris_activated(),
50        EthereumHardfork::Shanghai => builder.shanghai_activated(),
51        EthereumHardfork::Cancun => builder.cancun_activated(),
52        EthereumHardfork::Prague => builder.prague_activated(),
53        EthereumHardfork::Osaka => builder.osaka_activated(),
54        EthereumHardfork::Amsterdam => builder.amsterdam_activated(),
55        EthereumHardfork::Bogota => builder.bogota_activated(),
56        fork => panic!("{fork} can not be activated at genesis"),
57    };
58    Arc::new(builder.build())
59}
60
61/// Creates Ethereum [`PayloadAttributes`] that are valid for the hardforks active in `chain_spec`
62/// at `timestamp`.
63///
64/// Withdrawals are set once Shanghai is active, the parent beacon block root once Cancun is
65/// active, and a slot number once Amsterdam is active. The payload builder requires a slot number
66/// for EIP-7843; tests use the timestamp as a deterministic dummy slot because the exact beacon
67/// slot is irrelevant for local e2e payloads.
68///
69/// This is the default attributes generator of [`E2ETestSetupBuilder`](crate::E2ETestSetupBuilder),
70/// so the same test works against any hardfork schedule, including forks activating mid-test.
71pub fn eth_payload_attributes<C: EthereumHardforks>(
72    chain_spec: &C,
73    timestamp: u64,
74) -> PayloadAttributes {
75    PayloadAttributes {
76        timestamp,
77        prev_randao: B256::ZERO,
78        suggested_fee_recipient: Address::ZERO,
79        withdrawals: chain_spec.is_shanghai_active_at_timestamp(timestamp).then(Vec::new),
80        parent_beacon_block_root: chain_spec
81            .is_cancun_active_at_timestamp(timestamp)
82            .then_some(B256::ZERO),
83        slot_number: chain_spec.is_amsterdam_active_at_timestamp(timestamp).then_some(timestamp),
84        ..Default::default()
85    }
86}