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 > ContextSetters for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
140{
141 fn set_tx(&mut self, tx: Self::Tx) {
142 self.tx = tx;
143 }
144
145 fn set_block(&mut self, block: Self::Block) {
146 self.block = block;
147 }
148}
149
150impl<
151 BLOCK: Block + Default,
152 TX: Transaction + Default,
153 DB: Database,
154 JOURNAL: JournalTr<Database = DB>,
155 CHAIN: Default,
156 > Context<BLOCK, TX, CfgEnv, DB, JOURNAL, CHAIN>
157{
158 pub fn new(db: DB, spec: SpecId) -> Self {
162 let mut journaled_state = JOURNAL::new(db);
163 journaled_state.set_spec_id(spec);
164 Self {
165 tx: TX::default(),
166 block: BLOCK::default(),
167 cfg: CfgEnv {
168 spec,
169 ..Default::default()
170 },
171 local: LocalContext::default(),
172 journaled_state,
173 chain: Default::default(),
174 error: Ok(()),
175 }
176 }
177}
178
179impl<BLOCK, TX, CFG, DB, JOURNAL, CHAIN> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
180where
181 BLOCK: Block,
182 TX: Transaction,
183 CFG: Cfg,
184 DB: Database,
185 JOURNAL: JournalTr<Database = DB>,
186{
187 pub fn with_new_journal<OJOURNAL: JournalTr<Database = DB>>(
189 self,
190 mut journal: OJOURNAL,
191 ) -> Context<BLOCK, TX, CFG, DB, OJOURNAL, CHAIN> {
192 journal.set_spec_id(self.cfg.spec().into());
193 Context {
194 tx: self.tx,
195 block: self.block,
196 cfg: self.cfg,
197 journaled_state: journal,
198 local: self.local,
199 chain: self.chain,
200 error: Ok(()),
201 }
202 }
203
204 pub fn with_db<ODB: Database>(
208 self,
209 db: ODB,
210 ) -> Context<BLOCK, TX, CFG, ODB, Journal<ODB>, CHAIN> {
211 let spec = self.cfg.spec().into();
212 let mut journaled_state = Journal::new(db);
213 journaled_state.set_spec_id(spec);
214 Context {
215 tx: self.tx,
216 block: self.block,
217 cfg: self.cfg,
218 journaled_state,
219 local: self.local,
220 chain: self.chain,
221 error: Ok(()),
222 }
223 }
224
225 pub fn with_ref_db<ODB: DatabaseRef>(
227 self,
228 db: ODB,
229 ) -> Context<BLOCK, TX, CFG, WrapDatabaseRef<ODB>, Journal<WrapDatabaseRef<ODB>>, CHAIN> {
230 let spec = self.cfg.spec().into();
231 let mut journaled_state = Journal::new(WrapDatabaseRef(db));
232 journaled_state.set_spec_id(spec);
233 Context {
234 tx: self.tx,
235 block: self.block,
236 cfg: self.cfg,
237 journaled_state,
238 local: self.local,
239 chain: self.chain,
240 error: Ok(()),
241 }
242 }
243
244 pub fn with_block<OB: Block>(self, block: OB) -> Context<OB, TX, CFG, DB, JOURNAL, CHAIN> {
246 Context {
247 tx: self.tx,
248 block,
249 cfg: self.cfg,
250 journaled_state: self.journaled_state,
251 local: self.local,
252 chain: self.chain,
253 error: Ok(()),
254 }
255 }
256 pub fn with_tx<OTX: Transaction>(
258 self,
259 tx: OTX,
260 ) -> Context<BLOCK, OTX, CFG, DB, JOURNAL, CHAIN> {
261 Context {
262 tx,
263 block: self.block,
264 cfg: self.cfg,
265 journaled_state: self.journaled_state,
266 local: self.local,
267 chain: self.chain,
268 error: Ok(()),
269 }
270 }
271
272 pub fn with_chain<OC>(self, chain: OC) -> Context<BLOCK, TX, CFG, DB, JOURNAL, OC> {
274 Context {
275 tx: self.tx,
276 block: self.block,
277 cfg: self.cfg,
278 journaled_state: self.journaled_state,
279 local: self.local,
280 chain,
281 error: Ok(()),
282 }
283 }
284
285 pub fn with_cfg<OCFG: Cfg>(
287 mut self,
288 cfg: OCFG,
289 ) -> Context<BLOCK, TX, OCFG, DB, JOURNAL, CHAIN> {
290 self.journaled_state.set_spec_id(cfg.spec().into());
291 Context {
292 tx: self.tx,
293 block: self.block,
294 cfg,
295 journaled_state: self.journaled_state,
296 local: self.local,
297 chain: self.chain,
298 error: Ok(()),
299 }
300 }
301
302 #[must_use]
304 pub fn modify_cfg_chained<F>(mut self, f: F) -> Self
305 where
306 F: FnOnce(&mut CFG),
307 {
308 f(&mut self.cfg);
309 self.journaled_state.set_spec_id(self.cfg.spec().into());
310 self
311 }
312
313 #[must_use]
315 pub fn modify_block_chained<F>(mut self, f: F) -> Self
316 where
317 F: FnOnce(&mut BLOCK),
318 {
319 self.modify_block(f);
320 self
321 }
322
323 #[must_use]
325 pub fn modify_tx_chained<F>(mut self, f: F) -> Self
326 where
327 F: FnOnce(&mut TX),
328 {
329 self.modify_tx(f);
330 self
331 }
332
333 #[must_use]
335 pub fn modify_chain_chained<F>(mut self, f: F) -> Self
336 where
337 F: FnOnce(&mut CHAIN),
338 {
339 self.modify_chain(f);
340 self
341 }
342
343 #[must_use]
345 pub fn modify_db_chained<F>(mut self, f: F) -> Self
346 where
347 F: FnOnce(&mut DB),
348 {
349 self.modify_db(f);
350 self
351 }
352
353 #[must_use]
355 pub fn modify_journal_chained<F>(mut self, f: F) -> Self
356 where
357 F: FnOnce(&mut JOURNAL),
358 {
359 self.modify_journal(f);
360 self
361 }
362
363 pub fn modify_block<F>(&mut self, f: F)
365 where
366 F: FnOnce(&mut BLOCK),
367 {
368 f(&mut self.block);
369 }
370
371 pub fn modify_tx<F>(&mut self, f: F)
373 where
374 F: FnOnce(&mut TX),
375 {
376 f(&mut self.tx);
377 }
378
379 pub fn modify_cfg<F>(&mut self, f: F)
381 where
382 F: FnOnce(&mut CFG),
383 {
384 f(&mut self.cfg);
385 self.journaled_state.set_spec_id(self.cfg.spec().into());
386 }
387
388 pub fn modify_chain<F>(&mut self, f: F)
390 where
391 F: FnOnce(&mut CHAIN),
392 {
393 f(&mut self.chain);
394 }
395
396 pub fn modify_db<F>(&mut self, f: F)
398 where
399 F: FnOnce(&mut DB),
400 {
401 f(self.journaled_state.db_mut());
402 }
403
404 pub fn modify_journal<F>(&mut self, f: F)
406 where
407 F: FnOnce(&mut JOURNAL),
408 {
409 f(&mut self.journaled_state);
410 }
411}