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    context::{ContextError, ContextSetters},
5    Block, Cfg, ContextTr, JournalTr, LocalContextTr, Transaction,
6};
7use database_interface::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef};
8use derive_where::derive_where;
9use primitives::hardfork::SpecId;
10
11/// EVM context contains data that EVM needs for execution.
12#[derive_where(Clone, Debug; BLOCK, CFG, CHAIN, TX, DB, JOURNAL, <DB as Database>::Error, LOCAL)]
13pub struct Context<
14    BLOCK = BlockEnv,
15    TX = TxEnv,
16    CFG = CfgEnv,
17    DB: Database = EmptyDB,
18    JOURNAL: JournalTr<Database = DB> = Journal<DB>,
19    CHAIN = (),
20    LOCAL: LocalContextTr = LocalContext,
21> {
22    /// Block information.
23    pub block: BLOCK,
24    /// Transaction information.
25    pub tx: TX,
26    /// Configurations.
27    pub cfg: CFG,
28    /// EVM State with journaling support and database.
29    pub journaled_state: JOURNAL,
30    /// Inner context.
31    pub chain: CHAIN,
32    /// Local context that is filled by execution.
33    pub local: LOCAL,
34    /// Error that happened during execution.
35    pub error: Result<(), ContextError<DB::Error>>,
36}
37
38impl<
39        BLOCK: Block,
40        TX: Transaction,
41        DB: Database,
42        CFG: Cfg,
43        JOURNAL: JournalTr<Database = DB>,
44        CHAIN,
45        LOCAL: LocalContextTr,
46    > ContextTr for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL>
47{
48    type Block = BLOCK;
49    type Tx = TX;
50    type Cfg = CFG;
51    type Db = DB;
52    type Journal = JOURNAL;
53    type Chain = CHAIN;
54    type Local = LOCAL;
55
56    #[inline]
57    fn tx(&self) -> &Self::Tx {
58        &self.tx
59    }
60
61    #[inline]
62    fn block(&self) -> &Self::Block {
63        &self.block
64    }
65
66    #[inline]
67    fn cfg(&self) -> &Self::Cfg {
68        &self.cfg
69    }
70
71    #[inline]
72    fn journal(&self) -> &Self::Journal {
73        &self.journaled_state
74    }
75
76    #[inline]
77    fn journal_mut(&mut self) -> &mut Self::Journal {
78        &mut self.journaled_state
79    }
80
81    #[inline]
82    fn journal_ref(&self) -> &Self::Journal {
83        &self.journaled_state
84    }
85
86    #[inline]
87    fn db(&self) -> &Self::Db {
88        self.journaled_state.db()
89    }
90
91    #[inline]
92    fn db_mut(&mut self) -> &mut Self::Db {
93        self.journaled_state.db_mut()
94    }
95
96    #[inline]
97    fn chain(&self) -> &Self::Chain {
98        &self.chain
99    }
100
101    #[inline]
102    fn chain_mut(&mut self) -> &mut Self::Chain {
103        &mut self.chain
104    }
105
106    #[inline]
107    fn local(&self) -> &Self::Local {
108        &self.local
109    }
110
111    #[inline]
112    fn local_mut(&mut self) -> &mut Self::Local {
113        &mut self.local
114    }
115
116    #[inline]
117    fn error(&mut self) -> &mut Result<(), ContextError<<Self::Db as Database>::Error>> {
118        &mut self.error
119    }
120
121    #[inline]
122    fn tx_journal_mut(&mut self) -> (&Self::Tx, &mut Self::Journal) {
123        (&self.tx, &mut self.journaled_state)
124    }
125
126    #[inline]
127    fn tx_local_mut(&mut self) -> (&Self::Tx, &mut Self::Local) {
128        (&self.tx, &mut self.local)
129    }
130}
131
132impl<
133        BLOCK: Block,
134        TX: Transaction,
135        DB: Database,
136        CFG: Cfg,
137        JOURNAL: JournalTr<Database = DB>,
138        CHAIN,
139        LOCAL: LocalContextTr,
140    > ContextSetters for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL>
141{
142    fn set_tx(&mut self, tx: Self::Tx) {
143        self.tx = tx;
144    }
145
146    fn set_block(&mut self, block: Self::Block) {
147        self.block = block;
148    }
149}
150
151impl<
152        BLOCK: Block + Default,
153        TX: Transaction + Default,
154        DB: Database,
155        JOURNAL: JournalTr<Database = DB>,
156        CHAIN: Default,
157        LOCAL: LocalContextTr + Default,
158    > Context<BLOCK, TX, CfgEnv, DB, JOURNAL, CHAIN, LOCAL>
159{
160    /// Creates a new context with a new database type.
161    ///
162    /// This will create a new [`Journal`] object.
163    pub fn new(db: DB, spec: SpecId) -> Self {
164        let mut journaled_state = JOURNAL::new(db);
165        journaled_state.set_spec_id(spec);
166        Self {
167            tx: TX::default(),
168            block: BLOCK::default(),
169            cfg: CfgEnv {
170                spec,
171                ..Default::default()
172            },
173            local: LOCAL::default(),
174            journaled_state,
175            chain: Default::default(),
176            error: Ok(()),
177        }
178    }
179}
180
181impl<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL>
182where
183    BLOCK: Block,
184    TX: Transaction,
185    CFG: Cfg,
186    DB: Database,
187    JOURNAL: JournalTr<Database = DB>,
188    LOCAL: LocalContextTr,
189{
190    /// Creates a new context with a new journal type. New journal needs to have the same database type.
191    pub fn with_new_journal<OJOURNAL: JournalTr<Database = DB>>(
192        self,
193        mut journal: OJOURNAL,
194    ) -> Context<BLOCK, TX, CFG, DB, OJOURNAL, CHAIN, LOCAL> {
195        journal.set_spec_id(self.cfg.spec().into());
196        Context {
197            tx: self.tx,
198            block: self.block,
199            cfg: self.cfg,
200            journaled_state: journal,
201            local: self.local,
202            chain: self.chain,
203            error: Ok(()),
204        }
205    }
206
207    /// Creates a new context with a new database type.
208    ///
209    /// This will create a new [`Journal`] object.
210    pub fn with_db<ODB: Database>(
211        self,
212        db: ODB,
213    ) -> Context<BLOCK, TX, CFG, ODB, Journal<ODB>, CHAIN, LOCAL> {
214        let spec = self.cfg.spec().into();
215        let mut journaled_state = Journal::new(db);
216        journaled_state.set_spec_id(spec);
217        Context {
218            tx: self.tx,
219            block: self.block,
220            cfg: self.cfg,
221            journaled_state,
222            local: self.local,
223            chain: self.chain,
224            error: Ok(()),
225        }
226    }
227
228    /// Creates a new context with a new `DatabaseRef` type.
229    pub fn with_ref_db<ODB: DatabaseRef>(
230        self,
231        db: ODB,
232    ) -> Context<BLOCK, TX, CFG, WrapDatabaseRef<ODB>, Journal<WrapDatabaseRef<ODB>>, CHAIN, LOCAL>
233    {
234        let spec = self.cfg.spec().into();
235        let mut journaled_state = Journal::new(WrapDatabaseRef(db));
236        journaled_state.set_spec_id(spec);
237        Context {
238            tx: self.tx,
239            block: self.block,
240            cfg: self.cfg,
241            journaled_state,
242            local: self.local,
243            chain: self.chain,
244            error: Ok(()),
245        }
246    }
247
248    /// Creates a new context with a new block type.
249    pub fn with_block<OB: Block>(
250        self,
251        block: OB,
252    ) -> Context<OB, TX, CFG, DB, JOURNAL, CHAIN, LOCAL> {
253        Context {
254            tx: self.tx,
255            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    /// Creates a new context with a new transaction type.
264    pub fn with_tx<OTX: Transaction>(
265        self,
266        tx: OTX,
267    ) -> Context<BLOCK, OTX, CFG, DB, JOURNAL, CHAIN, LOCAL> {
268        Context {
269            tx,
270            block: self.block,
271            cfg: self.cfg,
272            journaled_state: self.journaled_state,
273            local: self.local,
274            chain: self.chain,
275            error: Ok(()),
276        }
277    }
278
279    /// Creates a new context with a new chain type.
280    pub fn with_chain<OC>(self, chain: OC) -> Context<BLOCK, TX, CFG, DB, JOURNAL, OC, LOCAL> {
281        Context {
282            tx: self.tx,
283            block: self.block,
284            cfg: self.cfg,
285            journaled_state: self.journaled_state,
286            local: self.local,
287            chain,
288            error: Ok(()),
289        }
290    }
291
292    /// Creates a new context with a new chain type.
293    pub fn with_cfg<OCFG: Cfg>(
294        mut self,
295        cfg: OCFG,
296    ) -> Context<BLOCK, TX, OCFG, DB, JOURNAL, CHAIN, LOCAL> {
297        self.journaled_state.set_spec_id(cfg.spec().into());
298        Context {
299            tx: self.tx,
300            block: self.block,
301            cfg,
302            journaled_state: self.journaled_state,
303            local: self.local,
304            chain: self.chain,
305            error: Ok(()),
306        }
307    }
308
309    /// Creates a new context with a new local context type.
310    pub fn with_local<OL: LocalContextTr>(
311        self,
312        local: OL,
313    ) -> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, OL> {
314        Context {
315            tx: self.tx,
316            block: self.block,
317            cfg: self.cfg,
318            journaled_state: self.journaled_state,
319            local,
320            chain: self.chain,
321            error: Ok(()),
322        }
323    }
324
325    /// Modifies the context configuration.
326    #[must_use]
327    pub fn modify_cfg_chained<F>(mut self, f: F) -> Self
328    where
329        F: FnOnce(&mut CFG),
330    {
331        f(&mut self.cfg);
332        self.journaled_state.set_spec_id(self.cfg.spec().into());
333        self
334    }
335
336    /// Modifies the context block.
337    #[must_use]
338    pub fn modify_block_chained<F>(mut self, f: F) -> Self
339    where
340        F: FnOnce(&mut BLOCK),
341    {
342        self.modify_block(f);
343        self
344    }
345
346    /// Modifies the context transaction.
347    #[must_use]
348    pub fn modify_tx_chained<F>(mut self, f: F) -> Self
349    where
350        F: FnOnce(&mut TX),
351    {
352        self.modify_tx(f);
353        self
354    }
355
356    /// Modifies the context chain.
357    #[must_use]
358    pub fn modify_chain_chained<F>(mut self, f: F) -> Self
359    where
360        F: FnOnce(&mut CHAIN),
361    {
362        self.modify_chain(f);
363        self
364    }
365
366    /// Modifies the context database.
367    #[must_use]
368    pub fn modify_db_chained<F>(mut self, f: F) -> Self
369    where
370        F: FnOnce(&mut DB),
371    {
372        self.modify_db(f);
373        self
374    }
375
376    /// Modifies the context journal.
377    #[must_use]
378    pub fn modify_journal_chained<F>(mut self, f: F) -> Self
379    where
380        F: FnOnce(&mut JOURNAL),
381    {
382        self.modify_journal(f);
383        self
384    }
385
386    /// Modifies the context block.
387    pub fn modify_block<F>(&mut self, f: F)
388    where
389        F: FnOnce(&mut BLOCK),
390    {
391        f(&mut self.block);
392    }
393
394    /// Modifies the context transaction.
395    pub fn modify_tx<F>(&mut self, f: F)
396    where
397        F: FnOnce(&mut TX),
398    {
399        f(&mut self.tx);
400    }
401
402    /// Modifies the context configuration.
403    pub fn modify_cfg<F>(&mut self, f: F)
404    where
405        F: FnOnce(&mut CFG),
406    {
407        f(&mut self.cfg);
408        self.journaled_state.set_spec_id(self.cfg.spec().into());
409    }
410
411    /// Modifies the context chain.
412    pub fn modify_chain<F>(&mut self, f: F)
413    where
414        F: FnOnce(&mut CHAIN),
415    {
416        f(&mut self.chain);
417    }
418
419    /// Modifies the context database.
420    pub fn modify_db<F>(&mut self, f: F)
421    where
422        F: FnOnce(&mut DB),
423    {
424        f(self.journaled_state.db_mut());
425    }
426
427    /// Modifies the context journal.
428    pub fn modify_journal<F>(&mut self, f: F)
429    where
430        F: FnOnce(&mut JOURNAL),
431    {
432        f(&mut self.journaled_state);
433    }
434
435    /// Modifies the local context.
436    pub fn modify_local<F>(&mut self, f: F)
437    where
438        F: FnOnce(&mut LOCAL),
439    {
440        f(&mut self.local);
441    }
442}