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#[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 pub block: BLOCK,
19 pub tx: TX,
21 pub cfg: CFG,
23 pub journaled_state: JOURNAL,
25 pub chain: CHAIN,
27 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 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 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 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 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 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 #[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 #[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 #[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 #[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 #[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 #[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 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}