1use crate::context::{SStoreResult, SelfDestructResult};
3use core::ops::{Deref, DerefMut};
4use database_interface::Database;
5use primitives::{
6 hardfork::SpecId, Address, Bytes, HashSet, Log, StorageKey, StorageValue, B256, U256,
7};
8use state::{
9 bytecode::{EOF_MAGIC_BYTES, EOF_MAGIC_HASH},
10 Account, Bytecode,
11};
12use std::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
41 fn sstore(
43 &mut self,
44 address: Address,
45 key: StorageKey,
46 value: StorageValue,
47 ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error>;
48
49 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
51
52 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
54
55 fn log(&mut self, log: Log);
57
58 fn selfdestruct(
60 &mut self,
61 address: Address,
62 target: Address,
63 ) -> Result<StateLoad<SelfDestructResult>, <Self::Database as Database>::Error>;
64
65 fn warm_account_and_storage(
67 &mut self,
68 address: Address,
69 storage_keys: impl IntoIterator<Item = StorageKey>,
70 ) -> Result<(), <Self::Database as Database>::Error>;
71
72 fn warm_account(&mut self, address: Address);
74
75 fn warm_precompiles(&mut self, addresses: HashSet<Address>);
77
78 fn precompile_addresses(&self) -> &HashSet<Address>;
80
81 fn set_spec_id(&mut self, spec_id: SpecId);
83
84 fn touch_account(&mut self, address: Address);
86
87 fn transfer(
89 &mut self,
90 from: Address,
91 to: Address,
92 balance: U256,
93 ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
94
95 fn caller_accounting_journal_entry(
97 &mut self,
98 address: Address,
99 old_balance: U256,
100 bump_nonce: bool,
101 );
102
103 fn balance_incr(
105 &mut self,
106 address: Address,
107 balance: U256,
108 ) -> Result<(), <Self::Database as Database>::Error>;
109
110 fn nonce_bump_journal_entry(&mut self, address: Address);
112
113 fn load_account(
115 &mut self,
116 address: Address,
117 ) -> Result<StateLoad<&mut Account>, <Self::Database as Database>::Error>;
118
119 fn load_account_code(
121 &mut self,
122 address: Address,
123 ) -> Result<StateLoad<&mut Account>, <Self::Database as Database>::Error>;
124
125 fn load_account_delegated(
127 &mut self,
128 address: Address,
129 ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
130
131 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
133
134 #[inline]
138 fn set_code(&mut self, address: Address, code: Bytecode) {
139 let hash = code.hash_slow();
140 self.set_code_with_hash(address, code, hash);
141 }
142
143 #[inline]
147 fn code(
148 &mut self,
149 address: Address,
150 ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
151 let a = self.load_account_code(address)?;
152 let code = a.info.code.as_ref().unwrap();
154
155 let code = if code.is_eof() {
156 EOF_MAGIC_BYTES.clone()
157 } else {
158 code.original_bytes()
159 };
160
161 Ok(StateLoad::new(code, a.is_cold))
162 }
163
164 fn code_hash(
169 &mut self,
170 address: Address,
171 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
172 let acc = self.load_account_code(address)?;
173 if acc.is_empty() {
174 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
175 }
176 let code = acc.info.code.as_ref().unwrap();
178
179 let hash = if code.is_eof() {
180 EOF_MAGIC_HASH
181 } else {
182 acc.info.code_hash
183 };
184
185 Ok(StateLoad::new(hash, acc.is_cold))
186 }
187
188 fn clear(&mut self) {
190 let _ = self.finalize();
191 }
192
193 fn checkpoint(&mut self) -> JournalCheckpoint;
196
197 fn checkpoint_commit(&mut self);
199
200 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
202
203 fn create_account_checkpoint(
205 &mut self,
206 caller: Address,
207 address: Address,
208 balance: U256,
209 spec_id: SpecId,
210 ) -> Result<JournalCheckpoint, TransferError>;
211
212 fn depth(&self) -> usize;
214
215 fn take_logs(&mut self) -> Vec<Log>;
217
218 fn commit_tx(&mut self);
220
221 fn discard_tx(&mut self);
226
227 fn finalize(&mut self) -> Self::State;
229}
230
231#[derive(Copy, Clone, Debug, PartialEq, Eq)]
233pub enum TransferError {
234 OutOfFunds,
236 OverflowPayment,
238 CreateCollision,
240}
241
242#[derive(Debug, Copy, Clone, PartialEq, Eq)]
244#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
245pub struct JournalCheckpoint {
246 pub log_i: usize,
248 pub journal_i: usize,
250}
251
252#[derive(Clone, Debug, Default, PartialEq, Eq)]
254#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
255pub struct StateLoad<T> {
256 pub data: T,
258 pub is_cold: bool,
260}
261
262impl<T> Deref for StateLoad<T> {
263 type Target = T;
264
265 fn deref(&self) -> &Self::Target {
266 &self.data
267 }
268}
269
270impl<T> DerefMut for StateLoad<T> {
271 fn deref_mut(&mut self) -> &mut Self::Target {
272 &mut self.data
273 }
274}
275
276impl<T> StateLoad<T> {
277 pub fn new(data: T, is_cold: bool) -> Self {
279 Self { data, is_cold }
280 }
281
282 pub fn map<B, F>(self, f: F) -> StateLoad<B>
286 where
287 F: FnOnce(T) -> B,
288 {
289 StateLoad::new(f(self.data), self.is_cold)
290 }
291}
292
293#[derive(Clone, Debug, Default, PartialEq, Eq)]
295#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
296pub struct AccountLoad {
297 pub is_delegate_account_cold: Option<bool>,
299 pub is_empty: bool,
301}