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 touch_account(&mut self, address: Address);
124
125 fn transfer(
127 &mut self,
128 from: Address,
129 to: Address,
130 balance: U256,
131 ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
132
133 fn transfer_loaded(
135 &mut self,
136 from: Address,
137 to: Address,
138 balance: U256,
139 ) -> Option<TransferError>;
140
141 #[deprecated]
143 fn caller_accounting_journal_entry(
144 &mut self,
145 address: Address,
146 old_balance: U256,
147 bump_nonce: bool,
148 );
149
150 fn balance_incr(
152 &mut self,
153 address: Address,
154 balance: U256,
155 ) -> Result<(), <Self::Database as Database>::Error>;
156
157 #[deprecated]
159 fn nonce_bump_journal_entry(&mut self, address: Address);
160
161 fn load_account(
163 &mut self,
164 address: Address,
165 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
166
167 #[inline]
169 #[deprecated(note = "Use `load_account_with_code` instead")]
170 fn load_account_code(
171 &mut self,
172 address: Address,
173 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error> {
174 self.load_account_with_code(address)
175 }
176
177 fn load_account_with_code(
179 &mut self,
180 address: Address,
181 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
182
183 fn load_account_delegated(
185 &mut self,
186 address: Address,
187 ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
188
189 #[inline]
191 fn load_account_mut(
192 &mut self,
193 address: Address,
194 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error> {
195 self.load_account_mut_skip_cold_load(address, false)
196 }
197
198 fn load_account_mut_skip_cold_load(
200 &mut self,
201 address: Address,
202 skip_cold_load: bool,
203 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error>;
204
205 #[inline]
207 fn load_account_with_code_mut(
208 &mut self,
209 address: Address,
210 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error> {
211 self.load_account_mut_optional_code(address, true)
212 }
213
214 fn load_account_mut_optional_code(
216 &mut self,
217 address: Address,
218 load_code: bool,
219 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error>;
220
221 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
223
224 #[inline]
228 fn set_code(&mut self, address: Address, code: Bytecode) {
229 let hash = code.hash_slow();
230 self.set_code_with_hash(address, code, hash);
231 }
232
233 #[inline]
235 fn code(
236 &mut self,
237 address: Address,
238 ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
239 let a = self.load_account_with_code(address)?;
240 let code = a.info.code.as_ref().unwrap().original_bytes();
242
243 Ok(StateLoad::new(code, a.is_cold))
244 }
245
246 fn code_hash(
248 &mut self,
249 address: Address,
250 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
251 let acc = self.load_account_with_code(address)?;
252 if acc.is_empty() {
253 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
254 }
255 let hash = acc.info.code_hash;
256 Ok(StateLoad::new(hash, acc.is_cold))
257 }
258
259 fn clear(&mut self) {
261 let _ = self.finalize();
262 }
263
264 fn checkpoint(&mut self) -> JournalCheckpoint;
267
268 fn checkpoint_commit(&mut self);
270
271 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
273
274 fn create_account_checkpoint(
276 &mut self,
277 caller: Address,
278 address: Address,
279 balance: U256,
280 spec_id: SpecId,
281 ) -> Result<JournalCheckpoint, TransferError>;
282
283 fn depth(&self) -> usize;
285
286 fn commit_tx(&mut self);
288
289 fn discard_tx(&mut self);
294
295 fn finalize(&mut self) -> Self::State;
297
298 fn load_account_info_skip_cold_load(
300 &mut self,
301 _address: Address,
302 _load_code: bool,
303 _skip_cold_load: bool,
304 ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>>;
305}
306
307#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
309#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
310pub enum JournalLoadError<E> {
311 DBError(E),
313 ColdLoadSkipped,
315}
316
317pub type JournalLoadErasedError = JournalLoadError<ErasedError>;
319
320impl<E> JournalLoadError<E> {
321 #[inline]
323 pub fn is_db_error(&self) -> bool {
324 matches!(self, JournalLoadError::DBError(_))
325 }
326
327 #[inline]
329 pub fn is_cold_load_skipped(&self) -> bool {
330 matches!(self, JournalLoadError::ColdLoadSkipped)
331 }
332
333 #[inline]
335 pub fn take_db_error(self) -> Option<E> {
336 if let JournalLoadError::DBError(e) = self {
337 Some(e)
338 } else {
339 None
340 }
341 }
342
343 #[inline]
345 pub fn unwrap_db_error(self) -> E {
346 if let JournalLoadError::DBError(e) = self {
347 e
348 } else {
349 panic!("Expected DBError");
350 }
351 }
352
353 #[inline]
355 pub fn into_parts(self) -> (LoadError, Option<E>) {
356 match self {
357 JournalLoadError::DBError(e) => (LoadError::DBError, Some(e)),
358 JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None),
359 }
360 }
361
362 #[inline]
364 pub fn map<B, F>(self, f: F) -> JournalLoadError<B>
365 where
366 F: FnOnce(E) -> B,
367 {
368 match self {
369 JournalLoadError::DBError(e) => JournalLoadError::DBError(f(e)),
370 JournalLoadError::ColdLoadSkipped => JournalLoadError::ColdLoadSkipped,
371 }
372 }
373}
374
375impl<E> From<E> for JournalLoadError<E> {
376 fn from(e: E) -> Self {
377 JournalLoadError::DBError(e)
378 }
379}
380
381impl<E> From<JournalLoadError<E>> for LoadError {
382 fn from(e: JournalLoadError<E>) -> Self {
383 match e {
384 JournalLoadError::DBError(_) => LoadError::DBError,
385 JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
386 }
387 }
388}
389
390#[derive(Copy, Clone, Debug, PartialEq, Eq)]
392pub enum TransferError {
393 OutOfFunds,
395 OverflowPayment,
397 CreateCollision,
399}
400
401#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
403#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
404pub struct JournalCheckpoint {
405 pub log_i: usize,
407 pub journal_i: usize,
409}
410
411#[derive(Clone, Debug, Default, PartialEq, Eq)]
413#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
414pub struct StateLoad<T> {
415 pub data: T,
417 pub is_cold: bool,
419}
420
421impl<T> Deref for StateLoad<T> {
422 type Target = T;
423
424 fn deref(&self) -> &Self::Target {
425 &self.data
426 }
427}
428
429impl<T> DerefMut for StateLoad<T> {
430 fn deref_mut(&mut self) -> &mut Self::Target {
431 &mut self.data
432 }
433}
434
435impl<T> StateLoad<T> {
436 #[inline]
438 pub fn new(data: T, is_cold: bool) -> Self {
439 Self { data, is_cold }
440 }
441
442 #[inline]
446 pub fn map<B, F>(self, f: F) -> StateLoad<B>
447 where
448 F: FnOnce(T) -> B,
449 {
450 StateLoad::new(f(self.data), self.is_cold)
451 }
452}
453
454#[derive(Clone, Debug, Default, PartialEq, Eq)]
456#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
457pub struct AccountLoad {
458 pub is_delegate_account_cold: Option<bool>,
460 pub is_empty: bool,
462}
463
464#[derive(Clone, Debug, Default, PartialEq, Eq)]
466#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
467pub struct AccountInfoLoad<'a> {
468 pub account: Cow<'a, AccountInfo>,
470 pub is_cold: bool,
472 pub is_empty: bool,
474}
475
476impl<'a> AccountInfoLoad<'a> {
477 #[inline]
479 pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
480 Self {
481 account: Cow::Borrowed(account),
482 is_cold,
483 is_empty,
484 }
485 }
486
487 #[inline]
491 pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
492 where
493 F: FnOnce(Cow<'a, AccountInfo>) -> O,
494 {
495 StateLoad::new(f(self.account), self.is_cold)
496 }
497}
498
499impl<'a> Deref for AccountInfoLoad<'a> {
500 type Target = AccountInfo;
501
502 fn deref(&self) -> &Self::Target {
503 &self.account
504 }
505}