revm_context_interface/
journaled_state.rs

1//! Journaled state trait [`JournalTr`] and related types.
2
3pub mod account;
4pub mod entry;
5
6use crate::{
7    context::{SStoreResult, SelfDestructResult},
8    host::LoadError,
9    journaled_state::{account::JournaledAccount, entry::JournalEntryTr},
10};
11use core::ops::{Deref, DerefMut};
12use database_interface::Database;
13use primitives::{
14    hardfork::SpecId, Address, Bytes, HashMap, HashSet, Log, StorageKey, StorageValue, B256, U256,
15};
16use state::{Account, AccountInfo, Bytecode};
17use std::{borrow::Cow, vec::Vec};
18
19/// Trait that contains database and journal of all changes that were made to the state.
20pub trait JournalTr {
21    /// Database type that is used in the journal.
22    type Database: Database;
23    /// State type that is returned by the journal after finalization.
24    type State;
25    /// Journal Entry type that is used in the journal.
26    type JournalEntry: JournalEntryTr;
27
28    /// Creates new Journaled state.
29    ///
30    /// Dont forget to set spec_id.
31    fn new(database: Self::Database) -> Self;
32
33    /// Returns a mutable reference to the database.
34    fn db_mut(&mut self) -> &mut Self::Database;
35
36    /// Returns an immutable reference to the database.
37    fn db(&self) -> &Self::Database;
38
39    /// Returns the storage value from Journal state.
40    ///
41    /// Loads the storage from database if not found in Journal state.
42    fn sload(
43        &mut self,
44        address: Address,
45        key: StorageKey,
46    ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error> {
47        // unwrapping is safe as we only can get DBError
48        self.sload_skip_cold_load(address, key, false)
49            .map_err(JournalLoadError::unwrap_db_error)
50    }
51
52    /// Loads the storage value from Journal state.
53    fn sload_skip_cold_load(
54        &mut self,
55        _address: Address,
56        _key: StorageKey,
57        _skip_cold_load: bool,
58    ) -> Result<StateLoad<StorageValue>, JournalLoadError<<Self::Database as Database>::Error>>;
59
60    /// Stores the storage value in Journal state.
61    fn sstore(
62        &mut self,
63        address: Address,
64        key: StorageKey,
65        value: StorageValue,
66    ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
67        // unwrapping is safe as we only can get DBError
68        self.sstore_skip_cold_load(address, key, value, false)
69            .map_err(JournalLoadError::unwrap_db_error)
70    }
71
72    /// Stores the storage value in Journal state.
73    fn sstore_skip_cold_load(
74        &mut self,
75        _address: Address,
76        _key: StorageKey,
77        _value: StorageValue,
78        _skip_cold_load: bool,
79    ) -> Result<StateLoad<SStoreResult>, JournalLoadError<<Self::Database as Database>::Error>>;
80
81    /// Loads transient storage value.
82    fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
83
84    /// Stores transient storage value.
85    fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
86
87    /// Logs the log in Journal state.
88    fn log(&mut self, log: Log);
89
90    /// Marks the account for selfdestruction and transfers all the balance to the target.
91    fn selfdestruct(
92        &mut self,
93        address: Address,
94        target: Address,
95    ) -> Result<StateLoad<SelfDestructResult>, <Self::Database as Database>::Error>;
96
97    /// Sets access list inside journal.
98    fn warm_access_list(&mut self, access_list: HashMap<Address, HashSet<StorageKey>>);
99
100    /// Warms the coinbase account.
101    fn warm_coinbase_account(&mut self, address: Address);
102
103    /// Warms the precompiles.
104    fn warm_precompiles(&mut self, addresses: HashSet<Address>);
105
106    /// Returns the addresses of the precompiles.
107    fn precompile_addresses(&self) -> &HashSet<Address>;
108
109    /// Sets the spec id.
110    fn set_spec_id(&mut self, spec_id: SpecId);
111
112    /// Touches the account.
113    fn touch_account(&mut self, address: Address);
114
115    /// Transfers the balance from one account to another.
116    fn transfer(
117        &mut self,
118        from: Address,
119        to: Address,
120        balance: U256,
121    ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
122
123    /// Transfers the balance from one account to another. Assume form and to are loaded.
124    fn transfer_loaded(
125        &mut self,
126        from: Address,
127        to: Address,
128        balance: U256,
129    ) -> Option<TransferError>;
130
131    /// Increments the balance of the account.
132    fn caller_accounting_journal_entry(
133        &mut self,
134        address: Address,
135        old_balance: U256,
136        bump_nonce: bool,
137    );
138
139    /// Increments the balance of the account.
140    fn balance_incr(
141        &mut self,
142        address: Address,
143        balance: U256,
144    ) -> Result<(), <Self::Database as Database>::Error>;
145
146    /// Increments the nonce of the account.
147    fn nonce_bump_journal_entry(&mut self, address: Address);
148
149    /// Loads the account.
150    fn load_account(
151        &mut self,
152        address: Address,
153    ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
154
155    /// Loads the account code, use `load_account_with_code` instead.
156    #[inline]
157    #[deprecated(note = "Use `load_account_with_code` instead")]
158    fn load_account_code(
159        &mut self,
160        address: Address,
161    ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error> {
162        self.load_account_with_code(address)
163    }
164
165    /// Loads the account with code.
166    fn load_account_with_code(
167        &mut self,
168        address: Address,
169    ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
170
171    /// Loads the account delegated.
172    fn load_account_delegated(
173        &mut self,
174        address: Address,
175    ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
176
177    /// Loads the journaled account.
178    #[inline]
179    fn load_account_mut(
180        &mut self,
181        address: Address,
182    ) -> Result<
183        StateLoad<JournaledAccount<'_, Self::JournalEntry>>,
184        <Self::Database as Database>::Error,
185    > {
186        self.load_account_mut_optional_code(address, false)
187    }
188
189    /// Loads the journaled account.
190    #[inline]
191    fn load_account_with_code_mut(
192        &mut self,
193        address: Address,
194    ) -> Result<
195        StateLoad<JournaledAccount<'_, Self::JournalEntry>>,
196        <Self::Database as Database>::Error,
197    > {
198        self.load_account_mut_optional_code(address, true)
199    }
200
201    /// Loads the journaled account.
202    fn load_account_mut_optional_code(
203        &mut self,
204        address: Address,
205        load_code: bool,
206    ) -> Result<
207        StateLoad<JournaledAccount<'_, Self::JournalEntry>>,
208        <Self::Database as Database>::Error,
209    >;
210
211    /// Sets bytecode with hash. Assume that account is warm.
212    fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
213
214    /// Sets bytecode and calculates hash.
215    ///
216    /// Assume account is warm.
217    #[inline]
218    fn set_code(&mut self, address: Address, code: Bytecode) {
219        let hash = code.hash_slow();
220        self.set_code_with_hash(address, code, hash);
221    }
222
223    /// Returns account code bytes and if address is cold loaded.
224    #[inline]
225    fn code(
226        &mut self,
227        address: Address,
228    ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
229        let a = self.load_account_with_code(address)?;
230        // SAFETY: Safe to unwrap as load_code will insert code if it is empty.
231        let code = a.info.code.as_ref().unwrap().original_bytes();
232
233        Ok(StateLoad::new(code, a.is_cold))
234    }
235
236    /// Gets code hash of account.
237    fn code_hash(
238        &mut self,
239        address: Address,
240    ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
241        let acc = self.load_account_with_code(address)?;
242        if acc.is_empty() {
243            return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
244        }
245        let hash = acc.info.code_hash;
246        Ok(StateLoad::new(hash, acc.is_cold))
247    }
248
249    /// Called at the end of the transaction to clean all residue data from journal.
250    fn clear(&mut self) {
251        let _ = self.finalize();
252    }
253
254    /// Creates a checkpoint of the current state. State can be revert to this point
255    /// if needed.
256    fn checkpoint(&mut self) -> JournalCheckpoint;
257
258    /// Commits the changes made since the last checkpoint.
259    fn checkpoint_commit(&mut self);
260
261    /// Reverts the changes made since the last checkpoint.
262    fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
263
264    /// Creates a checkpoint of the account creation.
265    fn create_account_checkpoint(
266        &mut self,
267        caller: Address,
268        address: Address,
269        balance: U256,
270        spec_id: SpecId,
271    ) -> Result<JournalCheckpoint, TransferError>;
272
273    /// Returns the depth of the journal.
274    fn depth(&self) -> usize;
275
276    /// Take logs from journal.
277    fn take_logs(&mut self) -> Vec<Log>;
278
279    /// Commit current transaction journal and returns transaction logs.
280    fn commit_tx(&mut self);
281
282    /// Discard current transaction journal by removing journal entries and logs and incrementing the transaction id.
283    ///
284    /// This function is useful to discard intermediate state that is interrupted by error and it will not revert
285    /// any already committed changes and it is safe to call it multiple times.
286    fn discard_tx(&mut self);
287
288    /// Clear current journal resetting it to initial state and return changes state.
289    fn finalize(&mut self) -> Self::State;
290
291    /// Loads the account info from Journal state.
292    fn load_account_info_skip_cold_load(
293        &mut self,
294        _address: Address,
295        _load_code: bool,
296        _skip_cold_load: bool,
297    ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>>;
298}
299
300/// Error that can happen when loading account info.
301#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
302#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
303pub enum JournalLoadError<E> {
304    /// Database error.
305    DBError(E),
306    /// Cold load skipped.
307    ColdLoadSkipped,
308}
309
310impl<E> JournalLoadError<E> {
311    /// Returns true if the error is a database error.
312    #[inline]
313    pub fn is_db_error(&self) -> bool {
314        matches!(self, JournalLoadError::DBError(_))
315    }
316
317    /// Returns true if the error is a cold load skipped.
318    #[inline]
319    pub fn is_cold_load_skipped(&self) -> bool {
320        matches!(self, JournalLoadError::ColdLoadSkipped)
321    }
322
323    /// Takes the error if it is a database error.
324    #[inline]
325    pub fn take_db_error(self) -> Option<E> {
326        if let JournalLoadError::DBError(e) = self {
327            Some(e)
328        } else {
329            None
330        }
331    }
332
333    /// Unwraps the error if it is a database error.
334    #[inline]
335    pub fn unwrap_db_error(self) -> E {
336        if let JournalLoadError::DBError(e) = self {
337            e
338        } else {
339            panic!("Expected DBError");
340        }
341    }
342
343    /// Converts the error to a load error.
344    #[inline]
345    pub fn into_parts(self) -> (LoadError, Option<E>) {
346        match self {
347            JournalLoadError::DBError(e) => (LoadError::DBError, Some(e)),
348            JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None),
349        }
350    }
351}
352
353impl<E> From<E> for JournalLoadError<E> {
354    fn from(e: E) -> Self {
355        JournalLoadError::DBError(e)
356    }
357}
358
359impl<E> From<JournalLoadError<E>> for LoadError {
360    fn from(e: JournalLoadError<E>) -> Self {
361        match e {
362            JournalLoadError::DBError(_) => LoadError::DBError,
363            JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
364        }
365    }
366}
367
368/// Transfer and creation result
369#[derive(Copy, Clone, Debug, PartialEq, Eq)]
370pub enum TransferError {
371    /// Caller does not have enough funds
372    OutOfFunds,
373    /// Overflow in target account
374    OverflowPayment,
375    /// Create collision.
376    CreateCollision,
377}
378
379/// SubRoutine checkpoint that will help us to go back from this
380#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
381#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
382pub struct JournalCheckpoint {
383    /// Checkpoint to where on revert we will go back to.
384    pub log_i: usize,
385    /// Checkpoint to where on revert we will go back to and revert other journal entries.
386    pub journal_i: usize,
387}
388
389/// State load information that contains the data and if the account or storage is cold loaded
390#[derive(Clone, Debug, Default, PartialEq, Eq)]
391#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
392pub struct StateLoad<T> {
393    /// Returned data
394    pub data: T,
395    /// Is account is cold loaded
396    pub is_cold: bool,
397}
398
399impl<T> Deref for StateLoad<T> {
400    type Target = T;
401
402    fn deref(&self) -> &Self::Target {
403        &self.data
404    }
405}
406
407impl<T> DerefMut for StateLoad<T> {
408    fn deref_mut(&mut self) -> &mut Self::Target {
409        &mut self.data
410    }
411}
412
413impl<T> StateLoad<T> {
414    /// Returns a new [`StateLoad`] with the given data and cold load status.
415    #[inline]
416    pub fn new(data: T, is_cold: bool) -> Self {
417        Self { data, is_cold }
418    }
419
420    /// Maps the data of the [`StateLoad`] to a new value.
421    ///
422    /// Useful for transforming the data of the [`StateLoad`] without changing the cold load status.
423    #[inline]
424    pub fn map<B, F>(self, f: F) -> StateLoad<B>
425    where
426        F: FnOnce(T) -> B,
427    {
428        StateLoad::new(f(self.data), self.is_cold)
429    }
430}
431
432/// Result of the account load from Journal state
433#[derive(Clone, Debug, Default, PartialEq, Eq)]
434#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
435pub struct AccountLoad {
436    /// Does account have delegate code and delegated account is cold loaded
437    pub is_delegate_account_cold: Option<bool>,
438    /// Is account empty, if `true` account is not created
439    pub is_empty: bool,
440}
441
442/// Result of the account load from Journal state
443#[derive(Clone, Debug, Default, PartialEq, Eq)]
444#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
445pub struct AccountInfoLoad<'a> {
446    /// Account info
447    pub account: Cow<'a, AccountInfo>,
448    /// Is account cold loaded
449    pub is_cold: bool,
450    /// Is account empty, if `true` account is not created
451    pub is_empty: bool,
452}
453
454impl<'a> AccountInfoLoad<'a> {
455    /// Creates new [`AccountInfoLoad`] with the given account info, cold load status and empty status.
456    pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
457        Self {
458            account: Cow::Borrowed(account),
459            is_cold,
460            is_empty,
461        }
462    }
463
464    /// Maps the account info of the [`AccountInfoLoad`] to a new [`StateLoad`].
465    ///
466    /// Useful for transforming the account info of the [`AccountInfoLoad`] and preserving the cold load status.
467    pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
468    where
469        F: FnOnce(Cow<'a, AccountInfo>) -> O,
470    {
471        StateLoad::new(f(self.account), self.is_cold)
472    }
473}
474
475impl<'a> Deref for AccountInfoLoad<'a> {
476    type Target = AccountInfo;
477
478    fn deref(&self) -> &Self::Target {
479        &self.account
480    }
481}