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    fn tx(&self) -> &Self::Tx {
57        &self.tx
58    }
59
60    fn block(&self) -> &Self::Block {
61        &self.block
62    }
63
64    fn cfg(&self) -> &Self::Cfg {
65        &self.cfg
66    }
67
68    fn journal(&mut self) -> &mut Self::Journal {
69        &mut self.journaled_state
70    }
71
72    fn journal_ref(&self) -> &Self::Journal {
73        &self.journaled_state
74    }
75
76    fn db(&mut self) -> &mut Self::Db {
77        self.journaled_state.db()
78    }
79
80    fn db_ref(&self) -> &Self::Db {
81        self.journaled_state.db_ref()
82    }
83
84    fn chain(&mut self) -> &mut Self::Chain {
85        &mut self.chain
86    }
87
88    fn chain_ref(&self) -> &Self::Chain {
89        &self.chain
90    }
91
92    fn local(&mut self) -> &mut Self::Local {
93        &mut self.local
94    }
95
96    fn error(&mut self) -> &mut Result<(), ContextError<<Self::Db as Database>::Error>> {
97        &mut self.error
98    }
99
100    fn tx_journal(&mut self) -> (&mut Self::Tx, &mut Self::Journal) {
101        (&mut self.tx, &mut self.journaled_state)
102    }
103
104    fn tx_local(&mut self) -> (&Self::Tx, &mut Self::Local) {
105        (&self.tx, &mut self.local)
106    }
107}
108
109impl<
110        BLOCK: Block,
111        TX: Transaction,
112        DB: Database,
113        CFG: Cfg,
114        JOURNAL: JournalTr<Database = DB>,
115        CHAIN,
116    > ContextSetters for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
117{
118    fn set_tx(&mut self, tx: Self::Tx) {
119        self.tx = tx;
120    }
121
122    fn set_block(&mut self, block: Self::Block) {
123        self.block = block;
124    }
125}
126
127impl<
128        BLOCK: Block + Default,
129        TX: Transaction + Default,
130        DB: Database,
131        JOURNAL: JournalTr<Database = DB>,
132        CHAIN: Default,
133    > Context<BLOCK, TX, CfgEnv, DB, JOURNAL, CHAIN>
134{
135    /// Creates a new context with a new database type.
136    ///
137    /// This will create a new [`Journal`] object.
138    pub fn new(db: DB, spec: SpecId) -> Self {
139        let mut journaled_state = JOURNAL::new(db);
140        journaled_state.set_spec_id(spec);
141        Self {
142            tx: TX::default(),
143            block: BLOCK::default(),
144            cfg: CfgEnv {
145                spec,
146                ..Default::default()
147            },
148            local: LocalContext::default(),
149            journaled_state,
150            chain: Default::default(),
151            error: Ok(()),
152        }
153    }
154}
155
156impl<BLOCK, TX, CFG, DB, JOURNAL, CHAIN> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
157where
158    BLOCK: Block,
159    TX: Transaction,
160    CFG: Cfg,
161    DB: Database,
162    JOURNAL: JournalTr<Database = DB>,
163{
164    /// Creates a new context with a new journal type. New journal needs to have the same database type.
165    pub fn with_new_journal<OJOURNAL: JournalTr<Database = DB>>(
166        self,
167        mut journal: OJOURNAL,
168    ) -> Context<BLOCK, TX, CFG, DB, OJOURNAL, CHAIN> {
169        journal.set_spec_id(self.cfg.spec().into());
170        Context {
171            tx: self.tx,
172            block: self.block,
173            cfg: self.cfg,
174            journaled_state: journal,
175            local: self.local,
176            chain: self.chain,
177            error: Ok(()),
178        }
179    }
180
181    /// Creates a new context with a new database type.
182    ///
183    /// This will create a new [`Journal`] object.
184    pub fn with_db<ODB: Database>(
185        self,
186        db: ODB,
187    ) -> Context<BLOCK, TX, CFG, ODB, Journal<ODB>, CHAIN> {
188        let spec = self.cfg.spec().into();
189        let mut journaled_state = Journal::new(db);
190        journaled_state.set_spec_id(spec);
191        Context {
192            tx: self.tx,
193            block: self.block,
194            cfg: self.cfg,
195            journaled_state,
196            local: self.local,
197            chain: self.chain,
198            error: Ok(()),
199        }
200    }
201
202    /// Creates a new context with a new `DatabaseRef` type.
203    pub fn with_ref_db<ODB: DatabaseRef>(
204        self,
205        db: ODB,
206    ) -> Context<BLOCK, TX, CFG, WrapDatabaseRef<ODB>, Journal<WrapDatabaseRef<ODB>>, CHAIN> {
207        let spec = self.cfg.spec().into();
208        let mut journaled_state = Journal::new(WrapDatabaseRef(db));
209        journaled_state.set_spec_id(spec);
210        Context {
211            tx: self.tx,
212            block: self.block,
213            cfg: self.cfg,
214            journaled_state,
215            local: self.local,
216            chain: self.chain,
217            error: Ok(()),
218        }
219    }
220
221    /// Creates a new context with a new block type.
222    pub fn with_block<OB: Block>(self, block: OB) -> Context<OB, TX, CFG, DB, JOURNAL, CHAIN> {
223        Context {
224            tx: self.tx,
225            block,
226            cfg: self.cfg,
227            journaled_state: self.journaled_state,
228            local: self.local,
229            chain: self.chain,
230            error: Ok(()),
231        }
232    }
233    /// Creates a new context with a new transaction type.
234    pub fn with_tx<OTX: Transaction>(
235        self,
236        tx: OTX,
237    ) -> Context<BLOCK, OTX, CFG, DB, JOURNAL, CHAIN> {
238        Context {
239            tx,
240            block: self.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
249    /// Creates a new context with a new chain type.
250    pub fn with_chain<OC>(self, chain: OC) -> Context<BLOCK, TX, CFG, DB, JOURNAL, OC> {
251        Context {
252            tx: self.tx,
253            block: self.block,
254            cfg: self.cfg,
255            journaled_state: self.journaled_state,
256            local: self.local,
257            chain,
258            error: Ok(()),
259        }
260    }
261
262    /// Creates a new context with a new chain type.
263    pub fn with_cfg<OCFG: Cfg>(
264        mut self,
265        cfg: OCFG,
266    ) -> Context<BLOCK, TX, OCFG, DB, JOURNAL, CHAIN> {
267        self.journaled_state.set_spec_id(cfg.spec().into());
268        Context {
269            tx: self.tx,
270            block: self.block,
271            cfg,
272            journaled_state: self.journaled_state,
273            local: self.local,
274            chain: self.chain,
275            error: Ok(()),
276        }
277    }
278
279    /// Modifies the context configuration.
280    #[must_use]
281    pub fn modify_cfg_chained<F>(mut self, f: F) -> Self
282    where
283        F: FnOnce(&mut CFG),
284    {
285        f(&mut self.cfg);
286        self.journaled_state.set_spec_id(self.cfg.spec().into());
287        self
288    }
289
290    /// Modifies the context block.
291    #[must_use]
292    pub fn modify_block_chained<F>(mut self, f: F) -> Self
293    where
294        F: FnOnce(&mut BLOCK),
295    {
296        self.modify_block(f);
297        self
298    }
299
300    /// Modifies the context transaction.
301    #[must_use]
302    pub fn modify_tx_chained<F>(mut self, f: F) -> Self
303    where
304        F: FnOnce(&mut TX),
305    {
306        self.modify_tx(f);
307        self
308    }
309
310    /// Modifies the context chain.
311    #[must_use]
312    pub fn modify_chain_chained<F>(mut self, f: F) -> Self
313    where
314        F: FnOnce(&mut CHAIN),
315    {
316        self.modify_chain(f);
317        self
318    }
319
320    /// Modifies the context database.
321    #[must_use]
322    pub fn modify_db_chained<F>(mut self, f: F) -> Self
323    where
324        F: FnOnce(&mut DB),
325    {
326        self.modify_db(f);
327        self
328    }
329
330    /// Modifies the context journal.
331    #[must_use]
332    pub fn modify_journal_chained<F>(mut self, f: F) -> Self
333    where
334        F: FnOnce(&mut JOURNAL),
335    {
336        self.modify_journal(f);
337        self
338    }
339
340    /// Modifies the context block.
341    pub fn modify_block<F>(&mut self, f: F)
342    where
343        F: FnOnce(&mut BLOCK),
344    {
345        f(&mut self.block);
346    }
347
348    /// Modifies the context transaction.
349    pub fn modify_tx<F>(&mut self, f: F)
350    where
351        F: FnOnce(&mut TX),
352    {
353        f(&mut self.tx);
354    }
355
356    /// Modifies the context configuration.
357    pub fn modify_cfg<F>(&mut self, f: F)
358    where
359        F: FnOnce(&mut CFG),
360    {
361        f(&mut self.cfg);
362        self.journaled_state.set_spec_id(self.cfg.spec().into());
363    }
364
365    /// Modifies the context chain.
366    pub fn modify_chain<F>(&mut self, f: F)
367    where
368        F: FnOnce(&mut CHAIN),
369    {
370        f(&mut self.chain);
371    }
372
373    /// Modifies the context database.
374    pub fn modify_db<F>(&mut self, f: F)
375    where
376        F: FnOnce(&mut DB),
377    {
378        f(self.journaled_state.db());
379    }
380
381    /// Modifies the context journal.
382    pub fn modify_journal<F>(&mut self, f: F)
383    where
384        F: FnOnce(&mut JOURNAL),
385    {
386        f(&mut self.journaled_state);
387    }
388}