revm_context/
context.rs

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