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