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 slot_num(&self) -> U256;
49 fn chain_id(&self) -> U256;
51
52 fn effective_gas_price(&self) -> U256;
56 fn caller(&self) -> Address;
58 fn blob_hash(&self, number: usize) -> Option<U256>;
60
61 fn max_initcode_size(&self) -> usize;
65
66 fn gas_params(&self) -> &GasParams;
68
69 fn block_hash(&mut self, number: u64) -> Option<B256>;
73
74 fn selfdestruct(
78 &mut self,
79 address: Address,
80 target: Address,
81 skip_cold_load: bool,
82 ) -> Result<StateLoad<SelfDestructResult>, LoadError>;
83
84 fn log(&mut self, log: Log);
86
87 fn sstore_skip_cold_load(
89 &mut self,
90 address: Address,
91 key: StorageKey,
92 value: StorageValue,
93 skip_cold_load: bool,
94 ) -> Result<StateLoad<SStoreResult>, LoadError>;
95
96 fn sstore(
98 &mut self,
99 address: Address,
100 key: StorageKey,
101 value: StorageValue,
102 ) -> Option<StateLoad<SStoreResult>> {
103 self.sstore_skip_cold_load(address, key, value, false).ok()
104 }
105
106 fn sload_skip_cold_load(
108 &mut self,
109 address: Address,
110 key: StorageKey,
111 skip_cold_load: bool,
112 ) -> Result<StateLoad<StorageValue>, LoadError>;
113
114 fn sload(&mut self, address: Address, key: StorageKey) -> Option<StateLoad<StorageValue>> {
116 self.sload_skip_cold_load(address, key, false).ok()
117 }
118
119 fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
121
122 fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
124
125 fn load_account_info_skip_cold_load(
134 &mut self,
135 address: Address,
136 load_code: bool,
137 skip_cold_load: bool,
138 ) -> Result<AccountInfoLoad<'_>, LoadError>;
139
140 #[inline]
142 fn balance(&mut self, address: Address) -> Option<StateLoad<U256>> {
143 self.load_account_info_skip_cold_load(address, false, false)
144 .ok()
145 .map(|load| load.into_state_load(|i| i.balance))
146 }
147
148 #[inline]
150 fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>> {
151 let account = self
152 .load_account_info_skip_cold_load(address, true, false)
153 .ok()?;
154
155 let mut account_load = StateLoad::new(
156 AccountLoad {
157 is_delegate_account_cold: None,
158 is_empty: account.is_empty,
159 },
160 account.is_cold,
161 );
162
163 if let Some(Bytecode::Eip7702(code)) = &account.code {
165 let address = code.address();
166 let delegate_account = self
167 .load_account_info_skip_cold_load(address, true, false)
168 .ok()?;
169 account_load.data.is_delegate_account_cold = Some(delegate_account.is_cold);
170 account_load.data.is_empty = delegate_account.is_empty;
171 }
172
173 Some(account_load)
174 }
175
176 #[inline]
178 fn load_account_code(&mut self, address: Address) -> Option<StateLoad<Bytes>> {
179 self.load_account_info_skip_cold_load(address, true, false)
180 .ok()
181 .map(|load| {
182 load.into_state_load(|i| {
183 i.code
184 .as_ref()
185 .map(|b| b.original_bytes())
186 .unwrap_or_default()
187 })
188 })
189 }
190
191 #[inline]
193 fn load_account_code_hash(&mut self, address: Address) -> Option<StateLoad<B256>> {
194 self.load_account_info_skip_cold_load(address, false, false)
195 .ok()
196 .map(|load| {
197 load.into_state_load(|i| {
198 if i.is_empty() {
199 B256::ZERO
200 } else {
201 i.code_hash
202 }
203 })
204 })
205 }
206}
207
208#[derive(Default, Debug)]
210pub struct DummyHost {
211 gas_params: GasParams,
212}
213
214impl DummyHost {
215 pub fn new(spec: SpecId) -> Self {
217 Self {
218 gas_params: GasParams::new_spec(spec),
219 }
220 }
221}
222
223impl Host for DummyHost {
224 fn basefee(&self) -> U256 {
225 U256::ZERO
226 }
227
228 fn blob_gasprice(&self) -> U256 {
229 U256::ZERO
230 }
231
232 fn gas_limit(&self) -> U256 {
233 U256::ZERO
234 }
235
236 fn gas_params(&self) -> &GasParams {
237 &self.gas_params
238 }
239
240 fn difficulty(&self) -> U256 {
241 U256::ZERO
242 }
243
244 fn prevrandao(&self) -> Option<U256> {
245 None
246 }
247
248 fn block_number(&self) -> U256 {
249 U256::ZERO
250 }
251
252 fn timestamp(&self) -> U256 {
253 U256::ZERO
254 }
255
256 fn beneficiary(&self) -> Address {
257 Address::ZERO
258 }
259
260 fn slot_num(&self) -> U256 {
261 U256::ZERO
262 }
263
264 fn chain_id(&self) -> U256 {
265 U256::ZERO
266 }
267
268 fn effective_gas_price(&self) -> U256 {
269 U256::ZERO
270 }
271
272 fn caller(&self) -> Address {
273 Address::ZERO
274 }
275
276 fn blob_hash(&self, _number: usize) -> Option<U256> {
277 None
278 }
279
280 fn max_initcode_size(&self) -> usize {
281 0
282 }
283
284 fn block_hash(&mut self, _number: u64) -> Option<B256> {
285 None
286 }
287
288 fn selfdestruct(
289 &mut self,
290 _address: Address,
291 _target: Address,
292 _skip_cold_load: bool,
293 ) -> Result<StateLoad<SelfDestructResult>, LoadError> {
294 Err(LoadError::ColdLoadSkipped)
295 }
296
297 fn log(&mut self, _log: Log) {}
298
299 fn tstore(&mut self, _address: Address, _key: StorageKey, _value: StorageValue) {}
300
301 fn tload(&mut self, _address: Address, _key: StorageKey) -> StorageValue {
302 StorageValue::ZERO
303 }
304
305 fn load_account_info_skip_cold_load(
306 &mut self,
307 _address: Address,
308 _load_code: bool,
309 _skip_cold_load: bool,
310 ) -> Result<AccountInfoLoad<'_>, LoadError> {
311 Err(LoadError::DBError)
312 }
313
314 fn sstore_skip_cold_load(
315 &mut self,
316 _address: Address,
317 _key: StorageKey,
318 _value: StorageValue,
319 _skip_cold_load: bool,
320 ) -> Result<StateLoad<SStoreResult>, LoadError> {
321 Err(LoadError::DBError)
322 }
323
324 fn sload_skip_cold_load(
325 &mut self,
326 _address: Address,
327 _key: StorageKey,
328 _skip_cold_load: bool,
329 ) -> Result<StateLoad<StorageValue>, LoadError> {
330 Err(LoadError::DBError)
331 }
332}