revm_interpreter/
host.rs

1use context_interface::{
2    context::{ContextTr, SStoreResult, SelfDestructResult, StateLoad},
3    journaled_state::AccountLoad,
4    Block, Cfg, Database, JournalTr, LocalContextTr, Transaction, TransactionType,
5};
6use primitives::{Address, Bytes, Log, StorageKey, StorageValue, B256, U256};
7
8use crate::instructions::utility::IntoU256;
9
10/// Host trait with all methods that are needed by the Interpreter.
11///
12/// This trait is implemented for all types that have `ContextTr` trait.
13///
14/// There are few groups of functions which are Block, Transaction, Config, Database and Journal functions.
15pub trait Host {
16    /* Block */
17
18    /// Block basefee, calls ContextTr::block().basefee()
19    fn basefee(&self) -> U256;
20    /// Block blob gasprice, calls `ContextTr::block().blob_gasprice()`
21    fn blob_gasprice(&self) -> U256;
22    /// Block gas limit, calls ContextTr::block().gas_limit()
23    fn gas_limit(&self) -> U256;
24    /// Block difficulty, calls ContextTr::block().difficulty()
25    fn difficulty(&self) -> U256;
26    /// Block prevrandao, calls ContextTr::block().prevrandao()
27    fn prevrandao(&self) -> Option<U256>;
28    /// Block number, calls ContextTr::block().number()
29    fn block_number(&self) -> U256;
30    /// Block timestamp, calls ContextTr::block().timestamp()
31    fn timestamp(&self) -> U256;
32    /// Block beneficiary, calls ContextTr::block().beneficiary()
33    fn beneficiary(&self) -> Address;
34    /// Chain id, calls ContextTr::cfg().chain_id()
35    fn chain_id(&self) -> U256;
36
37    /* Transaction */
38
39    /// Transaction effective gas price, calls `ContextTr::tx().effective_gas_price(basefee as u128)`
40    fn effective_gas_price(&self) -> U256;
41    /// Transaction caller, calls `ContextTr::tx().caller()`
42    fn caller(&self) -> Address;
43    /// Transaction blob hash, calls `ContextTr::tx().blob_hash(number)`
44    fn blob_hash(&self, number: usize) -> Option<U256>;
45    /// Initcodes mapped to the hash.
46    fn initcode_by_hash(&mut self, hash: B256) -> Option<Bytes>;
47
48    /* Config */
49
50    /// Max initcode size, calls `ContextTr::cfg().max_code_size().saturating_mul(2)`
51    fn max_initcode_size(&self) -> usize;
52
53    /* Database */
54
55    /// Block hash, calls `ContextTr::journal_mut().db().block_hash(number)`
56    fn block_hash(&mut self, number: u64) -> Option<B256>;
57
58    /* Journal */
59
60    /// Selfdestruct account, calls `ContextTr::journal_mut().selfdestruct(address, target)`
61    fn selfdestruct(
62        &mut self,
63        address: Address,
64        target: Address,
65    ) -> Option<StateLoad<SelfDestructResult>>;
66
67    /// Log, calls `ContextTr::journal_mut().log(log)`
68    fn log(&mut self, log: Log);
69    /// Sstore, calls `ContextTr::journal_mut().sstore(address, key, value)`
70    fn sstore(
71        &mut self,
72        address: Address,
73        key: StorageKey,
74        value: StorageValue,
75    ) -> Option<StateLoad<SStoreResult>>;
76
77    /// Sload, calls `ContextTr::journal_mut().sload(address, key)`
78    fn sload(&mut self, address: Address, key: StorageKey) -> Option<StateLoad<StorageValue>>;
79    /// Tstore, calls `ContextTr::journal_mut().tstore(address, key, value)`
80    fn tstore(&mut self, address: Address, key: StorageKey, value: StorageValue);
81    /// Tload, calls `ContextTr::journal_mut().tload(address, key)`
82    fn tload(&mut self, address: Address, key: StorageKey) -> StorageValue;
83    /// Balance, calls `ContextTr::journal_mut().load_account(address)`
84    fn balance(&mut self, address: Address) -> Option<StateLoad<U256>>;
85    /// Load account delegated, calls `ContextTr::journal_mut().load_account_delegated(address)`
86    fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>>;
87    /// Load account code, calls `ContextTr::journal_mut().load_account_code(address)`
88    fn load_account_code(&mut self, address: Address) -> Option<StateLoad<Bytes>>;
89    /// Load account code hash, calls `ContextTr::journal_mut().code_hash(address)`
90    fn load_account_code_hash(&mut self, address: Address) -> Option<StateLoad<B256>>;
91}
92
93impl<CTX: ContextTr> Host for CTX {
94    /* Block */
95
96    fn basefee(&self) -> U256 {
97        U256::from(self.block().basefee())
98    }
99
100    fn blob_gasprice(&self) -> U256 {
101        U256::from(self.block().blob_gasprice().unwrap_or(0))
102    }
103
104    fn gas_limit(&self) -> U256 {
105        U256::from(self.block().gas_limit())
106    }
107
108    fn difficulty(&self) -> U256 {
109        self.block().difficulty()
110    }
111
112    fn prevrandao(&self) -> Option<U256> {
113        self.block().prevrandao().map(|r| r.into_u256())
114    }
115
116    fn block_number(&self) -> U256 {
117        self.block().number()
118    }
119
120    fn timestamp(&self) -> U256 {
121        U256::from(self.block().timestamp())
122    }
123
124    fn beneficiary(&self) -> Address {
125        self.block().beneficiary()
126    }
127
128    fn chain_id(&self) -> U256 {
129        U256::from(self.cfg().chain_id())
130    }
131
132    /* Transaction */
133
134    fn effective_gas_price(&self) -> U256 {
135        let basefee = self.block().basefee();
136        U256::from(self.tx().effective_gas_price(basefee as u128))
137    }
138
139    fn caller(&self) -> Address {
140        self.tx().caller()
141    }
142
143    fn blob_hash(&self, number: usize) -> Option<U256> {
144        let tx = &self.tx();
145        if tx.tx_type() != TransactionType::Eip4844 {
146            return None;
147        }
148        tx.blob_versioned_hashes()
149            .get(number)
150            .map(|t| U256::from_be_bytes(t.0))
151    }
152
153    fn initcode_by_hash(&mut self, hash: B256) -> Option<Bytes> {
154        self.local_mut().get_validated_initcode(hash)
155    }
156
157    /* Config */
158
159    fn max_initcode_size(&self) -> usize {
160        self.cfg().max_code_size().saturating_mul(2)
161    }
162
163    /* Database */
164
165    fn block_hash(&mut self, requested_number: u64) -> Option<B256> {
166        self.db_mut()
167            .block_hash(requested_number)
168            .map_err(|e| {
169                *self.error() = Err(e.into());
170            })
171            .ok()
172    }
173
174    /* Journal */
175
176    fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>> {
177        self.journal_mut()
178            .load_account_delegated(address)
179            .map_err(|e| {
180                *self.error() = Err(e.into());
181            })
182            .ok()
183    }
184
185    /// Gets balance of `address` and if the account is cold.
186    fn balance(&mut self, address: Address) -> Option<StateLoad<U256>> {
187        self.journal_mut()
188            .load_account(address)
189            .map(|acc| acc.map(|a| a.info.balance))
190            .map_err(|e| {
191                *self.error() = Err(e.into());
192            })
193            .ok()
194    }
195
196    /// Gets code of `address` and if the account is cold.
197    fn load_account_code(&mut self, address: Address) -> Option<StateLoad<Bytes>> {
198        self.journal_mut()
199            .code(address)
200            .map_err(|e| {
201                *self.error() = Err(e.into());
202            })
203            .ok()
204    }
205
206    /// Gets code hash of `address` and if the account is cold.
207    fn load_account_code_hash(&mut self, address: Address) -> Option<StateLoad<B256>> {
208        self.journal_mut()
209            .code_hash(address)
210            .map_err(|e| {
211                *self.error() = Err(e.into());
212            })
213            .ok()
214    }
215
216    /// Gets storage value of `address` at `index` and if the account is cold.
217    fn sload(&mut self, address: Address, index: StorageKey) -> Option<StateLoad<StorageValue>> {
218        self.journal_mut()
219            .sload(address, index)
220            .map_err(|e| {
221                *self.error() = Err(e.into());
222            })
223            .ok()
224    }
225
226    /// Sets storage value of account address at index.
227    ///
228    /// Returns [`StateLoad`] with [`SStoreResult`] that contains original/new/old storage value.
229    fn sstore(
230        &mut self,
231        address: Address,
232        index: StorageKey,
233        value: StorageValue,
234    ) -> Option<StateLoad<SStoreResult>> {
235        self.journal_mut()
236            .sstore(address, index, value)
237            .map_err(|e| {
238                *self.error() = Err(e.into());
239            })
240            .ok()
241    }
242
243    /// Gets the transient storage value of `address` at `index`.
244    fn tload(&mut self, address: Address, index: StorageKey) -> StorageValue {
245        self.journal_mut().tload(address, index)
246    }
247
248    /// Sets the transient storage value of `address` at `index`.
249    fn tstore(&mut self, address: Address, index: StorageKey, value: StorageValue) {
250        self.journal_mut().tstore(address, index, value)
251    }
252
253    /// Emits a log owned by `address` with given `LogData`.
254    fn log(&mut self, log: Log) {
255        self.journal_mut().log(log);
256    }
257
258    /// Marks `address` to be deleted, with funds transferred to `target`.
259    fn selfdestruct(
260        &mut self,
261        address: Address,
262        target: Address,
263    ) -> Option<StateLoad<SelfDestructResult>> {
264        self.journal_mut()
265            .selfdestruct(address, target)
266            .map_err(|e| {
267                *self.error() = Err(e.into());
268            })
269            .ok()
270    }
271}
272
273/// Dummy host that implements [`Host`] trait and  returns all default values.
274pub struct DummyHost;
275
276impl Host for DummyHost {
277    fn basefee(&self) -> U256 {
278        U256::ZERO
279    }
280
281    fn blob_gasprice(&self) -> U256 {
282        U256::ZERO
283    }
284
285    fn gas_limit(&self) -> U256 {
286        U256::ZERO
287    }
288
289    fn difficulty(&self) -> U256 {
290        U256::ZERO
291    }
292
293    fn prevrandao(&self) -> Option<U256> {
294        None
295    }
296
297    fn block_number(&self) -> U256 {
298        U256::ZERO
299    }
300
301    fn timestamp(&self) -> U256 {
302        U256::ZERO
303    }
304
305    fn beneficiary(&self) -> Address {
306        Address::ZERO
307    }
308
309    fn chain_id(&self) -> U256 {
310        U256::ZERO
311    }
312
313    fn effective_gas_price(&self) -> U256 {
314        U256::ZERO
315    }
316
317    fn caller(&self) -> Address {
318        Address::ZERO
319    }
320
321    fn initcode_by_hash(&mut self, _hash: B256) -> Option<Bytes> {
322        None
323    }
324
325    fn blob_hash(&self, _number: usize) -> Option<U256> {
326        None
327    }
328
329    fn max_initcode_size(&self) -> usize {
330        0
331    }
332
333    fn block_hash(&mut self, _number: u64) -> Option<B256> {
334        None
335    }
336
337    fn selfdestruct(
338        &mut self,
339        _address: Address,
340        _target: Address,
341    ) -> Option<StateLoad<SelfDestructResult>> {
342        None
343    }
344
345    fn log(&mut self, _log: Log) {}
346
347    fn sstore(
348        &mut self,
349        _address: Address,
350        _key: StorageKey,
351        _value: StorageValue,
352    ) -> Option<StateLoad<SStoreResult>> {
353        None
354    }
355
356    fn sload(&mut self, _address: Address, _key: StorageKey) -> Option<StateLoad<StorageValue>> {
357        None
358    }
359
360    fn tstore(&mut self, _address: Address, _key: StorageKey, _value: StorageValue) {}
361
362    fn tload(&mut self, _address: Address, _key: StorageKey) -> StorageValue {
363        StorageValue::ZERO
364    }
365
366    fn balance(&mut self, _address: Address) -> Option<StateLoad<U256>> {
367        None
368    }
369
370    fn load_account_delegated(&mut self, _address: Address) -> Option<StateLoad<AccountLoad>> {
371        None
372    }
373
374    fn load_account_code(&mut self, _address: Address) -> Option<StateLoad<Bytes>> {
375        None
376    }
377
378    fn load_account_code_hash(&mut self, _address: Address) -> Option<StateLoad<B256>> {
379        None
380    }
381}