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: 0 additions & 1 deletion Cargo.lock

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

3 changes: 1 addition & 2 deletions crates/context/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,17 @@ all = "warn"

[dependencies]
# revm
interpreter.workspace = true
context-interface.workspace = true
primitives.workspace = true
database-interface.workspace = true
state.workspace = true
specification.workspace = true
bytecode.workspace = true
auto_impl.workspace = true

# misc
derive-where.workspace = true
cfg-if.workspace = true
auto_impl.workspace = true

# Optional
serde = { workspace = true, features = ["derive", "rc"], optional = true }
Expand Down
128 changes: 2 additions & 126 deletions crates/context/interface/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub use crate::journaled_state::StateLoad;
use crate::{journaled_state::AccountLoad, Block, Cfg, Database, Journal, Transaction};
use crate::{Block, Cfg, Database, Journal, Transaction};
use auto_impl::auto_impl;
use primitives::{Address, Bytes, Log, B256, BLOCK_HASH_HISTORY, U256};
use primitives::U256;

#[auto_impl(&mut, Box)]
pub trait ContextTr {
Expand All @@ -22,130 +22,6 @@ pub trait ContextTr {
fn chain(&mut self) -> &mut Self::Chain;
fn error(&mut self) -> &mut Result<(), <Self::Db as Database>::Error>;
fn tx_journal(&mut self) -> (&mut Self::Tx, &mut Self::Journal);
// default implementationHost calls interface

/// Gets the block hash of the given block `number`.
fn block_hash(&mut self, requested_number: u64) -> Option<B256> {
let block_number = self.block().number();

let Some(diff) = block_number.checked_sub(requested_number) else {
return Some(B256::ZERO);
};

// blockhash should push zero if number is same as current block number.
if diff == 0 {
return Some(B256::ZERO);
}

if diff <= BLOCK_HASH_HISTORY {
return self
.journal()
.db()
.block_hash(requested_number)
.map_err(|e| {
*self.error() = Err(e);
})
.ok();
}

Some(B256::ZERO)
}

fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>> {
self.journal()
.load_account_delegated(address)
.map_err(|e| {
*self.error() = Err(e);
})
.ok()
}

/// Gets balance of `address` and if the account is cold.
fn balance(&mut self, address: Address) -> Option<StateLoad<U256>> {
self.journal()
.load_account(address)
.map(|acc| acc.map(|a| a.info.balance))
.map_err(|e| {
*self.error() = Err(e);
})
.ok()
}

/// Gets code of `address` and if the account is cold.
fn code(&mut self, address: Address) -> Option<StateLoad<Bytes>> {
self.journal()
.code(address)
.map_err(|e| {
*self.error() = Err(e);
})
.ok()
}

/// Gets code hash of `address` and if the account is cold.
fn code_hash(&mut self, address: Address) -> Option<StateLoad<B256>> {
self.journal()
.code_hash(address)
.map_err(|e| {
*self.error() = Err(e);
})
.ok()
}

/// Gets storage value of `address` at `index` and if the account is cold.
fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>> {
self.journal()
.sload(address, index)
.map_err(|e| {
*self.error() = Err(e);
})
.ok()
}

/// Sets storage value of account address at index.
///
/// Returns [`StateLoad`] with [`SStoreResult`] that contains original/new/old storage value.
fn sstore(
&mut self,
address: Address,
index: U256,
value: U256,
) -> Option<StateLoad<SStoreResult>> {
self.journal()
.sstore(address, index, value)
.map_err(|e| {
*self.error() = Err(e);
})
.ok()
}

/// Gets the transient storage value of `address` at `index`.
fn tload(&mut self, address: Address, index: U256) -> U256 {
self.journal().tload(address, index)
}

/// Sets the transient storage value of `address` at `index`.
fn tstore(&mut self, address: Address, index: U256, value: U256) {
self.journal().tstore(address, index, value)
}

/// Emits a log owned by `address` with given `LogData`.
fn log(&mut self, log: Log) {
self.journal().log(log);
}

/// Marks `address` to be deleted, with funds transferred to `target`.
fn selfdestruct(
&mut self,
address: Address,
target: Address,
) -> Option<StateLoad<SelfDestructResult>> {
self.journal()
.selfdestruct(address, target)
.map_err(|e| {
*self.error() = Err(e);
})
.ok()
}
}

/// Represents the result of an `sstore` operation.
Expand Down
44 changes: 41 additions & 3 deletions crates/context/interface/src/journaled_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use core::ops::{Deref, DerefMut};
use database_interface::Database;
use primitives::{Address, Bytes, HashSet, Log, B256, U256};
use specification::hardfork::SpecId;
use state::{Account, Bytecode};
use state::{
bytecode::{EOF_MAGIC_BYTES, EOF_MAGIC_HASH},
Account, Bytecode,
};

pub trait Journal {
type Database: Database;
Expand Down Expand Up @@ -108,15 +111,50 @@ pub trait Journal {
self.set_code_with_hash(address, code, hash);
}

/// Returns account code bytes and if address is cold loaded.
///
/// In case of EOF account it will return `EOF_MAGIC` (0xEF00) as code.
#[inline]
fn code(
&mut self,
address: Address,
) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error>;
) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
let a = self.load_account_code(address)?;
// SAFETY: Safe to unwrap as load_code will insert code if it is empty.
let code = a.info.code.as_ref().unwrap();

let code = if code.is_eof() {
EOF_MAGIC_BYTES.clone()
} else {
code.original_bytes()
};

Ok(StateLoad::new(code, a.is_cold))
}

/// Gets code hash of account.
///
/// In case of EOF account it will return `EOF_MAGIC_HASH`
/// (the hash of `0xEF00`).
fn code_hash(
&mut self,
address: Address,
) -> Result<StateLoad<B256>, <Self::Database as Database>::Error>;
) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
let acc = self.load_account_code(address)?;
if acc.is_empty() {
return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
}
// SAFETY: Safe to unwrap as load_code will insert code if it is empty.
let code = acc.info.code.as_ref().unwrap();

let hash = if code.is_eof() {
EOF_MAGIC_HASH
} else {
acc.info.code_hash
};

Ok(StateLoad::new(hash, acc.is_cold))
}

/// Called at the end of the transaction to clean all residue data from journal.
fn clear(&mut self);
Expand Down
3 changes: 1 addition & 2 deletions crates/context/src/cfg.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
pub use context_interface::Cfg;

use interpreter::MAX_CODE_SIZE;
use specification::hardfork::SpecId;
use specification::{eip170::MAX_CODE_SIZE, hardfork::SpecId};
use std::{vec, vec::Vec};

/// EVM configuration
Expand Down
67 changes: 6 additions & 61 deletions crates/context/src/journaled_state.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use bytecode::{Bytecode, EOF_MAGIC_BYTES, EOF_MAGIC_HASH};
use context_interface::journaled_state::{AccountLoad, Journal, JournalCheckpoint, TransferError};
use bytecode::Bytecode;
use context_interface::{
context::{SStoreResult, SelfDestructResult, StateLoad},
journaled_state::{AccountLoad, Journal, JournalCheckpoint, TransferError},
};
use database_interface::Database;
use interpreter::{SStoreResult, SelfDestructResult, StateLoad};
use primitives::{
hash_map::Entry, Address, Bytes, HashMap, HashSet, Log, B256, KECCAK_EMPTY, PRECOMPILE3, U256,
hash_map::Entry, Address, HashMap, HashSet, Log, B256, KECCAK_EMPTY, PRECOMPILE3, U256,
};
use specification::hardfork::{SpecId, SpecId::*};
use state::{Account, EvmState, EvmStorageSlot, TransientStorage};
Expand Down Expand Up @@ -144,20 +146,6 @@ impl<DB: Database> Journal for JournaledState<DB> {
self.spec = spec_id;
}

fn code(
&mut self,
address: Address,
) -> Result<StateLoad<primitives::Bytes>, <Self::Database as Database>::Error> {
self.code(address)
}

fn code_hash(
&mut self,
address: Address,
) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
self.code_hash(address)
}

fn transfer(
&mut self,
from: &Address,
Expand Down Expand Up @@ -417,49 +405,6 @@ impl<DB: Database> JournaledState<DB> {
Ok(None)
}

/// Returns account code bytes and if address is cold loaded.
///
/// In case of EOF account it will return `EOF_MAGIC` (0xEF00) as code.
#[inline]
pub fn code(&mut self, address: Address) -> Result<StateLoad<Bytes>, <DB as Database>::Error> {
let a = self.load_account_code(address)?;
// SAFETY: Safe to unwrap as load_code will insert code if it is empty.
let code = a.info.code.as_ref().unwrap();

let code = if code.is_eof() {
EOF_MAGIC_BYTES.clone()
} else {
code.original_bytes()
};

Ok(StateLoad::new(code, a.is_cold))
}

/// Gets code hash of address.
///
/// In case of EOF account it will return `EOF_MAGIC_HASH`
/// (the hash of `0xEF00`).
#[inline]
pub fn code_hash(
&mut self,
address: Address,
) -> Result<StateLoad<B256>, <DB as Database>::Error> {
let acc = self.load_account_code(address)?;
if acc.is_empty() {
return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
}
// SAFETY: Safe to unwrap as load_code will insert code if it is empty.
let code = acc.info.code.as_ref().unwrap();

let hash = if code.is_eof() {
EOF_MAGIC_HASH
} else {
acc.info.code_hash
};

Ok(StateLoad::new(hash, acc.is_cold))
}

/// Creates account or returns false if collision is detected.
///
/// There are few steps done:
Expand Down
Loading
Loading