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, 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
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().db().block_hash(number)`
54    fn block_hash(&mut self, number: u64) -> Option<B256>;
55
56    /* Journal */
57
58    /// Selfdestruct account, calls `ContextTr::journal().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().log(log)`
66    fn log(&mut self, log: Log);
67    /// Sstore, calls `ContextTr::journal().sstore(address, key, value)`
68    fn sstore(
69        &mut self,
70        address: Address,
71        key: U256,
72        value: U256,
73    ) -> Option<StateLoad<SStoreResult>>;
74
75    /// Sload, calls `ContextTr::journal().sload(address, key)`
76    fn sload(&mut self, address: Address, key: U256) -> Option<StateLoad<U256>>;
77    /// Tstore, calls `ContextTr::journal().tstore(address, key, value)`
78    fn tstore(&mut self, address: Address, key: U256, value: U256);
79    /// Tload, calls `ContextTr::journal().tload(address, key)`
80    fn tload(&mut self, address: Address, key: U256) -> U256;
81    /// Balance, calls `ContextTr::journal().load_account(address)`
82    fn balance(&mut self, address: Address) -> Option<StateLoad<U256>>;
83    /// Load account delegated, calls `ContextTr::journal().load_account_delegated(address)`
84    fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>>;
85    /// Load account code, calls `ContextTr::journal().load_account_code(address)`
86    fn load_account_code(&mut self, address: Address) -> Option<StateLoad<Bytes>>;
87    /// Load account code hash, calls `ContextTr::journal().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) -> u64 {
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_code_size().saturating_mul(2)
155    }
156
157    /* Database */
158
159    fn block_hash(&mut self, requested_number: u64) -> Option<B256> {
160        self.journal()
161            .db()
162            .block_hash(requested_number)
163            .map_err(|e| {
164                *self.error() = Err(e.into());
165            })
166            .ok()
167    }
168
169    /* Journal */
170
171    fn load_account_delegated(&mut self, address: Address) -> Option<StateLoad<AccountLoad>> {
172        self.journal()
173            .load_account_delegated(address)
174            .map_err(|e| {
175                *self.error() = Err(e.into());
176            })
177            .ok()
178    }
179
180    /// Gets balance of `address` and if the account is cold.
181    fn balance(&mut self, address: Address) -> Option<StateLoad<U256>> {
182        self.journal()
183            .load_account(address)
184            .map(|acc| acc.map(|a| a.info.balance))
185            .map_err(|e| {
186                *self.error() = Err(e.into());
187            })
188            .ok()
189    }
190
191    /// Gets code of `address` and if the account is cold.
192    fn load_account_code(&mut self, address: Address) -> Option<StateLoad<Bytes>> {
193        self.journal()
194            .code(address)
195            .map_err(|e| {
196                *self.error() = Err(e.into());
197            })
198            .ok()
199    }
200
201    /// Gets code hash of `address` and if the account is cold.
202    fn load_account_code_hash(&mut self, address: Address) -> Option<StateLoad<B256>> {
203        self.journal()
204            .code_hash(address)
205            .map_err(|e| {
206                *self.error() = Err(e.into());
207            })
208            .ok()
209    }
210
211    /// Gets storage value of `address` at `index` and if the account is cold.
212    fn sload(&mut self, address: Address, index: U256) -> Option<StateLoad<U256>> {
213        self.journal()
214            .sload(address, index)
215            .map_err(|e| {
216                *self.error() = Err(e.into());
217            })
218            .ok()
219    }
220
221    /// Sets storage value of account address at index.
222    ///
223    /// Returns [`StateLoad`] with [`SStoreResult`] that contains original/new/old storage value.
224    fn sstore(
225        &mut self,
226        address: Address,
227        index: U256,
228        value: U256,
229    ) -> Option<StateLoad<SStoreResult>> {
230        self.journal()
231            .sstore(address, index, value)
232            .map_err(|e| {
233                *self.error() = Err(e.into());
234            })
235            .ok()
236    }
237
238    /// Gets the transient storage value of `address` at `index`.
239    fn tload(&mut self, address: Address, index: U256) -> U256 {
240        self.journal().tload(address, index)
241    }
242
243    /// Sets the transient storage value of `address` at `index`.
244    fn tstore(&mut self, address: Address, index: U256, value: U256) {
245        self.journal().tstore(address, index, value)
246    }
247
248    /// Emits a log owned by `address` with given `LogData`.
249    fn log(&mut self, log: Log) {
250        self.journal().log(log);
251    }
252
253    /// Marks `address` to be deleted, with funds transferred to `target`.
254    fn selfdestruct(
255        &mut self,
256        address: Address,
257        target: Address,
258    ) -> Option<StateLoad<SelfDestructResult>> {
259        self.journal()
260            .selfdestruct(address, target)
261            .map_err(|e| {
262                *self.error() = Err(e.into());
263            })
264            .ok()
265    }
266}
267
268/// Dummy host that implements [`Host`] trait and  returns all default values.
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) -> u64 {
293        0
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: U256,
342        _value: U256,
343    ) -> Option<StateLoad<SStoreResult>> {
344        None
345    }
346
347    fn sload(&mut self, _address: Address, _key: U256) -> Option<StateLoad<U256>> {
348        None
349    }
350
351    fn tstore(&mut self, _address: Address, _key: U256, _value: U256) {}
352
353    fn tload(&mut self, _address: Address, _key: U256) -> U256 {
354        U256::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}