Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions crates/evm/src/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub use system_calls::*;

pub mod state_changes;

pub mod state;
pub use state::*;

pub mod calc;

/// The result of executing a block.
Expand Down
52 changes: 52 additions & 0 deletions crates/evm/src/block/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//! State database abstraction.

use alloy_primitives::Address;
use revm::database::State;

/// A type which has the state of the blockchain.
///
/// This trait encapsulates some of the functionality found in [`State`]
pub trait StateDB: revm::Database {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo we can keep StateDB here, hard to find a good name here -.-

/// State clear EIP-161 is enabled in Spurious Dragon hardfork.
fn set_state_clear_flag(&mut self, has_state_clear: bool);

/// Iterates over received balances and increment all account balances.
///
/// **Note**: If account is not found inside cache state it will be loaded from database.
///
/// Update will create transitions for all accounts that are updated.
///
/// If using this to implement withdrawals, zero balances must be filtered out before calling
/// this function.
fn increment_balances(
&mut self,
balances: impl IntoIterator<Item = (Address, u128)>,
) -> Result<(), Self::Error>;
}

/// auto_impl unable to reconcile return associated type from supertrait
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe <Self as Database>::Error works here, but we can keep this as is as welll

impl<T: StateDB> StateDB for &mut T {
fn set_state_clear_flag(&mut self, has_state_clear: bool) {
StateDB::set_state_clear_flag(*self, has_state_clear);
}

fn increment_balances(
&mut self,
balances: impl IntoIterator<Item = (Address, u128)>,
) -> Result<(), Self::Error> {
StateDB::increment_balances(*self, balances)
}
}

impl<DB: revm::Database> StateDB for State<DB> {
fn set_state_clear_flag(&mut self, has_state_clear: bool) {
self.cache.set_state_clear_flag(has_state_clear);
}

fn increment_balances(
&mut self,
balances: impl IntoIterator<Item = (Address, u128)>,
) -> Result<(), Self::Error> {
Self::increment_balances(self, balances)
}
}
9 changes: 4 additions & 5 deletions crates/evm/src/block/state_changes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use alloy_hardforks::EthereumHardforks;
use alloy_primitives::{map::HashMap, Address};
use revm::{
context::Block,
database::State,
state::{Account, AccountStatus, EvmState},
Database,
};
Expand Down Expand Up @@ -110,24 +109,24 @@ pub fn insert_post_block_withdrawals_balance_increments(
/// Zero balance increments are ignored and won't create state entries.
pub fn balance_increment_state<DB>(
balance_increments: &HashMap<Address, u128>,
state: &mut State<DB>,
state: &mut DB,
) -> Result<EvmState, BlockExecutionError>
where
DB: Database,
{
let mut load_account = |address: &Address| -> Result<(Address, Account), BlockExecutionError> {
let cache_account = state.load_cache_account(*address).map_err(|_| {
let cache_account = state.basic(*address).map_err(|_| {
BlockExecutionError::msg("could not load account for balance increment")
})?;

let account = cache_account.account.as_ref().ok_or_else(|| {
let account = cache_account.as_ref().ok_or_else(|| {
BlockExecutionError::msg("could not load account for balance increment")
})?;

Ok((
*address,
Account {
info: account.info.clone(),
info: account.clone(),
storage: Default::default(),
status: AccountStatus::Touched,
transaction_id: 0,
Expand Down
9 changes: 4 additions & 5 deletions crates/op-evm/src/block/canyon.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloy_evm::Database;
use alloy_op_hardforks::OpHardforks;
use alloy_primitives::{address, b256, hex, Address, Bytes, B256};
use revm::{database::State, primitives::HashMap, state::Bytecode, DatabaseCommit};
use revm::{primitives::HashMap, state::Bytecode, DatabaseCommit};

/// The address of the create2 deployer
const CREATE_2_DEPLOYER_ADDR: Address = address!("0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2");
Expand All @@ -19,10 +19,10 @@ const CREATE_2_DEPLOYER_BYTECODE: [u8; 1584] = hex!("608060405260043610610043576
pub(crate) fn ensure_create2_deployer<DB>(
chain_spec: impl OpHardforks,
timestamp: u64,
db: &mut State<DB>,
db: &mut DB,
) -> Result<(), DB::Error>
where
DB: Database,
DB: Database + DatabaseCommit,
{
// If the canyon hardfork is active at the current timestamp, and it was not active at the
// previous block timestamp (heuristically, block time is not perfectly constant at 2s), and the
Expand All @@ -31,10 +31,9 @@ where
&& !chain_spec.is_canyon_active_at_timestamp(timestamp.saturating_sub(2))
{
// Load the create2 deployer account from the cache.
let acc = db.load_cache_account(CREATE_2_DEPLOYER_ADDR)?;
let mut acc_info = db.basic(CREATE_2_DEPLOYER_ADDR)?.unwrap_or_default();

// Update the account info with the create2 deployer codehash and bytecode.
let mut acc_info = acc.account_info().unwrap_or_default();
acc_info.code_hash = CREATE_2_DEPLOYER_CODEHASH;
acc_info.code = Some(Bytecode::new_raw(Bytes::from_static(&CREATE_2_DEPLOYER_BYTECODE)));

Expand Down
26 changes: 8 additions & 18 deletions crates/op-evm/src/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use alloy_evm::{
state_changes::{balance_increment_state, post_block_balance_increments},
BlockExecutionError, BlockExecutionResult, BlockExecutor, BlockExecutorFactory,
BlockExecutorFor, BlockValidationError, ExecutableTx, OnStateHook,
StateChangePostBlockSource, StateChangeSource, SystemCaller,
StateChangePostBlockSource, StateChangeSource, StateDB, SystemCaller,
},
eth::receipt_builder::ReceiptBuilderCtx,
Database, Evm, EvmFactory, FromRecoveredTx, FromTxWithEncoded,
Expand All @@ -27,7 +27,7 @@ use receipt_builder::OpReceiptBuilder;
use revm::{
context::{result::ResultAndState, Block},
database::State,
DatabaseCommit, Inspector,
Database as _, DatabaseCommit, Inspector,
};

mod canyon;
Expand Down Expand Up @@ -127,11 +127,10 @@ pub enum OpBlockExecutionError {
},
}

impl<'db, DB, E, R, Spec> OpBlockExecutor<E, R, Spec>
impl<E, R, Spec> OpBlockExecutor<E, R, Spec>
where
DB: Database + 'db,
E: Evm<
DB = &'db mut State<DB>,
DB: Database + DatabaseCommit + StateDB,
Tx: FromRecoveredTx<R::Transaction> + FromTxWithEncoded<R::Transaction> + OpTxEnv,
>,
R: OpReceiptBuilder<Transaction: Transaction + Encodable2718, Receipt: TxReceipt>,
Expand All @@ -150,10 +149,7 @@ where

// Load the L1 block contract into the cache. If the L1 block contract is not pre-loaded the
// database will panic when trying to fetch the DA footprint gas scalar.
self.evm
.db_mut()
.load_cache_account(L1_BLOCK_CONTRACT)
.map_err(BlockExecutionError::other)?;
self.evm.db_mut().basic(L1_BLOCK_CONTRACT).map_err(BlockExecutionError::other)?;

let da_footprint_gas_scalar = L1BlockInfo::fetch_da_footprint_gas_scalar(self.evm.db_mut())
.map_err(BlockExecutionError::other)?
Expand All @@ -163,11 +159,10 @@ where
}
}

impl<'db, DB, E, R, Spec> BlockExecutor for OpBlockExecutor<E, R, Spec>
impl<E, R, Spec> BlockExecutor for OpBlockExecutor<E, R, Spec>
where
DB: Database + 'db,
E: Evm<
DB = &'db mut State<DB>,
DB: Database + DatabaseCommit + StateDB,
Tx: FromRecoveredTx<R::Transaction> + FromTxWithEncoded<R::Transaction> + OpTxEnv,
>,
R: OpReceiptBuilder<Transaction: Transaction + Encodable2718, Receipt: TxReceipt>,
Expand Down Expand Up @@ -255,12 +250,7 @@ where
// were not introduced in Bedrock. In addition, regular transactions don't have deposit
// nonces, so we don't need to touch the DB for those.
let depositor = (self.is_regolith && is_deposit)
.then(|| {
self.evm
.db_mut()
.load_cache_account(*tx.signer())
.map(|acc| acc.account_info().unwrap_or_default())
})
.then(|| self.evm.db_mut().basic(*tx.signer()).map(|acc| acc.unwrap_or_default()))
.transpose()
.map_err(BlockExecutionError::other)?;

Expand Down