1use crate::context::{SStoreResult, SelfDestructResult};
2use core::ops::{Deref, DerefMut};
3use database_interface::Database;
4use primitives::{
5 hardfork::SpecId, Address, Bytes, HashSet, Log, StorageKey, StorageValue, B256, U256,
6};
7use state::{
8 bytecode::{EOF_MAGIC_BYTES, EOF_MAGIC_HASH},
9 Account, Bytecode,
10};
11
12pub trait JournalTr {
14 type Database: Database;
15 type FinalOutput;
16
17 fn new(database: Self::Database) -> Self;
21
22 fn db_ref(&self) -> &Self::Database;
24
25 fn db(&mut self) -> &mut Self::Database;
27
28 fn sload(
32 &mut self,
33 address: Address,
34 key: StorageKey,
35 ) -> Result<StateLoad<StorageValue>, <Self::Database as Database>::Error>;
36
37 fn sstore(
39 &mut self,
40 address: Address,
41 key: StorageKey,
42 value: StorageValue,
43 ) -> Result<StateLoad<SStoreResult>, <Self::Database as Database>::Error>;
44
45 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
47
48 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
50
51 fn log(&mut self, log: Log);
53
54 fn selfdestruct(
56 &mut self,
57 address: Address,
58 target: Address,
59 ) -> Result<StateLoad<SelfDestructResult>, <Self::Database as Database>::Error>;
60
61 fn warm_account_and_storage(
63 &mut self,
64 address: Address,
65 storage_keys: impl IntoIterator<Item = StorageKey>,
66 ) -> Result<(), <Self::Database as Database>::Error>;
67
68 fn warm_account(&mut self, address: Address);
70
71 fn warm_precompiles(&mut self, addresses: HashSet<Address>);
73
74 fn precompile_addresses(&self) -> &HashSet<Address>;
76
77 fn set_spec_id(&mut self, spec_id: SpecId);
79
80 fn touch_account(&mut self, address: Address);
82
83 fn transfer(
85 &mut self,
86 from: Address,
87 to: Address,
88 balance: U256,
89 ) -> Result<Option<TransferError>, <Self::Database as Database>::Error>;
90
91 fn inc_account_nonce(
93 &mut self,
94 address: Address,
95 ) -> Result<Option<u64>, <Self::Database as Database>::Error>;
96
97 fn load_account(
99 &mut self,
100 address: Address,
101 ) -> Result<StateLoad<&mut Account>, <Self::Database as Database>::Error>;
102
103 fn load_account_code(
105 &mut self,
106 address: Address,
107 ) -> Result<StateLoad<&mut Account>, <Self::Database as Database>::Error>;
108
109 fn load_account_delegated(
111 &mut self,
112 address: Address,
113 ) -> Result<StateLoad<AccountLoad>, <Self::Database as Database>::Error>;
114
115 fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256);
117
118 #[inline]
122 fn set_code(&mut self, address: Address, code: Bytecode) {
123 let hash = code.hash_slow();
124 self.set_code_with_hash(address, code, hash);
125 }
126
127 #[inline]
131 fn code(
132 &mut self,
133 address: Address,
134 ) -> Result<StateLoad<Bytes>, <Self::Database as Database>::Error> {
135 let a = self.load_account_code(address)?;
136 let code = a.info.code.as_ref().unwrap();
138
139 let code = if code.is_eof() {
140 EOF_MAGIC_BYTES.clone()
141 } else {
142 code.original_bytes()
143 };
144
145 Ok(StateLoad::new(code, a.is_cold))
146 }
147
148 fn code_hash(
153 &mut self,
154 address: Address,
155 ) -> Result<StateLoad<B256>, <Self::Database as Database>::Error> {
156 let acc = self.load_account_code(address)?;
157 if acc.is_empty() {
158 return Ok(StateLoad::new(B256::ZERO, acc.is_cold));
159 }
160 let code = acc.info.code.as_ref().unwrap();
162
163 let hash = if code.is_eof() {
164 EOF_MAGIC_HASH
165 } else {
166 acc.info.code_hash
167 };
168
169 Ok(StateLoad::new(hash, acc.is_cold))
170 }
171
172 fn clear(&mut self);
174
175 fn checkpoint(&mut self) -> JournalCheckpoint;
178
179 fn checkpoint_commit(&mut self);
181
182 fn checkpoint_revert(&mut self, checkpoint: JournalCheckpoint);
184
185 fn create_account_checkpoint(
187 &mut self,
188 caller: Address,
189 address: Address,
190 balance: U256,
191 spec_id: SpecId,
192 ) -> Result<JournalCheckpoint, TransferError>;
193
194 fn depth(&self) -> usize;
196
197 fn finalize(&mut self) -> Self::FinalOutput;
201}
202
203#[derive(Copy, Clone, Debug, PartialEq, Eq)]
205pub enum TransferError {
206 OutOfFunds,
208 OverflowPayment,
210 CreateCollision,
212}
213
214#[derive(Debug, Copy, Clone, PartialEq, Eq)]
216#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
217pub struct JournalCheckpoint {
218 pub log_i: usize,
219 pub journal_i: usize,
220}
221
222#[derive(Clone, Debug, Default, PartialEq, Eq)]
224#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
225pub struct StateLoad<T> {
226 pub data: T,
228 pub is_cold: bool,
230}
231
232impl<T> Deref for StateLoad<T> {
233 type Target = T;
234
235 fn deref(&self) -> &Self::Target {
236 &self.data
237 }
238}
239
240impl<T> DerefMut for StateLoad<T> {
241 fn deref_mut(&mut self) -> &mut Self::Target {
242 &mut self.data
243 }
244}
245
246impl<T> StateLoad<T> {
247 pub fn new(data: T, is_cold: bool) -> Self {
249 Self { data, is_cold }
250 }
251
252 pub fn map<B, F>(self, f: F) -> StateLoad<B>
256 where
257 F: FnOnce(T) -> B,
258 {
259 StateLoad::new(f(self.data), self.is_cold)
260 }
261}
262
263#[derive(Clone, Debug, Default, PartialEq, Eq)]
265#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
266pub struct AccountLoad {
267 pub is_delegate_account_cold: Option<bool>,
269 pub is_empty: bool,
271}