diff --git a/crates/primitives/src/genesis.rs b/crates/primitives/src/genesis.rs index 41fc943d4..2083b0d2f 100644 --- a/crates/primitives/src/genesis.rs +++ b/crates/primitives/src/genesis.rs @@ -5,7 +5,7 @@ use crate::{ proofs::{KeccakHasher, EMPTY_ROOT}, serde_helper::deserialize_json_u256, utils::serde_helpers::deserialize_stringified_u64, - Address, Bytes, H256, KECCAK_EMPTY, U256, + Account, Address, Bytes, H256, KECCAK_EMPTY, U256, }; use ethers_core::utils::GenesisAccount as EthersGenesisAccount; use reth_rlp::{encode_fixed_size, length_of_length, Encodable, Header as RlpHeader}; @@ -193,6 +193,17 @@ impl From for GenesisAccount { } } +impl From for Account { + fn from(value: GenesisAccount) -> Self { + Account { + // nonce must exist, so we default to zero when converting a genesis account + nonce: value.nonce.unwrap_or_default(), + balance: value.balance, + bytecode_hash: value.code.map(keccak256), + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/staged-sync/src/utils/init.rs b/crates/staged-sync/src/utils/init.rs index fbf5b7f9b..943d39b83 100644 --- a/crates/staged-sync/src/utils/init.rs +++ b/crates/staged-sync/src/utils/init.rs @@ -6,6 +6,7 @@ use reth_db::{ transaction::{DbTx, DbTxMut}, }; use reth_primitives::{keccak256, Account, Bytecode, ChainSpec, StorageEntry, H256}; +use reth_provider::{Transaction, TransactionError}; use reth_stages::StageKind; use std::{path::Path, sync::Arc}; use tracing::debug; @@ -31,6 +32,10 @@ pub enum InitDatabaseError { actual: H256, }, + /// Higher level error encountered when using a Transaction. + #[error(transparent)] + TransactionError(#[from] TransactionError), + /// Low-level database error. #[error(transparent)] DBError(#[from] reth_db::Error), @@ -62,7 +67,12 @@ pub fn init_genesis( let tx = db.tx_mut()?; insert_genesis_state::(&tx, genesis)?; + // use transaction to insert genesis header + let transaction = Transaction::new_raw(&db, tx); + insert_genesis_hashes(transaction, genesis)?; + // Insert header + let tx = db.tx_mut()?; tx.put::(0, hash)?; tx.put::(hash, 0)?; tx.put::(0, Default::default())?; @@ -115,7 +125,25 @@ pub fn insert_genesis_state( } } } + Ok(()) +} +/// Inserts hashes for the genesis state. +pub fn insert_genesis_hashes( + mut transaction: Transaction<'_, DB>, + genesis: &reth_primitives::Genesis, +) -> Result<(), InitDatabaseError> { + // insert and hash accounts to hashing table + let alloc_accounts = + genesis.alloc.clone().into_iter().map(|(addr, account)| (addr, Some(account.into()))); + transaction.insert_account_for_hashing(alloc_accounts)?; + + let alloc_storage = genesis.alloc.clone().into_iter().filter_map(|(addr, account)| { + // only return Some if there is storage + account.storage.map(|storage| (addr, storage.into_iter().map(|(k, v)| (k, v.into())))) + }); + transaction.insert_storage_for_hashing(alloc_storage)?; + transaction.commit()?; Ok(()) } diff --git a/crates/storage/provider/src/transaction.rs b/crates/storage/provider/src/transaction.rs index 1538f7c17..93571e5c2 100644 --- a/crates/storage/provider/src/transaction.rs +++ b/crates/storage/provider/src/transaction.rs @@ -1391,7 +1391,7 @@ fn unwind_storage_history_shards( } /// An error that can occur when using the transaction container -#[derive(Debug, thiserror::Error)] +#[derive(Debug, PartialEq, Eq, Clone, thiserror::Error)] pub enum TransactionError { /// The transaction encountered a database error. #[error(transparent)] diff --git a/crates/trie/src/errors.rs b/crates/trie/src/errors.rs index fb9f5ae8b..4743e9f74 100644 --- a/crates/trie/src/errors.rs +++ b/crates/trie/src/errors.rs @@ -1,7 +1,7 @@ use thiserror::Error; /// State root error. -#[derive(Error, Debug)] +#[derive(Error, Debug, PartialEq, Eq, Clone)] pub enum StateRootError { /// Internal database error. #[error(transparent)] @@ -21,7 +21,7 @@ impl From for reth_db::Error { } /// Storage root error. -#[derive(Error, Debug)] +#[derive(Error, PartialEq, Eq, Clone, Debug)] pub enum StorageRootError { /// Internal database error. #[error(transparent)]