fix(primitives): write withdrawal hash at genesis (#1654)

This commit is contained in:
Dan Cline
2023-03-08 11:30:50 -05:00
committed by GitHub
parent 161de9aadf
commit 9e1c341e16
4 changed files with 57 additions and 6 deletions

View File

@ -42,15 +42,16 @@ pub struct InitCommand {
impl InitCommand { impl InitCommand {
/// Execute the `init` command /// Execute the `init` command
pub async fn execute(&self) -> eyre::Result<()> { pub async fn execute(&self) -> eyre::Result<()> {
info!(target: "reth::cli", "reth import starting"); info!(target: "reth::cli", "reth init starting");
info!(target: "reth::cli", path = %self.db, "Opening database"); info!(target: "reth::cli", path = %self.db, "Opening database");
let db = Arc::new(init_db(&self.db)?); let db = Arc::new(init_db(&self.db)?);
info!(target: "reth::cli", "Database opened"); info!(target: "reth::cli", "Database opened");
info!(target: "reth::cli", "Writing genesis block"); info!(target: "reth::cli", "Writing genesis block");
init_genesis(db, self.chain.clone())?; let hash = init_genesis(db, self.chain.clone())?;
info!(target: "reth::cli", hash = ?hash, "Genesis block written");
Ok(()) Ok(())
} }
} }

View File

@ -1,7 +1,10 @@
use crate::{ use crate::{
constants::EIP1559_INITIAL_BASE_FEE, forkid::ForkFilterKey, header::Head, constants::{EIP1559_INITIAL_BASE_FEE, EMPTY_WITHDRAWALS},
proofs::genesis_state_root, BlockNumber, Chain, ForkFilter, ForkHash, ForkId, Genesis, forkid::ForkFilterKey,
GenesisAccount, Hardfork, Header, H160, H256, U256, header::Head,
proofs::genesis_state_root,
BlockNumber, Chain, ForkFilter, ForkHash, ForkId, Genesis, GenesisAccount, Hardfork, Header,
H160, H256, U256,
}; };
use ethers_core::utils::Genesis as EthersGenesis; use ethers_core::utils::Genesis as EthersGenesis;
use hex_literal::hex; use hex_literal::hex;
@ -142,6 +145,15 @@ impl ChainSpec {
None None
}; };
// If shanghai is activated, initialize the header with an empty withdrawals hash, and
// empty withdrawals list.
let withdrawals_root =
if self.fork(Hardfork::Shanghai).active_at_timestamp(self.genesis.timestamp) {
Some(EMPTY_WITHDRAWALS)
} else {
None
};
Header { Header {
gas_limit: self.genesis.gas_limit, gas_limit: self.genesis.gas_limit,
difficulty: self.genesis.difficulty, difficulty: self.genesis.difficulty,
@ -152,6 +164,7 @@ impl ChainSpec {
mix_hash: self.genesis.mix_hash, mix_hash: self.genesis.mix_hash,
beneficiary: self.genesis.coinbase, beneficiary: self.genesis.coinbase,
base_fee_per_gas, base_fee_per_gas,
withdrawals_root,
..Default::default() ..Default::default()
} }
} }
@ -587,7 +600,9 @@ mod tests {
AllGenesisFormats, Chain, ChainSpec, ChainSpecBuilder, ForkCondition, ForkHash, ForkId, AllGenesisFormats, Chain, ChainSpec, ChainSpecBuilder, ForkCondition, ForkHash, ForkId,
Genesis, Hardfork, Head, GOERLI, H256, MAINNET, SEPOLIA, U256, Genesis, Hardfork, Head, GOERLI, H256, MAINNET, SEPOLIA, U256,
}; };
use bytes::BytesMut;
use ethers_core::types as EtherType; use ethers_core::types as EtherType;
use reth_rlp::Encodable;
fn test_fork_ids(spec: &ChainSpec, cases: &[(Head, ForkId)]) { fn test_fork_ids(spec: &ChainSpec, cases: &[(Head, ForkId)]) {
for (block, expected_id) in cases { for (block, expected_id) in cases {
let computed_id = spec.fork_id(block); let computed_id = spec.fork_id(block);
@ -1025,6 +1040,37 @@ mod tests {
chainspec.hardforks.get(&Hardfork::Shanghai).unwrap(), chainspec.hardforks.get(&Hardfork::Shanghai).unwrap(),
&ForkCondition::Timestamp(0) &ForkCondition::Timestamp(0)
); );
// alloc key -> expected rlp mapping
let key_rlp = vec![
(hex_literal::hex!("658bdf435d810c91414ec09147daa6db62406379"), "f84d8089487a9a304539440000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"),
(hex_literal::hex!("aa00000000000000000000000000000000000000"), "f8440101a08afc95b7d18a226944b9c2070b6bda1c3a36afcc3730429d47579c94b9fe5850a0ce92c756baff35fa740c3557c1a971fd24d2d35b7c8e067880d50cd86bb0bc99"),
(hex_literal::hex!("bb00000000000000000000000000000000000000"), "f8440102a08afc95b7d18a226944b9c2070b6bda1c3a36afcc3730429d47579c94b9fe5850a0e25a53cbb501cec2976b393719c63d832423dd70a458731a0b64e4847bbca7d2"),
];
for (key, expected_rlp) in key_rlp {
let account = chainspec.genesis.alloc.get(&key.into()).expect("account should exist");
let mut account_rlp = BytesMut::new();
account.encode(&mut account_rlp);
assert_eq!(hex::encode(account_rlp), expected_rlp)
}
assert_eq!(chainspec.genesis_hash, None);
let expected_state_root: H256 =
hex_literal::hex!("078dc6061b1d8eaa8493384b59c9c65ceb917201221d08b80c4de6770b6ec7e7")
.into();
assert_eq!(chainspec.genesis_header().state_root, expected_state_root);
let expected_withdrawals_hash: H256 =
hex_literal::hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
.into();
assert_eq!(chainspec.genesis_header().withdrawals_root, Some(expected_withdrawals_hash));
let expected_hash: H256 =
hex_literal::hex!("1fc027d65f820d3eef441ebeec139ebe09e471cf98516dce7b5643ccb27f418c")
.into();
let hash = chainspec.genesis_hash();
assert_eq!(hash, expected_hash);
} }
#[test] #[test]

View File

@ -37,3 +37,7 @@ pub const KECCAK_EMPTY: H256 =
/// Ommer root of empty list. /// Ommer root of empty list.
pub const EMPTY_OMMER_ROOT: H256 = pub const EMPTY_OMMER_ROOT: H256 =
H256(hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347")); H256(hex!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"));
/// Withdrawals root of empty withdrawals set.
pub const EMPTY_WITHDRAWALS: H256 =
H256(hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"));

View File

@ -165,7 +165,7 @@ impl Encodable for GenesisAccount {
return EMPTY_ROOT return EMPTY_ROOT
} }
let storage_values = let storage_values =
storage.iter().filter(|(_k, &v)| v != KECCAK_EMPTY).map(|(&k, v)| { storage.iter().filter(|(_k, &v)| v != H256::zero()).map(|(&k, v)| {
let value = U256::from_be_bytes(**v); let value = U256::from_be_bytes(**v);
(k, encode_fixed_size(&value)) (k, encode_fixed_size(&value))
}); });