revm_interpreter/
host.rs

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