1use crate::{
4 context::{SStoreResult, SelfDestructResult, StateLoad},
5 journaled_state::{AccountInfoLoad, AccountLoad},
6};
7use auto_impl::auto_impl;
8use primitives::{Address, Bytes, Log, StorageKey, StorageValue, B256, U256};
9use state::Bytecode;
10
11#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14pub enum LoadError {
15 DBError,
17 ColdLoadSkipped,
19}
20
21#[auto_impl(&mut, Box)]
27pub trait Host {
28 fn basefee(&self) -> U256;
32 fn blob_gasprice(&self) -> U256;
34 fn gas_limit(&self) -> U256;
36 fn difficulty(&self) -> U256;
38 fn prevrandao(&self) -> Option<U256>;
40 fn block_number(&self) -> U256;
42 fn timestamp(&self) -> U256;
44 fn beneficiary(&self) -> Address;
46 fn chain_id(&self) -> U256;
48
49 fn effective_gas_price(&self) -> U256;
53 fn caller(&self) -> Address;
55 fn blob_hash(&self, number: usize) -> Option<U256>;
57
58 fn max_initcode_size(&self) -> usize;
62
63 fn block_hash(&mut self, number: u64) -> Option<B256>;
67
68 fn selfdestruct(
72 &mut self,
73 address: Address,
74 target: Address,
75 ) -> Option<StateLoad<SelfDestructResult>>;
76
77 fn log(&mut self, log: Log);
79
80 fn sstore_skip_cold_load(
82 &mut self,
83 address: Address,
84 key: StorageKey,
85 value: StorageValue,
86 skip_cold_load: bool,
87 ) -> Result<StateLoad<SStoreResult>, LoadError>;
88
89 fn sstore(
91 &mut self,
92 address: Address,
93 key: StorageKey,
94 value: StorageValue,
95 ) -> Option<StateLoad<SStoreResult>> {
96 self.sstore_skip_cold_load(address, key, value, false).ok()
97 }
98
99 fn sload_skip_cold_load(
101 &mut self,
102 address: Address,
103 key: StorageKey,
104 skip_cold_load: bool,
105 ) -> Result<StateLoad<StorageValue>, LoadError>;
106
107 fn sload(&mut self, address: Address, key: StorageKey) -> Option<StateLoad<StorageValue>> {
109 self.sload_skip_cold_load(address, key, false).ok()
110 }
111
112 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
114
115 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
117
118 fn load_account_info_skip_cold_load(
127 &mut self,
128 address: Address,
129 load_code: bool,
130 skip_cold_load: bool,
131 ) -> Result<AccountInfoLoad<'_>, LoadError>;
132
133 #[inline]
135 fn balance(&mut self, address: Address) -> Option<StateLoad<U256>> {
136 self.load_account_info_skip_cold_load(address, false, false)
137 .ok()
138 .map(|load| load.into_state_load(|i| i.balance))
139 }
140
141 #[inline]
143 fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>> {
144 let account = self
145 .load_account_info_skip_cold_load(address, true, false)
146 .ok()?;
147
148 let mut account_load = StateLoad::new(
149 AccountLoad {
150 is_delegate_account_cold: None,
151 is_empty: account.is_empty,
152 },
153 account.is_cold,
154 );
155
156 if let Some(Bytecode::Eip7702(code)) = &account.code {
158 let address = code.address();
159 let delegate_account = self
160 .load_account_info_skip_cold_load(address, true, false)
161 .ok()?;
162 account_load.data.is_delegate_account_cold = Some(delegate_account.is_cold);
163 account_load.data.is_empty = delegate_account.is_empty;
164 }
165
166 Some(account_load)
167 }
168
169 #[inline]
171 fn load_account_code(&mut self, address: Address) -> Option<StateLoad<Bytes>> {
172 self.load_account_info_skip_cold_load(address, true, false)
173 .ok()
174 .map(|load| {
175 load.into_state_load(|i| {
176 i.code
177 .as_ref()
178 .map(|b| b.original_bytes())
179 .unwrap_or_default()
180 })
181 })
182 }
183
184 #[inline]
186 fn load_account_code_hash(&mut self, address: Address) -> Option<StateLoad<B256>> {
187 self.load_account_info_skip_cold_load(address, false, false)
188 .ok()
189 .map(|load| {
190 load.into_state_load(|i| {
191 if i.is_empty() {
192 B256::ZERO
193 } else {
194 i.code_hash
195 }
196 })
197 })
198 }
199}
200
201#[derive(Debug)]
203pub struct DummyHost;
204
205impl Host for DummyHost {
206 fn basefee(&self) -> U256 {
207 U256::ZERO
208 }
209
210 fn blob_gasprice(&self) -> U256 {
211 U256::ZERO
212 }
213
214 fn gas_limit(&self) -> U256 {
215 U256::ZERO
216 }
217
218 fn difficulty(&self) -> U256 {
219 U256::ZERO
220 }
221
222 fn prevrandao(&self) -> Option<U256> {
223 None
224 }
225
226 fn block_number(&self) -> U256 {
227 U256::ZERO
228 }
229
230 fn timestamp(&self) -> U256 {
231 U256::ZERO
232 }
233
234 fn beneficiary(&self) -> Address {
235 Address::ZERO
236 }
237
238 fn chain_id(&self) -> U256 {
239 U256::ZERO
240 }
241
242 fn effective_gas_price(&self) -> U256 {
243 U256::ZERO
244 }
245
246 fn caller(&self) -> Address {
247 Address::ZERO
248 }
249
250 fn blob_hash(&self, _number: usize) -> Option<U256> {
251 None
252 }
253
254 fn max_initcode_size(&self) -> usize {
255 0
256 }
257
258 fn block_hash(&mut self, _number: u64) -> Option<B256> {
259 None
260 }
261
262 fn selfdestruct(
263 &mut self,
264 _address: Address,
265 _target: Address,
266 ) -> Option<StateLoad<SelfDestructResult>> {
267 None
268 }
269
270 fn log(&mut self, _log: Log) {}
271
272 fn tstore(&mut self, _address: Address, _key: StorageKey, _value: StorageValue) {}
273
274 fn tload(&mut self, _address: Address, _key: StorageKey) -> StorageValue {
275 StorageValue::ZERO
276 }
277
278 fn load_account_info_skip_cold_load(
279 &mut self,
280 _address: Address,
281 _load_code: bool,
282 _skip_cold_load: bool,
283 ) -> Result<AccountInfoLoad<'_>, LoadError> {
284 Err(LoadError::DBError)
285 }
286
287 fn sstore_skip_cold_load(
288 &mut self,
289 _address: Address,
290 _key: StorageKey,
291 _value: StorageValue,
292 _skip_cold_load: bool,
293 ) -> Result<StateLoad<SStoreResult>, LoadError> {
294 Err(LoadError::DBError)
295 }
296
297 fn sload_skip_cold_load(
298 &mut self,
299 _address: Address,
300 _key: StorageKey,
301 _skip_cold_load: bool,
302 ) -> Result<StateLoad<StorageValue>, LoadError> {
303 Err(LoadError::DBError)
304 }
305}