1use crate::{
3 context::{SStoreResult, SelfDestructResult},
4 host::LoadError,
5};
6use core::ops::{Deref, DerefMut};
7use database_interface::Database;
8use primitives::{
9 hardfork::SpecId, Address, Bytes, HashSet, Log, StorageKey, StorageValue, B256, U256,
10};
11use state::{Account, AccountInfo, Bytecode};
12use std::{borrow::Cow, vec::Vec};
13
14pub trait JournalTr {
16 type Database: Database;
18 type State;
20
21 fn new(database: Self::Database) -> Self;
25
26 fn db_mut(&mut self) -> &mut Self::Database;
28
29 fn db(&self) -> &Self::Database;
31
32 fn sload(
36 &mut self,
37 address: Address,
38 key: StorageKey,
39 ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error> {
40 self.sload_skip_cold_load(address, key, false)
42 .map_err(JournalLoadError::unwrap_db_error)
43 }
44
45 fn sload_skip_cold_load(
47 &mut self,
48 _address: Address,
49 _key: StorageKey,
50 _skip_cold_load: bool,
51 ) -> Result<StateLoad<StorageValue>, JournalLoadError<<Self::Database as Database>::Error>>;
52
53 fn sstore(
55 &mut self,
56 address: Address,
57 key: StorageKey,
58 value: StorageValue,
59 ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error> {
60 self.sstore_skip_cold_load(address, key, value, false)
62 .map_err(JournalLoadError::unwrap_db_error)
63 }
64
65 fn sstore_skip_cold_load(
67 &mut self,
68 _address: Address,
69 _key: StorageKey,
70 _value: StorageValue,
71 _skip_cold_load: bool,
72 ) -> Result<StateLoad<SStoreResult>, JournalLoadError<<Self::Database as Database>::Error>>;
73
74 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
76
77 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
79
80 fn log(&mut self, log: Log);
82
83 fn selfdestruct(
85 &mut self,
86 address: Address,
87 target: Address,
88 ) -> Result<StateLoad<SelfDestructResult>, <Self::Database as Database>::Error>;
89
90 fn warm_account_and_storage(
92 &mut self,
93 address: Address,
94 storage_keys: impl IntoIterator<Item = StorageKey>,
95 ) -> Result<(), <Self::Database as Database>::Error>;
96
97 fn warm_account(
99 &mut self,
100 address: Address,
101 ) -> Result<(), <Self::Database as Database>::Error> {
102 self.warm_account_and_storage(address, [])
103 }
104
105 fn warm_coinbase_account(&mut self, address: Address);
107
108 fn warm_precompiles(&mut self, addresses: HashSet<Address>);
110
111 fn precompile_addresses(&self) -> &HashSet<Address>;
113
114 fn set_spec_id(&mut self, spec_id: SpecId);
116
117 fn touch_account(&mut self, address: Address);
119
120 fn transfer(
122 &mut self,
123 from: Address,
124 to: Address,
125 balance: U256,
126 ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
127
128 fn transfer_loaded(
130 &mut self,
131 from: Address,
132 to: Address,
133 balance: U256,
134 ) -> Option<TransferError>;
135
136 fn caller_accounting_journal_entry(
138 &mut self,
139 address: Address,
140 old_balance: U256,
141 bump_nonce: bool,
142 );
143
144 fn balance_incr(
146 &mut self,
147 address: Address,
148 balance: U256,
149 ) -> Result<(), <Self::Database as Database>::Error>;
150
151 fn nonce_bump_journal_entry(&mut self, address: Address);
153
154 fn load_account(
156 &mut self,
157 address: Address,
158 ) -> Result<StateLoad<&mut Account>, <Self::Database as Database>::Error>;
159
160 fn load_account_code(
162 &mut self,
163 address: Address,
164 ) -> Result<StateLoad<&mut Account>, <Self::Database as Database>::Error>;
165
166 fn load_account_delegated(
168 &mut self,
169 address: Address,
170 ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
171
172 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
174
175 #[inline]
179 fn set_code(&mut self, address: Address, code: Bytecode) {
180 let hash = code.hash_slow();
181 self.set_code_with_hash(address, code, hash);
182 }
183
184 #[inline]
186 fn code(
187 &mut self,
188 address: Address,
189 ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
190 let a = self.load_account_code(address)?;
191 let code = a.info.code.as_ref().unwrap().original_bytes();
193
194 Ok(StateLoad::new(code, a.is_cold))
195 }
196
197 fn code_hash(
199 &mut self,
200 address: Address,
201 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
202 let acc = self.load_account_code(address)?;
203 if acc.is_empty() {
204 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
205 }
206 let hash = acc.info.code_hash;
207 Ok(StateLoad::new(hash, acc.is_cold))
208 }
209
210 fn clear(&mut self) {
212 let _ = self.finalize();
213 }
214
215 fn checkpoint(&mut self) -> JournalCheckpoint;
218
219 fn checkpoint_commit(&mut self);
221
222 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
224
225 fn create_account_checkpoint(
227 &mut self,
228 caller: Address,
229 address: Address,
230 balance: U256,
231 spec_id: SpecId,
232 ) -> Result<JournalCheckpoint, TransferError>;
233
234 fn depth(&self) -> usize;
236
237 fn take_logs(&mut self) -> Vec<Log>;
239
240 fn commit_tx(&mut self);
242
243 fn discard_tx(&mut self);
248
249 fn finalize(&mut self) -> Self::State;
251
252 fn load_account_info_skip_cold_load(
254 &mut self,
255 _address: Address,
256 _load_code: bool,
257 _skip_cold_load: bool,
258 ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>>;
259}
260
261#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
263#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
264pub enum JournalLoadError<E> {
265 DBError(E),
267 ColdLoadSkipped,
269}
270
271impl<E> JournalLoadError<E> {
272 #[inline]
274 pub fn is_db_error(&self) -> bool {
275 matches!(self, JournalLoadError::DBError(_))
276 }
277
278 #[inline]
280 pub fn is_cold_load_skipped(&self) -> bool {
281 matches!(self, JournalLoadError::ColdLoadSkipped)
282 }
283
284 #[inline]
286 pub fn take_db_error(self) -> Option<E> {
287 if let JournalLoadError::DBError(e) = self {
288 Some(e)
289 } else {
290 None
291 }
292 }
293
294 #[inline]
296 pub fn unwrap_db_error(self) -> E {
297 if let JournalLoadError::DBError(e) = self {
298 e
299 } else {
300 panic!("Expected DBError");
301 }
302 }
303
304 #[inline]
306 pub fn into_parts(self) -> (LoadError, Option<E>) {
307 match self {
308 JournalLoadError::DBError(e) => (LoadError::DBError, Some(e)),
309 JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None),
310 }
311 }
312}
313
314impl<E> From<E> for JournalLoadError<E> {
315 fn from(e: E) -> Self {
316 JournalLoadError::DBError(e)
317 }
318}
319
320impl<E> From<JournalLoadError<E>> for LoadError {
321 fn from(e: JournalLoadError<E>) -> Self {
322 match e {
323 JournalLoadError::DBError(_) => LoadError::DBError,
324 JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
325 }
326 }
327}
328
329#[derive(Copy, Clone, Debug, PartialEq, Eq)]
331pub enum TransferError {
332 OutOfFunds,
334 OverflowPayment,
336 CreateCollision,
338}
339
340#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
342#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
343pub struct JournalCheckpoint {
344 pub log_i: usize,
346 pub journal_i: usize,
348}
349
350#[derive(Clone, Debug, Default, PartialEq, Eq)]
352#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
353pub struct StateLoad<T> {
354 pub data: T,
356 pub is_cold: bool,
358}
359
360impl<T> Deref for StateLoad<T> {
361 type Target = T;
362
363 fn deref(&self) -> &Self::Target {
364 &self.data
365 }
366}
367
368impl<T> DerefMut for StateLoad<T> {
369 fn deref_mut(&mut self) -> &mut Self::Target {
370 &mut self.data
371 }
372}
373
374impl<T> StateLoad<T> {
375 pub fn new(data: T, is_cold: bool) -> Self {
377 Self { data, is_cold }
378 }
379
380 pub fn map<B, F>(self, f: F) -> StateLoad<B>
384 where
385 F: FnOnce(T) -> B,
386 {
387 StateLoad::new(f(self.data), self.is_cold)
388 }
389}
390
391#[derive(Clone, Debug, Default, PartialEq, Eq)]
393#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
394pub struct AccountLoad {
395 pub is_delegate_account_cold: Option<bool>,
397 pub is_empty: bool,
399}
400
401#[derive(Clone, Debug, Default, PartialEq, Eq)]
403#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
404pub struct AccountInfoLoad<'a> {
405 pub account: Cow<'a, AccountInfo>,
407 pub is_cold: bool,
409 pub is_empty: bool,
411}
412
413impl<'a> AccountInfoLoad<'a> {
414 pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
416 Self {
417 account: Cow::Borrowed(account),
418 is_cold,
419 is_empty,
420 }
421 }
422
423 pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
427 where
428 F: FnOnce(Cow<'a, AccountInfo>) -> O,
429 {
430 StateLoad::new(f(self.account), self.is_cold)
431 }
432}
433
434impl<'a> Deref for AccountInfoLoad<'a> {
435 type Target = AccountInfo;
436
437 fn deref(&self) -> &Self::Target {
438 &self.account
439 }
440}