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
39 fn db(&self) -> &Self::Database;
41
42 fn sload(
46 &mut self,
47 address: Address,
48 key: StorageKey,
49 ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error> {
50 self.sload_skip_cold_load(address, key, false)
52 .map_err(JournalLoadError::unwrap_db_error)
53 }
54
55 fn sload_skip_cold_load(
57 &mut self,
58 _address: Address,
59 _key: StorageKey,
60 _skip_cold_load: bool,
61 ) -> Result<StateLoad<StorageValue>, JournalLoadError<<Self::Database as Database>::Error>>;
62
63 fn sstore(
65 &mut self,
66 address: Address,
67 key: StorageKey,
68 value: StorageValue,
69 ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
70 self.sstore_skip_cold_load(address, key, value, false)
72 .map_err(JournalLoadError::unwrap_db_error)
73 }
74
75 fn sstore_skip_cold_load(
77 &mut self,
78 _address: Address,
79 _key: StorageKey,
80 _value: StorageValue,
81 _skip_cold_load: bool,
82 ) -> Result<StateLoad<SStoreResult>, JournalLoadError<<Self::Database as Database>::Error>>;
83
84 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
86
87 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
89
90 fn log(&mut self, log: Log);
92
93 fn take_logs(&mut self) -> Vec<Log>;
95
96 fn logs(&self) -> &[Log];
98
99 fn selfdestruct(
101 &mut self,
102 address: Address,
103 target: Address,
104 skip_cold_load: bool,
105 ) -> Result<StateLoad<SelfDestructResult>, JournalLoadError<<Self::Database as Database>::Error>>;
106
107 fn warm_access_list(&mut self, access_list: AddressMap<HashSet<StorageKey>>);
109
110 fn warm_coinbase_account(&mut self, address: Address);
112
113 fn warm_precompiles(&mut self, addresses: AddressSet);
115
116 fn precompile_addresses(&self) -> &AddressSet;
118
119 fn set_spec_id(&mut self, spec_id: SpecId);
121
122 fn set_eip7708_config(&mut self, disabled: bool, delayed_burn_disabled: bool);
132
133 fn touch_account(&mut self, address: Address);
135
136 fn transfer(
138 &mut self,
139 from: Address,
140 to: Address,
141 balance: U256,
142 ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
143
144 fn transfer_loaded(
146 &mut self,
147 from: Address,
148 to: Address,
149 balance: U256,
150 ) -> Option<TransferError>;
151
152 #[deprecated]
154 fn caller_accounting_journal_entry(
155 &mut self,
156 address: Address,
157 old_balance: U256,
158 bump_nonce: bool,
159 );
160
161 fn balance_incr(
163 &mut self,
164 address: Address,
165 balance: U256,
166 ) -> Result<(), <Self::Database as Database>::Error>;
167
168 #[deprecated]
170 fn nonce_bump_journal_entry(&mut self, address: Address);
171
172 fn load_account(
174 &mut self,
175 address: Address,
176 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
177
178 #[inline]
180 #[deprecated(note = "Use `load_account_with_code` instead")]
181 fn load_account_code(
182 &mut self,
183 address: Address,
184 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error> {
185 self.load_account_with_code(address)
186 }
187
188 fn load_account_with_code(
190 &mut self,
191 address: Address,
192 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
193
194 fn load_account_delegated(
196 &mut self,
197 address: Address,
198 ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
199
200 #[inline]
202 fn load_account_mut(
203 &mut self,
204 address: Address,
205 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error> {
206 self.load_account_mut_skip_cold_load(address, false)
207 }
208
209 fn load_account_mut_skip_cold_load(
211 &mut self,
212 address: Address,
213 skip_cold_load: bool,
214 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error>;
215
216 #[inline]
218 fn load_account_with_code_mut(
219 &mut self,
220 address: Address,
221 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error> {
222 self.load_account_mut_optional_code(address, true)
223 }
224
225 fn load_account_mut_optional_code(
227 &mut self,
228 address: Address,
229 load_code: bool,
230 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error>;
231
232 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
234
235 #[inline]
239 fn set_code(&mut self, address: Address, code: Bytecode) {
240 let hash = code.hash_slow();
241 self.set_code_with_hash(address, code, hash);
242 }
243
244 #[inline]
246 fn code(
247 &mut self,
248 address: Address,
249 ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
250 let a = self.load_account_with_code(address)?;
251 let code = a.info.code.as_ref().unwrap().original_bytes();
253
254 Ok(StateLoad::new(code, a.is_cold))
255 }
256
257 fn code_hash(
259 &mut self,
260 address: Address,
261 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
262 let acc = self.load_account_with_code(address)?;
263 if acc.is_empty() {
264 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
265 }
266 let hash = acc.info.code_hash;
267 Ok(StateLoad::new(hash, acc.is_cold))
268 }
269
270 fn clear(&mut self) {
272 let _ = self.finalize();
273 }
274
275 fn checkpoint(&mut self) -> JournalCheckpoint;
278
279 fn checkpoint_commit(&mut self);
281
282 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
284
285 fn create_account_checkpoint(
287 &mut self,
288 caller: Address,
289 address: Address,
290 balance: U256,
291 spec_id: SpecId,
292 ) -> Result<JournalCheckpoint, TransferError>;
293
294 fn depth(&self) -> usize;
296
297 fn commit_tx(&mut self);
299
300 fn discard_tx(&mut self);
305
306 fn finalize(&mut self) -> Self::State;
308
309 fn load_account_info_skip_cold_load(
311 &mut self,
312 _address: Address,
313 _load_code: bool,
314 _skip_cold_load: bool,
315 ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>>;
316}
317
318#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
320#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
321pub enum JournalLoadError<E> {
322 DBError(E),
324 ColdLoadSkipped,
326}
327
328pub type JournalLoadErasedError = JournalLoadError<ErasedError>;
330
331impl<E> JournalLoadError<E> {
332 #[inline]
334 pub fn is_db_error(&self) -> bool {
335 matches!(self, JournalLoadError::DBError(_))
336 }
337
338 #[inline]
340 pub fn is_cold_load_skipped(&self) -> bool {
341 matches!(self, JournalLoadError::ColdLoadSkipped)
342 }
343
344 #[inline]
346 pub fn take_db_error(self) -> Option<E> {
347 if let JournalLoadError::DBError(e) = self {
348 Some(e)
349 } else {
350 None
351 }
352 }
353
354 #[inline]
356 pub fn unwrap_db_error(self) -> E {
357 if let JournalLoadError::DBError(e) = self {
358 e
359 } else {
360 panic!("Expected DBError");
361 }
362 }
363
364 #[inline]
366 pub fn into_parts(self) -> (LoadError, Option<E>) {
367 match self {
368 JournalLoadError::DBError(e) => (LoadError::DBError, Some(e)),
369 JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None),
370 }
371 }
372
373 #[inline]
375 pub fn map<B, F>(self, f: F) -> JournalLoadError<B>
376 where
377 F: FnOnce(E) -> B,
378 {
379 match self {
380 JournalLoadError::DBError(e) => JournalLoadError::DBError(f(e)),
381 JournalLoadError::ColdLoadSkipped => JournalLoadError::ColdLoadSkipped,
382 }
383 }
384}
385
386impl<E> From<E> for JournalLoadError<E> {
387 fn from(e: E) -> Self {
388 JournalLoadError::DBError(e)
389 }
390}
391
392impl<E> From<JournalLoadError<E>> for LoadError {
393 fn from(e: JournalLoadError<E>) -> Self {
394 match e {
395 JournalLoadError::DBError(_) => LoadError::DBError,
396 JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
397 }
398 }
399}
400
401#[derive(Copy, Clone, Debug, PartialEq, Eq)]
403pub enum TransferError {
404 OutOfFunds,
406 OverflowPayment,
408 CreateCollision,
410}
411
412#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
414#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
415pub struct JournalCheckpoint {
416 pub log_i: usize,
418 pub journal_i: usize,
420 pub selfdestructed_i: usize,
422}
423
424#[derive(Clone, Debug, Default, PartialEq, Eq)]
426#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
427pub struct StateLoad<T> {
428 pub data: T,
430 pub is_cold: bool,
432}
433
434impl<T> Deref for StateLoad<T> {
435 type Target = T;
436
437 fn deref(&self) -> &Self::Target {
438 &self.data
439 }
440}
441
442impl<T> DerefMut for StateLoad<T> {
443 fn deref_mut(&mut self) -> &mut Self::Target {
444 &mut self.data
445 }
446}
447
448impl<T> StateLoad<T> {
449 #[inline]
451 pub fn new(data: T, is_cold: bool) -> Self {
452 Self { data, is_cold }
453 }
454
455 #[inline]
459 pub fn map<B, F>(self, f: F) -> StateLoad<B>
460 where
461 F: FnOnce(T) -> B,
462 {
463 StateLoad::new(f(self.data), self.is_cold)
464 }
465}
466
467#[derive(Clone, Debug, Default, PartialEq, Eq)]
469#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
470pub struct AccountLoad {
471 pub is_delegate_account_cold: Option<bool>,
473 pub is_empty: bool,
475}
476
477#[derive(Clone, Debug, Default, PartialEq, Eq)]
479#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
480pub struct AccountInfoLoad<'a> {
481 pub account: Cow<'a, AccountInfo>,
483 pub is_cold: bool,
485 pub is_empty: bool,
487}
488
489impl<'a> AccountInfoLoad<'a> {
490 #[inline]
492 pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
493 Self {
494 account: Cow::Borrowed(account),
495 is_cold,
496 is_empty,
497 }
498 }
499
500 #[inline]
504 pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
505 where
506 F: FnOnce(Cow<'a, AccountInfo>) -> O,
507 {
508 StateLoad::new(f(self.account), self.is_cold)
509 }
510}
511
512impl<'a> Deref for AccountInfoLoad<'a> {
513 type Target = AccountInfo;
514
515 fn deref(&self) -> &Self::Target {
516 &self.account
517 }
518}