1pub mod account;
4pub mod entry;
5
6use crate::{
7 context::{SStoreResult, SelfDestructResult},
8 host::LoadError,
9 journaled_state::{account::JournaledAccount, entry::JournalEntryTr},
10};
11use core::ops::{Deref, DerefMut};
12use database_interface::Database;
13use primitives::{
14 hardfork::SpecId, Address, Bytes, HashMap, HashSet, Log, StorageKey, StorageValue, B256, U256,
15};
16use state::{Account, AccountInfo, Bytecode};
17use std::{borrow::Cow, vec::Vec};
18
19pub trait JournalTr {
21 type Database: Database;
23 type State;
25 type JournalEntry: JournalEntryTr;
27
28 fn new(database: Self::Database) -> Self;
32
33 fn db_mut(&mut self) -> &mut Self::Database;
35
36 fn db(&self) -> &Self::Database;
38
39 fn sload(
43 &mut self,
44 address: Address,
45 key: StorageKey,
46 ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error> {
47 self.sload_skip_cold_load(address, key, false)
49 .map_err(JournalLoadError::unwrap_db_error)
50 }
51
52 fn sload_skip_cold_load(
54 &mut self,
55 _address: Address,
56 _key: StorageKey,
57 _skip_cold_load: bool,
58 ) -> Result<StateLoad<StorageValue>, JournalLoadError<<Self::Database as Database>::Error>>;
59
60 fn sstore(
62 &mut self,
63 address: Address,
64 key: StorageKey,
65 value: StorageValue,
66 ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
67 self.sstore_skip_cold_load(address, key, value, false)
69 .map_err(JournalLoadError::unwrap_db_error)
70 }
71
72 fn sstore_skip_cold_load(
74 &mut self,
75 _address: Address,
76 _key: StorageKey,
77 _value: StorageValue,
78 _skip_cold_load: bool,
79 ) -> Result<StateLoad<SStoreResult>, JournalLoadError<<Self::Database as Database>::Error>>;
80
81 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
83
84 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
86
87 fn log(&mut self, log: Log);
89
90 fn take_logs(&mut self) -> Vec<Log>;
92
93 fn logs(&self) -> &[Log];
95
96 fn selfdestruct(
98 &mut self,
99 address: Address,
100 target: Address,
101 skip_cold_load: bool,
102 ) -> Result<StateLoad<SelfDestructResult>, JournalLoadError<<Self::Database as Database>::Error>>;
103
104 fn warm_access_list(&mut self, access_list: HashMap<Address, HashSet<StorageKey>>);
106
107 fn warm_coinbase_account(&mut self, address: Address);
109
110 fn warm_precompiles(&mut self, addresses: HashSet<Address>);
112
113 fn precompile_addresses(&self) -> &HashSet<Address>;
115
116 fn set_spec_id(&mut self, spec_id: SpecId);
118
119 fn touch_account(&mut self, address: Address);
121
122 fn transfer(
124 &mut self,
125 from: Address,
126 to: Address,
127 balance: U256,
128 ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
129
130 fn transfer_loaded(
132 &mut self,
133 from: Address,
134 to: Address,
135 balance: U256,
136 ) -> Option<TransferError>;
137
138 fn caller_accounting_journal_entry(
140 &mut self,
141 address: Address,
142 old_balance: U256,
143 bump_nonce: bool,
144 );
145
146 fn balance_incr(
148 &mut self,
149 address: Address,
150 balance: U256,
151 ) -> Result<(), <Self::Database as Database>::Error>;
152
153 fn nonce_bump_journal_entry(&mut self, address: Address);
155
156 fn load_account(
158 &mut self,
159 address: Address,
160 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
161
162 #[inline]
164 #[deprecated(note = "Use `load_account_with_code` instead")]
165 fn load_account_code(
166 &mut self,
167 address: Address,
168 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error> {
169 self.load_account_with_code(address)
170 }
171
172 fn load_account_with_code(
174 &mut self,
175 address: Address,
176 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
177
178 fn load_account_delegated(
180 &mut self,
181 address: Address,
182 ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
183
184 #[inline]
186 fn load_account_mut(
187 &mut self,
188 address: Address,
189 ) -> Result<
190 StateLoad<JournaledAccount<'_, Self::JournalEntry>>,
191 <Self::Database as Database>::Error,
192 > {
193 self.load_account_mut_optional_code(address, false)
194 }
195
196 #[inline]
198 fn load_account_with_code_mut(
199 &mut self,
200 address: Address,
201 ) -> Result<
202 StateLoad<JournaledAccount<'_, Self::JournalEntry>>,
203 <Self::Database as Database>::Error,
204 > {
205 self.load_account_mut_optional_code(address, true)
206 }
207
208 fn load_account_mut_optional_code(
210 &mut self,
211 address: Address,
212 load_code: bool,
213 ) -> Result<
214 StateLoad<JournaledAccount<'_, Self::JournalEntry>>,
215 <Self::Database as Database>::Error,
216 >;
217
218 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
220
221 #[inline]
225 fn set_code(&mut self, address: Address, code: Bytecode) {
226 let hash = code.hash_slow();
227 self.set_code_with_hash(address, code, hash);
228 }
229
230 #[inline]
232 fn code(
233 &mut self,
234 address: Address,
235 ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
236 let a = self.load_account_with_code(address)?;
237 let code = a.info.code.as_ref().unwrap().original_bytes();
239
240 Ok(StateLoad::new(code, a.is_cold))
241 }
242
243 fn code_hash(
245 &mut self,
246 address: Address,
247 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
248 let acc = self.load_account_with_code(address)?;
249 if acc.is_empty() {
250 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
251 }
252 let hash = acc.info.code_hash;
253 Ok(StateLoad::new(hash, acc.is_cold))
254 }
255
256 fn clear(&mut self) {
258 let _ = self.finalize();
259 }
260
261 fn checkpoint(&mut self) -> JournalCheckpoint;
264
265 fn checkpoint_commit(&mut self);
267
268 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
270
271 fn create_account_checkpoint(
273 &mut self,
274 caller: Address,
275 address: Address,
276 balance: U256,
277 spec_id: SpecId,
278 ) -> Result<JournalCheckpoint, TransferError>;
279
280 fn depth(&self) -> usize;
282
283 fn commit_tx(&mut self);
285
286 fn discard_tx(&mut self);
291
292 fn finalize(&mut self) -> Self::State;
294
295 fn load_account_info_skip_cold_load(
297 &mut self,
298 _address: Address,
299 _load_code: bool,
300 _skip_cold_load: bool,
301 ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>>;
302}
303
304#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
306#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
307pub enum JournalLoadError<E> {
308 DBError(E),
310 ColdLoadSkipped,
312}
313
314impl<E> JournalLoadError<E> {
315 #[inline]
317 pub fn is_db_error(&self) -> bool {
318 matches!(self, JournalLoadError::DBError(_))
319 }
320
321 #[inline]
323 pub fn is_cold_load_skipped(&self) -> bool {
324 matches!(self, JournalLoadError::ColdLoadSkipped)
325 }
326
327 #[inline]
329 pub fn take_db_error(self) -> Option<E> {
330 if let JournalLoadError::DBError(e) = self {
331 Some(e)
332 } else {
333 None
334 }
335 }
336
337 #[inline]
339 pub fn unwrap_db_error(self) -> E {
340 if let JournalLoadError::DBError(e) = self {
341 e
342 } else {
343 panic!("Expected DBError");
344 }
345 }
346
347 #[inline]
349 pub fn into_parts(self) -> (LoadError, Option<E>) {
350 match self {
351 JournalLoadError::DBError(e) => (LoadError::DBError, Some(e)),
352 JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None),
353 }
354 }
355}
356
357impl<E> From<E> for JournalLoadError<E> {
358 fn from(e: E) -> Self {
359 JournalLoadError::DBError(e)
360 }
361}
362
363impl<E> From<JournalLoadError<E>> for LoadError {
364 fn from(e: JournalLoadError<E>) -> Self {
365 match e {
366 JournalLoadError::DBError(_) => LoadError::DBError,
367 JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
368 }
369 }
370}
371
372#[derive(Copy, Clone, Debug, PartialEq, Eq)]
374pub enum TransferError {
375 OutOfFunds,
377 OverflowPayment,
379 CreateCollision,
381}
382
383#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
385#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
386pub struct JournalCheckpoint {
387 pub log_i: usize,
389 pub journal_i: usize,
391}
392
393#[derive(Clone, Debug, Default, PartialEq, Eq)]
395#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
396pub struct StateLoad<T> {
397 pub data: T,
399 pub is_cold: bool,
401}
402
403impl<T> Deref for StateLoad<T> {
404 type Target = T;
405
406 fn deref(&self) -> &Self::Target {
407 &self.data
408 }
409}
410
411impl<T> DerefMut for StateLoad<T> {
412 fn deref_mut(&mut self) -> &mut Self::Target {
413 &mut self.data
414 }
415}
416
417impl<T> StateLoad<T> {
418 #[inline]
420 pub fn new(data: T, is_cold: bool) -> Self {
421 Self { data, is_cold }
422 }
423
424 #[inline]
428 pub fn map<B, F>(self, f: F) -> StateLoad<B>
429 where
430 F: FnOnce(T) -> B,
431 {
432 StateLoad::new(f(self.data), self.is_cold)
433 }
434}
435
436#[derive(Clone, Debug, Default, PartialEq, Eq)]
438#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
439pub struct AccountLoad {
440 pub is_delegate_account_cold: Option<bool>,
442 pub is_empty: bool,
444}
445
446#[derive(Clone, Debug, Default, PartialEq, Eq)]
448#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
449pub struct AccountInfoLoad<'a> {
450 pub account: Cow<'a, AccountInfo>,
452 pub is_cold: bool,
454 pub is_empty: bool,
456}
457
458impl<'a> AccountInfoLoad<'a> {
459 pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
461 Self {
462 account: Cow::Borrowed(account),
463 is_cold,
464 is_empty,
465 }
466 }
467
468 pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
472 where
473 F: FnOnce(Cow<'a, AccountInfo>) -> O,
474 {
475 StateLoad::new(f(self.account), self.is_cold)
476 }
477}
478
479impl<'a> Deref for AccountInfoLoad<'a> {
480 type Target = AccountInfo;
481
482 fn deref(&self) -> &Self::Target {
483 &self.account
484 }
485}