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 caller_accounting_journal_entry(
130 &mut self,
131 address: Address,
132 old_balance: U256,
133 bump_nonce: bool,
134 );
135
136 fn balance_incr(
138 &mut self,
139 address: Address,
140 balance: U256,
141 ) -> Result<(), <Self::Database as Database>::Error>;
142
143 fn nonce_bump_journal_entry(&mut self, address: Address);
145
146 fn load_account(
148 &mut self,
149 address: Address,
150 ) -> Result<StateLoad<&mut Account>, <Self::Database as Database>::Error>;
151
152 fn load_account_code(
154 &mut self,
155 address: Address,
156 ) -> Result<StateLoad<&mut Account>, <Self::Database as Database>::Error>;
157
158 fn load_account_delegated(
160 &mut self,
161 address: Address,
162 ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
163
164 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
166
167 #[inline]
171 fn set_code(&mut self, address: Address, code: Bytecode) {
172 let hash = code.hash_slow();
173 self.set_code_with_hash(address, code, hash);
174 }
175
176 #[inline]
178 fn code(
179 &mut self,
180 address: Address,
181 ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
182 let a = self.load_account_code(address)?;
183 let code = a.info.code.as_ref().unwrap().original_bytes();
185
186 Ok(StateLoad::new(code, a.is_cold))
187 }
188
189 fn code_hash(
191 &mut self,
192 address: Address,
193 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
194 let acc = self.load_account_code(address)?;
195 if acc.is_empty() {
196 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
197 }
198 let hash = acc.info.code_hash;
199 Ok(StateLoad::new(hash, acc.is_cold))
200 }
201
202 fn clear(&mut self) {
204 let _ = self.finalize();
205 }
206
207 fn checkpoint(&mut self) -> JournalCheckpoint;
210
211 fn checkpoint_commit(&mut self);
213
214 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
216
217 fn create_account_checkpoint(
219 &mut self,
220 caller: Address,
221 address: Address,
222 balance: U256,
223 spec_id: SpecId,
224 ) -> Result<JournalCheckpoint, TransferError>;
225
226 fn depth(&self) -> usize;
228
229 fn take_logs(&mut self) -> Vec<Log>;
231
232 fn commit_tx(&mut self);
234
235 fn discard_tx(&mut self);
240
241 fn finalize(&mut self) -> Self::State;
243
244 fn load_account_info_skip_cold_load(
246 &mut self,
247 _address: Address,
248 _load_code: bool,
249 _skip_cold_load: bool,
250 ) -> Result<AccountInfoLoad<'_>, JournalLoadError<<Self::Database as Database>::Error>>;
251}
252
253#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
255#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
256pub enum JournalLoadError<E> {
257 DBError(E),
259 ColdLoadSkipped,
261}
262
263impl<E> JournalLoadError<E> {
264 #[inline]
266 pub fn is_db_error(&self) -> bool {
267 matches!(self, JournalLoadError::DBError(_))
268 }
269
270 #[inline]
272 pub fn is_cold_load_skipped(&self) -> bool {
273 matches!(self, JournalLoadError::ColdLoadSkipped)
274 }
275
276 #[inline]
278 pub fn take_db_error(self) -> Option<E> {
279 if let JournalLoadError::DBError(e) = self {
280 Some(e)
281 } else {
282 None
283 }
284 }
285
286 #[inline]
288 pub fn unwrap_db_error(self) -> E {
289 if let JournalLoadError::DBError(e) = self {
290 e
291 } else {
292 panic!("Expected DBError");
293 }
294 }
295
296 #[inline]
298 pub fn into_parts(self) -> (LoadError, Option<E>) {
299 match self {
300 JournalLoadError::DBError(e) => (LoadError::DBError, Some(e)),
301 JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None),
302 }
303 }
304}
305
306impl<E> From<E> for JournalLoadError<E> {
307 fn from(e: E) -> Self {
308 JournalLoadError::DBError(e)
309 }
310}
311
312impl<E> From<JournalLoadError<E>> for LoadError {
313 fn from(e: JournalLoadError<E>) -> Self {
314 match e {
315 JournalLoadError::DBError(_) => LoadError::DBError,
316 JournalLoadError::ColdLoadSkipped => LoadError::ColdLoadSkipped,
317 }
318 }
319}
320
321#[derive(Copy, Clone, Debug, PartialEq, Eq)]
323pub enum TransferError {
324 OutOfFunds,
326 OverflowPayment,
328 CreateCollision,
330}
331
332#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
334#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
335pub struct JournalCheckpoint {
336 pub log_i: usize,
338 pub journal_i: usize,
340}
341
342#[derive(Clone, Debug, Default, PartialEq, Eq)]
344#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
345pub struct StateLoad<T> {
346 pub data: T,
348 pub is_cold: bool,
350}
351
352impl<T> Deref for StateLoad<T> {
353 type Target = T;
354
355 fn deref(&self) -> &Self::Target {
356 &self.data
357 }
358}
359
360impl<T> DerefMut for StateLoad<T> {
361 fn deref_mut(&mut self) -> &mut Self::Target {
362 &mut self.data
363 }
364}
365
366impl<T> StateLoad<T> {
367 pub fn new(data: T, is_cold: bool) -> Self {
369 Self { data, is_cold }
370 }
371
372 pub fn map<B, F>(self, f: F) -> StateLoad<B>
376 where
377 F: FnOnce(T) -> B,
378 {
379 StateLoad::new(f(self.data), self.is_cold)
380 }
381}
382
383#[derive(Clone, Debug, Default, PartialEq, Eq)]
385#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
386pub struct AccountLoad {
387 pub is_delegate_account_cold: Option<bool>,
389 pub is_empty: bool,
391}
392
393#[derive(Clone, Debug, Default, PartialEq, Eq)]
395#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
396pub struct AccountInfoLoad<'a> {
397 pub account: Cow<'a, AccountInfo>,
399 pub is_cold: bool,
401 pub is_empty: bool,
403}
404
405impl<'a> AccountInfoLoad<'a> {
406 pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self {
408 Self {
409 account: Cow::Borrowed(account),
410 is_cold,
411 is_empty,
412 }
413 }
414
415 pub fn into_state_load<F, O>(self, f: F) -> StateLoad<O>
419 where
420 F: FnOnce(Cow<'a, AccountInfo>) -> O,
421 {
422 StateLoad::new(f(self.account), self.is_cold)
423 }
424}
425
426impl<'a> Deref for AccountInfoLoad<'a> {
427 type Target = AccountInfo;
428
429 fn deref(&self) -> &Self::Target {
430 &self.account
431 }
432}