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    > ContextSetters for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
140{
141    fn set_tx(&mut self, tx: Self::Tx) {
142        self.tx = tx;
143    }
144
145    fn set_block(&mut self, block: Self::Block) {
146        self.block = block;
147    }
148}
149
150impl<
151        BLOCK: Block + Default,
152        TX: Transaction + Default,
153        DB: Database,
154        JOURNAL: JournalTr<Database = DB>,
155        CHAIN: Default,
156    > Context<BLOCK, TX, CfgEnv, DB, JOURNAL, CHAIN>
157{
158    /// Creates a new context with a new database type.
159    ///
160    /// This will create a new [`Journal`] object.
161    pub fn new(db: DB, spec: SpecId) -> Self {
162        let mut journaled_state = JOURNAL::new(db);
163        journaled_state.set_spec_id(spec);
164        Self {
165            tx: TX::default(),
166            block: BLOCK::default(),
167            cfg: CfgEnv {
168                spec,
169                ..Default::default()
170            },
171            local: LocalContext::default(),
172            journaled_state,
173            chain: Default::default(),
174            error: Ok(()),
175        }
176    }
177}
178
179impl<BLOCK, TX, CFG, DB, JOURNAL, CHAIN> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
180where
181    BLOCK: Block,
182    TX: Transaction,
183    CFG: Cfg,
184    DB: Database,
185    JOURNAL: JournalTr<Database = DB>,
186{
187    /// Creates a new context with a new journal type. New journal needs to have the same database type.
188    pub fn with_new_journal<OJOURNAL: JournalTr<Database = DB>>(
189        self,
190        mut journal: OJOURNAL,
191    ) -> Context<BLOCK, TX, CFG, DB, OJOURNAL, CHAIN> {
192        journal.set_spec_id(self.cfg.spec().into());
193        Context {
194            tx: self.tx,
195            block: self.block,
196            cfg: self.cfg,
197            journaled_state: journal,
198            local: self.local,
199            chain: self.chain,
200            error: Ok(()),
201        }
202    }
203
204    /// Creates a new context with a new database type.
205    ///
206    /// This will create a new [`Journal`] object.
207    pub fn with_db<ODB: Database>(
208        self,
209        db: ODB,
210    ) -> Context<BLOCK, TX, CFG, ODB, Journal<ODB>, CHAIN> {
211        let spec = self.cfg.spec().into();
212        let mut journaled_state = Journal::new(db);
213        journaled_state.set_spec_id(spec);
214        Context {
215            tx: self.tx,
216            block: self.block,
217            cfg: self.cfg,
218            journaled_state,
219            local: self.local,
220            chain: self.chain,
221            error: Ok(()),
222        }
223    }
224
225    /// Creates a new context with a new `DatabaseRef` type.
226    pub fn with_ref_db<ODB: DatabaseRef>(
227        self,
228        db: ODB,
229    ) -> Context<BLOCK, TX, CFG, WrapDatabaseRef<ODB>, Journal<WrapDatabaseRef<ODB>>, CHAIN> {
230        let spec = self.cfg.spec().into();
231        let mut journaled_state = Journal::new(WrapDatabaseRef(db));
232        journaled_state.set_spec_id(spec);
233        Context {
234            tx: self.tx,
235            block: self.block,
236            cfg: self.cfg,
237            journaled_state,
238            local: self.local,
239            chain: self.chain,
240            error: Ok(()),
241        }
242    }
243
244    /// Creates a new context with a new block type.
245    pub fn with_block<OB: Block>(self, block: OB) -> Context<OB, TX, CFG, DB, JOURNAL, CHAIN> {
246        Context {
247            tx: self.tx,
248            block,
249            cfg: self.cfg,
250            journaled_state: self.journaled_state,
251            local: self.local,
252            chain: self.chain,
253            error: Ok(()),
254        }
255    }
256    /// Creates a new context with a new transaction type.
257    pub fn with_tx<OTX: Transaction>(
258        self,
259        tx: OTX,
260    ) -> Context<BLOCK, OTX, CFG, DB, JOURNAL, CHAIN> {
261        Context {
262            tx,
263            block: self.block,
264            cfg: self.cfg,
265            journaled_state: self.journaled_state,
266            local: self.local,
267            chain: self.chain,
268            error: Ok(()),
269        }
270    }
271
272    /// Creates a new context with a new chain type.
273    pub fn with_chain<OC>(self, chain: OC) -> Context<BLOCK, TX, CFG, DB, JOURNAL, OC> {
274        Context {
275            tx: self.tx,
276            block: self.block,
277            cfg: self.cfg,
278            journaled_state: self.journaled_state,
279            local: self.local,
280            chain,
281            error: Ok(()),
282        }
283    }
284
285    /// Creates a new context with a new chain type.
286    pub fn with_cfg<OCFG: Cfg>(
287        mut self,
288        cfg: OCFG,
289    ) -> Context<BLOCK, TX, OCFG, DB, JOURNAL, CHAIN> {
290        self.journaled_state.set_spec_id(cfg.spec().into());
291        Context {
292            tx: self.tx,
293            block: self.block,
294            cfg,
295            journaled_state: self.journaled_state,
296            local: self.local,
297            chain: self.chain,
298            error: Ok(()),
299        }
300    }
301
302    /// Modifies the context configuration.
303    #[must_use]
304    pub fn modify_cfg_chained<F>(mut self, f: F) -> Self
305    where
306        F: FnOnce(&mut CFG),
307    {
308        f(&mut self.cfg);
309        self.journaled_state.set_spec_id(self.cfg.spec().into());
310        self
311    }
312
313    /// Modifies the context block.
314    #[must_use]
315    pub fn modify_block_chained<F>(mut self, f: F) -> Self
316    where
317        F: FnOnce(&mut BLOCK),
318    {
319        self.modify_block(f);
320        self
321    }
322
323    /// Modifies the context transaction.
324    #[must_use]
325    pub fn modify_tx_chained<F>(mut self, f: F) -> Self
326    where
327        F: FnOnce(&mut TX),
328    {
329        self.modify_tx(f);
330        self
331    }
332
333    /// Modifies the context chain.
334    #[must_use]
335    pub fn modify_chain_chained<F>(mut self, f: F) -> Self
336    where
337        F: FnOnce(&mut CHAIN),
338    {
339        self.modify_chain(f);
340        self
341    }
342
343    /// Modifies the context database.
344    #[must_use]
345    pub fn modify_db_chained<F>(mut self, f: F) -> Self
346    where
347        F: FnOnce(&mut DB),
348    {
349        self.modify_db(f);
350        self
351    }
352
353    /// Modifies the context journal.
354    #[must_use]
355    pub fn modify_journal_chained<F>(mut self, f: F) -> Self
356    where
357        F: FnOnce(&mut JOURNAL),
358    {
359        self.modify_journal(f);
360        self
361    }
362
363    /// Modifies the context block.
364    pub fn modify_block<F>(&mut self, f: F)
365    where
366        F: FnOnce(&mut BLOCK),
367    {
368        f(&mut self.block);
369    }
370
371    /// Modifies the context transaction.
372    pub fn modify_tx<F>(&mut self, f: F)
373    where
374        F: FnOnce(&mut TX),
375    {
376        f(&mut self.tx);
377    }
378
379    /// Modifies the context configuration.
380    pub fn modify_cfg<F>(&mut self, f: F)
381    where
382        F: FnOnce(&mut CFG),
383    {
384        f(&mut self.cfg);
385        self.journaled_state.set_spec_id(self.cfg.spec().into());
386    }
387
388    /// Modifies the context chain.
389    pub fn modify_chain<F>(&mut self, f: F)
390    where
391        F: FnOnce(&mut CHAIN),
392    {
393        f(&mut self.chain);
394    }
395
396    /// Modifies the context database.
397    pub fn modify_db<F>(&mut self, f: F)
398    where
399        F: FnOnce(&mut DB),
400    {
401        f(self.journaled_state.db_mut());
402    }
403
404    /// Modifies the context journal.
405    pub fn modify_journal<F>(&mut self, f: F)
406    where
407        F: FnOnce(&mut JOURNAL),
408    {
409        f(&mut self.journaled_state);
410    }
411}