1use 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#[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 pub block: BLOCK,
24 pub tx: TX,
26 pub cfg: CFG,
28 pub journaled_state: JOURNAL,
30 pub chain: CHAIN,
32 pub local: LOCAL,
34 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 #[inline]
57 fn tx(&self) -> &Self::Tx {
58 &self.tx
59 }
60
61 #[inline]
62 fn block(&self) -> &Self::Block {
63 &self.block
64 }
65
66 #[inline]
67 fn cfg(&self) -> &Self::Cfg {
68 &self.cfg
69 }
70
71 #[inline]
72 fn journal(&self) -> &Self::Journal {
73 &self.journaled_state
74 }
75
76 #[inline]
77 fn journal_mut(&mut self) -> &mut Self::Journal {
78 &mut self.journaled_state
79 }
80
81 #[inline]
82 fn journal_ref(&self) -> &Self::Journal {
83 &self.journaled_state
84 }
85
86 #[inline]
87 fn db(&self) -> &Self::Db {
88 self.journaled_state.db()
89 }
90
91 #[inline]
92 fn db_mut(&mut self) -> &mut Self::Db {
93 self.journaled_state.db_mut()
94 }
95
96 #[inline]
97 fn chain(&self) -> &Self::Chain {
98 &self.chain
99 }
100
101 #[inline]
102 fn chain_mut(&mut self) -> &mut Self::Chain {
103 &mut self.chain
104 }
105
106 #[inline]
107 fn local(&self) -> &Self::Local {
108 &self.local
109 }
110
111 #[inline]
112 fn local_mut(&mut self) -> &mut Self::Local {
113 &mut self.local
114 }
115
116 #[inline]
117 fn error(&mut self) -> &mut Result<(), ContextError<<Self::Db as Database>::Error>> {
118 &mut self.error
119 }
120
121 #[inline]
122 fn tx_journal_mut(&mut self) -> (&Self::Tx, &mut Self::Journal) {
123 (&self.tx, &mut self.journaled_state)
124 }
125
126 #[inline]
127 fn tx_local_mut(&mut self) -> (&Self::Tx, &mut Self::Local) {
128 (&self.tx, &mut self.local)
129 }
130}
131
132impl<
133 BLOCK: Block,
134 TX: Transaction,
135 DB: Database,
136 CFG: Cfg,
137 JOURNAL: JournalTr<Database = DB>,
138 CHAIN,
139 LOCAL: LocalContextTr,
140 > ContextSetters for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL>
141{
142 fn set_tx(&mut self, tx: Self::Tx) {
143 self.tx = tx;
144 }
145
146 fn set_block(&mut self, block: Self::Block) {
147 self.block = block;
148 }
149}
150
151impl<
152 BLOCK: Block + Default,
153 TX: Transaction + Default,
154 DB: Database,
155 JOURNAL: JournalTr<Database = DB>,
156 CHAIN: Default,
157 LOCAL: LocalContextTr + Default,
158 > Context<BLOCK, TX, CfgEnv, DB, JOURNAL, CHAIN, LOCAL>
159{
160 pub fn new(db: DB, spec: SpecId) -> Self {
164 let mut journaled_state = JOURNAL::new(db);
165 journaled_state.set_spec_id(spec);
166 Self {
167 tx: TX::default(),
168 block: BLOCK::default(),
169 cfg: CfgEnv {
170 spec,
171 ..Default::default()
172 },
173 local: LOCAL::default(),
174 journaled_state,
175 chain: Default::default(),
176 error: Ok(()),
177 }
178 }
179}
180
181impl<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, LOCAL>
182where
183 BLOCK: Block,
184 TX: Transaction,
185 CFG: Cfg,
186 DB: Database,
187 JOURNAL: JournalTr<Database = DB>,
188 LOCAL: LocalContextTr,
189{
190 pub fn with_new_journal<OJOURNAL: JournalTr<Database = DB>>(
192 self,
193 mut journal: OJOURNAL,
194 ) -> Context<BLOCK, TX, CFG, DB, OJOURNAL, CHAIN, LOCAL> {
195 journal.set_spec_id(self.cfg.spec().into());
196 Context {
197 tx: self.tx,
198 block: self.block,
199 cfg: self.cfg,
200 journaled_state: journal,
201 local: self.local,
202 chain: self.chain,
203 error: Ok(()),
204 }
205 }
206
207 pub fn with_db<ODB: Database>(
211 self,
212 db: ODB,
213 ) -> Context<BLOCK, TX, CFG, ODB, Journal<ODB>, CHAIN, LOCAL> {
214 let spec = self.cfg.spec().into();
215 let mut journaled_state = Journal::new(db);
216 journaled_state.set_spec_id(spec);
217 Context {
218 tx: self.tx,
219 block: self.block,
220 cfg: self.cfg,
221 journaled_state,
222 local: self.local,
223 chain: self.chain,
224 error: Ok(()),
225 }
226 }
227
228 pub fn with_ref_db<ODB: DatabaseRef>(
230 self,
231 db: ODB,
232 ) -> Context<BLOCK, TX, CFG, WrapDatabaseRef<ODB>, Journal<WrapDatabaseRef<ODB>>, CHAIN, LOCAL>
233 {
234 let spec = self.cfg.spec().into();
235 let mut journaled_state = Journal::new(WrapDatabaseRef(db));
236 journaled_state.set_spec_id(spec);
237 Context {
238 tx: self.tx,
239 block: self.block,
240 cfg: self.cfg,
241 journaled_state,
242 local: self.local,
243 chain: self.chain,
244 error: Ok(()),
245 }
246 }
247
248 pub fn with_block<OB: Block>(
250 self,
251 block: OB,
252 ) -> Context<OB, TX, CFG, DB, JOURNAL, CHAIN, LOCAL> {
253 Context {
254 tx: self.tx,
255 block,
256 cfg: self.cfg,
257 journaled_state: self.journaled_state,
258 local: self.local,
259 chain: self.chain,
260 error: Ok(()),
261 }
262 }
263 pub fn with_tx<OTX: Transaction>(
265 self,
266 tx: OTX,
267 ) -> Context<BLOCK, OTX, CFG, DB, JOURNAL, CHAIN, LOCAL> {
268 Context {
269 tx,
270 block: self.block,
271 cfg: self.cfg,
272 journaled_state: self.journaled_state,
273 local: self.local,
274 chain: self.chain,
275 error: Ok(()),
276 }
277 }
278
279 pub fn with_chain<OC>(self, chain: OC) -> Context<BLOCK, TX, CFG, DB, JOURNAL, OC, LOCAL> {
281 Context {
282 tx: self.tx,
283 block: self.block,
284 cfg: self.cfg,
285 journaled_state: self.journaled_state,
286 local: self.local,
287 chain,
288 error: Ok(()),
289 }
290 }
291
292 pub fn with_cfg<OCFG: Cfg>(
294 mut self,
295 cfg: OCFG,
296 ) -> Context<BLOCK, TX, OCFG, DB, JOURNAL, CHAIN, LOCAL> {
297 self.journaled_state.set_spec_id(cfg.spec().into());
298 Context {
299 tx: self.tx,
300 block: self.block,
301 cfg,
302 journaled_state: self.journaled_state,
303 local: self.local,
304 chain: self.chain,
305 error: Ok(()),
306 }
307 }
308
309 pub fn with_local<OL: LocalContextTr>(
311 self,
312 local: OL,
313 ) -> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN, OL> {
314 Context {
315 tx: self.tx,
316 block: self.block,
317 cfg: self.cfg,
318 journaled_state: self.journaled_state,
319 local,
320 chain: self.chain,
321 error: Ok(()),
322 }
323 }
324
325 #[must_use]
327 pub fn modify_cfg_chained<F>(mut self, f: F) -> Self
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 self
334 }
335
336 #[must_use]
338 pub fn modify_block_chained<F>(mut self, f: F) -> Self
339 where
340 F: FnOnce(&mut BLOCK),
341 {
342 self.modify_block(f);
343 self
344 }
345
346 #[must_use]
348 pub fn modify_tx_chained<F>(mut self, f: F) -> Self
349 where
350 F: FnOnce(&mut TX),
351 {
352 self.modify_tx(f);
353 self
354 }
355
356 #[must_use]
358 pub fn modify_chain_chained<F>(mut self, f: F) -> Self
359 where
360 F: FnOnce(&mut CHAIN),
361 {
362 self.modify_chain(f);
363 self
364 }
365
366 #[must_use]
368 pub fn modify_db_chained<F>(mut self, f: F) -> Self
369 where
370 F: FnOnce(&mut DB),
371 {
372 self.modify_db(f);
373 self
374 }
375
376 #[must_use]
378 pub fn modify_journal_chained<F>(mut self, f: F) -> Self
379 where
380 F: FnOnce(&mut JOURNAL),
381 {
382 self.modify_journal(f);
383 self
384 }
385
386 pub fn modify_block<F>(&mut self, f: F)
388 where
389 F: FnOnce(&mut BLOCK),
390 {
391 f(&mut self.block);
392 }
393
394 pub fn modify_tx<F>(&mut self, f: F)
396 where
397 F: FnOnce(&mut TX),
398 {
399 f(&mut self.tx);
400 }
401
402 pub fn modify_cfg<F>(&mut self, f: F)
404 where
405 F: FnOnce(&mut CFG),
406 {
407 f(&mut self.cfg);
408 self.journaled_state.set_spec_id(self.cfg.spec().into());
409 }
410
411 pub fn modify_chain<F>(&mut self, f: F)
413 where
414 F: FnOnce(&mut CHAIN),
415 {
416 f(&mut self.chain);
417 }
418
419 pub fn modify_db<F>(&mut self, f: F)
421 where
422 F: FnOnce(&mut DB),
423 {
424 f(self.journaled_state.db_mut());
425 }
426
427 pub fn modify_journal<F>(&mut self, f: F)
429 where
430 F: FnOnce(&mut JOURNAL),
431 {
432 f(&mut self.journaled_state);
433 }
434
435 pub fn modify_local<F>(&mut self, f: F)
437 where
438 F: FnOnce(&mut LOCAL),
439 {
440 f(&mut self.local);
441 }
442}