Skip to content

Commit

Permalink
feat: add more JournaledState methods to EvmContext (bluealloy#1158)
Browse files Browse the repository at this point in the history
* feat: add more JournaledState methods to EvmContext

* Update crates/revm/src/journaled_state.rs
  • Loading branch information
DaniPopes authored and fubuloubu committed Apr 11, 2024
1 parent 863dd72 commit ed56e46
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 49 deletions.
104 changes: 62 additions & 42 deletions crates/revm/src/context.rs
Expand Up @@ -7,12 +7,12 @@ use crate::{
journaled_state::JournaledState,
precompile::{Precompile, Precompiles},
primitives::{
keccak256, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, EVMError, Env, HandlerCfg,
HashSet, Spec, SpecId, SpecId::*, B256, U256,
keccak256, Account, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, EVMError, Env,
HandlerCfg, HashSet, Spec, SpecId, SpecId::*, B256, U256,
},
FrameOrResult, JournalCheckpoint, CALL_STACK_LIMIT,
};
use revm_interpreter::SStoreResult;
use revm_interpreter::{SStoreResult, SelfDestructResult};
use std::boxed::Box;

/// Main Context structure that contains both EvmContext and External context.
Expand Down Expand Up @@ -96,7 +96,7 @@ where
}

/// EVM contexts contains data that EVM needs for execution.
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct EvmContext<DB: Database> {
/// EVM Environment contains all the information about config, block and transaction that
/// evm needs.
Expand All @@ -114,39 +114,18 @@ pub struct EvmContext<DB: Database> {
pub l1_block_info: Option<crate::optimism::L1BlockInfo>,
}

impl<DB: Database + Clone> Clone for EvmContext<DB>
where
DB::Error: Clone,
{
fn clone(&self) -> Self {
Self {
env: self.env.clone(),
journaled_state: self.journaled_state.clone(),
db: self.db.clone(),
error: self.error.clone(),
precompiles: self.precompiles.clone(),
#[cfg(feature = "optimism")]
l1_block_info: self.l1_block_info.clone(),
}
}
}

impl<DB: Database> EvmContext<DB> {
pub fn with_db<ODB: Database>(self, db: ODB) -> EvmContext<ODB> {
EvmContext {
env: self.env,
journaled_state: self.journaled_state,
db,
error: Ok(()),
precompiles: self.precompiles,
#[cfg(feature = "optimism")]
l1_block_info: self.l1_block_info,
}
/// Creates a new context with the given database.
#[inline]
pub fn new(db: DB) -> Self {
Self::new_with_env(db, Box::default())
}

pub fn new(db: DB) -> Self {
/// Creates a new context with the given environment and database.
#[inline]
pub fn new_with_env(db: DB, env: Box<Env>) -> Self {
Self {
env: Box::default(),
env,
journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()),
db,
error: Ok(()),
Expand All @@ -156,24 +135,34 @@ impl<DB: Database> EvmContext<DB> {
}
}

/// New context with database and environment.
pub fn new_with_env(db: DB, env: Box<Env>) -> Self {
Self {
env,
journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()),
/// Sets the database.
///
/// Note that this will ignore the previous `error` if set.
#[inline]
pub fn with_db<ODB: Database>(self, db: ODB) -> EvmContext<ODB> {
EvmContext {
env: self.env,
journaled_state: self.journaled_state,
db,
error: Ok(()),
precompiles: Precompiles::default(),
precompiles: self.precompiles,
#[cfg(feature = "optimism")]
l1_block_info: None,
l1_block_info: self.l1_block_info,
}
}

/// Returns the configured EVM spec ID.
#[inline]
pub const fn spec_id(&self) -> SpecId {
self.journaled_state.spec
}

/// Returns the current depth of the journaled state.
#[inline]
pub fn depth(&self) -> u64 {
self.journaled_state.depth()
}

/// Sets precompiles
#[inline]
pub fn set_precompiles(&mut self, precompiles: Precompiles) {
Expand Down Expand Up @@ -206,9 +195,29 @@ impl<DB: Database> EvmContext<DB> {
self.db.block_hash(number).map_err(EVMError::Database)
}

/// Load account and return flags (is_cold, exists)
/// Mark account as touched as only touched accounts will be added to state.
#[inline]
pub fn touch(&mut self, address: &Address) {
self.journaled_state.touch(address);
}

/// Loads an account into memory. Returns `true` if it is cold accessed.
#[inline]
pub fn load_account(
&mut self,
address: Address,
) -> Result<(&mut Account, bool), EVMError<DB::Error>> {
self.journaled_state.load_account(address, &mut self.db)
}

/// Load account from database to JournaledState.
///
/// Return boolean pair where first is `is_cold` second bool `exists`.
#[inline]
pub fn load_account(&mut self, address: Address) -> Result<(bool, bool), EVMError<DB::Error>> {
pub fn load_account_exist(
&mut self,
address: Address,
) -> Result<(bool, bool), EVMError<DB::Error>> {
self.journaled_state
.load_account_exist(address, &mut self.db)
}
Expand Down Expand Up @@ -274,6 +283,17 @@ impl<DB: Database> EvmContext<DB> {
self.journaled_state.tstore(address, index, value)
}

/// Selfdestructs the account.
#[inline]
pub fn selfdestruct(
&mut self,
address: Address,
target: Address,
) -> Result<SelfDestructResult, EVMError<DB::Error>> {
self.journaled_state
.selfdestruct(address, target, &mut self.db)
}

/// Make create frame.
#[inline]
pub fn make_create_frame(
Expand Down
2 changes: 1 addition & 1 deletion crates/revm/src/evm.rs
Expand Up @@ -400,7 +400,7 @@ impl<EXT, DB: Database> Host for Evm<'_, EXT, DB> {
fn load_account(&mut self, address: Address) -> Option<(bool, bool)> {
self.context
.evm
.load_account(address)
.load_account_exist(address)
.map_err(|e| self.context.evm.error = Err(e))
.ok()
}
Expand Down
13 changes: 7 additions & 6 deletions crates/revm/src/journaled_state.rs
Expand Up @@ -95,7 +95,6 @@ impl JournaledState {
#[inline]
pub fn finalize(&mut self) -> (State, Vec<Log>) {
let state = mem::take(&mut self.state);

let logs = mem::take(&mut self.logs);
self.journal = vec![vec![]];
self.depth = 0;
Expand Down Expand Up @@ -568,9 +567,10 @@ impl JournaledState {
address: Address,
db: &mut DB,
) -> Result<(bool, bool), EVMError<DB::Error>> {
let is_spurious_dragon_enabled = SpecId::enabled(self.spec, SPURIOUS_DRAGON);
let spec = self.spec;
let (acc, is_cold) = self.load_account(address, db)?;

let is_spurious_dragon_enabled = SpecId::enabled(spec, SPURIOUS_DRAGON);
let exist = if is_spurious_dragon_enabled {
!acc.is_empty()
} else {
Expand Down Expand Up @@ -605,18 +605,19 @@ impl JournaledState {

/// Load storage slot
///
/// # Note
/// # Panics
///
/// Account is already present and loaded.
/// Panics if the account is not present in the state.
#[inline]
pub fn sload<DB: Database>(
&mut self,
address: Address,
key: U256,
db: &mut DB,
) -> Result<(U256, bool), EVMError<DB::Error>> {
let account = self.state.get_mut(&address).unwrap(); // assume acc is warm
// only if account is created in this tx we can assume that storage is empty.
// assume acc is warm
let account = self.state.get_mut(&address).unwrap();
// only if account is created in this tx we can assume that storage is empty.
let is_newly_created = account.is_created();
let load = match account.storage.entry(key) {
Entry::Occupied(occ) => (occ.get().present_value, false),
Expand Down

0 comments on commit ed56e46

Please sign in to comment.