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