revm_context/
context.rs

1use crate::{block::BlockEnv, cfg::CfgEnv, journaled_state::Journal, tx::TxEnv};
2use context_interface::{
3    context::{ContextError, ContextSetters},
4    Block, Cfg, ContextTr, JournalTr, Transaction,
5};
6use database_interface::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef};
7use derive_where::derive_where;
8use primitives::hardfork::SpecId;
9
10/// EVM context contains data that EVM needs for execution.
11#[derive_where(Clone, Debug; BLOCK, CFG, CHAIN, TX, DB, JOURNAL, <DB as Database>::Error)]
12pub struct Context<
13    BLOCK = BlockEnv,
14    TX = TxEnv,
15    CFG = CfgEnv,
16    DB: Database = EmptyDB,
17    JOURNAL: JournalTr<Database = DB> = Journal<DB>,
18    CHAIN = (),
19> {
20    /// Block information.
21    pub block: BLOCK,
22    /// Transaction information.
23    pub tx: TX,
24    /// Configurations.
25    pub cfg: CFG,
26    /// EVM State with journaling support and database.
27    pub journaled_state: JOURNAL,
28    /// Inner context.
29    pub chain: CHAIN,
30    /// Error that happened during execution.
31    pub error: Result<(), ContextError<DB::Error>>,
32}
33
34impl<
35        BLOCK: Block,
36        TX: Transaction,
37        DB: Database,
38        CFG: Cfg,
39        JOURNAL: JournalTr<Database = DB>,
40        CHAIN,
41    > ContextTr for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
42{
43    type Block = BLOCK;
44    type Tx = TX;
45    type Cfg = CFG;
46    type Db = DB;
47    type Journal = JOURNAL;
48    type Chain = CHAIN;
49
50    fn tx(&self) -> &Self::Tx {
51        &self.tx
52    }
53
54    fn block(&self) -> &Self::Block {
55        &self.block
56    }
57
58    fn cfg(&self) -> &Self::Cfg {
59        &self.cfg
60    }
61
62    fn journal(&mut self) -> &mut Self::Journal {
63        &mut self.journaled_state
64    }
65
66    fn journal_ref(&self) -> &Self::Journal {
67        &self.journaled_state
68    }
69
70    fn db(&mut self) -> &mut Self::Db {
71        self.journaled_state.db()
72    }
73
74    fn db_ref(&self) -> &Self::Db {
75        self.journaled_state.db_ref()
76    }
77
78    fn chain(&mut self) -> &mut Self::Chain {
79        &mut self.chain
80    }
81
82    fn error(&mut self) -> &mut Result<(), ContextError<<Self::Db as Database>::Error>> {
83        &mut self.error
84    }
85
86    fn tx_journal(&mut self) -> (&mut Self::Tx, &mut Self::Journal) {
87        (&mut self.tx, &mut self.journaled_state)
88    }
89
90    // Keep Default Implementation for Instructions Host Interface
91}
92
93impl<
94        BLOCK: Block,
95        TX: Transaction,
96        DB: Database,
97        CFG: Cfg,
98        JOURNAL: JournalTr<Database = DB>,
99        CHAIN,
100    > ContextSetters for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
101{
102    fn set_tx(&mut self, tx: Self::Tx) {
103        self.tx = tx;
104    }
105
106    fn set_block(&mut self, block: Self::Block) {
107        self.block = block;
108    }
109}
110
111impl<
112        BLOCK: Block + Default,
113        TX: Transaction + Default,
114        DB: Database,
115        JOURNAL: JournalTr<Database = DB>,
116        CHAIN: Default,
117    > Context<BLOCK, TX, CfgEnv, DB, JOURNAL, CHAIN>
118{
119    pub fn new(db: DB, spec: SpecId) -> Self {
120        let mut journaled_state = JOURNAL::new(db);
121        journaled_state.set_spec_id(spec);
122        Self {
123            tx: TX::default(),
124            block: BLOCK::default(),
125            cfg: CfgEnv {
126                spec,
127                ..Default::default()
128            },
129            journaled_state,
130            chain: Default::default(),
131            error: Ok(()),
132        }
133    }
134}
135
136impl<BLOCK, TX, CFG, DB, JOURNAL, CHAIN> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
137where
138    BLOCK: Block,
139    TX: Transaction,
140    CFG: Cfg,
141    DB: Database,
142    JOURNAL: JournalTr<Database = DB>,
143{
144    pub fn with_new_journal<OJOURNAL: JournalTr<Database = DB>>(
145        self,
146        mut journal: OJOURNAL,
147    ) -> Context<BLOCK, TX, CFG, DB, OJOURNAL, CHAIN> {
148        journal.set_spec_id(self.cfg.spec().into());
149        Context {
150            tx: self.tx,
151            block: self.block,
152            cfg: self.cfg,
153            journaled_state: journal,
154            chain: self.chain,
155            error: Ok(()),
156        }
157    }
158
159    /// Creates a new context with a new database type.
160    pub fn with_db<ODB: Database>(
161        self,
162        db: ODB,
163    ) -> Context<BLOCK, TX, CFG, ODB, Journal<ODB>, CHAIN> {
164        let spec = self.cfg.spec().into();
165        let mut journaled_state = Journal::new(spec, db);
166        journaled_state.set_spec_id(spec);
167        Context {
168            tx: self.tx,
169            block: self.block,
170            cfg: self.cfg,
171            journaled_state,
172            chain: self.chain,
173            error: Ok(()),
174        }
175    }
176
177    /// Creates a new context with a new `DatabaseRef` type.
178    pub fn with_ref_db<ODB: DatabaseRef>(
179        self,
180        db: ODB,
181    ) -> Context<BLOCK, TX, CFG, WrapDatabaseRef<ODB>, Journal<WrapDatabaseRef<ODB>>, CHAIN> {
182        let spec = self.cfg.spec().into();
183        let mut journaled_state = Journal::new(spec, WrapDatabaseRef(db));
184        journaled_state.set_spec_id(spec);
185        Context {
186            tx: self.tx,
187            block: self.block,
188            cfg: self.cfg,
189            journaled_state,
190            chain: self.chain,
191            error: Ok(()),
192        }
193    }
194
195    /// Creates a new context with a new block type.
196    pub fn with_block<OB: Block>(self, block: OB) -> Context<OB, TX, CFG, DB, JOURNAL, CHAIN> {
197        Context {
198            tx: self.tx,
199            block,
200            cfg: self.cfg,
201            journaled_state: self.journaled_state,
202            chain: self.chain,
203            error: Ok(()),
204        }
205    }
206    /// Creates a new context with a new transaction type.
207    pub fn with_tx<OTX: Transaction>(
208        self,
209        tx: OTX,
210    ) -> Context<BLOCK, OTX, CFG, DB, JOURNAL, CHAIN> {
211        Context {
212            tx,
213            block: self.block,
214            cfg: self.cfg,
215            journaled_state: self.journaled_state,
216            chain: self.chain,
217            error: Ok(()),
218        }
219    }
220
221    /// Creates a new context with a new chain type.
222    pub fn with_chain<OC>(self, chain: OC) -> Context<BLOCK, TX, CFG, DB, JOURNAL, OC> {
223        Context {
224            tx: self.tx,
225            block: self.block,
226            cfg: self.cfg,
227            journaled_state: self.journaled_state,
228            chain,
229            error: Ok(()),
230        }
231    }
232
233    /// Creates a new context with a new chain type.
234    pub fn with_cfg<OCFG: Cfg>(
235        mut self,
236        cfg: OCFG,
237    ) -> Context<BLOCK, TX, OCFG, DB, JOURNAL, CHAIN> {
238        self.journaled_state.set_spec_id(cfg.spec().into());
239        Context {
240            tx: self.tx,
241            block: self.block,
242            cfg,
243            journaled_state: self.journaled_state,
244            chain: self.chain,
245            error: Ok(()),
246        }
247    }
248
249    /// Modifies the context configuration.
250    #[must_use]
251    pub fn modify_cfg_chained<F>(mut self, f: F) -> Self
252    where
253        F: FnOnce(&mut CFG),
254    {
255        f(&mut self.cfg);
256        self.journaled_state.set_spec_id(self.cfg.spec().into());
257        self
258    }
259
260    /// Modifies the context block.
261    #[must_use]
262    pub fn modify_block_chained<F>(mut self, f: F) -> Self
263    where
264        F: FnOnce(&mut BLOCK),
265    {
266        self.modify_block(f);
267        self
268    }
269
270    /// Modifies the context transaction.
271    #[must_use]
272    pub fn modify_tx_chained<F>(mut self, f: F) -> Self
273    where
274        F: FnOnce(&mut TX),
275    {
276        self.modify_tx(f);
277        self
278    }
279
280    /// Modifies the context chain.
281    #[must_use]
282    pub fn modify_chain_chained<F>(mut self, f: F) -> Self
283    where
284        F: FnOnce(&mut CHAIN),
285    {
286        self.modify_chain(f);
287        self
288    }
289
290    /// Modifies the context database.
291    #[must_use]
292    pub fn modify_db_chained<F>(mut self, f: F) -> Self
293    where
294        F: FnOnce(&mut DB),
295    {
296        self.modify_db(f);
297        self
298    }
299
300    /// Modifies the context journal.
301    #[must_use]
302    pub fn modify_journal_chained<F>(mut self, f: F) -> Self
303    where
304        F: FnOnce(&mut JOURNAL),
305    {
306        self.modify_journal(f);
307        self
308    }
309
310    /// Modifies the context block.
311    pub fn modify_block<F>(&mut self, f: F)
312    where
313        F: FnOnce(&mut BLOCK),
314    {
315        f(&mut self.block);
316    }
317
318    pub fn modify_tx<F>(&mut self, f: F)
319    where
320        F: FnOnce(&mut TX),
321    {
322        f(&mut self.tx);
323    }
324
325    pub fn modify_cfg<F>(&mut self, f: F)
326    where
327        F: FnOnce(&mut CFG),
328    {
329        f(&mut self.cfg);
330        self.journaled_state.set_spec_id(self.cfg.spec().into());
331    }
332
333    pub fn modify_chain<F>(&mut self, f: F)
334    where
335        F: FnOnce(&mut CHAIN),
336    {
337        f(&mut self.chain);
338    }
339
340    pub fn modify_db<F>(&mut self, f: F)
341    where
342        F: FnOnce(&mut DB),
343    {
344        f(self.journaled_state.db());
345    }
346
347    pub fn modify_journal<F>(&mut self, f: F)
348    where
349        F: FnOnce(&mut JOURNAL),
350    {
351        f(&mut self.journaled_state);
352    }
353}