pub mod inner;
pub mod warm_addresses;
pub use context_interface::journaled_state::entry::{JournalEntry, JournalEntryTr};
pub use inner::{JournalCfg, JournalInner};
use bytecode::Bytecode;
use context_interface::{
context::{SStoreResult, SelfDestructResult, StateLoad},
journaled_state::{
account::JournaledAccount, AccountInfoLoad, AccountLoad, JournalCheckpoint,
JournalLoadError, JournalTr, TransferError,
},
};
use core::ops::{Deref, DerefMut};
use database_interface::Database;
use primitives::{
hardfork::SpecId, Address, AddressMap, AddressSet, HashSet, Log, StorageKey, StorageValue,
B256, U256,
};
use state::{Account, EvmState};
use std::vec::Vec;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Journal<DB, ENTRY = JournalEntry>
where
ENTRY: JournalEntryTr,
{
pub database: DB,
pub inner: JournalInner<ENTRY>,
}
impl<DB, ENTRY> Deref for Journal<DB, ENTRY>
where
ENTRY: JournalEntryTr,
{
type Target = JournalInner<ENTRY>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<DB, ENTRY> DerefMut for Journal<DB, ENTRY>
where
ENTRY: JournalEntryTr,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<DB, ENTRY: JournalEntryTr> Journal<DB, ENTRY> {
pub fn new_with_inner(database: DB, inner: JournalInner<ENTRY>) -> Self {
Self { database, inner }
}
pub fn into_init(self) -> JournalInner<ENTRY> {
self.inner
}
}
impl<DB, ENTRY: JournalEntryTr + Clone> Journal<DB, ENTRY> {
pub fn to_inner(&self) -> JournalInner<ENTRY> {
self.inner.clone()
}
}
impl<DB: Database, ENTRY: JournalEntryTr> JournalTr for Journal<DB, ENTRY> {
type Database = DB;
type State = EvmState;
type JournaledAccount<'a>
= JournaledAccount<'a, DB, ENTRY>
where
ENTRY: 'a,
DB: 'a;
fn new(database: DB) -> Journal<DB, ENTRY> {
Self {
inner: JournalInner::new(),
database,
}
}
fn db(&self) -> &Self::Database {
&self.database
}
fn db_mut(&mut self) -> &mut Self::Database {
&mut self.database
}
fn sload(
&mut self,
address: Address,
key: StorageKey,
) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error> {
self.inner
.sload_assume_account_present(&mut self.database, address, key, false)
.map_err(JournalLoadError::unwrap_db_error)
}
fn sstore(
&mut self,
address: Address,
key: StorageKey,
value: StorageValue,
) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
self.inner
.sstore_assume_account_present(&mut self.database, address, key, value, false)
.map_err(JournalLoadError::unwrap_db_error)
}
fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue {
self.inner.tload(address, key)
}
fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue) {
self.inner.tstore(address, key, value)
}
fn log(&mut self, log: Log) {
self.inner.log(log)
}
#[inline]
fn logs(&self) -> &[Log] {
&self.inner.logs
}
#[inline]
fn take_logs(&mut self) -> Vec<Log> {
self.inner.take_logs()
}
fn selfdestruct(
&mut self,
address: Address,
target: Address,
skip_cold_load: bool,
) -> Result<StateLoad<SelfDestructResult>, JournalLoadError<<Self::Database as Database>::Error>>
{
self.inner
.selfdestruct(&mut self.database, address, target, skip_cold_load)
}
#[inline]
fn warm_access_list(&mut self, access_list: AddressMap<HashSet<StorageKey>>) {
self.inner.warm_addresses.set_access_list(access_list);
}
fn warm_coinbase_account(&mut self, address: Address) {
self.inner.warm_addresses.set_coinbase(address);
}
fn warm_precompiles(&mut self, precompiles: AddressSet) {
self.inner
.warm_addresses
.set_precompile_addresses(precompiles);
}
#[inline]
fn precompile_addresses(&self) -> &AddressSet {
self.inner.warm_addresses.precompiles()
}
#[inline]
fn depth(&self) -> usize {
self.inner.depth
}
#[inline]
fn set_spec_id(&mut self, spec_id: SpecId) {
self.inner.cfg.spec = spec_id;
}
#[inline]
fn set_eip7708_config(&mut self, disabled: bool, delayed_burn_disabled: bool) {
self.inner
.set_eip7708_config(disabled, delayed_burn_disabled);
}
#[inline]
fn transfer(
&mut self,
from: Address,
to: Address,
balance: U256,
) -> Result<Option<TransferError>, DB::Error> {
self.inner.transfer(&mut self.database, from, to, balance)
}
#[inline]
fn transfer_loaded(
&mut self,
from: Address,
to: Address,
balance: U256,
) -> Option<TransferError> {
self.inner.transfer_loaded(from, to, balance)
}
#[inline]
fn touch_account(&mut self, address: Address) {
self.inner.touch(address);
}
#[inline]
#[allow(deprecated)]
fn caller_accounting_journal_entry(
&mut self,
address: Address,
old_balance: U256,
bump_nonce: bool,
) {
self.inner
.caller_accounting_journal_entry(address, old_balance, bump_nonce);
}
#[inline]
fn balance_incr(
&mut self,
address: Address,
balance: U256,
) -> Result<(), <Self::Database as Database>::Error> {
self.inner
.balance_incr(&mut self.database, address, balance)
}
#[inline]
#[allow(deprecated)]
fn nonce_bump_journal_entry(&mut self, address: Address) {
self.inner.nonce_bump_journal_entry(address)
}
#[inline]
fn load_account(&mut self, address: Address) -> Result<StateLoad<&Account>, DB::Error> {
self.inner.load_account(&mut self.database, address)
}
#[inline]
fn load_account_mut_skip_cold_load(
&mut self,
address: Address,
skip_cold_load: bool,
) -> Result<StateLoad<Self::JournaledAccount<'_>>, JournalLoadError<DB::Error>> {
self.inner
.load_account_mut_optional(&mut self.database, address, skip_cold_load)
}
#[inline]
fn load_account_mut_optional_code(
&mut self,
address: Address,
load_code: bool,
) -> Result<StateLoad<Self::JournaledAccount<'_>>, DB::Error> {
self.inner
.load_account_mut_optional_code(&mut self.database, address, load_code, false)
.map_err(JournalLoadError::unwrap_db_error)
}
#[inline]
fn load_account_with_code(
&mut self,
address: Address,
) -> Result<StateLoad<&Account>, DB::Error> {
self.inner.load_code(&mut self.database, address)
}
#[inline]
fn load_account_delegated(
&mut self,
address: Address,
) -> Result<StateLoad<AccountLoad>, DB::Error> {
self.inner
.load_account_delegated(&mut self.database, address)
}
#[inline]
fn checkpoint(&mut self) -> JournalCheckpoint {
self.inner.checkpoint()
}
#[inline]
fn checkpoint_commit(&mut self) {
self.inner.checkpoint_commit()
}
#[inline]
fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) {
self.inner.checkpoint_revert(checkpoint)
}
#[inline]
fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256) {
self.inner.set_code_with_hash(address, code, hash);
}
#[inline]
fn create_account_checkpoint(
&mut self,
caller: Address,
address: Address,
balance: U256,
spec_id: SpecId,
) -> Result<JournalCheckpoint, TransferError> {
self.inner
.create_account_checkpoint(caller, address, balance, spec_id)
}
#[inline]
fn commit_tx(&mut self) {
self.inner.commit_tx()
}
#[inline]
fn discard_tx(&mut self) {
self.inner.discard_tx();
}
#[inline]
fn finalize(&mut self) -> Self::State {
self.inner.finalize()
}
#[inline]
fn sload_skip_cold_load(
&mut self,
address: Address,
key: StorageKey,
skip_cold_load: bool,
) -> Result<StateLoad<StorageValue>, JournalLoadError<<Self::Database as Database>::Error>>
{
self.inner
.sload_assume_account_present(&mut self.database, address, key, skip_cold_load)
}
#[inline]
fn sstore_skip_cold_load(
&mut self,
address: Address,
key: StorageKey,
value: StorageValue,
skip_cold_load: bool,
) -> Result<StateLoad<SStoreResult>, JournalLoadError<<Self::Database as Database>::Error>>
{
self.inner.sstore_assume_account_present(
&mut self.database,
address,
key,
value,
skip_cold_load,
)
}
#[inline]
fn load_account_info_skip_cold_load(
&mut self,
address: Address,
load_code: bool,
skip_cold_load: bool,
) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>> {
let spec = self.inner.cfg.spec;
self.inner
.load_account_optional(&mut self.database, address, load_code, skip_cold_load)
.map(|a| {
AccountInfoLoad::new(&a.data.info, a.is_cold, a.state_clear_aware_is_empty(spec))
})
}
}