reth_seismic_chainspec/
lib.rs

1//! Seismic-Reth chain specs.
2
3#![doc(
4    html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
5    html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
6    issue_tracker_base_url = "https://github.com/SeismicSystems/seismic-reth/issues/"
7)]
8#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
9#![cfg_attr(not(feature = "std"), no_std)]
10
11use std::sync::Arc;
12
13use alloy_chains::Chain;
14use alloy_consensus::constants::DEV_GENESIS_HASH;
15use alloy_primitives::{b256, B256, U256};
16use reth_chainspec::{make_genesis_header, ChainSpec, DEV_HARDFORKS};
17use reth_primitives_traits::{sync::LazyLock, SealedHeader};
18use reth_seismic_forks::{SEISMIC_DEV_HARDFORKS, SEISMIC_MAINNET_HARDFORKS};
19
20/// Genesis hash for the Seismic mainnet
21/// Calculated by rlp encoding the genesis header and hashing it
22pub const SEISMIC_MAINNET_GENESIS_HASH: B256 =
23    b256!("0xd548d4a126d72e43d893b3826c07ad24bddbaeee267489baff2f73fff2ac0976");
24
25/// Genesis hash for the Seismic devnet
26/// Calculated by rlp encoding the genesis header and hashing it
27/// Currently matches the mainnet genesis hash because they have matching hardforks
28pub const SEISMIC_DEV_GENESIS_HASH: B256 =
29    b256!("0x655cc1ecc77fe1eab4b1e62a1f461b7fddc9b06109b5ab3e9dc68c144b30c773");
30
31/// Seismic devnet specification
32pub static SEISMIC_DEV: LazyLock<Arc<ChainSpec>> = LazyLock::new(|| {
33    let genesis = serde_json::from_str(include_str!("../res/genesis/dev.json"))
34        .expect("Can't deserialize Dev testnet genesis json");
35    let hardforks = SEISMIC_DEV_HARDFORKS.clone();
36    ChainSpec {
37        chain: Chain::from_id(5124),
38        genesis_header: SealedHeader::new(
39            make_genesis_header(&genesis, &hardforks),
40            SEISMIC_DEV_GENESIS_HASH,
41        ),
42        genesis,
43        paris_block_and_final_difficulty: Some((0, U256::from(0))),
44        hardforks: DEV_HARDFORKS.clone(),
45        ..Default::default()
46    }
47    .into()
48});
49
50// TODO: remove this once we launch devnet with consensus
51/// Seismic old devnet specification
52pub static SEISMIC_DEV_OLD: LazyLock<Arc<ChainSpec>> = LazyLock::new(|| {
53    let genesis = serde_json::from_str(include_str!("../res/genesis/dev.json"))
54        .expect("Can't deserialize Dev testnet genesis json");
55    let hardforks = SEISMIC_DEV_HARDFORKS.clone();
56    ChainSpec {
57        chain: Chain::from_id(5124),
58        genesis_header: SealedHeader::new(
59            make_genesis_header(&genesis, &hardforks),
60            DEV_GENESIS_HASH,
61        ),
62        genesis,
63        paris_block_and_final_difficulty: Some((0, U256::from(0))),
64        hardforks: DEV_HARDFORKS.clone(),
65        ..Default::default()
66    }
67    .into()
68});
69
70/// Seismic Mainnet
71pub static SEISMIC_MAINNET: LazyLock<Arc<ChainSpec>> = LazyLock::new(|| {
72    let genesis = serde_json::from_str(include_str!("../res/genesis/mainnet.json"))
73        .expect("Can't deserialize Mainnet genesis json");
74    let hardforks = SEISMIC_MAINNET_HARDFORKS.clone();
75    let mut spec = ChainSpec {
76        chain: Chain::from_id(5123),
77        genesis_header: SealedHeader::new(
78            make_genesis_header(&genesis, &hardforks),
79            SEISMIC_MAINNET_GENESIS_HASH,
80        ),
81        genesis,
82        paris_block_and_final_difficulty: Some((0, U256::from(0))),
83        hardforks,
84        ..Default::default()
85    };
86    spec.genesis.config.dao_fork_support = true;
87    spec.into()
88});
89
90/// Returns `true` if the given chain is a seismic chain.
91pub fn is_chain_seismic(chain: &Chain) -> bool {
92    chain.id() == SEISMIC_MAINNET.chain.id() || chain.id() == SEISMIC_DEV.chain.id()
93}
94
95#[cfg(test)]
96mod tests {
97    use crate::*;
98    use alloy_consensus::constants::MAINNET_GENESIS_HASH;
99    use reth_chainspec::MAINNET;
100    use reth_ethereum_forks::EthereumHardfork;
101    use reth_seismic_forks::SeismicHardfork;
102
103    #[test]
104    fn seismic_mainnet_genesis() {
105        let genesis = SEISMIC_MAINNET.genesis_header();
106        let eth_genesis = MAINNET.genesis_header();
107        assert_ne!(
108            genesis.hash_slow(),
109            eth_genesis.hash_slow(),
110            "Seismic spec should not match eth genesis"
111        );
112        assert_eq!(
113            genesis.hash_slow(),
114            SEISMIC_MAINNET_GENESIS_HASH,
115            "Seismic spec has correct genesis hash"
116        );
117    }
118
119    // Test that the latest fork id is the latest seismic fork (mercury)
120    #[test]
121    fn latest_seismic_mainnet_fork_id_with_builder() {
122        let seismic_mainnet = &SEISMIC_MAINNET;
123        assert_eq!(
124            seismic_mainnet.hardfork_fork_id(SeismicHardfork::Mercury).unwrap(),
125            seismic_mainnet.latest_fork_id()
126        )
127    }
128
129    // Check display contains all eth mainnet hardforks and the seismic mercury fork
130    #[test]
131    fn display_hardforks() {
132        let content = SEISMIC_MAINNET.display_hardforks().to_string();
133        let eth_mainnet = EthereumHardfork::mainnet();
134        for (eth_hf, _) in eth_mainnet {
135            assert!(content.contains(eth_hf.name()), "missing hardfork {eth_hf}");
136        }
137        assert!(content.contains("Mercury"));
138    }
139
140    #[test]
141    fn genesis_header_hash() {
142        // Confirm how eth mainnet genesis header hash is calculated
143        let expected = MAINNET_GENESIS_HASH;
144        let genesis =
145            serde_json::from_str(include_str!("../../../chainspec/res/genesis/mainnet.json"))
146                .expect("Can't deserialize Mainnet genesis json");
147        let hardforks = EthereumHardfork::mainnet().into();
148        let genesis_header = make_genesis_header(&genesis, &hardforks);
149        let actual_hash = genesis_header.hash_slow();
150        assert_eq!(actual_hash, expected);
151
152        // Confirm seismic mainnet genesis header hash is calculated correctly
153        let expected = SEISMIC_MAINNET_GENESIS_HASH;
154        let genesis = serde_json::from_str(include_str!("../res/genesis/mainnet.json")) // note: same as Ethereum, needs to be updated before launch
155            .expect("Can't deserialize Seismic Mainnet genesis json");
156        let hardforks = SEISMIC_MAINNET_HARDFORKS.clone();
157        let genesis_header = make_genesis_header(&genesis, &hardforks);
158        let actual_hash = genesis_header.hash_slow();
159        assert_eq!(actual_hash, expected);
160
161        // Confirm seismic devnet genesis header hash is calculated correctly
162        let expected = SEISMIC_DEV_GENESIS_HASH;
163        let genesis = serde_json::from_str(include_str!("../res/genesis/dev.json"))
164            .expect("Can't deserialize Seismic devnet genesis json");
165        let hardforks = SEISMIC_DEV_HARDFORKS.clone();
166        let genesis_header = make_genesis_header(&genesis, &hardforks);
167        let actual_hash = genesis_header.hash_slow();
168        assert_eq!(actual_hash, expected);
169    }
170}