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 .map_err(JournalLoadError::unwrap_db_error)
208 }
209
210 fn load_account_mut_skip_cold_load(
212 &mut self,
213 address: Address,
214 skip_cold_load: bool,
215 ) -> Result<
216 StateLoad<Self::JournaledAccount<'_>>,
217 JournalLoadError<<Self::Database as Database>::Error>,
218 >;
219
220 #[inline]
222 fn load_account_with_code_mut(
223 &mut self,
224 address: Address,
225 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error> {
226 self.load_account_mut_optional_code(address, true)
227 }
228
229 fn load_account_mut_optional_code(
231 &mut self,
232 address: Address,
233 load_code: bool,
234 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error>;
235
236 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
238
239 #[inline]
243 fn set_code(&mut self, address: Address, code: Bytecode) {
244 let hash = code.hash_slow();
245 self.set_code_with_hash(address, code, hash);
246 }
247
248 #[inline]
250 fn code(
251 &mut self,
252 address: Address,
253 ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
254 let a = self.load_account_with_code(address)?;
255 let code = a.info.code.as_ref().unwrap().original_bytes();
257
258 Ok(StateLoad::new(code, a.is_cold))
259 }
260
261 fn code_hash(
263 &mut self,
264 address: Address,
265 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
266 let acc = self.load_account_with_code(address)?;
267 if acc.is_empty() {
268 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
269 }
270 let hash = acc.info.code_hash;
271 Ok(StateLoad::new(hash, acc.is_cold))
272 }
273
274 fn clear(&mut self) {
276 let _ = self.finalize();
277 }
278
279 fn checkpoint(&mut self) -> JournalCheckpoint;
282
283 fn checkpoint_commit(&mut self);
285
286 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
288
289 fn create_account_checkpoint(
291 &mut self,
292 caller: Address,
293 address: Address,
294 balance: U256,
295 spec_id: SpecId,
296 ) -> Result<JournalCheckpoint, TransferError>;
297
298 fn depth(&self) -> usize;
300
301 fn commit_tx(&mut self);
303
304 fn discard_tx(&mut self);
309
310 fn finalize(&mut self) -> Self::State;
312
313 fn load_account_info_skip_cold_load(
315 &mut self,
316 _address: Address,
317 _load_code: bool,
318 _skip_cold_load: bool,
319 ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>>;
320}
321
322#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
324#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
325pub enum JournalLoadError<E> {
326 DBError(E),
328 ColdLoadSkipped,
330}
331
332pub type JournalLoadErasedError = JournalLoadError<ErasedError>;
334
335impl<E> JournalLoadError<E> {
336 #[inline]
338 pub fn is_db_error(&self) -> bool {
339 matches!(self, JournalLoadError::DBError(_))
340 }
341
342 #[inline]
344 pub fn is_cold_load_skipped(&self) -> bool {
345 matches!(self, JournalLoadError::ColdLoadSkipped)
346 }
347
348 #[inline]
350 pub fn take_db_error(self) -> Option<E> {
351 if let JournalLoadError::DBError(e) = self {
352 Some(e)
353 } else {
354 None
355 }
356 }
357
358 #[inline]
360 pub fn unwrap_db_error(self) -> E {
361 if let JournalLoadError::DBError(e) = self {
362 e
363 } else {
364 panic!("Expected DBError");
365 }
366 }
367
368 #[inline]
370 pub fn into_parts(self) -> (LoadError, Option<E>) {
371 match self {
372 JournalLoadError::DBError(e) => (LoadError::DBError, Some(e)),
373 JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None),
374 }
375 }
376
377 #[inline]
379 pub fn map<B, F>(self, f: F) -> JournalLoadError<B>
380 where
381 F: FnOnce(E) -> B,
382 {
383 match self {
384 JournalLoadError::DBError(e) => JournalLoadError::DBError(f(e)),
385 JournalLoadError::ColdLoadSkipped => JournalLoadError::ColdLoadSkipped,
386 }
387 }
388}
389
390impl<E> From<E> for JournalLoadError<E> {
391 fn from(e: E) -> Self {
392 JournalLoadError::DBError(e)
393 }
394}
395
396impl<E> From<JournalLoadError<E>> for LoadError {
397 fn from(e: JournalLoadError<E>) -> Self {
398 match e {
399 JournalLoadError::DBError(_) => LoadError::DBError,
400 JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
401 }
402 }
403}
404
405#[derive(Copy, Clone, Debug, PartialEq, Eq)]
407pub enum TransferError {
408 OutOfFunds,
410 OverflowPayment,
412 CreateCollision,
414}
415
416#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
418#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
419pub struct JournalCheckpoint {
420 pub log_i: usize,
422 pub journal_i: usize,
424 pub selfdestructed_i: usize,
426}
427
428#[derive(Clone, Debug, Default, PartialEq, Eq)]
430#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
431pub struct StateLoad<T> {
432 pub data: T,
434 pub is_cold: bool,
436}
437
438impl<T> Deref for StateLoad<T> {
439 type Target = T;
440
441 fn deref(&self) -> &Self::Target {
442 &self.data
443 }
444}
445
446impl<T> DerefMut for StateLoad<T> {
447 fn deref_mut(&mut self) -> &mut Self::Target {
448 &mut self.data
449 }
450}
451
452impl<T> StateLoad<T> {
453 #[inline]
455 pub fn new(data: T, is_cold: bool) -> Self {
456 Self { data, is_cold }
457 }
458
459 #[inline]
463 pub fn map<B, F>(self, f: F) -> StateLoad<B>
464 where
465 F: FnOnce(T) -> B,
466 {
467 StateLoad::new(f(self.data), self.is_cold)
468 }
469}
470
471#[derive(Clone, Debug, Default, PartialEq, Eq)]
473#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
474pub struct AccountLoad {
475 pub is_delegate_account_cold: Option<bool>,
477 pub is_empty: bool,
479}
480
481#[derive(Clone, Debug, Default, PartialEq, Eq)]
483#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
484pub struct AccountInfoLoad<'a> {
485 pub account: Cow<'a, AccountInfo>,
487 pub is_cold: bool,
489 pub is_empty: bool,
491}
492
493impl<'a> AccountInfoLoad<'a> {
494 #[inline]
496 pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
497 Self {
498 account: Cow::Borrowed(account),
499 is_cold,
500 is_empty,
501 }
502 }
503
504 #[inline]
508 pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
509 where
510 F: FnOnce(Cow<'a, AccountInfo>) -> O,
511 {
512 StateLoad::new(f(self.account), self.is_cold)
513 }
514}
515
516impl<'a> Deref for AccountInfoLoad<'a> {
517 type Target = AccountInfo;
518
519 fn deref(&self) -> &Self::Target {
520 &self.account
521 }
522}