1pub mod account;
4pub mod entry;
5
6use crate::{
7 context::{SStoreResult, SelfDestructResult},
8 host::LoadError,
9 journaled_state::{account::JournaledAccount, entry::JournalEntryTr},
10};
11use core::ops::{Deref, DerefMut};
12use database_interface::Database;
13use primitives::{
14 hardfork::SpecId, Address, Bytes, HashMap, HashSet, Log, StorageKey, StorageValue, B256, U256,
15};
16use state::{Account, AccountInfo, Bytecode};
17use std::{borrow::Cow, vec::Vec};
18
19pub trait JournalTr {
21 type Database: Database;
23 type State;
25 type JournalEntry: JournalEntryTr;
27
28 fn new(database: Self::Database) -> Self;
32
33 fn db_mut(&mut self) -> &mut Self::Database;
35
36 fn db(&self) -> &Self::Database;
38
39 fn sload(
43 &mut self,
44 address: Address,
45 key: StorageKey,
46 ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error> {
47 self.sload_skip_cold_load(address, key, false)
49 .map_err(JournalLoadError::unwrap_db_error)
50 }
51
52 fn sload_skip_cold_load(
54 &mut self,
55 _address: Address,
56 _key: StorageKey,
57 _skip_cold_load: bool,
58 ) -> Result<StateLoad<StorageValue>, JournalLoadError<<Self::Database as Database>::Error>>;
59
60 fn sstore(
62 &mut self,
63 address: Address,
64 key: StorageKey,
65 value: StorageValue,
66 ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
67 self.sstore_skip_cold_load(address, key, value, false)
69 .map_err(JournalLoadError::unwrap_db_error)
70 }
71
72 fn sstore_skip_cold_load(
74 &mut self,
75 _address: Address,
76 _key: StorageKey,
77 _value: StorageValue,
78 _skip_cold_load: bool,
79 ) -> Result<StateLoad<SStoreResult>, JournalLoadError<<Self::Database as Database>::Error>>;
80
81 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
83
84 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
86
87 fn log(&mut self, log: Log);
89
90 fn selfdestruct(
92 &mut self,
93 address: Address,
94 target: Address,
95 ) -> Result<StateLoad<SelfDestructResult>, <Self::Database as Database>::Error>;
96
97 fn warm_access_list(&mut self, access_list: HashMap<Address, HashSet<StorageKey>>);
99
100 fn warm_coinbase_account(&mut self, address: Address);
102
103 fn warm_precompiles(&mut self, addresses: HashSet<Address>);
105
106 fn precompile_addresses(&self) -> &HashSet<Address>;
108
109 fn set_spec_id(&mut self, spec_id: SpecId);
111
112 fn touch_account(&mut self, address: Address);
114
115 fn transfer(
117 &mut self,
118 from: Address,
119 to: Address,
120 balance: U256,
121 ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
122
123 fn transfer_loaded(
125 &mut self,
126 from: Address,
127 to: Address,
128 balance: U256,
129 ) -> Option<TransferError>;
130
131 fn caller_accounting_journal_entry(
133 &mut self,
134 address: Address,
135 old_balance: U256,
136 bump_nonce: bool,
137 );
138
139 fn balance_incr(
141 &mut self,
142 address: Address,
143 balance: U256,
144 ) -> Result<(), <Self::Database as Database>::Error>;
145
146 fn nonce_bump_journal_entry(&mut self, address: Address);
148
149 fn load_account(
151 &mut self,
152 address: Address,
153 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
154
155 #[inline]
157 #[deprecated(note = "Use `load_account_with_code` instead")]
158 fn load_account_code(
159 &mut self,
160 address: Address,
161 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error> {
162 self.load_account_with_code(address)
163 }
164
165 fn load_account_with_code(
167 &mut self,
168 address: Address,
169 ) -> Result<StateLoad<&Account>, <Self::Database as Database>::Error>;
170
171 fn load_account_delegated(
173 &mut self,
174 address: Address,
175 ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
176
177 #[inline]
179 fn load_account_mut(
180 &mut self,
181 address: Address,
182 ) -> Result<
183 StateLoad<JournaledAccount<'_, Self::JournalEntry>>,
184 <Self::Database as Database>::Error,
185 > {
186 self.load_account_mut_optional_code(address, false)
187 }
188
189 #[inline]
191 fn load_account_with_code_mut(
192 &mut self,
193 address: Address,
194 ) -> Result<
195 StateLoad<JournaledAccount<'_, Self::JournalEntry>>,
196 <Self::Database as Database>::Error,
197 > {
198 self.load_account_mut_optional_code(address, true)
199 }
200
201 fn load_account_mut_optional_code(
203 &mut self,
204 address: Address,
205 load_code: bool,
206 ) -> Result<
207 StateLoad<JournaledAccount<'_, Self::JournalEntry>>,
208 <Self::Database as Database>::Error,
209 >;
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 take_logs(&mut self) -> Vec<Log>;
278
279 fn commit_tx(&mut self);
281
282 fn discard_tx(&mut self);
287
288 fn finalize(&mut self) -> Self::State;
290
291 fn load_account_info_skip_cold_load(
293 &mut self,
294 _address: Address,
295 _load_code: bool,
296 _skip_cold_load: bool,
297 ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>>;
298}
299
300#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
302#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
303pub enum JournalLoadError<E> {
304 DBError(E),
306 ColdLoadSkipped,
308}
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
353impl<E> From<E> for JournalLoadError<E> {
354 fn from(e: E) -> Self {
355 JournalLoadError::DBError(e)
356 }
357}
358
359impl<E> From<JournalLoadError<E>> for LoadError {
360 fn from(e: JournalLoadError<E>) -> Self {
361 match e {
362 JournalLoadError::DBError(_) => LoadError::DBError,
363 JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
364 }
365 }
366}
367
368#[derive(Copy, Clone, Debug, PartialEq, Eq)]
370pub enum TransferError {
371 OutOfFunds,
373 OverflowPayment,
375 CreateCollision,
377}
378
379#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
381#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
382pub struct JournalCheckpoint {
383 pub log_i: usize,
385 pub journal_i: usize,
387}
388
389#[derive(Clone, Debug, Default, PartialEq, Eq)]
391#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
392pub struct StateLoad<T> {
393 pub data: T,
395 pub is_cold: bool,
397}
398
399impl<T> Deref for StateLoad<T> {
400 type Target = T;
401
402 fn deref(&self) -> &Self::Target {
403 &self.data
404 }
405}
406
407impl<T> DerefMut for StateLoad<T> {
408 fn deref_mut(&mut self) -> &mut Self::Target {
409 &mut self.data
410 }
411}
412
413impl<T> StateLoad<T> {
414 #[inline]
416 pub fn new(data: T, is_cold: bool) -> Self {
417 Self { data, is_cold }
418 }
419
420 #[inline]
424 pub fn map<B, F>(self, f: F) -> StateLoad<B>
425 where
426 F: FnOnce(T) -> B,
427 {
428 StateLoad::new(f(self.data), self.is_cold)
429 }
430}
431
432#[derive(Clone, Debug, Default, PartialEq, Eq)]
434#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
435pub struct AccountLoad {
436 pub is_delegate_account_cold: Option<bool>,
438 pub is_empty: bool,
440}
441
442#[derive(Clone, Debug, Default, PartialEq, Eq)]
444#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
445pub struct AccountInfoLoad<'a> {
446 pub account: Cow<'a, AccountInfo>,
448 pub is_cold: bool,
450 pub is_empty: bool,
452}
453
454impl<'a> AccountInfoLoad<'a> {
455 pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
457 Self {
458 account: Cow::Borrowed(account),
459 is_cold,
460 is_empty,
461 }
462 }
463
464 pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
468 where
469 F: FnOnce(Cow<'a, AccountInfo>) -> O,
470 {
471 StateLoad::new(f(self.account), self.is_cold)
472 }
473}
474
475impl<'a> Deref for AccountInfoLoad<'a> {
476 type Target = AccountInfo;
477
478 fn deref(&self) -> &Self::Target {
479 &self.account
480 }
481}