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 fn tx(&self) -> &Self::Tx {
57 &self.tx
58 }
59
60 fn block(&self) -> &Self::Block {
61 &self.block
62 }
63
64 fn cfg(&self) -> &Self::Cfg {
65 &self.cfg
66 }
67
68 fn journal(&mut self) -> &mut Self::Journal {
69 &mut self.journaled_state
70 }
71
72 fn journal_ref(&self) -> &Self::Journal {
73 &self.journaled_state
74 }
75
76 fn db(&mut self) -> &mut Self::Db {
77 self.journaled_state.db()
78 }
79
80 fn db_ref(&self) -> &Self::Db {
81 self.journaled_state.db_ref()
82 }
83
84 fn chain(&mut self) -> &mut Self::Chain {
85 &mut self.chain
86 }
87
88 fn chain_ref(&self) -> &Self::Chain {
89 &self.chain
90 }
91
92 fn local(&mut self) -> &mut Self::Local {
93 &mut self.local
94 }
95
96 fn error(&mut self) -> &mut Result<(), ContextError<<Self::Db as Database>::Error>> {
97 &mut self.error
98 }
99
100 fn tx_journal(&mut self) -> (&mut Self::Tx, &mut Self::Journal) {
101 (&mut self.tx, &mut self.journaled_state)
102 }
103
104 fn tx_local(&mut self) -> (&Self::Tx, &mut Self::Local) {
105 (&self.tx, &mut self.local)
106 }
107}
108
109impl<
110 BLOCK: Block,
111 TX: Transaction,
112 DB: Database,
113 CFG: Cfg,
114 JOURNAL: JournalTr<Database = DB>,
115 CHAIN,
116 > ContextSetters for Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
117{
118 fn set_tx(&mut self, tx: Self::Tx) {
119 self.tx = tx;
120 }
121
122 fn set_block(&mut self, block: Self::Block) {
123 self.block = block;
124 }
125}
126
127impl<
128 BLOCK: Block + Default,
129 TX: Transaction + Default,
130 DB: Database,
131 JOURNAL: JournalTr<Database = DB>,
132 CHAIN: Default,
133 > Context<BLOCK, TX, CfgEnv, DB, JOURNAL, CHAIN>
134{
135 pub fn new(db: DB, spec: SpecId) -> Self {
139 let mut journaled_state = JOURNAL::new(db);
140 journaled_state.set_spec_id(spec);
141 Self {
142 tx: TX::default(),
143 block: BLOCK::default(),
144 cfg: CfgEnv {
145 spec,
146 ..Default::default()
147 },
148 local: LocalContext::default(),
149 journaled_state,
150 chain: Default::default(),
151 error: Ok(()),
152 }
153 }
154}
155
156impl<BLOCK, TX, CFG, DB, JOURNAL, CHAIN> Context<BLOCK, TX, CFG, DB, JOURNAL, CHAIN>
157where
158 BLOCK: Block,
159 TX: Transaction,
160 CFG: Cfg,
161 DB: Database,
162 JOURNAL: JournalTr<Database = DB>,
163{
164 pub fn with_new_journal<OJOURNAL: JournalTr<Database = DB>>(
166 self,
167 mut journal: OJOURNAL,
168 ) -> Context<BLOCK, TX, CFG, DB, OJOURNAL, CHAIN> {
169 journal.set_spec_id(self.cfg.spec().into());
170 Context {
171 tx: self.tx,
172 block: self.block,
173 cfg: self.cfg,
174 journaled_state: journal,
175 local: self.local,
176 chain: self.chain,
177 error: Ok(()),
178 }
179 }
180
181 pub fn with_db<ODB: Database>(
185 self,
186 db: ODB,
187 ) -> Context<BLOCK, TX, CFG, ODB, Journal<ODB>, CHAIN> {
188 let spec = self.cfg.spec().into();
189 let mut journaled_state = Journal::new(db);
190 journaled_state.set_spec_id(spec);
191 Context {
192 tx: self.tx,
193 block: self.block,
194 cfg: self.cfg,
195 journaled_state,
196 local: self.local,
197 chain: self.chain,
198 error: Ok(()),
199 }
200 }
201
202 pub fn with_ref_db<ODB: DatabaseRef>(
204 self,
205 db: ODB,
206 ) -> Context<BLOCK, TX, CFG, WrapDatabaseRef<ODB>, Journal<WrapDatabaseRef<ODB>>, CHAIN> {
207 let spec = self.cfg.spec().into();
208 let mut journaled_state = Journal::new(WrapDatabaseRef(db));
209 journaled_state.set_spec_id(spec);
210 Context {
211 tx: self.tx,
212 block: self.block,
213 cfg: self.cfg,
214 journaled_state,
215 local: self.local,
216 chain: self.chain,
217 error: Ok(()),
218 }
219 }
220
221 pub fn with_block<OB: Block>(self, block: OB) -> Context<OB, TX, CFG, DB, JOURNAL, CHAIN> {
223 Context {
224 tx: self.tx,
225 block,
226 cfg: self.cfg,
227 journaled_state: self.journaled_state,
228 local: self.local,
229 chain: self.chain,
230 error: Ok(()),
231 }
232 }
233 pub fn with_tx<OTX: Transaction>(
235 self,
236 tx: OTX,
237 ) -> Context<BLOCK, OTX, CFG, DB, JOURNAL, CHAIN> {
238 Context {
239 tx,
240 block: self.block,
241 cfg: self.cfg,
242 journaled_state: self.journaled_state,
243 local: self.local,
244 chain: self.chain,
245 error: Ok(()),
246 }
247 }
248
249 pub fn with_chain<OC>(self, chain: OC) -> Context<BLOCK, TX, CFG, DB, JOURNAL, OC> {
251 Context {
252 tx: self.tx,
253 block: self.block,
254 cfg: self.cfg,
255 journaled_state: self.journaled_state,
256 local: self.local,
257 chain,
258 error: Ok(()),
259 }
260 }
261
262 pub fn with_cfg<OCFG: Cfg>(
264 mut self,
265 cfg: OCFG,
266 ) -> Context<BLOCK, TX, OCFG, DB, JOURNAL, CHAIN> {
267 self.journaled_state.set_spec_id(cfg.spec().into());
268 Context {
269 tx: self.tx,
270 block: self.block,
271 cfg,
272 journaled_state: self.journaled_state,
273 local: self.local,
274 chain: self.chain,
275 error: Ok(()),
276 }
277 }
278
279 #[must_use]
281 pub fn modify_cfg_chained<F>(mut self, f: F) -> Self
282 where
283 F: FnOnce(&mut CFG),
284 {
285 f(&mut self.cfg);
286 self.journaled_state.set_spec_id(self.cfg.spec().into());
287 self
288 }
289
290 #[must_use]
292 pub fn modify_block_chained<F>(mut self, f: F) -> Self
293 where
294 F: FnOnce(&mut BLOCK),
295 {
296 self.modify_block(f);
297 self
298 }
299
300 #[must_use]
302 pub fn modify_tx_chained<F>(mut self, f: F) -> Self
303 where
304 F: FnOnce(&mut TX),
305 {
306 self.modify_tx(f);
307 self
308 }
309
310 #[must_use]
312 pub fn modify_chain_chained<F>(mut self, f: F) -> Self
313 where
314 F: FnOnce(&mut CHAIN),
315 {
316 self.modify_chain(f);
317 self
318 }
319
320 #[must_use]
322 pub fn modify_db_chained<F>(mut self, f: F) -> Self
323 where
324 F: FnOnce(&mut DB),
325 {
326 self.modify_db(f);
327 self
328 }
329
330 #[must_use]
332 pub fn modify_journal_chained<F>(mut self, f: F) -> Self
333 where
334 F: FnOnce(&mut JOURNAL),
335 {
336 self.modify_journal(f);
337 self
338 }
339
340 pub fn modify_block<F>(&mut self, f: F)
342 where
343 F: FnOnce(&mut BLOCK),
344 {
345 f(&mut self.block);
346 }
347
348 pub fn modify_tx<F>(&mut self, f: F)
350 where
351 F: FnOnce(&mut TX),
352 {
353 f(&mut self.tx);
354 }
355
356 pub fn modify_cfg<F>(&mut self, f: F)
358 where
359 F: FnOnce(&mut CFG),
360 {
361 f(&mut self.cfg);
362 self.journaled_state.set_spec_id(self.cfg.spec().into());
363 }
364
365 pub fn modify_chain<F>(&mut self, f: F)
367 where
368 F: FnOnce(&mut CHAIN),
369 {
370 f(&mut self.chain);
371 }
372
373 pub fn modify_db<F>(&mut self, f: F)
375 where
376 F: FnOnce(&mut DB),
377 {
378 f(self.journaled_state.db());
379 }
380
381 pub fn modify_journal<F>(&mut self, f: F)
383 where
384 F: FnOnce(&mut JOURNAL),
385 {
386 f(&mut self.journaled_state);
387 }
388}