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, ENTRY>
97    where
98        Self: 'a;
99
100    fn new(database: DB) -> Journal<DB, ENTRY> {
101        Self {
102            inner: JournalInner::new(),
103            database,
104        }
105    }
106
107    fn db(&self) -> &Self::Database {
108        &self.database
109    }
110
111    fn db_mut(&mut self) -> &mut Self::Database {
112        &mut self.database
113    }
114
115    fn sload(
116        &mut self,
117        address: Address,
118        key: StorageKey,
119    ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error> {
120        self.inner
121            .sload(&mut self.database, address, key, false)
122            .map_err(JournalLoadError::unwrap_db_error)
123    }
124
125    fn sstore(
126        &mut self,
127        address: Address,
128        key: StorageKey,
129        value: StorageValue,
130    ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
131        self.inner
132            .sstore(&mut self.database, address, key, value, false)
133            .map_err(JournalLoadError::unwrap_db_error)
134    }
135
136    fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue {
137        self.inner.tload(address, key)
138    }
139
140    fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue) {
141        self.inner.tstore(address, key, value)
142    }
143
144    fn log(&mut self, log: Log) {
145        self.inner.log(log)
146    }
147
148    #[inline]
149    fn logs(&self) -> &[Log] {
150        &self.inner.logs
151    }
152
153    #[inline]
154    fn take_logs(&mut self) -> Vec<Log> {
155        self.inner.take_logs()
156    }
157
158    fn selfdestruct(
159        &mut self,
160        address: Address,
161        target: Address,
162        skip_cold_load: bool,
163    ) -> Result<StateLoad<SelfDestructResult>, JournalLoadError<<Self::Database as Database>::Error>>
164    {
165        self.inner
166            .selfdestruct(&mut self.database, address, target, skip_cold_load)
167    }
168
169    #[inline]
170    fn warm_access_list(&mut self, access_list: HashMap<Address, HashSet<StorageKey>>) {
171        self.inner.warm_addresses.set_access_list(access_list);
172    }
173
174    fn warm_coinbase_account(&mut self, address: Address) {
175        self.inner.warm_addresses.set_coinbase(address);
176    }
177
178    fn warm_precompiles(&mut self, precompiles: HashSet<Address>) {
179        self.inner
180            .warm_addresses
181            .set_precompile_addresses(precompiles);
182    }
183
184    #[inline]
185    fn precompile_addresses(&self) -> &HashSet<Address> {
186        self.inner.warm_addresses.precompiles()
187    }
188
189    /// Returns call depth.
190    #[inline]
191    fn depth(&self) -> usize {
192        self.inner.depth
193    }
194
195    #[inline]
196    fn set_spec_id(&mut self, spec_id: SpecId) {
197        self.inner.spec = spec_id;
198    }
199
200    #[inline]
201    fn transfer(
202        &mut self,
203        from: Address,
204        to: Address,
205        balance: U256,
206    ) -> Result<Option<TransferError>, DB::Error> {
207        self.inner.transfer(&mut self.database, from, to, balance)
208    }
209
210    #[inline]
211    fn transfer_loaded(
212        &mut self,
213        from: Address,
214        to: Address,
215        balance: U256,
216    ) -> Option<TransferError> {
217        self.inner.transfer_loaded(from, to, balance)
218    }
219
220    #[inline]
221    fn touch_account(&mut self, address: Address) {
222        self.inner.touch(address);
223    }
224
225    #[inline]
226    fn caller_accounting_journal_entry(
227        &mut self,
228        address: Address,
229        old_balance: U256,
230        bump_nonce: bool,
231    ) {
232        self.inner
233            .caller_accounting_journal_entry(address, old_balance, bump_nonce);
234    }
235
236    /// Increments the balance of the account.
237    #[inline]
238    fn balance_incr(
239        &mut self,
240        address: Address,
241        balance: U256,
242    ) -> Result<(), <Self::Database as Database>::Error> {
243        self.inner
244            .balance_incr(&mut self.database, address, balance)
245    }
246
247    /// Increments the nonce of the account.
248    #[inline]
249    fn nonce_bump_journal_entry(&mut self, address: Address) {
250        self.inner.nonce_bump_journal_entry(address)
251    }
252
253    #[inline]
254    fn load_account(&mut self, address: Address) -> Result<StateLoad<&Account>, DB::Error> {
255        self.inner.load_account(&mut self.database, address)
256    }
257
258    #[inline]
259    fn load_account_mut_optional_code(
260        &mut self,
261        address: Address,
262        load_code: bool,
263    ) -> Result<StateLoad<Self::JournaledAccount<'_>>, DB::Error> {
264        self.inner
265            .load_account_mut_optional_code(&mut self.database, address, load_code, false)
266            .map_err(JournalLoadError::unwrap_db_error)
267    }
268
269    #[inline]
270    fn load_account_with_code(
271        &mut self,
272        address: Address,
273    ) -> Result<StateLoad<&Account>, DB::Error> {
274        self.inner.load_code(&mut self.database, address)
275    }
276
277    #[inline]
278    fn load_account_delegated(
279        &mut self,
280        address: Address,
281    ) -> Result<StateLoad<AccountLoad>, DB::Error> {
282        self.inner
283            .load_account_delegated(&mut self.database, address)
284    }
285
286    #[inline]
287    fn checkpoint(&mut self) -> JournalCheckpoint {
288        self.inner.checkpoint()
289    }
290
291    #[inline]
292    fn checkpoint_commit(&mut self) {
293        self.inner.checkpoint_commit()
294    }
295
296    #[inline]
297    fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) {
298        self.inner.checkpoint_revert(checkpoint)
299    }
300
301    #[inline]
302    fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256) {
303        self.inner.set_code_with_hash(address, code, hash);
304    }
305
306    #[inline]
307    fn create_account_checkpoint(
308        &mut self,
309        caller: Address,
310        address: Address,
311        balance: U256,
312        spec_id: SpecId,
313    ) -> Result<JournalCheckpoint, TransferError> {
314        // Ignore error.
315        self.inner
316            .create_account_checkpoint(caller, address, balance, spec_id)
317    }
318
319    #[inline]
320    fn commit_tx(&mut self) {
321        self.inner.commit_tx()
322    }
323
324    #[inline]
325    fn discard_tx(&mut self) {
326        self.inner.discard_tx();
327    }
328
329    /// Clear current journal resetting it to initial state and return changes state.
330    #[inline]
331    fn finalize(&mut self) -> Self::State {
332        self.inner.finalize()
333    }
334
335    #[inline]
336    fn sload_skip_cold_load(
337        &mut self,
338        address: Address,
339        key: StorageKey,
340        skip_cold_load: bool,
341    ) -> Result<StateLoad<StorageValue>, JournalLoadError<<Self::Database as Database>::Error>>
342    {
343        self.inner
344            .sload(&mut self.database, address, key, skip_cold_load)
345    }
346
347    #[inline]
348    fn sstore_skip_cold_load(
349        &mut self,
350        address: Address,
351        key: StorageKey,
352        value: StorageValue,
353        skip_cold_load: bool,
354    ) -> Result<StateLoad<SStoreResult>, JournalLoadError<<Self::Database as Database>::Error>>
355    {
356        self.inner
357            .sstore(&mut self.database, address, key, value, skip_cold_load)
358    }
359
360    #[inline]
361    fn load_account_info_skip_cold_load(
362        &mut self,
363        address: Address,
364        load_code: bool,
365        skip_cold_load: bool,
366    ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>> {
367        let spec = self.inner.spec;
368        self.inner
369            .load_account_optional(&mut self.database, address, load_code, skip_cold_load)
370            .map(|a| {
371                AccountInfoLoad::new(&a.data.info, a.is_cold, a.state_clear_aware_is_empty(spec))
372            })
373    }
374}