Skip to content

Commit

Permalink
feat: to_plain_state
Browse files Browse the repository at this point in the history
  • Loading branch information
prestwich committed Sep 16, 2024
1 parent 1ad8604 commit fea8057
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 5 deletions.
10 changes: 7 additions & 3 deletions crates/primitives/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,13 @@ impl AccountInfo {
}

/// Returns account info without the code.
pub fn without_code(mut self) -> Self {
self.take_bytecode();
self
pub fn without_code(&self) -> Self {
Self {
balance: self.balance,
nonce: self.nonce,
code_hash: self.code_hash,
code: None,
}
}

/// Returns if an account is empty.
Expand Down
64 changes: 63 additions & 1 deletion crates/revm/src/db/states/bundle_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,68 @@ impl BundleState {
self.reverts.push(reverts);
}

/// Generate a [`StateChangeset`] from the bundle state without consuming
/// it.
pub fn to_plain_state(&self, is_value_known: OriginalValuesKnown) -> StateChangeset {
// pessimistically pre-allocate assuming _all_ accounts changed.
let state_len = self.state.len();
let mut accounts = Vec::with_capacity(state_len);
let mut storage = Vec::with_capacity(state_len);

for (address, account) in self.state.iter() {
// append account info if it is changed.
let was_destroyed = account.was_destroyed();
if is_value_known.is_not_known() || account.is_info_changed() {
let info = account.info.as_ref().map(AccountInfo::without_code);
accounts.push((*address, info));
}

// append storage changes

// NOTE: Assumption is that revert is going to remove whole plain storage from
// database so we can check if plain state was wiped or not.
let mut account_storage_changed = Vec::with_capacity(account.storage.len());

for (key, slot) in account.storage.iter().map(|(k, v)| (*k, *v)) {
// If storage was destroyed that means that storage was wiped.
// In that case we need to check if present storage value is different then ZERO.
let destroyed_and_not_zero = was_destroyed && !slot.present_value.is_zero();

// If account is not destroyed check if original values was changed,
// so we can update it.
let not_destroyed_and_changed = !was_destroyed && slot.is_changed();

if is_value_known.is_not_known()
|| destroyed_and_not_zero
|| not_destroyed_and_changed
{
account_storage_changed.push((key, slot.present_value));
}
}

if !account_storage_changed.is_empty() || was_destroyed {
// append storage changes to account.
storage.push(PlainStorageChangeset {
address: *address,
wipe_storage: was_destroyed,
storage: account_storage_changed,
});
}
}

let contracts = self
.contracts
.iter()
// remove empty bytecodes
.filter_map(|(b, code)| (*b != KECCAK_EMPTY).then_some((*b, code.clone())))
.collect::<Vec<_>>();
StateChangeset {
accounts,
storage,
contracts,
}
}

/// Consume the bundle state and return plain state.
pub fn into_plain_state(self, is_value_known: OriginalValuesKnown) -> StateChangeset {
// pessimistically pre-allocate assuming _all_ accounts changed.
Expand All @@ -592,7 +654,7 @@ impl BundleState {
// append account info if it is changed.
let was_destroyed = account.was_destroyed();
if is_value_known.is_not_known() || account.is_info_changed() {
let info = account.info.map(AccountInfo::without_code);
let info = account.info.as_ref().map(AccountInfo::without_code);
accounts.push((address, info));
}

Expand Down
2 changes: 1 addition & 1 deletion crates/revm/src/db/states/plain_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl PlainAccount {
}

/// This type keeps track of the current value of a storage slot.
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct StorageSlot {
/// The value of the storage slot before it was changed.
Expand Down

0 comments on commit fea8057

Please sign in to comment.