revm_context_interface/
journaled_state.rs

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