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