revm_context_interface/
journaled_state.rs

1//! Journaled state trait [`JournalTr`] and related types.
2use crate::context::{SStoreResult, SelfDestructResult};
3use core::ops::{Deref, DerefMut};
4use database_interface::Database;
5use primitives::{
6    hardfork::SpecId, Address, Bytes, HashSet, Log, StorageKey, StorageValue, B256, U256,
7};
8use state::{Account, Bytecode};
9use std::vec::Vec;
10
11/// Trait that contains database and journal of all changes that were made to the state.
12pub trait JournalTr {
13    /// Database type that is used in the journal.
14    type Database: Database;
15    /// State type that is returned by the journal after finalization.
16    type State;
17
18    /// Creates new Journaled state.
19    ///
20    /// Dont forget to set spec_id.
21    fn new(database: Self::Database) -> Self;
22
23    /// Returns the database.
24    fn db_mut(&mut self) -> &mut Self::Database;
25
26    /// Returns the mutable database.
27    fn db(&self) -> &Self::Database;
28
29    /// Returns the storage value from Journal state.
30    ///
31    /// Loads the storage from database if not found in Journal state.
32    fn sload(
33        &mut self,
34        address: Address,
35        key: StorageKey,
36    ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error>;
37
38    /// Stores the storage value in Journal state.
39    fn sstore(
40        &mut self,
41        address: Address,
42        key: StorageKey,
43        value: StorageValue,
44    ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error>;
45
46    /// Loads transient storage value.
47    fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
48
49    /// Stores transient storage value.
50    fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
51
52    /// Logs the log in Journal state.
53    fn log(&mut self, log: Log);
54
55    /// Marks the account for selfdestruction and transfers all the balance to the target.
56    fn selfdestruct(
57        &mut self,
58        address: Address,
59        target: Address,
60    ) -> Result<StateLoad<SelfDestructResult>, <Self::Database as Database>::Error>;
61
62    /// Warms the account and storage.
63    fn warm_account_and_storage(
64        &mut self,
65        address: Address,
66        storage_keys: impl IntoIterator<Item = StorageKey>,
67    ) -> Result<(), <Self::Database as Database>::Error>;
68
69    /// Warms the account.
70    fn warm_account(&mut self, address: Address);
71
72    /// Warms the coinbase account.
73    fn warm_coinbase_account(&mut self, address: Address);
74
75    /// Warms the precompiles.
76    fn warm_precompiles(&mut self, addresses: HashSet<Address>);
77
78    /// Returns the addresses of the precompiles.
79    fn precompile_addresses(&self) -> &HashSet<Address>;
80
81    /// Sets the spec id.
82    fn set_spec_id(&mut self, spec_id: SpecId);
83
84    /// Touches the account.
85    fn touch_account(&mut self, address: Address);
86
87    /// Transfers the balance from one account to another.
88    fn transfer(
89        &mut self,
90        from: Address,
91        to: Address,
92        balance: U256,
93    ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
94
95    /// Increments the balance of the account.
96    fn caller_accounting_journal_entry(
97        &mut self,
98        address: Address,
99        old_balance: U256,
100        bump_nonce: bool,
101    );
102
103    /// Increments the balance of the account.
104    fn balance_incr(
105        &mut self,
106        address: Address,
107        balance: U256,
108    ) -> Result<(), <Self::Database as Database>::Error>;
109
110    /// Increments the nonce of the account.
111    fn nonce_bump_journal_entry(&mut self, address: Address);
112
113    /// Loads the account.
114    fn load_account(
115        &mut self,
116        address: Address,
117    ) -> Result<StateLoad<&mut Account>, <Self::Database as Database>::Error>;
118
119    /// Loads the account code.
120    fn load_account_code(
121        &mut self,
122        address: Address,
123    ) -> Result<StateLoad<&mut Account>, <Self::Database as Database>::Error>;
124
125    /// Loads the account delegated.
126    fn load_account_delegated(
127        &mut self,
128        address: Address,
129    ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
130
131    /// Sets bytecode with hash. Assume that account is warm.
132    fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
133
134    /// Sets bytecode and calculates hash.
135    ///
136    /// Assume account is warm.
137    #[inline]
138    fn set_code(&mut self, address: Address, code: Bytecode) {
139        let hash = code.hash_slow();
140        self.set_code_with_hash(address, code, hash);
141    }
142
143    /// Returns account code bytes and if address is cold loaded.
144    #[inline]
145    fn code(
146        &mut self,
147        address: Address,
148    ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
149        let a = self.load_account_code(address)?;
150        // SAFETY: Safe to unwrap as load_code will insert code if it is empty.
151        let code = a.info.code.as_ref().unwrap();
152        let code = code.original_bytes();
153
154        Ok(StateLoad::new(code, a.is_cold))
155    }
156
157    /// Gets code hash of account.
158    fn code_hash(
159        &mut self,
160        address: Address,
161    ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
162        let acc = self.load_account_code(address)?;
163        if acc.is_empty() {
164            return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
165        }
166        // SAFETY: Safe to unwrap as load_code will insert code if it is empty.
167        let _code = acc.info.code.as_ref().unwrap();
168
169        let hash = acc.info.code_hash;
170
171        Ok(StateLoad::new(hash, acc.is_cold))
172    }
173
174    /// Called at the end of the transaction to clean all residue data from journal.
175    fn clear(&mut self) {
176        let _ = self.finalize();
177    }
178
179    /// Creates a checkpoint of the current state. State can be revert to this point
180    /// if needed.
181    fn checkpoint(&mut self) -> JournalCheckpoint;
182
183    /// Commits the changes made since the last checkpoint.
184    fn checkpoint_commit(&mut self);
185
186    /// Reverts the changes made since the last checkpoint.
187    fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
188
189    /// Creates a checkpoint of the account creation.
190    fn create_account_checkpoint(
191        &mut self,
192        caller: Address,
193        address: Address,
194        balance: U256,
195        spec_id: SpecId,
196    ) -> Result<JournalCheckpoint, TransferError>;
197
198    /// Returns the depth of the journal.
199    fn depth(&self) -> usize;
200
201    /// Take logs from journal.
202    fn take_logs(&mut self) -> Vec<Log>;
203
204    /// Commit current transaction journal and returns transaction logs.
205    fn commit_tx(&mut self);
206
207    /// Discard current transaction journal by removing journal entries and logs and incrementing the transaction id.
208    ///
209    /// This function is useful to discard intermediate state that is interrupted by error and it will not revert
210    /// any already committed changes and it is safe to call it multiple times.
211    fn discard_tx(&mut self);
212
213    /// Clear current journal resetting it to initial state and return changes state.
214    fn finalize(&mut self) -> Self::State;
215}
216
217/// Transfer and creation result
218#[derive(Copy, Clone, Debug, PartialEq, Eq)]
219pub enum TransferError {
220    /// Caller does not have enough funds
221    OutOfFunds,
222    /// Overflow in target account
223    OverflowPayment,
224    /// Create collision.
225    CreateCollision,
226}
227
228/// SubRoutine checkpoint that will help us to go back from this
229#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
230#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
231pub struct JournalCheckpoint {
232    /// Checkpoint to where on revert we will go back to.
233    pub log_i: usize,
234    /// Checkpoint to where on revert we will go back to and revert other journal entries.
235    pub journal_i: usize,
236}
237
238/// State load information that contains the data and if the account or storage is cold loaded
239#[derive(Clone, Debug, Default, PartialEq, Eq)]
240#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
241pub struct StateLoad<T> {
242    /// Returned data
243    pub data: T,
244    /// Is account is cold loaded
245    pub is_cold: bool,
246}
247
248impl<T> Deref for StateLoad<T> {
249    type Target = T;
250
251    fn deref(&self) -> &Self::Target {
252        &self.data
253    }
254}
255
256impl<T> DerefMut for StateLoad<T> {
257    fn deref_mut(&mut self) -> &mut Self::Target {
258        &mut self.data
259    }
260}
261
262impl<T> StateLoad<T> {
263    /// Returns a new [`StateLoad`] with the given data and cold load status.
264    pub fn new(data: T, is_cold: bool) -> Self {
265        Self { data, is_cold }
266    }
267
268    /// Maps the data of the [`StateLoad`] to a new value.
269    ///
270    /// Useful for transforming the data of the [`StateLoad`] without changing the cold load status.
271    pub fn map<B, F>(self, f: F) -> StateLoad<B>
272    where
273        F: FnOnce(T) -> B,
274    {
275        StateLoad::new(f(self.data), self.is_cold)
276    }
277}
278
279/// Result of the account load from Journal state
280#[derive(Clone, Debug, Default, PartialEq, Eq)]
281#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
282pub struct AccountLoad {
283    /// Does account have delegate code and delegated account is cold loaded
284    pub is_delegate_account_cold: Option<bool>,
285    /// Is account empty, if `true` account is not created
286    pub is_empty: bool,
287}