Skip to main content

revm_context/
context.rs

1//! This module contains [`Context`] struct and implements [`ContextTr`] trait for it.
2use crate::{block::BlockEnv, cfg::CfgEnv, journal::Journal, tx::TxEnv, LocalContext};
3use context_interface::{
4    cfg::GasParams,
5    context::{ContextError, ContextSetters, SStoreResult, SelfDestructResult, StateLoad},
6    host::LoadError,
7    journaled_state::AccountInfoLoad,
8    Block, Cfg, ContextTr, Host, JournalTr, LocalContextTr, Transaction, TransactionType,
9};
10use database_interface::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef};
11use derive_where::derive_where;
12use primitives::{
13    hardfork::SpecId, hints_util::cold_path, Address, Log, StorageKey, StorageValue, B256, U256,
14};
15
16/// EVM context contains data that EVM needs for execution.
17#[derive_where(Clone, Debug; BLOCK, CFG, CHAIN, TX, DB, JOURNAL, <DB as Database>::Error, LOCAL)]
18pub struct Context<
19    BLOCK = BlockEnv,
20    TX = TxEnv,
21    CFG = CfgEnv,
22    DB: Database = EmptyDB,
23    JOURNAL: JournalTr<Database = DB> = Journal<DB>,
24    CHAIN = (),
25    LOCAL: LocalContextTr = LocalContext,
26> {
27    /// Block information.
28    pub block: BLOCK,
29    /// Transaction information.
30    pub tx: TX,
31    /// Configurations.
32    pub cfg: CFG,
33    /// EVM State with journaling support and database.
34    pub journaled_state: JOURNAL,
35    /// Inner context.
36    pub chain: CHAIN,
37    /// Local context that is filled by execution.
38    pub local: LOCAL,
39    /// Error that happened during execution.
40    pub error: Result<(), ContextError<DB::Error>>,
41}
42
43#[inline]
44fn sync_cfg_to_journal<CFG: Cfg, JOURNAL: JournalTr>(cfg: &CFG, journal: &mut JOURNAL) {
45    journal.set_spec_id(cfg.spec().into());
46    journal.set_eip7708_config(
47        cfg.is_eip7708_disabled(),
48        cfg.is_eip7708_delayed_burn_disabled(),
49    );
50}
51
52impl<
53        BLOCK: Block,
54        TX: Transaction,
55        DB: Database,
56        CFG: Cfg,
57        JOURNAL: JournalTr<Database = DB>,
58        CHAIN,
59        LOCAL: LocalContextTr,
60    > ContextTr for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL>
61{
62    type Block = BLOCK;
63    type Tx = TX;
64    type Cfg = CFG;
65    type Db = DB;
66    type Journal = JOURNAL;
67    type Chain = CHAIN;
68    type Local = LOCAL;
69
70    #[inline]
71    fn all(
72        &self,
73    ) -> (
74        &Self::Block,
75        &Self::Tx,
76        &Self::Cfg,
77        &Self::Db,
78        &Self::Journal,
79        &Self::Chain,
80        &Self::Local,
81    ) {
82        let block = &self.block;
83        let tx = &self.tx;
84        let cfg = &self.cfg;
85        let db = self.journaled_state.db();
86        let journal = &self.journaled_state;
87        let chain = &self.chain;
88        let local = &self.local;
89
90        (block, tx, cfg, db, journal, chain, local)
91    }
92
93    #[inline]
94    fn all_mut(
95        &mut self,
96    ) -> (
97        &Self::Block,
98        &Self::Tx,
99        &Self::Cfg,
100        &mut Self::Journal,
101        &mut Self::Chain,
102        &mut Self::Local,
103    ) {
104        let block = &self.block;
105        let tx = &self.tx;
106        let cfg = &self.cfg;
107        let journal = &mut self.journaled_state;
108        let chain = &mut self.chain;
109        let local = &mut self.local;
110
111        (block, tx, cfg, journal, chain, local)
112    }
113
114    #[inline]
115    fn error(&mut self) -> &mut Result<(), ContextError<<Self::Db as Database>::Error>> {
116        &mut self.error
117    }
118}
119
120impl<
121        BLOCK: Block,
122        TX: Transaction,
123        DB: Database,
124        CFG: Cfg,
125        JOURNAL: JournalTr<Database = DB>,
126        CHAIN,
127        LOCAL: LocalContextTr,
128    > ContextSetters for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL>
129{
130    fn set_tx(&mut self, tx: Self::Tx) {
131        self.tx = tx;
132    }
133
134    fn set_block(&mut self, block: Self::Block) {
135        self.block = block;
136    }
137}
138
139impl<
140        BLOCK: Block + Default,
141        TX: Transaction + Default,
142        DB: Database,
143        JOURNAL: JournalTr<Database = DB>,
144        CHAIN: Default,
145        LOCAL: LocalContextTr + Default,
146        SPEC: Default + Into<SpecId> + Clone,
147    > Context<BLOCK, TX, CfgEnv<SPEC>, DB, JOURNAL, CHAIN, LOCAL>
148{
149    /// Creates a new context with a new database type.
150    ///
151    /// This will create a new [`Journal`] object.
152    pub fn new(db: DB, spec: SPEC) -> Self {
153        let cfg = CfgEnv::new_with_spec(spec);
154        let mut journaled_state = JOURNAL::new(db);
155        sync_cfg_to_journal(&cfg, &mut journaled_state);
156        Self {
157            tx: TX::default(),
158            block: BLOCK::default(),
159            cfg,
160            local: LOCAL::default(),
161            journaled_state,
162            chain: Default::default(),
163            error: Ok(()),
164        }
165    }
166}
167
168impl<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL>
169where
170    BLOCK: Block,
171    TX: Transaction,
172    CFG: Cfg,
173    DB: Database,
174    JOURNAL: JournalTr<Database = DB>,
175    LOCAL: LocalContextTr,
176{
177    /// Creates a new context with a new journal type. New journal needs to have the same database type.
178    pub fn with_new_journal<OJOURNAL: JournalTr<Database = DB>>(
179        self,
180        mut journal: OJOURNAL,
181    ) -> Context<BLOCK, TX, CFG, DB, OJOURNAL, CHAIN, LOCAL> {
182        sync_cfg_to_journal(&self.cfg, &mut journal);
183        Context {
184            tx: self.tx,
185            block: self.block,
186            cfg: self.cfg,
187            journaled_state: journal,
188            local: self.local,
189            chain: self.chain,
190            error: Ok(()),
191        }
192    }
193
194    /// Creates a new context with a new database type.
195    ///
196    /// This will create a new [`Journal`] object.
197    pub fn with_db<ODB: Database>(
198        self,
199        db: ODB,
200    ) -> Context<BLOCK, TX, CFG, ODB, Journal<ODB>, CHAIN, LOCAL> {
201        let mut journaled_state = Journal::new(db);
202        sync_cfg_to_journal(&self.cfg, &mut journaled_state);
203        Context {
204            tx: self.tx,
205            block: self.block,
206            cfg: self.cfg,
207            journaled_state,
208            local: self.local,
209            chain: self.chain,
210            error: Ok(()),
211        }
212    }
213
214    /// Creates a new context with a new `DatabaseRef` type.
215    pub fn with_ref_db<ODB: DatabaseRef>(
216        self,
217        db: ODB,
218    ) -> Context<BLOCK, TX, CFG, WrapDatabaseRef<ODB>, Journal<WrapDatabaseRef<ODB>>, CHAIN, LOCAL>
219    {
220        let mut journaled_state = Journal::new(WrapDatabaseRef(db));
221        sync_cfg_to_journal(&self.cfg, &mut journaled_state);
222        Context {
223            tx: self.tx,
224            block: self.block,
225            cfg: self.cfg,
226            journaled_state,
227            local: self.local,
228            chain: self.chain,
229            error: Ok(()),
230        }
231    }
232
233    /// Creates a new context with a new block type.
234    pub fn with_block<OB: Block>(
235        self,
236        block: OB,
237    ) -> Context<OB, TX, CFG, DB, JOURNAL, CHAIN, LOCAL> {
238        Context {
239            tx: self.tx,
240            block,
241            cfg: self.cfg,
242            journaled_state: self.journaled_state,
243            local: self.local,
244            chain: self.chain,
245            error: Ok(()),
246        }
247    }
248    /// Creates a new context with a new transaction type.
249    pub fn with_tx<OTX: Transaction>(
250        self,
251        tx: OTX,
252    ) -> Context<BLOCK, OTX, CFG, DB, JOURNAL, CHAIN, LOCAL> {
253        Context {
254            tx,
255            block: self.block,
256            cfg: self.cfg,
257            journaled_state: self.journaled_state,
258            local: self.local,
259            chain: self.chain,
260            error: Ok(()),
261        }
262    }
263
264    /// Creates a new context with a new chain type.
265    pub fn with_chain<OC>(self, chain: OC) -> Context<BLOCK, TX, CFG, DB, JOURNAL, OC, LOCAL> {
266        Context {
267            tx: self.tx,
268            block: self.block,
269            cfg: self.cfg,
270            journaled_state: self.journaled_state,
271            local: self.local,
272            chain,
273            error: Ok(()),
274        }
275    }
276
277    /// Creates a new context with a new chain type.
278    pub fn with_cfg<OCFG: Cfg>(
279        mut self,
280        cfg: OCFG,
281    ) -> Context<BLOCK, TX, OCFG, DB, JOURNAL, CHAIN, LOCAL> {
282        sync_cfg_to_journal(&cfg, &mut self.journaled_state);
283        Context {
284            tx: self.tx,
285            block: self.block,
286            cfg,
287            journaled_state: self.journaled_state,
288            local: self.local,
289            chain: self.chain,
290            error: Ok(()),
291        }
292    }
293
294    /// Creates a new context with a new local context type.
295    pub fn with_local<OL: LocalContextTr>(
296        self,
297        local: OL,
298    ) -> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, OL> {
299        Context {
300            tx: self.tx,
301            block: self.block,
302            cfg: self.cfg,
303            journaled_state: self.journaled_state,
304            local,
305            chain: self.chain,
306            error: Ok(()),
307        }
308    }
309
310    /// Modifies the context configuration.
311    #[must_use]
312    pub fn modify_cfg_chained<F>(mut self, f: F) -> Self
313    where
314        F: FnOnce(&mut CFG),
315    {
316        f(&mut self.cfg);
317        sync_cfg_to_journal(&self.cfg, &mut self.journaled_state);
318        self
319    }
320
321    /// Modifies the context block.
322    #[must_use]
323    pub fn modify_block_chained<F>(mut self, f: F) -> Self
324    where
325        F: FnOnce(&mut BLOCK),
326    {
327        self.modify_block(f);
328        self
329    }
330
331    /// Modifies the context transaction.
332    #[must_use]
333    pub fn modify_tx_chained<F>(mut self, f: F) -> Self
334    where
335        F: FnOnce(&mut TX),
336    {
337        self.modify_tx(f);
338        self
339    }
340
341    /// Modifies the context chain.
342    #[must_use]
343    pub fn modify_chain_chained<F>(mut self, f: F) -> Self
344    where
345        F: FnOnce(&mut CHAIN),
346    {
347        self.modify_chain(f);
348        self
349    }
350
351    /// Modifies the context database.
352    #[must_use]
353    pub fn modify_db_chained<F>(mut self, f: F) -> Self
354    where
355        F: FnOnce(&mut DB),
356    {
357        self.modify_db(f);
358        self
359    }
360
361    /// Modifies the context journal.
362    #[must_use]
363    pub fn modify_journal_chained<F>(mut self, f: F) -> Self
364    where
365        F: FnOnce(&mut JOURNAL),
366    {
367        self.modify_journal(f);
368        self
369    }
370
371    /// Modifies the context block.
372    pub fn modify_block<F>(&mut self, f: F)
373    where
374        F: FnOnce(&mut BLOCK),
375    {
376        f(&mut self.block);
377    }
378
379    /// Modifies the context transaction.
380    pub fn modify_tx<F>(&mut self, f: F)
381    where
382        F: FnOnce(&mut TX),
383    {
384        f(&mut self.tx);
385    }
386
387    /// Modifies the context configuration.
388    pub fn modify_cfg<F>(&mut self, f: F)
389    where
390        F: FnOnce(&mut CFG),
391    {
392        f(&mut self.cfg);
393        sync_cfg_to_journal(&self.cfg, &mut self.journaled_state);
394    }
395
396    /// Modifies the context chain.
397    pub fn modify_chain<F>(&mut self, f: F)
398    where
399        F: FnOnce(&mut CHAIN),
400    {
401        f(&mut self.chain);
402    }
403
404    /// Modifies the context database.
405    pub fn modify_db<F>(&mut self, f: F)
406    where
407        F: FnOnce(&mut DB),
408    {
409        f(self.journaled_state.db_mut());
410    }
411
412    /// Modifies the context journal.
413    pub fn modify_journal<F>(&mut self, f: F)
414    where
415        F: FnOnce(&mut JOURNAL),
416    {
417        f(&mut self.journaled_state);
418    }
419
420    /// Modifies the local context.
421    pub fn modify_local<F>(&mut self, f: F)
422    where
423        F: FnOnce(&mut LOCAL),
424    {
425        f(&mut self.local);
426    }
427}
428
429impl<
430        BLOCK: Block,
431        TX: Transaction,
432        CFG: Cfg,
433        DB: Database,
434        JOURNAL: JournalTr<Database = DB>,
435        CHAIN,
436        LOCAL: LocalContextTr,
437    > Host for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL>
438{
439    /* Block */
440
441    fn basefee(&self) -> U256 {
442        U256::from(self.block().basefee())
443    }
444
445    fn blob_gasprice(&self) -> U256 {
446        U256::from(self.block().blob_gasprice().unwrap_or(0))
447    }
448
449    fn gas_limit(&self) -> U256 {
450        U256::from(self.block().gas_limit())
451    }
452
453    fn difficulty(&self) -> U256 {
454        self.block().difficulty()
455    }
456
457    fn prevrandao(&self) -> Option<U256> {
458        self.block().prevrandao().map(|r| r.into())
459    }
460
461    #[inline]
462    fn gas_params(&self) -> &GasParams {
463        self.cfg().gas_params()
464    }
465
466    fn is_amsterdam_eip8037_enabled(&self) -> bool {
467        self.cfg().is_amsterdam_eip8037_enabled()
468    }
469
470    fn block_number(&self) -> U256 {
471        self.block().number()
472    }
473
474    fn timestamp(&self) -> U256 {
475        U256::from(self.block().timestamp())
476    }
477
478    fn beneficiary(&self) -> Address {
479        self.block().beneficiary()
480    }
481
482    fn slot_num(&self) -> U256 {
483        U256::from(self.block().slot_num())
484    }
485
486    fn chain_id(&self) -> U256 {
487        U256::from(self.cfg().chain_id())
488    }
489
490    /* Transaction */
491
492    fn effective_gas_price(&self) -> U256 {
493        let basefee = self.block().basefee();
494        U256::from(self.tx().effective_gas_price(basefee as u128))
495    }
496
497    fn caller(&self) -> Address {
498        self.tx().caller()
499    }
500
501    fn blob_hash(&self, number: usize) -> Option<U256> {
502        let tx = &self.tx();
503        if tx.tx_type() != TransactionType::Eip4844 {
504            return None;
505        }
506        tx.blob_versioned_hashes()
507            .get(number)
508            .map(|t| U256::from_be_bytes(t.0))
509    }
510
511    /* Config */
512
513    fn max_initcode_size(&self) -> usize {
514        self.cfg().max_initcode_size()
515    }
516
517    /* Database */
518
519    fn block_hash(&mut self, requested_number: u64) -> Option<B256> {
520        self.db_mut()
521            .block_hash(requested_number)
522            .map_err(|e| {
523                cold_path();
524                *self.error() = Err(e.into());
525            })
526            .ok()
527    }
528
529    /* Journal */
530
531    /// Gets the transient storage value of `address` at `index`.
532    fn tload(&mut self, address: Address, index: StorageKey) -> StorageValue {
533        self.journal_mut().tload(address, index)
534    }
535
536    /// Sets the transient storage value of `address` at `index`.
537    fn tstore(&mut self, address: Address, index: StorageKey, value: StorageValue) {
538        self.journal_mut().tstore(address, index, value)
539    }
540
541    /// Emits a log owned by `address` with given `LogData`.
542    fn log(&mut self, log: Log) {
543        self.journal_mut().log(log);
544    }
545
546    /// Marks `address` to be deleted, with funds transferred to `target`.
547    #[inline]
548    fn selfdestruct(
549        &mut self,
550        address: Address,
551        target: Address,
552        skip_cold_load: bool,
553    ) -> Result<StateLoad<SelfDestructResult>, LoadError> {
554        self.journal_mut()
555            .selfdestruct(address, target, skip_cold_load)
556            .map_err(|e| {
557                cold_path();
558                let (ret, err) = e.into_parts();
559                if let Some(err) = err {
560                    *self.error() = Err(err.into());
561                }
562                ret
563            })
564    }
565
566    #[inline]
567    fn sstore_skip_cold_load(
568        &mut self,
569        address: Address,
570        key: StorageKey,
571        value: StorageValue,
572        skip_cold_load: bool,
573    ) -> Result<StateLoad<SStoreResult>, LoadError> {
574        self.journal_mut()
575            .sstore_skip_cold_load(address, key, value, skip_cold_load)
576            .map_err(|e| {
577                cold_path();
578                let (ret, err) = e.into_parts();
579                if let Some(err) = err {
580                    *self.error() = Err(err.into());
581                }
582                ret
583            })
584    }
585
586    #[inline]
587    fn sload_skip_cold_load(
588        &mut self,
589        address: Address,
590        key: StorageKey,
591        skip_cold_load: bool,
592    ) -> Result<StateLoad<StorageValue>, LoadError> {
593        self.journal_mut()
594            .sload_skip_cold_load(address, key, skip_cold_load)
595            .map_err(|e| {
596                cold_path();
597                let (ret, err) = e.into_parts();
598                if let Some(err) = err {
599                    *self.error() = Err(err.into());
600                }
601                ret
602            })
603    }
604
605    #[inline]
606    fn load_account_info_skip_cold_load(
607        &mut self,
608        address: Address,
609        load_code: bool,
610        skip_cold_load: bool,
611    ) -> Result<AccountInfoLoad<'_>, LoadError> {
612        match self.journaled_state.load_account_info_skip_cold_load(
613            address,
614            load_code,
615            skip_cold_load,
616        ) {
617            Ok(a) => Ok(a),
618            Err(e) => {
619                cold_path();
620                let (ret, err) = e.into_parts();
621                if let Some(err) = err {
622                    self.error = Err(err.into());
623                }
624                Err(ret)
625            }
626        }
627    }
628}