revm_context_interface/
journaled_state.rs

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