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, Bytes, HashMap, HashSet, Log, StorageKey, StorageValue, B256, U256,
16};
17use state::{Account, AccountInfo, Bytecode};
18use std::{borrow::Cow, vec::Vec};
19pub trait JournalTr {
21 type Database: Database;
23 type State;
25 type JournaledAccount<'a>: JournaledAccountTr
27 where
28 Self: 'a;
29
30 fn new(database: Self::Database) -> Self;
34
35 fn db_mut(&mut self) -> &mut Self::Database;
37
38 fn db(&self) -> &Self::Database;
40
41 fn sload(
45 &mut self,
46 address: Address,
47 key: StorageKey,
48 ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error> {
49 self.sload_skip_cold_load(address, key, false)
51 .map_err(JournalLoadError::unwrap_db_error)
52 }
53
54 fn sload_skip_cold_load(
56 &mut self,
57 _address: Address,
58 _key: StorageKey,
59 _skip_cold_load: bool,
60 ) -> Result<StateLoad<StorageValue>, JournalLoadError<<Self::Database as Database>::Error>>;
61
62 fn sstore(
64 &mut self,
65 address: Address,
66 key: StorageKey,
67 value: StorageValue,
68 ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
69 self.sstore_skip_cold_load(address, key, value, false)
71 .map_err(JournalLoadError::unwrap_db_error)
72 }
73
74 fn sstore_skip_cold_load(
76 &mut self,
77 _address: Address,
78 _key: StorageKey,
79 _value: StorageValue,
80 _skip_cold_load: bool,
81 ) -> Result<StateLoad<SStoreResult>, JournalLoadError<<Self::Database as Database>::Error>>;
82
83 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
85
86 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
88
89 fn log(&mut self, log: Log);
91
92 fn take_logs(&mut self) -> Vec<Log>;
94
95 fn logs(&self) -> &[Log];
97
98 fn selfdestruct(
100 &mut self,
101 address: Address,
102 target: Address,
103 skip_cold_load: bool,
104 ) -> Result<StateLoad<SelfDestructResult>, JournalLoadError<<Self::Database as Database>::Error>>;
105
106 fn warm_access_list(&mut self, access_list: HashMap<Address, HashSet<StorageKey>>);
108
109 fn warm_coinbase_account(&mut self, address: Address);
111
112 fn warm_precompiles(&mut self, addresses: HashSet<Address>);
114
115 fn precompile_addresses(&self) -> &HashSet<Address>;
117
118 fn set_spec_id(&mut self, spec_id: SpecId);
120
121 fn touch_account(&mut self, address: Address);
123
124 fn transfer(
126 &mut self,
127 from: Address,
128 to: Address,
129 balance: U256,
130 ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
131
132 fn transfer_loaded(
134 &mut self,
135 from: Address,
136 to: Address,
137 balance: U256,
138 ) -> Option<TransferError>;
139
140 fn caller_accounting_journal_entry(
142 &mut self,
143 address: Address,
144 old_balance: U256,
145 bump_nonce: bool,
146 );
147
148 fn balance_incr(
150 &mut self,
151 address: Address,
152 balance: U256,
153 ) -> Result<(), <Self::Database as Database>::Error>;
154
155 fn nonce_bump_journal_entry(&mut self, address: Address);
157
158 fn load_account(
160 &mut self,
161 address: Address,
162 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
163
164 #[inline]
166 #[deprecated(note = "Use `load_account_with_code` instead")]
167 fn load_account_code(
168 &mut self,
169 address: Address,
170 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error> {
171 self.load_account_with_code(address)
172 }
173
174 fn load_account_with_code(
176 &mut self,
177 address: Address,
178 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
179
180 fn load_account_delegated(
182 &mut self,
183 address: Address,
184 ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
185
186 #[inline]
188 fn load_account_mut(
189 &mut self,
190 address: Address,
191 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error> {
192 self.load_account_mut_skip_cold_load(address, false)
193 }
194
195 fn load_account_mut_skip_cold_load(
197 &mut self,
198 address: Address,
199 skip_cold_load: bool,
200 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error>;
201
202 #[inline]
204 fn load_account_with_code_mut(
205 &mut self,
206 address: Address,
207 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error> {
208 self.load_account_mut_optional_code(address, true)
209 }
210
211 fn load_account_mut_optional_code(
213 &mut self,
214 address: Address,
215 load_code: bool,
216 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error>;
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
314pub type JournalLoadErasedError = JournalLoadError<ErasedError>;
316
317impl<E> JournalLoadError<E> {
318 #[inline]
320 pub fn is_db_error(&self) -> bool {
321 matches!(self, JournalLoadError::DBError(_))
322 }
323
324 #[inline]
326 pub fn is_cold_load_skipped(&self) -> bool {
327 matches!(self, JournalLoadError::ColdLoadSkipped)
328 }
329
330 #[inline]
332 pub fn take_db_error(self) -> Option<E> {
333 if let JournalLoadError::DBError(e) = self {
334 Some(e)
335 } else {
336 None
337 }
338 }
339
340 #[inline]
342 pub fn unwrap_db_error(self) -> E {
343 if let JournalLoadError::DBError(e) = self {
344 e
345 } else {
346 panic!("Expected DBError");
347 }
348 }
349
350 #[inline]
352 pub fn into_parts(self) -> (LoadError, Option<E>) {
353 match self {
354 JournalLoadError::DBError(e) => (LoadError::DBError, Some(e)),
355 JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None),
356 }
357 }
358
359 #[inline]
361 pub fn map<B, F>(self, f: F) -> JournalLoadError<B>
362 where
363 F: FnOnce(E) -> B,
364 {
365 match self {
366 JournalLoadError::DBError(e) => JournalLoadError::DBError(f(e)),
367 JournalLoadError::ColdLoadSkipped => JournalLoadError::ColdLoadSkipped,
368 }
369 }
370}
371
372impl<E> From<E> for JournalLoadError<E> {
373 fn from(e: E) -> Self {
374 JournalLoadError::DBError(e)
375 }
376}
377
378impl<E> From<JournalLoadError<E>> for LoadError {
379 fn from(e: JournalLoadError<E>) -> Self {
380 match e {
381 JournalLoadError::DBError(_) => LoadError::DBError,
382 JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
383 }
384 }
385}
386
387#[derive(Copy, Clone, Debug, PartialEq, Eq)]
389pub enum TransferError {
390 OutOfFunds,
392 OverflowPayment,
394 CreateCollision,
396}
397
398#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
400#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
401pub struct JournalCheckpoint {
402 pub log_i: usize,
404 pub journal_i: usize,
406}
407
408#[derive(Clone, Debug, Default, PartialEq, Eq)]
410#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
411pub struct StateLoad<T> {
412 pub data: T,
414 pub is_cold: bool,
416}
417
418impl<T> Deref for StateLoad<T> {
419 type Target = T;
420
421 fn deref(&self) -> &Self::Target {
422 &self.data
423 }
424}
425
426impl<T> DerefMut for StateLoad<T> {
427 fn deref_mut(&mut self) -> &mut Self::Target {
428 &mut self.data
429 }
430}
431
432impl<T> StateLoad<T> {
433 #[inline]
435 pub fn new(data: T, is_cold: bool) -> Self {
436 Self { data, is_cold }
437 }
438
439 #[inline]
443 pub fn map<B, F>(self, f: F) -> StateLoad<B>
444 where
445 F: FnOnce(T) -> B,
446 {
447 StateLoad::new(f(self.data), self.is_cold)
448 }
449}
450
451#[derive(Clone, Debug, Default, PartialEq, Eq)]
453#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
454pub struct AccountLoad {
455 pub is_delegate_account_cold: Option<bool>,
457 pub is_empty: bool,
459}
460
461#[derive(Clone, Debug, Default, PartialEq, Eq)]
463#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
464pub struct AccountInfoLoad<'a> {
465 pub account: Cow<'a, AccountInfo>,
467 pub is_cold: bool,
469 pub is_empty: bool,
471}
472
473impl<'a> AccountInfoLoad<'a> {
474 #[inline]
476 pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
477 Self {
478 account: Cow::Borrowed(account),
479 is_cold,
480 is_empty,
481 }
482 }
483
484 #[inline]
488 pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
489 where
490 F: FnOnce(Cow<'a, AccountInfo>) -> O,
491 {
492 StateLoad::new(f(self.account), self.is_cold)
493 }
494}
495
496impl<'a> Deref for AccountInfoLoad<'a> {
497 type Target = AccountInfo;
498
499 fn deref(&self) -> &Self::Target {
500 &self.account
501 }
502}