1pub mod account;
4pub mod entry;
5
6use crate::{
7 context::{SStoreResult, SelfDestructResult},
8 host::LoadError,
9 journaled_state::account::JournaledAccountTr,
10 ErasedError,
11};
12use core::ops::{Deref, DerefMut};
13use database_interface::Database;
14use primitives::{
15 hardfork::SpecId, Address, AddressMap, AddressSet, Bytes, HashSet, Log, StorageKey,
16 StorageValue, B256, U256,
17};
18use state::{Account, AccountInfo, Bytecode};
19use std::{borrow::Cow, vec::Vec};
20pub trait JournalTr {
22 type Database: Database;
24 type State;
26 type JournaledAccount<'a>: JournaledAccountTr
28 where
29 Self: 'a;
30
31 fn new(database: Self::Database) -> Self;
35
36 fn db_mut(&mut self) -> &mut Self::Database {
38 self.db_and_state_mut().0
39 }
40
41 fn db(&self) -> &Self::Database {
43 self.db_and_state().0
44 }
45
46 fn evm_state_mut(&mut self) -> &mut Self::State {
48 self.db_and_state_mut().1
49 }
50
51 fn evm_state(&self) -> &Self::State {
53 self.db_and_state().1
54 }
55
56 fn db_and_state(&self) -> (&Self::Database, &Self::State);
58
59 fn db_and_state_mut(&mut self) -> (&mut Self::Database, &mut Self::State);
61
62 fn sload(
66 &mut self,
67 address: Address,
68 key: StorageKey,
69 ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error> {
70 self.sload_skip_cold_load(address, key, false)
72 .map_err(JournalLoadError::unwrap_db_error)
73 }
74
75 fn sload_skip_cold_load(
77 &mut self,
78 _address: Address,
79 _key: StorageKey,
80 _skip_cold_load: bool,
81 ) -> Result<StateLoad<StorageValue>, JournalLoadError<<Self::Database as Database>::Error>>;
82
83 fn sstore(
85 &mut self,
86 address: Address,
87 key: StorageKey,
88 value: StorageValue,
89 ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
90 self.sstore_skip_cold_load(address, key, value, false)
92 .map_err(JournalLoadError::unwrap_db_error)
93 }
94
95 fn sstore_skip_cold_load(
97 &mut self,
98 _address: Address,
99 _key: StorageKey,
100 _value: StorageValue,
101 _skip_cold_load: bool,
102 ) -> Result<StateLoad<SStoreResult>, JournalLoadError<<Self::Database as Database>::Error>>;
103
104 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
106
107 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
109
110 fn log(&mut self, log: Log);
112
113 fn take_logs(&mut self) -> Vec<Log>;
115
116 fn logs(&self) -> &[Log];
118
119 fn selfdestruct(
121 &mut self,
122 address: Address,
123 target: Address,
124 skip_cold_load: bool,
125 ) -> Result<StateLoad<SelfDestructResult>, JournalLoadError<<Self::Database as Database>::Error>>;
126
127 fn warm_access_list(&mut self, access_list: AddressMap<HashSet<StorageKey>>);
129
130 fn warm_coinbase_account(&mut self, address: Address);
132
133 fn warm_precompiles(&mut self, addresses: &AddressSet);
135
136 fn precompile_addresses(&self) -> &AddressSet;
138
139 fn set_spec_id(&mut self, spec_id: SpecId);
141
142 fn set_eip7708_config(&mut self, disabled: bool, eip8246_delayed_clear_disabled: bool);
153
154 fn touch_account(&mut self, address: Address);
156
157 fn transfer(
159 &mut self,
160 from: Address,
161 to: Address,
162 balance: U256,
163 ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
164
165 fn transfer_loaded(
167 &mut self,
168 from: Address,
169 to: Address,
170 balance: U256,
171 ) -> Option<TransferError>;
172
173 #[deprecated]
175 fn caller_accounting_journal_entry(
176 &mut self,
177 address: Address,
178 old_balance: U256,
179 bump_nonce: bool,
180 );
181
182 fn balance_incr(
184 &mut self,
185 address: Address,
186 balance: U256,
187 ) -> Result<(), <Self::Database as Database>::Error>;
188
189 #[deprecated]
191 fn nonce_bump_journal_entry(&mut self, address: Address);
192
193 fn load_account(
195 &mut self,
196 address: Address,
197 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
198
199 #[inline]
201 #[deprecated(note = "Use `load_account_with_code` instead")]
202 fn load_account_code(
203 &mut self,
204 address: Address,
205 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error> {
206 self.load_account_with_code(address)
207 }
208
209 fn load_account_with_code(
211 &mut self,
212 address: Address,
213 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
214
215 fn load_account_delegated(
217 &mut self,
218 address: Address,
219 ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
220
221 #[inline]
223 fn load_account_mut(
224 &mut self,
225 address: Address,
226 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error> {
227 self.load_account_mut_skip_cold_load(address, false)
228 .map_err(JournalLoadError::unwrap_db_error)
229 }
230
231 fn load_account_mut_skip_cold_load(
233 &mut self,
234 address: Address,
235 skip_cold_load: bool,
236 ) -> Result<
237 StateLoad<Self::JournaledAccount<'_>>,
238 JournalLoadError<<Self::Database as Database>::Error>,
239 >;
240
241 #[inline]
243 fn load_account_with_code_mut(
244 &mut self,
245 address: Address,
246 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error> {
247 self.load_account_mut_optional_code(address, true)
248 }
249
250 fn load_account_mut_optional_code(
252 &mut self,
253 address: Address,
254 load_code: bool,
255 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error>;
256
257 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
259
260 #[inline]
264 fn set_code(&mut self, address: Address, code: Bytecode) {
265 let hash = code.hash_slow();
266 self.set_code_with_hash(address, code, hash);
267 }
268
269 #[inline]
271 fn code(
272 &mut self,
273 address: Address,
274 ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
275 let a = self.load_account_with_code(address)?;
276 let code = a.info.code.as_ref().unwrap().original_bytes();
278
279 Ok(StateLoad::new(code, a.is_cold))
280 }
281
282 fn code_hash(
284 &mut self,
285 address: Address,
286 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
287 let acc = self.load_account_with_code(address)?;
288 if acc.is_empty() {
289 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
290 }
291 let hash = acc.info.code_hash;
292 Ok(StateLoad::new(hash, acc.is_cold))
293 }
294
295 fn clear(&mut self) {
297 let _ = self.finalize();
298 }
299
300 fn checkpoint(&mut self) -> JournalCheckpoint;
303
304 fn checkpoint_commit(&mut self);
306
307 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
309
310 fn create_account_checkpoint(
312 &mut self,
313 caller: Address,
314 address: Address,
315 balance: U256,
316 spec_id: SpecId,
317 ) -> Result<JournalCheckpoint, TransferError>;
318
319 fn depth(&self) -> usize;
321
322 fn commit_tx(&mut self);
324
325 fn discard_tx(&mut self);
330
331 fn finalize(&mut self) -> Self::State;
333
334 fn load_account_info_skip_cold_load(
336 &mut self,
337 _address: Address,
338 _load_code: bool,
339 _skip_cold_load: bool,
340 ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>>;
341}
342
343#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
345#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
346pub enum JournalLoadError<E> {
347 DBError(E),
349 ColdLoadSkipped,
351}
352
353pub type JournalLoadErasedError = JournalLoadError<ErasedError>;
355
356impl<E> JournalLoadError<E> {
357 #[inline]
359 pub const fn is_db_error(&self) -> bool {
360 matches!(self, JournalLoadError::DBError(_))
361 }
362
363 #[inline]
365 pub const fn is_cold_load_skipped(&self) -> bool {
366 matches!(self, JournalLoadError::ColdLoadSkipped)
367 }
368
369 #[inline]
371 pub fn take_db_error(self) -> Option<E> {
372 if let JournalLoadError::DBError(e) = self {
373 Some(e)
374 } else {
375 None
376 }
377 }
378
379 #[inline]
381 pub fn unwrap_db_error(self) -> E {
382 if let JournalLoadError::DBError(e) = self {
383 e
384 } else {
385 panic!("Expected DBError");
386 }
387 }
388
389 #[inline]
391 pub fn into_parts(self) -> (LoadError, Option<E>) {
392 match self {
393 JournalLoadError::DBError(e) => (LoadError::DBError, Some(e)),
394 JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None),
395 }
396 }
397
398 #[inline]
400 pub fn map<B, F>(self, f: F) -> JournalLoadError<B>
401 where
402 F: FnOnce(E) -> B,
403 {
404 match self {
405 JournalLoadError::DBError(e) => JournalLoadError::DBError(f(e)),
406 JournalLoadError::ColdLoadSkipped => JournalLoadError::ColdLoadSkipped,
407 }
408 }
409}
410
411impl<E> From<E> for JournalLoadError<E> {
412 fn from(e: E) -> Self {
413 JournalLoadError::DBError(e)
414 }
415}
416
417impl<E> From<JournalLoadError<E>> for LoadError {
418 fn from(e: JournalLoadError<E>) -> Self {
419 match e {
420 JournalLoadError::DBError(_) => LoadError::DBError,
421 JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
422 }
423 }
424}
425
426#[derive(Copy, Clone, Debug, PartialEq, Eq)]
428pub enum TransferError {
429 OutOfFunds,
431 OverflowPayment,
433 CreateCollision,
435}
436
437#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
439#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
440pub struct JournalCheckpoint {
441 pub log_i: usize,
443 pub journal_i: usize,
445 pub selfdestructed_i: usize,
447}
448
449#[derive(Clone, Debug, Default, PartialEq, Eq)]
451#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
452pub struct StateLoad<T> {
453 pub data: T,
455 pub is_cold: bool,
457}
458
459impl<T> Deref for StateLoad<T> {
460 type Target = T;
461
462 fn deref(&self) -> &Self::Target {
463 &self.data
464 }
465}
466
467impl<T> DerefMut for StateLoad<T> {
468 fn deref_mut(&mut self) -> &mut Self::Target {
469 &mut self.data
470 }
471}
472
473impl<T> StateLoad<T> {
474 #[inline]
476 pub const fn new(data: T, is_cold: bool) -> Self {
477 Self { data, is_cold }
478 }
479
480 #[inline]
484 pub fn map<B, F>(self, f: F) -> StateLoad<B>
485 where
486 F: FnOnce(T) -> B,
487 {
488 StateLoad::new(f(self.data), self.is_cold)
489 }
490}
491
492#[derive(Clone, Debug, Default, PartialEq, Eq)]
494#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
495pub struct AccountLoad {
496 pub is_delegate_account_cold: Option<bool>,
498 pub is_empty: bool,
500}
501
502#[derive(Clone, Debug, Default, PartialEq, Eq)]
504#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
505pub struct AccountInfoLoad<'a> {
506 pub account: Cow<'a, AccountInfo>,
508 pub is_cold: bool,
510 pub is_empty: bool,
512}
513
514impl<'a> AccountInfoLoad<'a> {
515 #[inline]
517 pub const fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
518 Self {
519 account: Cow::Borrowed(account),
520 is_cold,
521 is_empty,
522 }
523 }
524
525 #[inline]
529 pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
530 where
531 F: FnOnce(Cow<'a, AccountInfo>) -> O,
532 {
533 StateLoad::new(f(self.account), self.is_cold)
534 }
535}
536
537impl<'a> Deref for AccountInfoLoad<'a> {
538 type Target = AccountInfo;
539
540 fn deref(&self) -> &Self::Target {
541 &self.account
542 }
543}