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, 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) -> u64;
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().db().block_hash(number)`
56    fn block_hash(&mut self, number: u64) -> Option<B256>;
57
58    /* Journal */
59
60    /// Selfdestruct account, calls `ContextTr::journal().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().log(log)`
68    fn log(&mut self, log: Log);
69    /// Sstore, calls `ContextTr::journal().sstore(address, key, value)`
70    fn sstore(
71        &mut self,
72        address: Address,
73        key: U256,
74        value: U256,
75    ) -> Option<StateLoad<SStoreResult>>;
76
77    /// Sload, calls `ContextTr::journal().sload(address, key)`
78    fn sload(&mut self, address: Address, key: U256) -> Option<StateLoad<U256>>;
79    /// Tstore, calls `ContextTr::journal().tstore(address, key, value)`
80    fn tstore(&mut self, address: Address, key: U256, value: U256);
81    /// Tload, calls `ContextTr::journal().tload(address, key)`
82    fn tload(&mut self, address: Address, key: U256) -> U256;
83    /// Balance, calls `ContextTr::journal().load_account(address)`
84    fn balance(&mut self, address: Address) -> Option<StateLoad<U256>>;
85    /// Load account delegated, calls `ContextTr::journal().load_account_delegated(address)`
86    fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>>;
87    /// Load account code, calls `ContextTr::journal().load_account_code(address)`
88    fn load_account_code(&mut self, address: Address) -> Option<StateLoad<Bytes>>;
89    /// Load account code hash, calls `ContextTr::journal().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) -> u64 {
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().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.journal()
167            .db()
168            .block_hash(requested_number)
169            .map_err(|e| {
170                *self.error() = Err(e.into());
171            })
172            .ok()
173    }
174
175    /* Journal */
176
177    fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>> {
178        self.journal()
179            .load_account_delegated(address)
180            .map_err(|e| {
181                *self.error() = Err(e.into());
182            })
183            .ok()
184    }
185
186    /// Gets balance of `address` and if the account is cold.
187    fn balance(&mut self, address: Address) -> Option<StateLoad<U256>> {
188        self.journal()
189            .load_account(address)
190            .map(|acc| acc.map(|a| a.info.balance))
191            .map_err(|e| {
192                *self.error() = Err(e.into());
193            })
194            .ok()
195    }
196
197    /// Gets code of `address` and if the account is cold.
198    fn load_account_code(&mut self, address: Address) -> Option<StateLoad<Bytes>> {
199        self.journal()
200            .code(address)
201            .map_err(|e| {
202                *self.error() = Err(e.into());
203            })
204            .ok()
205    }
206
207    /// Gets code hash of `address` and if the account is cold.
208    fn load_account_code_hash(&mut self, address: Address) -> Option<StateLoad<B256>> {
209        self.journal()
210            .code_hash(address)
211            .map_err(|e| {
212                *self.error() = Err(e.into());
213            })
214            .ok()
215    }
216
217    /// Gets storage value of `address` at `index` and if the account is cold.
218    fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>> {
219        self.journal()
220            .sload(address, index)
221            .map_err(|e| {
222                *self.error() = Err(e.into());
223            })
224            .ok()
225    }
226
227    /// Sets storage value of account address at index.
228    ///
229    /// Returns [`StateLoad`] with [`SStoreResult`] that contains original/new/old storage value.
230    fn sstore(
231        &mut self,
232        address: Address,
233        index: U256,
234        value: U256,
235    ) -> Option<StateLoad<SStoreResult>> {
236        self.journal()
237            .sstore(address, index, value)
238            .map_err(|e| {
239                *self.error() = Err(e.into());
240            })
241            .ok()
242    }
243
244    /// Gets the transient storage value of `address` at `index`.
245    fn tload(&mut self, address: Address, index: U256) -> U256 {
246        self.journal().tload(address, index)
247    }
248
249    /// Sets the transient storage value of `address` at `index`.
250    fn tstore(&mut self, address: Address, index: U256, value: U256) {
251        self.journal().tstore(address, index, value)
252    }
253
254    /// Emits a log owned by `address` with given `LogData`.
255    fn log(&mut self, log: Log) {
256        self.journal().log(log);
257    }
258
259    /// Marks `address` to be deleted, with funds transferred to `target`.
260    fn selfdestruct(
261        &mut self,
262        address: Address,
263        target: Address,
264    ) -> Option<StateLoad<SelfDestructResult>> {
265        self.journal()
266            .selfdestruct(address, target)
267            .map_err(|e| {
268                *self.error() = Err(e.into());
269            })
270            .ok()
271    }
272}
273
274/// Dummy host that implements [`Host`] trait and  returns all default values.
275pub struct DummyHost;
276
277impl Host for DummyHost {
278    fn basefee(&self) -> U256 {
279        U256::ZERO
280    }
281
282    fn blob_gasprice(&self) -> U256 {
283        U256::ZERO
284    }
285
286    fn gas_limit(&self) -> U256 {
287        U256::ZERO
288    }
289
290    fn difficulty(&self) -> U256 {
291        U256::ZERO
292    }
293
294    fn prevrandao(&self) -> Option<U256> {
295        None
296    }
297
298    fn block_number(&self) -> u64 {
299        0
300    }
301
302    fn timestamp(&self) -> U256 {
303        U256::ZERO
304    }
305
306    fn beneficiary(&self) -> Address {
307        Address::ZERO
308    }
309
310    fn chain_id(&self) -> U256 {
311        U256::ZERO
312    }
313
314    fn effective_gas_price(&self) -> U256 {
315        U256::ZERO
316    }
317
318    fn caller(&self) -> Address {
319        Address::ZERO
320    }
321
322    fn initcode_by_hash(&mut self, _hash: B256) -> Option<Bytes> {
323        None
324    }
325
326    fn blob_hash(&self, _number: usize) -> Option<U256> {
327        None
328    }
329
330    fn max_initcode_size(&self) -> usize {
331        0
332    }
333
334    fn block_hash(&mut self, _number: u64) -> Option<B256> {
335        None
336    }
337
338    fn selfdestruct(
339        &mut self,
340        _address: Address,
341        _target: Address,
342    ) -> Option<StateLoad<SelfDestructResult>> {
343        None
344    }
345
346    fn log(&mut self, _log: Log) {}
347
348    fn sstore(
349        &mut self,
350        _address: Address,
351        _key: U256,
352        _value: U256,
353    ) -> Option<StateLoad<SStoreResult>> {
354        None
355    }
356
357    fn sload(&mut self, _address: Address, _key: U256) -> Option<StateLoad<U256>> {
358        None
359    }
360
361    fn tstore(&mut self, _address: Address, _key: U256, _value: U256) {}
362
363    fn tload(&mut self, _address: Address, _key: U256) -> U256 {
364        U256::ZERO
365    }
366
367    fn balance(&mut self, _address: Address) -> Option<StateLoad<U256>> {
368        None
369    }
370
371    fn load_account_delegated(&mut self, _address: Address) -> Option<StateLoad<AccountLoad>> {
372        None
373    }
374
375    fn load_account_code(&mut self, _address: Address) -> Option<StateLoad<Bytes>> {
376        None
377    }
378
379    fn load_account_code_hash(&mut self, _address: Address) -> Option<StateLoad<B256>> {
380        None
381    }
382}