mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(op): init genesis alloc (#7748)
This commit is contained in:
@ -133,7 +133,8 @@ impl Command {
|
||||
StageId::Execution.to_string(),
|
||||
Default::default(),
|
||||
)?;
|
||||
insert_genesis_state::<DatabaseEnv>(tx, self.chain.genesis())?;
|
||||
let alloc = &self.chain.genesis().alloc;
|
||||
insert_genesis_state::<DatabaseEnv>(tx, alloc.len(), alloc.iter())?;
|
||||
}
|
||||
StageEnum::AccountHashing => {
|
||||
tx.clear::<tables::HashedAccounts>()?;
|
||||
@ -191,7 +192,7 @@ impl Command {
|
||||
StageId::IndexStorageHistory.to_string(),
|
||||
Default::default(),
|
||||
)?;
|
||||
insert_genesis_history(&provider_rw, &self.chain.genesis)?;
|
||||
insert_genesis_history(&provider_rw, self.chain.genesis.alloc.iter())?;
|
||||
}
|
||||
StageEnum::TxLookup => {
|
||||
tx.clear::<tables::TransactionHashNumbers>()?;
|
||||
|
||||
@ -7,8 +7,8 @@ use reth_db::{
|
||||
};
|
||||
use reth_interfaces::{db::DatabaseError, provider::ProviderResult};
|
||||
use reth_primitives::{
|
||||
stage::StageId, Account, Bytecode, ChainSpec, Receipts, StaticFileSegment, StorageEntry, B256,
|
||||
U256,
|
||||
stage::StageId, Account, Address, Bytecode, ChainSpec, GenesisAccount, Receipts,
|
||||
StaticFileSegment, StorageEntry, B256, U256,
|
||||
};
|
||||
use reth_provider::{
|
||||
bundle_state::{BundleStateInit, RevertsInit},
|
||||
@ -72,17 +72,19 @@ pub fn init_genesis<DB: Database>(factory: ProviderFactory<DB>) -> Result<B256,
|
||||
|
||||
debug!("Writing genesis block.");
|
||||
|
||||
let alloc = &genesis.alloc;
|
||||
|
||||
// use transaction to insert genesis header
|
||||
let provider_rw = factory.provider_rw()?;
|
||||
insert_genesis_hashes(&provider_rw, genesis)?;
|
||||
insert_genesis_history(&provider_rw, genesis)?;
|
||||
insert_genesis_hashes(&provider_rw, alloc.iter())?;
|
||||
insert_genesis_history(&provider_rw, alloc.iter())?;
|
||||
|
||||
// Insert header
|
||||
let tx = provider_rw.into_tx();
|
||||
let static_file_provider = factory.static_file_provider();
|
||||
insert_genesis_header::<DB>(&tx, &static_file_provider, chain.clone())?;
|
||||
|
||||
insert_genesis_state::<DB>(&tx, genesis)?;
|
||||
insert_genesis_state::<DB>(&tx, alloc.len(), alloc.iter())?;
|
||||
|
||||
// insert sync stage
|
||||
for stage in StageId::ALL.iter() {
|
||||
@ -96,16 +98,16 @@ pub fn init_genesis<DB: Database>(factory: ProviderFactory<DB>) -> Result<B256,
|
||||
}
|
||||
|
||||
/// Inserts the genesis state into the database.
|
||||
pub fn insert_genesis_state<DB: Database>(
|
||||
pub fn insert_genesis_state<'a, 'b, DB: Database>(
|
||||
tx: &<DB as Database>::TXMut,
|
||||
genesis: &reth_primitives::Genesis,
|
||||
capacity: usize,
|
||||
alloc: impl Iterator<Item = (&'a Address, &'b GenesisAccount)>,
|
||||
) -> ProviderResult<()> {
|
||||
let capacity = genesis.alloc.len();
|
||||
let mut state_init: BundleStateInit = HashMap::with_capacity(capacity);
|
||||
let mut reverts_init = HashMap::with_capacity(capacity);
|
||||
let mut contracts: HashMap<B256, Bytecode> = HashMap::with_capacity(capacity);
|
||||
|
||||
for (address, account) in &genesis.alloc {
|
||||
for (address, account) in alloc {
|
||||
let bytecode_hash = if let Some(code) = &account.code {
|
||||
let bytecode = Bytecode::new_raw(code.clone());
|
||||
let hash = bytecode.hash_slow();
|
||||
@ -163,24 +165,24 @@ pub fn insert_genesis_state<DB: Database>(
|
||||
}
|
||||
|
||||
/// Inserts hashes for the genesis state.
|
||||
pub fn insert_genesis_hashes<DB: Database>(
|
||||
pub fn insert_genesis_hashes<'a, 'b, DB: Database>(
|
||||
provider: &DatabaseProviderRW<DB>,
|
||||
genesis: &reth_primitives::Genesis,
|
||||
alloc: impl Iterator<Item = (&'a Address, &'b GenesisAccount)> + Clone,
|
||||
) -> ProviderResult<()> {
|
||||
// insert and hash accounts to hashing table
|
||||
let alloc_accounts = genesis
|
||||
.alloc
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(addr, account)| (addr, Some(Account::from_genesis_account(account))));
|
||||
let alloc_accounts =
|
||||
alloc.clone().map(|(addr, account)| (*addr, Some(Account::from_genesis_account(account))));
|
||||
provider.insert_account_for_hashing(alloc_accounts)?;
|
||||
|
||||
let alloc_storage = genesis.alloc.clone().into_iter().filter_map(|(addr, account)| {
|
||||
let alloc_storage = alloc.filter_map(|(addr, account)| {
|
||||
// only return Some if there is storage
|
||||
account.storage.map(|storage| {
|
||||
account.storage.as_ref().map(|storage| {
|
||||
(
|
||||
addr,
|
||||
storage.into_iter().map(|(key, value)| StorageEntry { key, value: value.into() }),
|
||||
*addr,
|
||||
storage
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(key, value)| StorageEntry { key, value: value.into() }),
|
||||
)
|
||||
})
|
||||
});
|
||||
@ -190,17 +192,15 @@ pub fn insert_genesis_hashes<DB: Database>(
|
||||
}
|
||||
|
||||
/// Inserts history indices for genesis accounts and storage.
|
||||
pub fn insert_genesis_history<DB: Database>(
|
||||
pub fn insert_genesis_history<'a, 'b, DB: Database>(
|
||||
provider: &DatabaseProviderRW<DB>,
|
||||
genesis: &reth_primitives::Genesis,
|
||||
alloc: impl Iterator<Item = (&'a Address, &'b GenesisAccount)> + Clone,
|
||||
) -> ProviderResult<()> {
|
||||
let account_transitions =
|
||||
genesis.alloc.keys().map(|addr| (*addr, vec![0])).collect::<BTreeMap<_, _>>();
|
||||
alloc.clone().map(|(addr, _)| (*addr, vec![0])).collect::<BTreeMap<_, _>>();
|
||||
provider.insert_account_history_index(account_transitions)?;
|
||||
|
||||
let storage_transitions = genesis
|
||||
.alloc
|
||||
.iter()
|
||||
let storage_transitions = alloc
|
||||
.filter_map(|(addr, account)| account.storage.as_ref().map(|storage| (addr, storage)))
|
||||
.flat_map(|(addr, storage)| storage.iter().map(|(key, _)| ((*addr, *key), vec![0])))
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
@ -235,6 +235,8 @@ pub fn insert_genesis_header<DB: Database>(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::*;
|
||||
|
||||
use reth_db::{
|
||||
@ -244,7 +246,7 @@ mod tests {
|
||||
DatabaseEnv,
|
||||
};
|
||||
use reth_primitives::{
|
||||
Address, Chain, ForkTimestamps, Genesis, GenesisAccount, IntegerList, GOERLI,
|
||||
Address, Chain, ChainSpec, ForkTimestamps, Genesis, GenesisAccount, IntegerList, GOERLI,
|
||||
GOERLI_GENESIS_HASH, MAINNET, MAINNET_GENESIS_HASH, SEPOLIA, SEPOLIA_GENESIS_HASH,
|
||||
};
|
||||
use reth_provider::test_utils::create_test_provider_factory_with_chain_spec;
|
||||
|
||||
@ -35,13 +35,13 @@ impl Account {
|
||||
self.bytecode_hash.map_or(true, |hash| hash == KECCAK_EMPTY)
|
||||
}
|
||||
|
||||
/// Converts [GenesisAccount] to [Account] type
|
||||
pub fn from_genesis_account(value: GenesisAccount) -> Self {
|
||||
/// Makes an [Account] from [GenesisAccount] type
|
||||
pub fn from_genesis_account(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),
|
||||
bytecode_hash: value.code.as_ref().map(keccak256),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -207,9 +207,8 @@ mod tests {
|
||||
let genesis = chain_spec.genesis();
|
||||
let alloc_accounts = genesis
|
||||
.alloc
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|(addr, account)| (addr, Some(Account::from_genesis_account(account))));
|
||||
.iter()
|
||||
.map(|(addr, account)| (*addr, Some(Account::from_genesis_account(account))));
|
||||
provider.insert_account_for_hashing(alloc_accounts).unwrap();
|
||||
|
||||
let alloc_storage = genesis.alloc.clone().into_iter().filter_map(|(addr, account)| {
|
||||
|
||||
Reference in New Issue
Block a user