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
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions crates/context/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ bytecode.workspace = true
# misc
derive-where.workspace = true
cfg-if.workspace = true
bitvec.workspace = true

# Optional
serde = { workspace = true, features = ["derive", "rc"], optional = true }
Expand All @@ -45,6 +46,7 @@ std = [
"database-interface/std",
"primitives/std",
"state/std",
"bitvec/std",
]
serde = [
"dep:serde",
Expand All @@ -55,6 +57,7 @@ serde = [
"database/serde",
"database-interface/serde",
"derive-where/serde",
"bitvec/serde",
]
dev = [
"memory_limit",
Expand Down
3 changes: 0 additions & 3 deletions crates/context/interface/src/journaled_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ pub trait JournalTr {
storage_keys: impl IntoIterator<Item = StorageKey>,
) -> Result<(), <Self::Database as Database>::Error>;

/// Warms the account.
fn warm_account(&mut self, address: Address);

/// Warms the coinbase account.
fn warm_coinbase_account(&mut self, address: Address);

Expand Down
14 changes: 5 additions & 9 deletions crates/context/src/journal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! and inner submodule contains [`JournalInner`] struct that contains state.
pub mod entry;
pub mod inner;
pub mod warm_addresses;

pub use entry::{JournalEntry, JournalEntryTr};
pub use inner::JournalInner;
Expand Down Expand Up @@ -140,24 +141,19 @@ impl<DB: Database, ENTRY: JournalEntryTr> JournalTr for Journal<DB, ENTRY> {
self.inner.selfdestruct(&mut self.database, address, target)
}

fn warm_account(&mut self, address: Address) {
self.inner.warm_preloaded_addresses.insert(address);
}

fn warm_coinbase_account(&mut self, address: Address) {
self.inner.warm_coinbase_address = Some(address);
self.inner.warm_addresses.set_coinbase(address);
}

fn warm_precompiles(&mut self, precompiles: HashSet<Address>) {
self.inner.precompiles = precompiles;
self.inner
.warm_preloaded_addresses
.clone_from(&self.inner.precompiles);
.warm_addresses
.set_precompile_addresses(precompiles);
}

#[inline]
fn precompile_addresses(&self) -> &HashSet<Address> {
&self.inner.precompiles
self.inner.warm_addresses.precompiles()
}

/// Returns call depth.
Expand Down
65 changes: 13 additions & 52 deletions crates/context/src/journal/inner.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Module containing the [`JournalInner`] that is part of [`crate::Journal`].
use crate::entry::SelfdestructionRevertStatus;
use crate::{entry::SelfdestructionRevertStatus, warm_addresses::WarmAddresses};

use super::JournalEntryTr;
use bytecode::Bytecode;
Expand All @@ -12,7 +12,7 @@ use database_interface::Database;
use primitives::{
hardfork::SpecId::{self, *},
hash_map::Entry,
Address, HashMap, HashSet, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256,
Address, HashMap, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256,
};
use state::{Account, EvmState, EvmStorageSlot, TransientStorage};
use std::vec::Vec;
Expand Down Expand Up @@ -53,17 +53,8 @@ pub struct JournalInner<ENTRY> {
/// [EIP-161]: https://eips.ethereum.org/EIPS/eip-161
/// [EIP-6780]: https://eips.ethereum.org/EIPS/eip-6780
pub spec: SpecId,
/// Warm loaded addresses are used to check if loaded address
/// should be considered cold or warm loaded when the account
/// is first accessed.
///
/// Note that this not include newly loaded accounts, account and storage
/// is considered warm if it is found in the `State`.
pub warm_preloaded_addresses: HashSet<Address>,
/// Warm coinbase address, stored separately to avoid cloning preloaded addresses.
pub warm_coinbase_address: Option<Address>,
/// Precompile addresses
pub precompiles: HashSet<Address>,
/// Warm addresses containing both coinbase and current precompiles.
pub warm_addresses: WarmAddresses,
}

impl<ENTRY: JournalEntryTr> Default for JournalInner<ENTRY> {
Expand All @@ -86,9 +77,7 @@ impl<ENTRY: JournalEntryTr> JournalInner<ENTRY> {
transaction_id: 0,
depth: 0,
spec: SpecId::default(),
warm_preloaded_addresses: HashSet::default(),
precompiles: HashSet::default(),
warm_coinbase_address: None,
warm_addresses: WarmAddresses::new(),
}
}

Expand Down Expand Up @@ -116,13 +105,10 @@ impl<ENTRY: JournalEntryTr> JournalInner<ENTRY> {
journal,
transaction_id,
spec,
warm_preloaded_addresses,
precompiles,
warm_coinbase_address,
warm_addresses,
} = self;
// Spec precompiles and state are not changed. It is always set again execution.
let _ = spec;
let _ = precompiles;
let _ = state;
transient_storage.clear();
*depth = 0;
Expand All @@ -131,11 +117,7 @@ impl<ENTRY: JournalEntryTr> JournalInner<ENTRY> {
journal.clear();

// Clear coinbase address warming for next tx
*warm_coinbase_address = None;
// Load precompiles into warm_preloaded_addresses.
// TODO for precompiles we can use max transaction_id so they are always touched warm loaded.
// at least after state clear EIP.
reset_preloaded_addresses(warm_preloaded_addresses, precompiles);
warm_addresses.clear_coinbase();
// increment transaction id.
*transaction_id += 1;
logs.clear();
Expand All @@ -152,11 +134,8 @@ impl<ENTRY: JournalEntryTr> JournalInner<ENTRY> {
journal,
transaction_id,
spec,
warm_preloaded_addresses,
warm_coinbase_address,
precompiles,
warm_addresses,
} = self;

let is_spurious_dragon_enabled = spec.is_enabled_in(SPURIOUS_DRAGON);
// iterate over all journals entries and revert our global state
journal.drain(..).rev().for_each(|entry| {
Expand All @@ -166,9 +145,9 @@ impl<ENTRY: JournalEntryTr> JournalInner<ENTRY> {
*depth = 0;
logs.clear();
*transaction_id += 1;

// Clear coinbase address warming for next tx
*warm_coinbase_address = None;
reset_preloaded_addresses(warm_preloaded_addresses, precompiles);
warm_addresses.clear_coinbase();
Copy link
Collaborator

Choose a reason for hiding this comment

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

this doesn't clear precompiles anymore?

Copy link
Collaborator

Choose a reason for hiding this comment

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

i guess it's always reset in set_precompile_addresses

Copy link
Member Author

Choose a reason for hiding this comment

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

set_precompile_addresses will reset it, and it is only called on spec_id change or if precompile address is empty.

}

/// Take the [`EvmState`] and clears the journal by resetting it to initial state.
Expand All @@ -187,16 +166,12 @@ impl<ENTRY: JournalEntryTr> JournalInner<ENTRY> {
journal,
transaction_id,
spec,
warm_preloaded_addresses,
warm_coinbase_address,
precompiles,
warm_addresses,
} = self;
// Spec is not changed. And it is always set again in execution.
let _ = spec;
// Clear coinbase address warming for next tx
*warm_coinbase_address = None;
// Load precompiles into warm_preloaded_addresses.
reset_preloaded_addresses(warm_preloaded_addresses, precompiles);
warm_addresses.clear_coinbase();

let state = mem::take(state);
logs.clear();
Expand Down Expand Up @@ -679,8 +654,7 @@ impl<ENTRY: JournalEntryTr> JournalInner<ENTRY> {
};

// Precompiles among some other account(coinbase included) are warm loaded so we need to take that into account
let is_cold = !self.warm_preloaded_addresses.contains(&address)
&& self.warm_coinbase_address.as_ref() != Some(&address);
let is_cold = self.warm_addresses.is_cold(&address);

StateLoad {
data: vac.insert(account),
Expand Down Expand Up @@ -881,16 +855,3 @@ pub fn sload_with_account<DB: Database, ENTRY: JournalEntryTr>(

Ok(StateLoad::new(value, is_cold))
}

fn reset_preloaded_addresses(
warm_preloaded_addresses: &mut HashSet<Address>,
precompiles: &HashSet<Address>,
) {
// `warm_preloaded_addresses` is append-only, and is initialized with `precompiles`.
// Avoid unnecessarily cloning if it hasn't changed.
if warm_preloaded_addresses.len() == precompiles.len() {
debug_assert_eq!(warm_preloaded_addresses, precompiles);
return;
}
warm_preloaded_addresses.clone_from(precompiles);
}
Loading
Loading