revm_context_interface/
journaled_state.rs

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