Skip to content

Commit

Permalink
feat(anvil): migrate in-house Genesis to alloy-genesis (#6970)
Browse files Browse the repository at this point in the history
* wip: migrate to alloy genesis

* feat: switch out from in-house genesis to alloy genesis

* chore: rem unneeded file

* chore: update alloy, use from_bytes

* chore: use proper fns on trait

* chore: use block number
  • Loading branch information
Evalir authored Feb 1, 2024
1 parent 4574f05 commit b73df7c
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 341 deletions.
31 changes: 16 additions & 15 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/anvil/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ alloy-rpc-trace-types.workspace = true
alloy-providers.workspace = true
alloy-transport.workspace = true
alloy-chains.workspace = true
alloy-genesis.workspace = true

# axum related
axum.workspace = true
Expand Down
8 changes: 8 additions & 0 deletions crates/anvil/core/src/eth/transaction/optimism.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,14 @@ impl Transaction for DepositTransactionRequest {
fn value(&self) -> U256 {
self.value
}

fn encode_for_signing(&self, out: &mut dyn alloy_rlp::BufMut) {
self.encode_for_signing(out)
}

fn payload_len_for_signature(&self) -> usize {
self.payload_len_for_signature()
}
}

impl From<DepositTransaction> for DepositTransactionRequest {
Expand Down
9 changes: 7 additions & 2 deletions crates/anvil/src/cmd.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::{
config::DEFAULT_MNEMONIC,
eth::{backend::db::SerializableState, pool::transactions::TransactionOrder, EthApi},
genesis::Genesis,
AccountGenerator, Hardfork, NodeConfig, CHAIN_ID,
};
use alloy_genesis::Genesis;
use alloy_primitives::{utils::Unit, U256};
use alloy_signer::coins_bip39::{English, Mnemonic};
use anvil_server::ServerConfig;
Expand Down Expand Up @@ -110,7 +110,7 @@ pub struct NodeArgs {
pub order: TransactionOrder,

/// Initialize the genesis block with the given `genesis.json` file.
#[clap(long, value_name = "PATH", value_parser = Genesis::parse)]
#[clap(long, value_name = "PATH", value_parser= read_genesis_file)]
pub init: Option<Genesis>,

/// This is an alias for both --load-state and --dump-state.
Expand Down Expand Up @@ -672,6 +672,11 @@ impl FromStr for ForkUrl {
}
}

/// Clap's value parser for genesis. Loads a genesis.json file.
fn read_genesis_file(path: &str) -> Result<Genesis, String> {
foundry_common::fs::read_json_file(path.as_ref()).map_err(|err| err.to_string())
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
18 changes: 13 additions & 5 deletions crates/anvil/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ use crate::{
fees::{INITIAL_BASE_FEE, INITIAL_GAS_PRICE},
pool::transactions::TransactionOrder,
},
genesis::Genesis,
mem,
mem::in_memory_db::MemDb,
FeeManager, Hardfork,
};
use alloy_genesis::Genesis;
use alloy_primitives::{hex, utils::Unit, U256};
use alloy_providers::provider::TempProvider;
use alloy_rpc_types::BlockNumberOrTag;
Expand Down Expand Up @@ -412,7 +412,7 @@ impl NodeConfig {
/// Returns the base fee to use
pub fn get_base_fee(&self) -> U256 {
self.base_fee
.or_else(|| self.genesis.as_ref().and_then(|g| g.base_fee_per_gas))
.or_else(|| self.genesis.as_ref().and_then(|g| g.base_fee_per_gas.map(U256::from)))
.unwrap_or_else(|| U256::from(INITIAL_BASE_FEE))
}

Expand Down Expand Up @@ -457,7 +457,7 @@ impl NodeConfig {
/// Returns the chain ID to use
pub fn get_chain_id(&self) -> u64 {
self.chain_id
.or_else(|| self.genesis.as_ref().and_then(|g| g.chain_id()))
.or_else(|| self.genesis.as_ref().map(|g| g.config.chain_id))
.unwrap_or(CHAIN_ID)
}

Expand Down Expand Up @@ -532,7 +532,7 @@ impl NodeConfig {
/// Returns the genesis timestamp to use
pub fn get_genesis_timestamp(&self) -> u64 {
self.genesis_timestamp
.or_else(|| self.genesis.as_ref().and_then(|g| g.timestamp))
.or_else(|| self.genesis.as_ref().map(|g| g.timestamp))
.unwrap_or_else(|| duration_since_unix_epoch().as_secs())
}

Expand Down Expand Up @@ -834,7 +834,15 @@ impl NodeConfig {

// if provided use all settings of `genesis.json`
if let Some(ref genesis) = self.genesis {
genesis.apply(&mut env);
env.cfg.chain_id = genesis.config.chain_id;
env.block.timestamp = U256::from(genesis.timestamp);
if let Some(base_fee) = genesis.base_fee_per_gas {
env.block.basefee = U256::from(base_fee);
}
if let Some(number) = genesis.number {
env.block.number = U256::from(number);
}
env.block.coinbase = genesis.coinbase;
}

let genesis = GenesisConfig {
Expand Down
35 changes: 23 additions & 12 deletions crates/anvil/src/eth/backend/genesis.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
//! Genesis settings

use crate::{
eth::backend::db::{Db, MaybeHashDatabase},
genesis::Genesis,
};
use crate::eth::backend::db::{Db, MaybeHashDatabase};
use alloy_genesis::{Genesis, GenesisAccount};
use alloy_primitives::{Address, B256, U256};
use foundry_evm::{
backend::{DatabaseError, DatabaseResult, StateSnapshot},
Expand Down Expand Up @@ -57,19 +55,31 @@ impl GenesisConfig {
mut db: RwLockWriteGuard<'_, Box<dyn Db>>,
) -> DatabaseResult<()> {
if let Some(ref genesis) = self.genesis_init {
for (addr, mut acc) in genesis.alloc.accounts.clone() {
for (addr, mut acc) in genesis.alloc.clone() {
let storage = std::mem::take(&mut acc.storage);
// insert all accounts
db.insert_account(addr, acc.into());
db.insert_account(addr, self.genesis_to_account_info(&acc));
// insert all storage values
for (k, v) in storage.iter() {
for (k, v) in storage.unwrap_or_default().iter() {
db.set_storage_at(addr, U256::from_be_bytes(k.0), U256::from_be_bytes(v.0))?;
}
}
}
Ok(())
}

/// Converts a [`GenesisAccount`] to an [`AccountInfo`]
fn genesis_to_account_info(&self, acc: &GenesisAccount) -> AccountInfo {
let GenesisAccount { code, balance, nonce, .. } = acc.clone();
let code = code.map(|code| Bytecode::new_raw(code.to_vec().into()));
AccountInfo {
balance,
nonce: nonce.unwrap_or_default(),
code_hash: code.as_ref().map(|code| code.hash_slow()).unwrap_or(KECCAK_EMPTY),
code,
}
}

/// Returns a database wrapper that points to the genesis and is aware of all provided
/// [AccountInfo]
pub(crate) fn state_db_at_genesis<'a>(
Expand Down Expand Up @@ -113,11 +123,12 @@ impl<'a> DatabaseRef for AtGenesisStateDb<'a> {
}

fn storage_ref(&self, address: Address, index: U256) -> DatabaseResult<U256> {
if let Some(acc) =
self.genesis.as_ref().and_then(|genesis| genesis.alloc.accounts.get(&(address)))
{
let value = acc.storage.get(&B256::from(index)).copied().unwrap_or_default();
return Ok(U256::from_be_bytes(value.0))
if let Some(acc) = self.genesis.as_ref().and_then(|genesis| genesis.alloc.get(&(address))) {
if let Some(storage) = acc.storage.as_ref() {
return Ok(U256::from_be_bytes(
storage.get(&B256::from(index)).copied().unwrap_or_default().0,
))
}
}
self.db.storage_ref(address, index)
}
Expand Down
Loading

0 comments on commit b73df7c

Please sign in to comment.