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;
7
8pub use entry::{JournalEntry, JournalEntryTr};
9pub use inner::JournalInner;
10
11use bytecode::Bytecode;
12use context_interface::{
13    context::{SStoreResult, SelfDestructResult, StateLoad},
14    journaled_state::{AccountLoad, JournalCheckpoint, JournalTr, TransferError},
15};
16use core::ops::{Deref, DerefMut};
17use database_interface::Database;
18use primitives::{hardfork::SpecId, Address, HashSet, Log, B256, U256};
19use state::{Account, EvmState};
20use std::vec::Vec;
21
22/// A journal of state changes internal to the EVM
23///
24/// On each additional call, the depth of the journaled state is increased (`depth`) and a new journal is added.
25///
26/// The journal contains every state change that happens within that call, making it possible to revert changes made in a specific call.
27#[derive(Debug, Clone, PartialEq, Eq)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29pub struct Journal<DB, ENTRY = JournalEntry>
30where
31    ENTRY: JournalEntryTr,
32{
33    /// Database
34    pub database: DB,
35    /// Inner journal state.
36    pub inner: JournalInner<ENTRY>,
37}
38
39impl<DB, ENTRY> Deref for Journal<DB, ENTRY>
40where
41    ENTRY: JournalEntryTr,
42{
43    type Target = JournalInner<ENTRY>;
44
45    fn deref(&self) -> &Self::Target {
46        &self.inner
47    }
48}
49
50impl<DB, ENTRY> DerefMut for Journal<DB, ENTRY>
51where
52    ENTRY: JournalEntryTr,
53{
54    fn deref_mut(&mut self) -> &mut Self::Target {
55        &mut self.inner
56    }
57}
58
59impl<DB, ENTRY: JournalEntryTr> Journal<DB, ENTRY> {
60    /// Creates a new JournaledState by copying state data from a JournalInit and provided database.
61    /// This allows reusing the state, logs, and other data from a previous execution context while
62    /// connecting it to a different database backend.
63    pub fn new_with_inner(database: DB, inner: JournalInner<ENTRY>) -> Self {
64        Self { database, inner }
65    }
66
67    /// Consumes the [`Journal`] and returns [`JournalInner`].
68    ///
69    /// If you need to preserve the original journal, use [`Self::to_inner`] instead which clones the state.
70    pub fn into_init(self) -> JournalInner<ENTRY> {
71        self.inner
72    }
73}
74
75impl<DB, ENTRY: JournalEntryTr + Clone> Journal<DB, ENTRY> {
76    /// Creates a new [`JournalInner`] by cloning all internal state data (state, storage, logs, etc)
77    /// This allows creating a new journaled state with the same state data but without
78    /// carrying over the original database.
79    ///
80    /// This is useful when you want to reuse the current state for a new transaction or
81    /// execution context, but want to start with a fresh database.
82    pub fn to_inner(&self) -> JournalInner<ENTRY> {
83        self.inner.clone()
84    }
85}
86
87/// Output of the journal after finalizing.
88#[derive(Debug, Clone, PartialEq, Eq)]
89#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
90pub struct JournalOutput {
91    /// Changes or touched accounts that loads, created or changed in the journal.
92    pub state: EvmState,
93    /// Logs that were emitted by contract calls.
94    pub logs: Vec<Log>,
95}
96
97impl<DB: Database, ENTRY: JournalEntryTr> JournalTr for Journal<DB, ENTRY> {
98    type Database = DB;
99    type FinalOutput = JournalOutput;
100
101    fn new(database: DB) -> Journal<DB, ENTRY> {
102        Self {
103            inner: JournalInner::new(),
104            database,
105        }
106    }
107
108    fn db_ref(&self) -> &Self::Database {
109        &self.database
110    }
111
112    fn db(&mut self) -> &mut Self::Database {
113        &mut self.database
114    }
115
116    fn sload(
117        &mut self,
118        address: Address,
119        key: U256,
120    ) -> Result<StateLoad<U256>, <Self::Database as Database>::Error> {
121        self.inner.sload(&mut self.database, address, key)
122    }
123
124    fn sstore(
125        &mut self,
126        address: Address,
127        key: U256,
128        value: U256,
129    ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
130        self.inner.sstore(&mut self.database, address, key, value)
131    }
132
133    fn tload(&mut self, address: Address, key: U256) -> U256 {
134        self.inner.tload(address, key)
135    }
136
137    fn tstore(&mut self, address: Address, key: U256, value: U256) {
138        self.inner.tstore(address, key, value)
139    }
140
141    fn log(&mut self, log: Log) {
142        self.inner.log(log)
143    }
144
145    fn selfdestruct(
146        &mut self,
147        address: Address,
148        target: Address,
149    ) -> Result<StateLoad<SelfDestructResult>, DB::Error> {
150        self.inner.selfdestruct(&mut self.database, address, target)
151    }
152
153    fn warm_account(&mut self, address: Address) {
154        self.inner.warm_preloaded_addresses.insert(address);
155    }
156
157    fn warm_precompiles(&mut self, address: HashSet<Address>) {
158        self.inner.precompiles = address;
159        self.inner.warm_preloaded_addresses = self.inner.precompiles.clone();
160    }
161
162    #[inline]
163    fn precompile_addresses(&self) -> &HashSet<Address> {
164        &self.inner.precompiles
165    }
166
167    /// Returns call depth.
168    #[inline]
169    fn depth(&self) -> usize {
170        self.inner.depth
171    }
172
173    #[inline]
174    fn warm_account_and_storage(
175        &mut self,
176        address: Address,
177        storage_keys: impl IntoIterator<Item = U256>,
178    ) -> Result<(), <Self::Database as Database>::Error> {
179        self.inner
180            .initial_account_load(&mut self.database, address, storage_keys)?;
181        Ok(())
182    }
183
184    #[inline]
185    fn set_spec_id(&mut self, spec_id: SpecId) {
186        self.inner.spec = spec_id;
187    }
188
189    #[inline]
190    fn transfer(
191        &mut self,
192        from: Address,
193        to: Address,
194        balance: U256,
195    ) -> Result<Option<TransferError>, DB::Error> {
196        self.inner.transfer(&mut self.database, from, to, balance)
197    }
198
199    #[inline]
200    fn touch_account(&mut self, address: Address) {
201        self.inner.touch(address);
202    }
203
204    #[inline]
205    fn inc_account_nonce(&mut self, address: Address) -> Result<Option<u64>, DB::Error> {
206        Ok(self.inner.inc_nonce(address))
207    }
208
209    #[inline]
210    fn load_account(&mut self, address: Address) -> Result<StateLoad<&mut Account>, DB::Error> {
211        self.inner.load_account(&mut self.database, address)
212    }
213
214    #[inline]
215    fn load_account_code(
216        &mut self,
217        address: Address,
218    ) -> Result<StateLoad<&mut Account>, DB::Error> {
219        self.inner.load_code(&mut self.database, address)
220    }
221
222    #[inline]
223    fn load_account_delegated(
224        &mut self,
225        address: Address,
226    ) -> Result<StateLoad<AccountLoad>, DB::Error> {
227        self.inner
228            .load_account_delegated(&mut self.database, address)
229    }
230
231    #[inline]
232    fn checkpoint(&mut self) -> JournalCheckpoint {
233        self.inner.checkpoint()
234    }
235
236    #[inline]
237    fn checkpoint_commit(&mut self) {
238        self.inner.checkpoint_commit()
239    }
240
241    #[inline]
242    fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint) {
243        self.inner.checkpoint_revert(checkpoint)
244    }
245
246    #[inline]
247    fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256) {
248        self.inner.set_code_with_hash(address, code, hash);
249    }
250
251    #[inline]
252    fn clear(&mut self) {
253        // Clears the inner journal state. Preserving only the spec and precompile addresses.
254        let _ = self.inner.clear_and_take_output();
255    }
256
257    #[inline]
258    fn create_account_checkpoint(
259        &mut self,
260        caller: Address,
261        address: Address,
262        balance: U256,
263        spec_id: SpecId,
264    ) -> Result<JournalCheckpoint, TransferError> {
265        // Ignore error.
266        self.inner
267            .create_account_checkpoint(caller, address, balance, spec_id)
268    }
269
270    #[inline]
271    fn finalize(&mut self) -> Self::FinalOutput {
272        self.inner.clear_and_take_output()
273    }
274}