revm_context/
journal.rs

1//! This module contains [`Journal`] struct and implements [`JournalTr`] trait for it.
2//!
3//! Entry submodule contains [`JournalEntry`] and [`JournalEntryTr`] traits.
4//! and inner submodule contains [`JournalInner`] struct that contains state.
5pub mod entry;
6pub mod inner;
7pub mod warm_addresses;
8
9pub use entry::{JournalEntry, JournalEntryTr};
10pub use inner::JournalInner;
11
12use bytecode::Bytecode;
13use context_interface::{
14    context::{SStoreResult, SelfDestructResult, StateLoad},
15    journaled_state::{
16        AccountInfoLoad, AccountLoad, JournalCheckpoint, JournalLoadError, JournalTr, TransferError,
17    },
18};
19use core::ops::{Deref, DerefMut};
20use database_interface::Database;
21use primitives::{hardfork::SpecId, Address, HashSet, Log, StorageKey, StorageValue, B256, U256};
22use state::{Account, EvmState};
23use std::vec::Vec;
24
25/// A journal of state changes internal to the EVM
26///
27/// On each additional call, the depth of the journaled state is increased (`depth`) and a new journal is added.
28///
29/// The journal contains every state change that happens within that call, making it possible to revert changes made in a specific call.
30#[derive(Debug, Clone, PartialEq, Eq)]
31#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
32pub struct Journal<DB, ENTRY = JournalEntry>
33where
34    ENTRY: JournalEntryTr,
35{
36    /// Database
37    pub database: DB,
38    /// Inner journal state.
39    pub inner: JournalInner<ENTRY>,
40}
41
42impl<DB, ENTRY> Deref for Journal<DB, ENTRY>
43where
44    ENTRY: JournalEntryTr,
45{
46    type Target = JournalInner<ENTRY>;
47
48    fn deref(&self) -> &Self::Target {
49        &self.inner
50    }
51}
52
53impl<DB, ENTRY> DerefMut for Journal<DB, ENTRY>
54where
55    ENTRY: JournalEntryTr,
56{
57    fn deref_mut(&mut self) -> &mut Self::Target {
58        &mut self.inner
59    }
60}
61
62impl<DB, ENTRY: JournalEntryTr> Journal<DB, ENTRY> {
63    /// Creates a new JournaledState by copying state data from a JournalInit and provided database.
64    /// This allows reusing the state, logs, and other data from a previous execution context while
65    /// connecting it to a different database backend.
66    pub fn new_with_inner(database: DB, inner: JournalInner<ENTRY>) -> Self {
67        Self { database, inner }
68    }
69
70    /// Consumes the [`Journal`] and returns [`JournalInner`].
71    ///
72    /// If you need to preserve the original journal, use [`Self::to_inner`] instead which clones the state.
73    pub fn into_init(self) -> JournalInner<ENTRY> {
74        self.inner
75    }
76}
77
78impl<DB, ENTRY: JournalEntryTr + Clone> Journal<DB, ENTRY> {
79    /// Creates a new [`JournalInner`] by cloning all internal state data (state, storage, logs, etc)
80    /// This allows creating a new journaled state with the same state data but without
81    /// carrying over the original database.
82    ///
83    /// This is useful when you want to reuse the current state for a new transaction or
84    /// execution context, but want to start with a fresh database.
85    pub fn to_inner(&self) -> JournalInner<ENTRY> {
86        self.inner.clone()
87    }
88}
89
90impl<DB: Database, ENTRY: JournalEntryTr> JournalTr for Journal<DB, ENTRY> {
91    type Database = DB;
92    type State = EvmState;
93
94    fn new(database: DB) -> Journal<DB, ENTRY> {
95        Self {
96            inner: JournalInner::new(),
97            database,
98        }
99    }
100
101    fn db(&self) -> &Self::Database {
102        &self.database
103    }
104
105    fn db_mut(&mut self) -> &mut Self::Database {
106        &mut self.database
107    }
108
109    fn sload(
110        &mut self,
111        address: Address,
112        key: StorageKey,
113    ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error> {
114        self.inner
115            .sload(&mut self.database, address, key, false)
116            .map_err(JournalLoadError::unwrap_db_error)
117    }
118
119    fn sstore(
120        &mut self,
121        address: Address,
122        key: StorageKey,
123        value: StorageValue,
124    ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
125        self.inner
126            .sstore(&mut self.database, address, key, value, false)
127            .map_err(JournalLoadError::unwrap_db_error)
128    }
129
130    fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue {
131        self.inner.tload(address, key)
132    }
133
134    fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue) {
135        self.inner.tstore(address, key, value)
136    }
137
138    fn log(&mut self, log: Log) {
139        self.inner.log(log)
140    }
141
142    fn selfdestruct(
143        &mut self,
144        address: Address,
145        target: Address,
146    ) -> Result<StateLoad<SelfDestructResult>, DB::Error> {
147        self.inner.selfdestruct(&mut self.database, address, target)
148    }
149
150    fn warm_coinbase_account(&mut self, address: Address) {
151        self.inner.warm_addresses.set_coinbase(address);
152    }
153
154    fn warm_precompiles(&mut self, precompiles: HashSet<Address>) {
155        self.inner
156            .warm_addresses
157            .set_precompile_addresses(precompiles);
158    }
159
160    #[inline]
161    fn precompile_addresses(&self) -> &HashSet<Address> {
162        self.inner.warm_addresses.precompiles()
163    }
164
165    /// Returns call depth.
166    #[inline]
167    fn depth(&self) -> usize {
168        self.inner.depth
169    }
170
171    #[inline]
172    fn warm_account_and_storage(
173        &mut self,
174        address: Address,
175        storage_keys: impl IntoIterator<Item = StorageKey>,
176    ) -> Result<(), <Self::Database as Database>::Error> {
177        self.inner
178            .load_account_optional(&mut self.database, address, false, storage_keys, false)
179            .map_err(JournalLoadError::unwrap_db_error)?;
180        Ok(())
181    }
182
183    #[inline]
184    fn set_spec_id(&mut self, spec_id: SpecId) {
185        self.inner.spec = spec_id;
186    }
187
188    #[inline]
189    fn transfer(
190        &mut self,
191        from: Address,
192        to: Address,
193        balance: U256,
194    ) -> Result<Option<TransferError>, DB::Error> {
195        self.inner.transfer(&mut self.database, from, to, balance)
196    }
197
198    #[inline]
199    fn transfer_loaded(
200        &mut self,
201        from: Address,
202        to: Address,
203        balance: U256,
204    ) -> Option<TransferError> {
205        self.inner.transfer_loaded(from, to, balance)
206    }
207
208    #[inline]
209    fn touch_account(&mut self, address: Address) {
210        self.inner.touch(address);
211    }
212
213    #[inline]
214    fn caller_accounting_journal_entry(
215        &mut self,
216        address: Address,
217        old_balance: U256,
218        bump_nonce: bool,
219    ) {
220        self.inner
221            .caller_accounting_journal_entry(address, old_balance, bump_nonce);
222    }
223
224    /// Increments the balance of the account.
225    #[inline]
226    fn balance_incr(
227        &mut self,
228        address: Address,
229        balance: U256,
230    ) -> Result<(), <Self::Database as Database>::Error> {
231        self.inner
232            .balance_incr(&mut self.database, address, balance)
233    }
234
235    /// Increments the nonce of the account.
236    #[inline]
237    fn nonce_bump_journal_entry(&mut self, address: Address) {
238        self.inner.nonce_bump_journal_entry(address)
239    }
240
241    #[inline]
242    fn load_account(&mut self, address: Address) -> Result<StateLoad<&mut Account>, DB::Error> {
243        self.inner.load_account(&mut self.database, address)
244    }
245
246    #[inline]
247    fn load_account_code(
248        &mut self,
249        address: Address,
250    ) -> Result<StateLoad<&mut Account>, DB::Error> {
251        self.inner.load_code(&mut self.database, address)
252    }
253
254    #[inline]
255    fn load_account_delegated(
256        &mut self,
257        address: Address,
258    ) -> Result<StateLoad<AccountLoad>, DB::Error> {
259        self.inner
260            .load_account_delegated(&mut self.database, address)
261    }
262
263    #[inline]
264    fn checkpoint(&mut self) -> JournalCheckpoint {
265        self.inner.checkpoint()
266    }
267
268    #[inline]
269    fn checkpoint_commit(&mut self) {
270        self.inner.checkpoint_commit()
271    }
272
273    #[inline]
274    fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) {
275        self.inner.checkpoint_revert(checkpoint)
276    }
277
278    #[inline]
279    fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256) {
280        self.inner.set_code_with_hash(address, code, hash);
281    }
282
283    #[inline]
284    fn create_account_checkpoint(
285        &mut self,
286        caller: Address,
287        address: Address,
288        balance: U256,
289        spec_id: SpecId,
290    ) -> Result<JournalCheckpoint, TransferError> {
291        // Ignore error.
292        self.inner
293            .create_account_checkpoint(caller, address, balance, spec_id)
294    }
295
296    #[inline]
297    fn take_logs(&mut self) -> Vec<Log> {
298        self.inner.take_logs()
299    }
300
301    #[inline]
302    fn commit_tx(&mut self) {
303        self.inner.commit_tx()
304    }
305
306    #[inline]
307    fn discard_tx(&mut self) {
308        self.inner.discard_tx();
309    }
310
311    /// Clear current journal resetting it to initial state and return changes state.
312    #[inline]
313    fn finalize(&mut self) -> Self::State {
314        self.inner.finalize()
315    }
316
317    #[inline]
318    fn sload_skip_cold_load(
319        &mut self,
320        address: Address,
321        key: StorageKey,
322        skip_cold_load: bool,
323    ) -> Result<StateLoad<StorageValue>, JournalLoadError<<Self::Database as Database>::Error>>
324    {
325        self.inner
326            .sload(&mut self.database, address, key, skip_cold_load)
327    }
328
329    #[inline]
330    fn sstore_skip_cold_load(
331        &mut self,
332        address: Address,
333        key: StorageKey,
334        value: StorageValue,
335        skip_cold_load: bool,
336    ) -> Result<StateLoad<SStoreResult>, JournalLoadError<<Self::Database as Database>::Error>>
337    {
338        self.inner
339            .sstore(&mut self.database, address, key, value, skip_cold_load)
340    }
341
342    fn load_account_info_skip_cold_load(
343        &mut self,
344        address: Address,
345        load_code: bool,
346        skip_cold_load: bool,
347    ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>> {
348        let spec = self.inner.spec;
349        self.inner
350            .load_account_optional(&mut self.database, address, load_code, [], skip_cold_load)
351            .map(|a| {
352                AccountInfoLoad::new(&a.data.info, a.is_cold, a.state_clear_aware_is_empty(spec))
353            })
354    }
355}