Skip to content

Commit

Permalink
inline journalstate functions
Browse files Browse the repository at this point in the history
  • Loading branch information
rakita committed Oct 20, 2023
1 parent 36f271f commit aab5537
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 25 deletions.
39 changes: 21 additions & 18 deletions crates/revm/src/journaled_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ impl JournaledState {
///
/// Note: This function will journal state after Spurious Dragon fork.
/// And will not take into account if account is not existing or empty.
///
/// # Note
///
/// Precompile addresses should be sorted.
pub fn new(spec: SpecId, precompile_addresses: Vec<Address>) -> JournaledState {
Self {
state: HashMap::new(),
Expand All @@ -52,19 +56,23 @@ impl JournaledState {
}

/// Return reference to state.
#[inline]
pub fn state(&mut self) -> &mut State {
&mut self.state
}

/// Mark account as touched as only touched accounts will be added to state.
/// This is especially important for state clear where touched empty accounts needs to
/// be removed from state.
#[inline]
pub fn touch(&mut self, address: &Address) {
if let Some(account) = self.state.get_mut(address) {
Self::touch_account(self.journal.last_mut().unwrap(), address, account);
}
}

/// Mark account as touched.
#[inline]
fn touch_account(journal: &mut Vec<JournalEntry>, address: &Address, account: &mut Account) {
if !account.is_touched() {
journal.push(JournalEntry::AccountTouched { address: *address });
Expand All @@ -73,6 +81,7 @@ impl JournaledState {
}

/// do cleanup and return modified state
#[inline]
pub fn finalize(&mut self) -> (State, Vec<Log>) {
let state = mem::take(&mut self.state);

Expand All @@ -89,18 +98,21 @@ impl JournaledState {
/// # Panics
///
/// Panics if the account has not been loaded and is missing from the state set.
#[inline]
pub fn account(&self, address: Address) -> &Account {
self.state
.get(&address)
.expect("Account expected to be loaded") // Always assume that acc is already loaded
}

#[inline]
pub fn depth(&self) -> u64 {
self.depth as u64
}

/// use it only if you know that acc is warm
/// Assume account is warm
#[inline]
pub fn set_code(&mut self, address: Address, code: Bytecode) {
let account = self.state.get_mut(&address).unwrap();
Self::touch_account(self.journal.last_mut().unwrap(), &address, account);
Expand Down Expand Up @@ -131,6 +143,7 @@ impl JournaledState {
Some(account.info.nonce)
}

#[inline]
pub fn transfer<DB: Database>(
&mut self,
from: &Address,
Expand Down Expand Up @@ -187,6 +200,7 @@ impl JournaledState {
///
/// Safety: It is assumed that caller balance is already checked and that
/// caller is already loaded inside evm. This is already done inside `create_inner`
#[inline]
pub fn create_account_checkpoint<SPEC: Spec>(
&mut self,
caller: Address,
Expand Down Expand Up @@ -274,6 +288,7 @@ impl JournaledState {
false
}

#[inline]
fn journal_revert(
state: &mut State,
transient_storage: &mut TransientStorage,
Expand Down Expand Up @@ -375,10 +390,14 @@ impl JournaledState {
checkpoint
}

/// Commit the checkpoint.
#[inline]
pub fn checkpoint_commit(&mut self) {
self.depth -= 1;
}

/// Reverts all changes to state until given checkpoint.
#[inline]
pub fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) {
let is_spurious_dragon_enabled = SpecId::enabled(self.spec, SPURIOUS_DRAGON);
let state = &mut self.state;
Expand Down Expand Up @@ -413,6 +432,7 @@ impl JournaledState {
/// * https://github.com/ethereum/go-ethereum/blob/141cd425310b503c5678e674a8c3872cf46b7086/core/vm/instructions.go#L832-L833
/// * https://github.com/ethereum/go-ethereum/blob/141cd425310b503c5678e674a8c3872cf46b7086/core/state/statedb.go#L449
/// * https://eips.ethereum.org/EIPS/eip-6780
#[inline]
pub fn selfdestruct<DB: Database>(
&mut self,
address: Address,
Expand Down Expand Up @@ -473,25 +493,8 @@ impl JournaledState {
})
}

pub fn initial_account_and_code_load<DB: Database>(
&mut self,
address: Address,
db: &mut DB,
) -> Result<&mut Account, DB::Error> {
let account = self.initial_account_load(address, &[], db)?;
if account.info.code.is_none() {
if account.info.code_hash == KECCAK_EMPTY {
account.info.code = Some(Bytecode::new());
} else {
// load code if requested
account.info.code = Some(db.code_by_hash(account.info.code_hash)?);
}
}

Ok(account)
}

/// Initial load of account. This load will not be tracked inside journal
#[inline]
pub fn initial_account_load<DB: Database>(
&mut self,
address: Address,
Expand Down
9 changes: 2 additions & 7 deletions documentation/src/crates/revm/journaled_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ This module is built around the `JournaledState` structure, which encapsulates t
If the target account does not exist, it's created. If the self-destructed account and the
target are the same, the balance will be lost.

- `initial_account_and_code_load`

This method initializes an account and loads its associated code from the database. If the
code does not exist, an empty code is associated with the account.

- `initial_account_load`

This method loads an account's basic information from the database without loading the code.
Expand Down Expand Up @@ -93,7 +88,7 @@ The [EIP-161](https://eips.ethereum.org/EIPS/eip-161) aims to optimize Ethereum'

An account is considered "empty" if it has no code, and its nonce and balance are both zero. An account is considered "dead" if it is non-existent or it is empty. An account is considered "touched" when it is involved in any potentially state-changing operation.

These rules have an impact on how state is managed within the [EIP-161](https://eips.ethereum.org/EIPS/eip-161) context, and this affects how the JournaledState module functions. For example, operations like `initial_account_and_code_load`, `initial_account_load`, and `selfdestruct` all need to take into account whether an account is empty or dead.
These rules have an impact on how state is managed within the [EIP-161](https://eips.ethereum.org/EIPS/eip-161) context, and this affects how the JournaledState module functions. For example, operations like `initial_account_load`, and `selfdestruct` all need to take into account whether an account is empty or dead.

#### Rationale

Expand All @@ -109,7 +104,7 @@ This EIP is particularly important because it introduced a way to unambiguously

[EIP-658](https://eips.ethereum.org/EIPS/eip-658) replaced the intermediate state root field in the receipt with a status code that indicates whether the top-level call of the transaction succeeded or failed. The status code is 1 for success and 0 for failure.

This EIP affects the JournaledState module, as the result of executing transactions and their success or failure status directly influences the state of the blockchain. The execution of state-modifying methods like `initial_account_and_code_load`, `selfdestruct`, `sstore`, and `log` can result in success or failure, and the status needs to be properly reflected in the transaction receipt.
This EIP affects the JournaledState module, as the result of executing transactions and their success or failure status directly influences the state of the blockchain. The execution of state-modifying methods like , `selfdestruct`, `sstore`, and `log` can result in success or failure, and the status needs to be properly reflected in the transaction receipt.

#### Rationale

Expand Down

0 comments on commit aab5537

Please sign in to comment.