Skip to content

Commit

Permalink
fix: replace mainnet TTD so geth mainnet genesis parsing works (#5290)
Browse files Browse the repository at this point in the history
Co-authored-by: Matthias Seitz <[email protected]>
  • Loading branch information
Rjected and mattsse committed Nov 8, 2023
1 parent 693dabb commit 5a822de
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 5 deletions.
36 changes: 31 additions & 5 deletions bin/reth/src/args/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,21 +47,47 @@ pub fn genesis_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, 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:
// <https://github.com/serde-rs/json/blob/4bc1eaa03a6160593575bc9bc60c94dba4cab1e3/src/de.rs#L1411-L1415>
// <https://github.com/serde-rs/json/blob/4bc1eaa03a6160593575bc9bc60c94dba4cab1e3/src/de.rs#L479-L484>
// <https://github.com/serde-rs/json/blob/4bc1eaa03a6160593575bc9bc60c94dba4cab1e3/src/de.rs#L102-L108>
//
// serde_json does have an arbitrary precision feature, but this breaks untagged
// enums in serde:
// <https://github.com/serde-rs/serde/issues/2230>
// <https://github.com/serde-rs/serde/issues/1183>
//
// To solve this, we surround the mainnet TTD with quotes, which our custom Visitor
// accepts.
if raw.contains("58750000000000000000000") &&
!raw.contains("\"58750000000000000000000\"")
{
raw = raw.replacen("58750000000000000000000", "\"58750000000000000000000\"", 1);
}

// both serialized Genesis and ChainSpec structs supported
let genesis: AllGenesisFormats = serde_json::from_str(&raw)?;

Arc::new(genesis.into())
}
})
Expand Down
21 changes: 21 additions & 0 deletions crates/primitives/src/chain/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Address>().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
Expand Down

0 comments on commit 5a822de

Please sign in to comment.