revm_context/
context.rs

1use crate::{block::BlockEnv, cfg::CfgEnv, journal::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    ///
161    /// This will create a new [`Journal`] object.
162    pub fn with_db<ODB: Database>(
163        self,
164        db: ODB,
165    ) -> Context<BLOCK, TX, CFG, ODB, Journal<ODB>, CHAIN> {
166        let spec = self.cfg.spec().into();
167        let mut journaled_state = Journal::new(db);
168        journaled_state.set_spec_id(spec);
169        Context {
170            tx: self.tx,
171            block: self.block,
172            cfg: self.cfg,
173            journaled_state,
174            chain: self.chain,
175            error: Ok(()),
176        }
177    }
178
179    /// Creates a new context with a new `DatabaseRef` type.
180    pub fn with_ref_db<ODB: DatabaseRef>(
181        self,
182        db: ODB,
183    ) -> Context<BLOCK, TX, CFG, WrapDatabaseRef<ODB>, Journal<WrapDatabaseRef<ODB>>, CHAIN> {
184        let spec = self.cfg.spec().into();
185        let mut journaled_state = Journal::new(WrapDatabaseRef(db));
186        journaled_state.set_spec_id(spec);
187        Context {
188            tx: self.tx,
189            block: self.block,
190            cfg: self.cfg,
191            journaled_state,
192            chain: self.chain,
193            error: Ok(()),
194        }
195    }
196
197    /// Creates a new context with a new block type.
198    pub fn with_block<OB: Block>(self, block: OB) -> Context<OB, TX, CFG, DB, JOURNAL, CHAIN> {
199        Context {
200            tx: self.tx,
201            block,
202            cfg: self.cfg,
203            journaled_state: self.journaled_state,
204            chain: self.chain,
205            error: Ok(()),
206        }
207    }
208    /// Creates a new context with a new transaction type.
209    pub fn with_tx<OTX: Transaction>(
210        self,
211        tx: OTX,
212    ) -> Context<BLOCK, OTX, CFG, DB, JOURNAL, CHAIN> {
213        Context {
214            tx,
215            block: self.block,
216            cfg: self.cfg,
217            journaled_state: self.journaled_state,
218            chain: self.chain,
219            error: Ok(()),
220        }
221    }
222
223    /// Creates a new context with a new chain type.
224    pub fn with_chain<OC>(self, chain: OC) -> Context<BLOCK, TX, CFG, DB, JOURNAL, OC> {
225        Context {
226            tx: self.tx,
227            block: self.block,
228            cfg: self.cfg,
229            journaled_state: self.journaled_state,
230            chain,
231            error: Ok(()),
232        }
233    }
234
235    /// Creates a new context with a new chain type.
236    pub fn with_cfg<OCFG: Cfg>(
237        mut self,
238        cfg: OCFG,
239    ) -> Context<BLOCK, TX, OCFG, DB, JOURNAL, CHAIN> {
240        self.journaled_state.set_spec_id(cfg.spec().into());
241        Context {
242            tx: self.tx,
243            block: self.block,
244            cfg,
245            journaled_state: self.journaled_state,
246            chain: self.chain,
247            error: Ok(()),
248        }
249    }
250
251    /// Modifies the context configuration.
252    #[must_use]
253    pub fn modify_cfg_chained<F>(mut self, f: F) -> Self
254    where
255        F: FnOnce(&mut CFG),
256    {
257        f(&mut self.cfg);
258        self.journaled_state.set_spec_id(self.cfg.spec().into());
259        self
260    }
261
262    /// Modifies the context block.
263    #[must_use]
264    pub fn modify_block_chained<F>(mut self, f: F) -> Self
265    where
266        F: FnOnce(&mut BLOCK),
267    {
268        self.modify_block(f);
269        self
270    }
271
272    /// Modifies the context transaction.
273    #[must_use]
274    pub fn modify_tx_chained<F>(mut self, f: F) -> Self
275    where
276        F: FnOnce(&mut TX),
277    {
278        self.modify_tx(f);
279        self
280    }
281
282    /// Modifies the context chain.
283    #[must_use]
284    pub fn modify_chain_chained<F>(mut self, f: F) -> Self
285    where
286        F: FnOnce(&mut CHAIN),
287    {
288        self.modify_chain(f);
289        self
290    }
291
292    /// Modifies the context database.
293    #[must_use]
294    pub fn modify_db_chained<F>(mut self, f: F) -> Self
295    where
296        F: FnOnce(&mut DB),
297    {
298        self.modify_db(f);
299        self
300    }
301
302    /// Modifies the context journal.
303    #[must_use]
304    pub fn modify_journal_chained<F>(mut self, f: F) -> Self
305    where
306        F: FnOnce(&mut JOURNAL),
307    {
308        self.modify_journal(f);
309        self
310    }
311
312    /// Modifies the context block.
313    pub fn modify_block<F>(&mut self, f: F)
314    where
315        F: FnOnce(&mut BLOCK),
316    {
317        f(&mut self.block);
318    }
319
320    pub fn modify_tx<F>(&mut self, f: F)
321    where
322        F: FnOnce(&mut TX),
323    {
324        f(&mut self.tx);
325    }
326
327    pub fn modify_cfg<F>(&mut self, f: F)
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    }
334
335    pub fn modify_chain<F>(&mut self, f: F)
336    where
337        F: FnOnce(&mut CHAIN),
338    {
339        f(&mut self.chain);
340    }
341
342    pub fn modify_db<F>(&mut self, f: F)
343    where
344        F: FnOnce(&mut DB),
345    {
346        f(self.journaled_state.db());
347    }
348
349    pub fn modify_journal<F>(&mut self, f: F)
350    where
351        F: FnOnce(&mut JOURNAL),
352    {
353        f(&mut self.journaled_state);
354    }
355}