reth_ethereum_cli/
chainspec.rs
1use reth_chainspec::{ChainSpec, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA};
2use reth_cli::chainspec::{parse_genesis, ChainSpecParser};
3use std::sync::Arc;
4
5pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "holesky", "hoodi", "dev"];
7
8pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error> {
13 Ok(match s {
14 "mainnet" => MAINNET.clone(),
15 "sepolia" => SEPOLIA.clone(),
16 "holesky" => HOLESKY.clone(),
17 "hoodi" => HOODI.clone(),
18 "dev" => DEV.clone(),
19 _ => Arc::new(parse_genesis(s)?.into()),
20 })
21}
22
23#[derive(Debug, Clone, Default)]
25#[non_exhaustive]
26pub struct EthereumChainSpecParser;
27
28impl ChainSpecParser for EthereumChainSpecParser {
29 type ChainSpec = ChainSpec;
30
31 const SUPPORTED_CHAINS: &'static [&'static str] = SUPPORTED_CHAINS;
32
33 fn parse(s: &str) -> eyre::Result<Arc<ChainSpec>> {
34 chain_value_parser(s)
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41 use reth_chainspec::EthereumHardforks;
42
43 #[test]
44 fn parse_known_chain_spec() {
45 for &chain in EthereumChainSpecParser::SUPPORTED_CHAINS {
46 assert!(<EthereumChainSpecParser as ChainSpecParser>::parse(chain).is_ok());
47 }
48 }
49
50 #[test]
51 fn parse_raw_chainspec_hardforks() {
52 let s = r#"{
53 "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
54 "uncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
55 "coinbase": "0x0000000000000000000000000000000000000000",
56 "stateRoot": "0x76f118cb05a8bc558388df9e3b4ad66ae1f17ef656e5308cb8f600717251b509",
57 "transactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
58 "receiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
59 "bloom": "0x000...000",
60 "difficulty": "0x00",
61 "number": "0x00",
62 "gasLimit": "0x016345785d8a0000",
63 "gasUsed": "0x00",
64 "timestamp": "0x01",
65 "extraData": "0x00",
66 "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
67 "nonce": "0x0000000000000000",
68 "baseFeePerGas": "0x07",
69 "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
70 "blobGasUsed": "0x00",
71 "excessBlobGas": "0x00",
72 "parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
73 "requestsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
74 "hash": "0xc20e1a771553139cdc77e6c3d5f64a7165d972d327eee9632c9c7d0fe839ded4",
75 "alloc": {},
76 "config": {
77 "ethash": {},
78 "chainId": 1,
79 "homesteadBlock": 0,
80 "daoForkSupport": true,
81 "eip150Block": 0,
82 "eip155Block": 0,
83 "eip158Block": 0,
84 "byzantiumBlock": 0,
85 "constantinopleBlock": 0,
86 "petersburgBlock": 0,
87 "istanbulBlock": 0,
88 "berlinBlock": 0,
89 "londonBlock": 0,
90 "terminalTotalDifficulty": 0,
91 "shanghaiTime": 0,
92 "cancunTime": 0,
93 "pragueTime": 0,
94 "osakaTime": 0
95 }
96}"#;
97
98 let spec = <EthereumChainSpecParser as ChainSpecParser>::parse(s).unwrap();
99 assert!(spec.is_shanghai_active_at_timestamp(0));
100 assert!(spec.is_cancun_active_at_timestamp(0));
101 assert!(spec.is_prague_active_at_timestamp(0));
102 assert!(spec.is_osaka_active_at_timestamp(0));
103 }
104}