1use crate::{
4 cfg::GasParams,
5 context::{SStoreResult, SelfDestructResult, StateLoad},
6 journaled_state::{AccountInfoLoad, AccountLoad},
7};
8use auto_impl::auto_impl;
9use primitives::{hardfork::SpecId, Address, Bytes, Log, StorageKey, StorageValue, B256, U256};
10use state::Bytecode;
11
12#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub enum LoadError {
16 DBError,
18 ColdLoadSkipped,
20}
21
22#[auto_impl(&mut, Box)]
28pub trait Host {
29 fn basefee(&self) -> U256;
33 fn blob_gasprice(&self) -> U256;
35 fn gas_limit(&self) -> U256;
37 fn difficulty(&self) -> U256;
39 fn prevrandao(&self) -> Option<U256>;
41 fn block_number(&self) -> U256;
43 fn timestamp(&self) -> U256;
45 fn beneficiary(&self) -> Address;
47 fn chain_id(&self) -> U256;
49
50 fn effective_gas_price(&self) -> U256;
54 fn caller(&self) -> Address;
56 fn blob_hash(&self, number: usize) -> Option<U256>;
58
59 fn max_initcode_size(&self) -> usize;
63
64 fn gas_params(&self) -> &GasParams;
66
67 fn block_hash(&mut self, number: u64) -> Option<B256>;
71
72 fn selfdestruct(
76 &mut self,
77 address: Address,
78 target: Address,
79 skip_cold_load: bool,
80 ) -> Result<StateLoad<SelfDestructResult>, LoadError>;
81
82 fn log(&mut self, log: Log);
84
85 fn sstore_skip_cold_load(
87 &mut self,
88 address: Address,
89 key: StorageKey,
90 value: StorageValue,
91 skip_cold_load: bool,
92 ) -> Result<StateLoad<SStoreResult>, LoadError>;
93
94 fn sstore(
96 &mut self,
97 address: Address,
98 key: StorageKey,
99 value: StorageValue,
100 ) -> Option<StateLoad<SStoreResult>> {
101 self.sstore_skip_cold_load(address, key, value, false).ok()
102 }
103
104 fn sload_skip_cold_load(
106 &mut self,
107 address: Address,
108 key: StorageKey,
109 skip_cold_load: bool,
110 ) -> Result<StateLoad<StorageValue>, LoadError>;
111
112 fn sload(&mut self, address: Address, key: StorageKey) -> Option<StateLoad<StorageValue>> {
114 self.sload_skip_cold_load(address, key, false).ok()
115 }
116
117 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
119
120 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
122
123 fn load_account_info_skip_cold_load(
132 &mut self,
133 address: Address,
134 load_code: bool,
135 skip_cold_load: bool,
136 ) -> Result<AccountInfoLoad<'_>, LoadError>;
137
138 #[inline]
140 fn balance(&mut self, address: Address) -> Option<StateLoad<U256>> {
141 self.load_account_info_skip_cold_load(address, false, false)
142 .ok()
143 .map(|load| load.into_state_load(|i| i.balance))
144 }
145
146 #[inline]
148 fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>> {
149 let account = self
150 .load_account_info_skip_cold_load(address, true, false)
151 .ok()?;
152
153 let mut account_load = StateLoad::new(
154 AccountLoad {
155 is_delegate_account_cold: None,
156 is_empty: account.is_empty,
157 },
158 account.is_cold,
159 );
160
161 if let Some(Bytecode::Eip7702(code)) = &account.code {
163 let address = code.address();
164 let delegate_account = self
165 .load_account_info_skip_cold_load(address, true, false)
166 .ok()?;
167 account_load.data.is_delegate_account_cold = Some(delegate_account.is_cold);
168 account_load.data.is_empty = delegate_account.is_empty;
169 }
170
171 Some(account_load)
172 }
173
174 #[inline]
176 fn load_account_code(&mut self, address: Address) -> Option<StateLoad<Bytes>> {
177 self.load_account_info_skip_cold_load(address, true, false)
178 .ok()
179 .map(|load| {
180 load.into_state_load(|i| {
181 i.code
182 .as_ref()
183 .map(|b| b.original_bytes())
184 .unwrap_or_default()
185 })
186 })
187 }
188
189 #[inline]
191 fn load_account_code_hash(&mut self, address: Address) -> Option<StateLoad<B256>> {
192 self.load_account_info_skip_cold_load(address, false, false)
193 .ok()
194 .map(|load| {
195 load.into_state_load(|i| {
196 if i.is_empty() {
197 B256::ZERO
198 } else {
199 i.code_hash
200 }
201 })
202 })
203 }
204}
205
206#[derive(Default, Debug)]
208pub struct DummyHost {
209 gas_params: GasParams,
210}
211
212impl DummyHost {
213 pub fn new(spec: SpecId) -> Self {
215 Self {
216 gas_params: GasParams::new_spec(spec).clone(),
217 }
218 }
219}
220
221impl Host for DummyHost {
222 fn basefee(&self) -> U256 {
223 U256::ZERO
224 }
225
226 fn blob_gasprice(&self) -> U256 {
227 U256::ZERO
228 }
229
230 fn gas_limit(&self) -> U256 {
231 U256::ZERO
232 }
233
234 fn gas_params(&self) -> &GasParams {
235 &self.gas_params
236 }
237
238 fn difficulty(&self) -> U256 {
239 U256::ZERO
240 }
241
242 fn prevrandao(&self) -> Option<U256> {
243 None
244 }
245
246 fn block_number(&self) -> U256 {
247 U256::ZERO
248 }
249
250 fn timestamp(&self) -> U256 {
251 U256::ZERO
252 }
253
254 fn beneficiary(&self) -> Address {
255 Address::ZERO
256 }
257
258 fn chain_id(&self) -> U256 {
259 U256::ZERO
260 }
261
262 fn effective_gas_price(&self) -> U256 {
263 U256::ZERO
264 }
265
266 fn caller(&self) -> Address {
267 Address::ZERO
268 }
269
270 fn blob_hash(&self, _number: usize) -> Option<U256> {
271 None
272 }
273
274 fn max_initcode_size(&self) -> usize {
275 0
276 }
277
278 fn block_hash(&mut self, _number: u64) -> Option<B256> {
279 None
280 }
281
282 fn selfdestruct(
283 &mut self,
284 _address: Address,
285 _target: Address,
286 _skip_cold_load: bool,
287 ) -> Result<StateLoad<SelfDestructResult>, LoadError> {
288 Err(LoadError::ColdLoadSkipped)
289 }
290
291 fn log(&mut self, _log: Log) {}
292
293 fn tstore(&mut self, _address: Address, _key: StorageKey, _value: StorageValue) {}
294
295 fn tload(&mut self, _address: Address, _key: StorageKey) -> StorageValue {
296 StorageValue::ZERO
297 }
298
299 fn load_account_info_skip_cold_load(
300 &mut self,
301 _address: Address,
302 _load_code: bool,
303 _skip_cold_load: bool,
304 ) -> Result<AccountInfoLoad<'_>, LoadError> {
305 Err(LoadError::DBError)
306 }
307
308 fn sstore_skip_cold_load(
309 &mut self,
310 _address: Address,
311 _key: StorageKey,
312 _value: StorageValue,
313 _skip_cold_load: bool,
314 ) -> Result<StateLoad<SStoreResult>, LoadError> {
315 Err(LoadError::DBError)
316 }
317
318 fn sload_skip_cold_load(
319 &mut self,
320 _address: Address,
321 _key: StorageKey,
322 _skip_cold_load: bool,
323 ) -> Result<StateLoad<StorageValue>, LoadError> {
324 Err(LoadError::DBError)
325 }
326}