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_optional_code(address, false)
193 }
194
195 #[inline]
197 fn load_account_with_code_mut(
198 &mut self,
199 address: Address,
200 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error> {
201 self.load_account_mut_optional_code(address, true)
202 }
203
204 fn load_account_mut_optional_code(
206 &mut self,
207 address: Address,
208 load_code: bool,
209 ) -> Result<StateLoad<Self::JournaledAccount<'_>>, <Self::Database as Database>::Error>;
210
211 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
213
214 #[inline]
218 fn set_code(&mut self, address: Address, code: Bytecode) {
219 let hash = code.hash_slow();
220 self.set_code_with_hash(address, code, hash);
221 }
222
223 #[inline]
225 fn code(
226 &mut self,
227 address: Address,
228 ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
229 let a = self.load_account_with_code(address)?;
230 let code = a.info.code.as_ref().unwrap().original_bytes();
232
233 Ok(StateLoad::new(code, a.is_cold))
234 }
235
236 fn code_hash(
238 &mut self,
239 address: Address,
240 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
241 let acc = self.load_account_with_code(address)?;
242 if acc.is_empty() {
243 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
244 }
245 let hash = acc.info.code_hash;
246 Ok(StateLoad::new(hash, acc.is_cold))
247 }
248
249 fn clear(&mut self) {
251 let _ = self.finalize();
252 }
253
254 fn checkpoint(&mut self) -> JournalCheckpoint;
257
258 fn checkpoint_commit(&mut self);
260
261 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
263
264 fn create_account_checkpoint(
266 &mut self,
267 caller: Address,
268 address: Address,
269 balance: U256,
270 spec_id: SpecId,
271 ) -> Result<JournalCheckpoint, TransferError>;
272
273 fn depth(&self) -> usize;
275
276 fn commit_tx(&mut self);
278
279 fn discard_tx(&mut self);
284
285 fn finalize(&mut self) -> Self::State;
287
288 fn load_account_info_skip_cold_load(
290 &mut self,
291 _address: Address,
292 _load_code: bool,
293 _skip_cold_load: bool,
294 ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>>;
295}
296
297#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
299#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
300pub enum JournalLoadError<E> {
301 DBError(E),
303 ColdLoadSkipped,
305}
306
307pub type JournalLoadErasedError = JournalLoadError<ErasedError>;
309
310impl<E> JournalLoadError<E> {
311 #[inline]
313 pub fn is_db_error(&self) -> bool {
314 matches!(self, JournalLoadError::DBError(_))
315 }
316
317 #[inline]
319 pub fn is_cold_load_skipped(&self) -> bool {
320 matches!(self, JournalLoadError::ColdLoadSkipped)
321 }
322
323 #[inline]
325 pub fn take_db_error(self) -> Option<E> {
326 if let JournalLoadError::DBError(e) = self {
327 Some(e)
328 } else {
329 None
330 }
331 }
332
333 #[inline]
335 pub fn unwrap_db_error(self) -> E {
336 if let JournalLoadError::DBError(e) = self {
337 e
338 } else {
339 panic!("Expected DBError");
340 }
341 }
342
343 #[inline]
345 pub fn into_parts(self) -> (LoadError, Option<E>) {
346 match self {
347 JournalLoadError::DBError(e) => (LoadError::DBError, Some(e)),
348 JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None),
349 }
350 }
351
352 #[inline]
354 pub fn map<B, F>(self, f: F) -> JournalLoadError<B>
355 where
356 F: FnOnce(E) -> B,
357 {
358 match self {
359 JournalLoadError::DBError(e) => JournalLoadError::DBError(f(e)),
360 JournalLoadError::ColdLoadSkipped => JournalLoadError::ColdLoadSkipped,
361 }
362 }
363}
364
365impl<E> From<E> for JournalLoadError<E> {
366 fn from(e: E) -> Self {
367 JournalLoadError::DBError(e)
368 }
369}
370
371impl<E> From<JournalLoadError<E>> for LoadError {
372 fn from(e: JournalLoadError<E>) -> Self {
373 match e {
374 JournalLoadError::DBError(_) => LoadError::DBError,
375 JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
376 }
377 }
378}
379
380#[derive(Copy, Clone, Debug, PartialEq, Eq)]
382pub enum TransferError {
383 OutOfFunds,
385 OverflowPayment,
387 CreateCollision,
389}
390
391#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
393#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
394pub struct JournalCheckpoint {
395 pub log_i: usize,
397 pub journal_i: usize,
399}
400
401#[derive(Clone, Debug, Default, PartialEq, Eq)]
403#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
404pub struct StateLoad<T> {
405 pub data: T,
407 pub is_cold: bool,
409}
410
411impl<T> Deref for StateLoad<T> {
412 type Target = T;
413
414 fn deref(&self) -> &Self::Target {
415 &self.data
416 }
417}
418
419impl<T> DerefMut for StateLoad<T> {
420 fn deref_mut(&mut self) -> &mut Self::Target {
421 &mut self.data
422 }
423}
424
425impl<T> StateLoad<T> {
426 #[inline]
428 pub fn new(data: T, is_cold: bool) -> Self {
429 Self { data, is_cold }
430 }
431
432 #[inline]
436 pub fn map<B, F>(self, f: F) -> StateLoad<B>
437 where
438 F: FnOnce(T) -> B,
439 {
440 StateLoad::new(f(self.data), self.is_cold)
441 }
442}
443
444#[derive(Clone, Debug, Default, PartialEq, Eq)]
446#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
447pub struct AccountLoad {
448 pub is_delegate_account_cold: Option<bool>,
450 pub is_empty: bool,
452}
453
454#[derive(Clone, Debug, Default, PartialEq, Eq)]
456#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
457pub struct AccountInfoLoad<'a> {
458 pub account: Cow<'a, AccountInfo>,
460 pub is_cold: bool,
462 pub is_empty: bool,
464}
465
466impl<'a> AccountInfoLoad<'a> {
467 #[inline]
469 pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
470 Self {
471 account: Cow::Borrowed(account),
472 is_cold,
473 is_empty,
474 }
475 }
476
477 #[inline]
481 pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
482 where
483 F: FnOnce(Cow<'a, AccountInfo>) -> O,
484 {
485 StateLoad::new(f(self.account), self.is_cold)
486 }
487}
488
489impl<'a> Deref for AccountInfoLoad<'a> {
490 type Target = AccountInfo;
491
492 fn deref(&self) -> &Self::Target {
493 &self.account
494 }
495}