From a1e86f25ce3d612982eb8cf679e5bfb7a5ca8fae Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Fri, 3 Nov 2023 22:14:09 -0400 Subject: [PATCH 1/3] fix: replace mainnet TTD so geth mainnet genesis parsing works --- bin/reth/src/args/utils.rs | 36 +++++++++++++++++++++++++---- crates/primitives/src/chain/spec.rs | 21 +++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/bin/reth/src/args/utils.rs b/bin/reth/src/args/utils.rs index 0f9ef5c6bb8e..a229b0381689 100644 --- a/bin/reth/src/args/utils.rs +++ b/bin/reth/src/args/utils.rs @@ -47,21 +47,47 @@ pub fn genesis_value_parser(s: &str) -> eyre::Result, eyre::Error "holesky" => HOLESKY.clone(), "dev" => DEV.clone(), _ => { - // both serialized Genesis and ChainSpec structs supported - let genesis: AllGenesisFormats = - // try to read json from path first + // try to read json from path first + let mut raw = match fs::read_to_string(PathBuf::from(shellexpand::full(s)?.into_owned())) { - Ok(raw) => serde_json::from_str(&raw)?, + Ok(raw) => raw, Err(io_err) => { // valid json may start with "\n", but must contain "{" if s.contains('{') { - serde_json::from_str(s)? + s.to_string() } else { return Err(io_err.into()) // assume invalid path } } }; + // The ethereum mainnet TTD is 58750000000000000000000, and geth serializes this + // without quotes, because that is how golang `big.Int`s marshal in JSON. Numbers + // are arbitrary precision in JSON, so this is valid JSON. This number is also + // greater than a `u64`. + // + // Unfortunately, serde_json only supports parsing up to `u64`, resorting to `f64` + // once `u64` overflows: + // + // + // + // + // serde_json does have an arbitrary precision feature, but this breaks untagged + // enums in serde: + // + // + // + // To solve this, we surround the mainnet TTD with quotes, which our custom Visitor + // accepts. + if raw.contains("58750000000000000000000") && + !raw.contains("\"58750000000000000000000\"") + { + raw = raw.replace("58750000000000000000000", "\"58750000000000000000000\""); + } + + // both serialized Genesis and ChainSpec structs supported + let genesis: AllGenesisFormats = serde_json::from_str(&raw)?; + Arc::new(genesis.into()) } }) diff --git a/crates/primitives/src/chain/spec.rs b/crates/primitives/src/chain/spec.rs index 81cce105c40c..9cebf52a8367 100644 --- a/crates/primitives/src/chain/spec.rs +++ b/crates/primitives/src/chain/spec.rs @@ -2253,6 +2253,27 @@ Post-merge hard forks (timestamp based): assert_eq!(genesis.config.cancun_time, Some(4661)); } + #[test] + fn test_parse_cancun_genesis_all_formats() { + let s = r#"{"config":{"ethash":{},"chainId":1337,"homesteadBlock":0,"eip150Block":0,"eip155Block":0,"eip158Block":0,"byzantiumBlock":0,"constantinopleBlock":0,"petersburgBlock":0,"istanbulBlock":0,"berlinBlock":0,"londonBlock":0,"terminalTotalDifficulty":0,"terminalTotalDifficultyPassed":true,"shanghaiTime":0,"cancunTime":4661},"nonce":"0x0","timestamp":"0x0","extraData":"0x","gasLimit":"0x4c4b40","difficulty":"0x1","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","coinbase":"0x0000000000000000000000000000000000000000","alloc":{"658bdf435d810c91414ec09147daa6db62406379":{"balance":"0x487a9a304539440000"},"aa00000000000000000000000000000000000000":{"code":"0x6042","storage":{"0x0000000000000000000000000000000000000000000000000000000000000000":"0x0000000000000000000000000000000000000000000000000000000000000000","0x0100000000000000000000000000000000000000000000000000000000000000":"0x0100000000000000000000000000000000000000000000000000000000000000","0x0200000000000000000000000000000000000000000000000000000000000000":"0x0200000000000000000000000000000000000000000000000000000000000000","0x0300000000000000000000000000000000000000000000000000000000000000":"0x0000000000000000000000000000000000000000000000000000000000000303"},"balance":"0x1","nonce":"0x1"},"bb00000000000000000000000000000000000000":{"code":"0x600154600354","storage":{"0x0000000000000000000000000000000000000000000000000000000000000000":"0x0000000000000000000000000000000000000000000000000000000000000000","0x0100000000000000000000000000000000000000000000000000000000000000":"0x0100000000000000000000000000000000000000000000000000000000000000","0x0200000000000000000000000000000000000000000000000000000000000000":"0x0200000000000000000000000000000000000000000000000000000000000000","0x0300000000000000000000000000000000000000000000000000000000000000":"0x0000000000000000000000000000000000000000000000000000000000000303"},"balance":"0x2","nonce":"0x1"}},"number":"0x0","gasUsed":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","baseFeePerGas":"0x3b9aca00"}"#; + let genesis: AllGenesisFormats = serde_json::from_str(s).unwrap(); + + // this should be the genesis format + let genesis = match genesis { + AllGenesisFormats::Geth(genesis) => genesis, + _ => panic!("expected geth genesis format"), + }; + + // assert that the alloc was picked up + let acc = genesis + .alloc + .get(&"0xaa00000000000000000000000000000000000000".parse::
().unwrap()) + .unwrap(); + assert_eq!(acc.balance, U256::from(1)); + // assert that the cancun time was picked up + assert_eq!(genesis.config.cancun_time, Some(4661)); + } + #[test] fn test_default_cancun_header_forkhash() { // set the gas limit from the hive test genesis according to the hash From a726e2a0964d92110d219d93fff816077d75fbf8 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sat, 4 Nov 2023 06:57:30 +0100 Subject: [PATCH 2/3] Update bin/reth/src/args/utils.rs --- bin/reth/src/args/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/reth/src/args/utils.rs b/bin/reth/src/args/utils.rs index a229b0381689..2d3c3b43bd5d 100644 --- a/bin/reth/src/args/utils.rs +++ b/bin/reth/src/args/utils.rs @@ -82,7 +82,7 @@ pub fn genesis_value_parser(s: &str) -> eyre::Result, eyre::Error if raw.contains("58750000000000000000000") && !raw.contains("\"58750000000000000000000\"") { - raw = raw.replace("58750000000000000000000", "\"58750000000000000000000\""); + raw = raw.replacen("58750000000000000000000", "\"58750000000000000000000\"",1); } // both serialized Genesis and ChainSpec structs supported From 29b634e321253d7f318bdb2fc19c0929e218a32d Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sat, 4 Nov 2023 07:00:06 +0100 Subject: [PATCH 3/3] rustfmt --- bin/reth/src/args/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/reth/src/args/utils.rs b/bin/reth/src/args/utils.rs index 2d3c3b43bd5d..ab195311088b 100644 --- a/bin/reth/src/args/utils.rs +++ b/bin/reth/src/args/utils.rs @@ -82,7 +82,7 @@ pub fn genesis_value_parser(s: &str) -> eyre::Result, eyre::Error if raw.contains("58750000000000000000000") && !raw.contains("\"58750000000000000000000\"") { - raw = raw.replacen("58750000000000000000000", "\"58750000000000000000000\"",1); + raw = raw.replacen("58750000000000000000000", "\"58750000000000000000000\"", 1); } // both serialized Genesis and ChainSpec structs supported