1use std::collections::HashSet;
22
23use parking_lot::RwLock;
24
25use sp_api::CallContext;
26use sp_consensus::BlockOrigin;
27use sp_core::offchain::OffchainStorage;
28use sp_runtime::{
29 traits::{Block as BlockT, HashingFor, NumberFor},
30 Justification, Justifications, StateVersion, Storage,
31};
32use sp_state_machine::{
33 backend::AsTrieBackend, ChildStorageCollection, IndexOperation, IterArgs,
34 OffchainChangesCollection, StorageCollection, StorageIterator,
35};
36use sp_storage::{ChildInfo, StorageData, StorageKey};
37pub use sp_trie::MerkleValue;
38
39use crate::{blockchain::Backend as BlockchainBackend, UsageInfo};
40
41pub use sp_state_machine::{Backend as StateBackend, BackendTransaction, KeyValueStates};
42
43pub type StateBackendFor<B, Block> = <B as Backend<Block>>::State;
45
46#[derive(Debug, Clone, Copy)]
48pub enum ImportNotificationAction {
49 RecentBlock,
51 EveryBlock,
53 Both,
55 None,
57}
58
59pub struct ImportSummary<Block: BlockT> {
64 pub hash: Block::Hash,
66 pub origin: BlockOrigin,
68 pub header: Block::Header,
70 pub is_new_best: bool,
72 pub storage_changes: Option<(StorageCollection, ChildStorageCollection)>,
74 pub tree_route: Option<sp_blockchain::TreeRoute<Block>>,
78 pub import_notification_action: ImportNotificationAction,
80}
81
82#[derive(Clone, Debug)]
84pub struct StaleBlock<Block: BlockT> {
85 pub hash: Block::Hash,
87 pub is_head: bool,
89}
90
91pub struct FinalizeSummary<Block: BlockT> {
96 pub header: Block::Header,
98 pub finalized: Vec<Block::Hash>,
102 pub stale_blocks: Vec<StaleBlock<Block>>,
104}
105
106pub struct ClientImportOperation<Block: BlockT, B: Backend<Block>> {
108 pub op: B::BlockImportOperation,
110 pub notify_imported: Option<ImportSummary<Block>>,
112 pub notify_finalized: Option<FinalizeSummary<Block>>,
114}
115
116pub fn apply_aux<'a, 'b: 'a, 'c: 'a, B, Block, D, I>(
118 operation: &mut ClientImportOperation<Block, B>,
119 insert: I,
120 delete: D,
121) -> sp_blockchain::Result<()>
122where
123 Block: BlockT,
124 B: Backend<Block>,
125 I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
126 D: IntoIterator<Item = &'a &'b [u8]>,
127{
128 operation.op.insert_aux(
129 insert
130 .into_iter()
131 .map(|(k, v)| (k.to_vec(), Some(v.to_vec())))
132 .chain(delete.into_iter().map(|k| (k.to_vec(), None))),
133 )
134}
135
136#[derive(Debug, Clone, Copy, PartialEq, Eq)]
138pub enum NewBlockState {
139 Normal,
141 Best,
143 Final,
145}
146
147impl NewBlockState {
148 pub fn is_best(self) -> bool {
150 match self {
151 NewBlockState::Best | NewBlockState::Final => true,
152 NewBlockState::Normal => false,
153 }
154 }
155
156 pub fn is_final(self) -> bool {
158 match self {
159 NewBlockState::Final => true,
160 NewBlockState::Best | NewBlockState::Normal => false,
161 }
162 }
163}
164
165pub trait BlockImportOperation<Block: BlockT> {
169 type State: StateBackend<HashingFor<Block>>;
171
172 fn state(&self) -> sp_blockchain::Result<Option<&Self::State>>;
176
177 fn set_block_data(
179 &mut self,
180 header: Block::Header,
181 body: Option<Vec<Block::Extrinsic>>,
182 indexed_body: Option<Vec<Vec<u8>>>,
183 justifications: Option<Justifications>,
184 state: NewBlockState,
185 ) -> sp_blockchain::Result<()>;
186
187 fn update_db_storage(
189 &mut self,
190 update: BackendTransaction<HashingFor<Block>>,
191 ) -> sp_blockchain::Result<()>;
192
193 fn set_genesis_state(
196 &mut self,
197 storage: Storage,
198 commit: bool,
199 state_version: StateVersion,
200 ) -> sp_blockchain::Result<Block::Hash>;
201
202 fn reset_storage(
204 &mut self,
205 storage: Storage,
206 state_version: StateVersion,
207 ) -> sp_blockchain::Result<Block::Hash>;
208
209 fn update_storage(
211 &mut self,
212 update: StorageCollection,
213 child_update: ChildStorageCollection,
214 ) -> sp_blockchain::Result<()>;
215
216 fn update_offchain_storage(
218 &mut self,
219 _offchain_update: OffchainChangesCollection,
220 ) -> sp_blockchain::Result<()> {
221 Ok(())
222 }
223
224 fn insert_aux<I>(&mut self, ops: I) -> sp_blockchain::Result<()>
228 where
229 I: IntoIterator<Item = (Vec<u8>, Option<Vec<u8>>)>;
230
231 fn mark_finalized(
234 &mut self,
235 hash: Block::Hash,
236 justification: Option<Justification>,
237 ) -> sp_blockchain::Result<()>;
238
239 fn mark_head(&mut self, hash: Block::Hash) -> sp_blockchain::Result<()>;
242
243 fn update_transaction_index(&mut self, index: Vec<IndexOperation>)
245 -> sp_blockchain::Result<()>;
246
247 fn set_create_gap(&mut self, create_gap: bool);
249}
250
251pub trait LockImportRun<Block: BlockT, B: Backend<Block>> {
253 fn lock_import_and_run<R, Err, F>(&self, f: F) -> Result<R, Err>
255 where
256 F: FnOnce(&mut ClientImportOperation<Block, B>) -> Result<R, Err>,
257 Err: From<sp_blockchain::Error>;
258}
259
260pub trait Finalizer<Block: BlockT, B: Backend<Block>> {
262 fn apply_finality(
272 &self,
273 operation: &mut ClientImportOperation<Block, B>,
274 block: Block::Hash,
275 justification: Option<Justification>,
276 notify: bool,
277 ) -> sp_blockchain::Result<()>;
278
279 fn finalize_block(
293 &self,
294 block: Block::Hash,
295 justification: Option<Justification>,
296 notify: bool,
297 ) -> sp_blockchain::Result<()>;
298}
299
300pub trait AuxStore {
306 fn insert_aux<
310 'a,
311 'b: 'a,
312 'c: 'a,
313 I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
314 D: IntoIterator<Item = &'a &'b [u8]>,
315 >(
316 &self,
317 insert: I,
318 delete: D,
319 ) -> sp_blockchain::Result<()>;
320
321 fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>>;
323}
324
325pub struct KeysIter<State, Block>
327where
328 State: StateBackend<HashingFor<Block>>,
329 Block: BlockT,
330{
331 inner: <State as StateBackend<HashingFor<Block>>>::RawIter,
332 state: State,
333}
334
335impl<State, Block> KeysIter<State, Block>
336where
337 State: StateBackend<HashingFor<Block>>,
338 Block: BlockT,
339{
340 pub fn new(
342 state: State,
343 prefix: Option<&StorageKey>,
344 start_at: Option<&StorageKey>,
345 ) -> Result<Self, State::Error> {
346 let mut args = IterArgs::default();
347 args.prefix = prefix.as_ref().map(|prefix| prefix.0.as_slice());
348 args.start_at = start_at.as_ref().map(|start_at| start_at.0.as_slice());
349 args.start_at_exclusive = true;
350
351 Ok(Self { inner: state.raw_iter(args)?, state })
352 }
353
354 pub fn new_child(
356 state: State,
357 child_info: ChildInfo,
358 prefix: Option<&StorageKey>,
359 start_at: Option<&StorageKey>,
360 ) -> Result<Self, State::Error> {
361 let mut args = IterArgs::default();
362 args.prefix = prefix.as_ref().map(|prefix| prefix.0.as_slice());
363 args.start_at = start_at.as_ref().map(|start_at| start_at.0.as_slice());
364 args.child_info = Some(child_info);
365 args.start_at_exclusive = true;
366
367 Ok(Self { inner: state.raw_iter(args)?, state })
368 }
369}
370
371impl<State, Block> Iterator for KeysIter<State, Block>
372where
373 Block: BlockT,
374 State: StateBackend<HashingFor<Block>>,
375{
376 type Item = StorageKey;
377
378 fn next(&mut self) -> Option<Self::Item> {
379 self.inner.next_key(&self.state)?.ok().map(StorageKey)
380 }
381}
382
383pub struct PairsIter<State, Block>
385where
386 State: StateBackend<HashingFor<Block>>,
387 Block: BlockT,
388{
389 inner: <State as StateBackend<HashingFor<Block>>>::RawIter,
390 state: State,
391}
392
393impl<State, Block> Iterator for PairsIter<State, Block>
394where
395 Block: BlockT,
396 State: StateBackend<HashingFor<Block>>,
397{
398 type Item = (StorageKey, StorageData);
399
400 fn next(&mut self) -> Option<Self::Item> {
401 self.inner
402 .next_pair(&self.state)?
403 .ok()
404 .map(|(key, value)| (StorageKey(key), StorageData(value)))
405 }
406}
407
408impl<State, Block> PairsIter<State, Block>
409where
410 State: StateBackend<HashingFor<Block>>,
411 Block: BlockT,
412{
413 pub fn new(
415 state: State,
416 prefix: Option<&StorageKey>,
417 start_at: Option<&StorageKey>,
418 ) -> Result<Self, State::Error> {
419 let mut args = IterArgs::default();
420 args.prefix = prefix.as_ref().map(|prefix| prefix.0.as_slice());
421 args.start_at = start_at.as_ref().map(|start_at| start_at.0.as_slice());
422 args.start_at_exclusive = true;
423
424 Ok(Self { inner: state.raw_iter(args)?, state })
425 }
426}
427
428pub trait StorageProvider<Block: BlockT, B: Backend<Block>> {
430 fn storage(
432 &self,
433 hash: Block::Hash,
434 key: &StorageKey,
435 ) -> sp_blockchain::Result<Option<StorageData>>;
436
437 fn storage_hash(
439 &self,
440 hash: Block::Hash,
441 key: &StorageKey,
442 ) -> sp_blockchain::Result<Option<Block::Hash>>;
443
444 fn storage_keys(
447 &self,
448 hash: Block::Hash,
449 prefix: Option<&StorageKey>,
450 start_key: Option<&StorageKey>,
451 ) -> sp_blockchain::Result<KeysIter<B::State, Block>>;
452
453 fn storage_pairs(
456 &self,
457 hash: <Block as BlockT>::Hash,
458 prefix: Option<&StorageKey>,
459 start_key: Option<&StorageKey>,
460 ) -> sp_blockchain::Result<PairsIter<B::State, Block>>;
461
462 fn child_storage(
465 &self,
466 hash: Block::Hash,
467 child_info: &ChildInfo,
468 key: &StorageKey,
469 ) -> sp_blockchain::Result<Option<StorageData>>;
470
471 fn child_storage_keys(
474 &self,
475 hash: Block::Hash,
476 child_info: ChildInfo,
477 prefix: Option<&StorageKey>,
478 start_key: Option<&StorageKey>,
479 ) -> sp_blockchain::Result<KeysIter<B::State, Block>>;
480
481 fn child_storage_hash(
484 &self,
485 hash: Block::Hash,
486 child_info: &ChildInfo,
487 key: &StorageKey,
488 ) -> sp_blockchain::Result<Option<Block::Hash>>;
489
490 fn closest_merkle_value(
492 &self,
493 hash: Block::Hash,
494 key: &StorageKey,
495 ) -> sp_blockchain::Result<Option<MerkleValue<Block::Hash>>>;
496
497 fn child_closest_merkle_value(
499 &self,
500 hash: Block::Hash,
501 child_info: &ChildInfo,
502 key: &StorageKey,
503 ) -> sp_blockchain::Result<Option<MerkleValue<Block::Hash>>>;
504}
505
506#[derive(Debug, Clone, Copy)]
510pub enum TrieCacheContext {
511 Trusted,
519 Untrusted,
523}
524
525impl From<CallContext> for TrieCacheContext {
526 fn from(call_context: CallContext) -> Self {
527 match call_context {
528 CallContext::Onchain => TrieCacheContext::Trusted,
529 CallContext::Offchain => TrieCacheContext::Untrusted,
530 }
531 }
532}
533
534pub trait Backend<Block: BlockT>: AuxStore + Send + Sync {
557 type BlockImportOperation: BlockImportOperation<Block, State = Self::State>;
559 type Blockchain: BlockchainBackend<Block>;
561 type State: StateBackend<HashingFor<Block>>
563 + Send
564 + AsTrieBackend<
565 HashingFor<Block>,
566 TrieBackendStorage = <Self::State as StateBackend<HashingFor<Block>>>::TrieBackendStorage,
567 >;
568 type OffchainStorage: OffchainStorage;
570
571 fn begin_operation(&self) -> sp_blockchain::Result<Self::BlockImportOperation>;
575
576 fn begin_state_operation(
578 &self,
579 operation: &mut Self::BlockImportOperation,
580 block: Block::Hash,
581 ) -> sp_blockchain::Result<()>;
582
583 fn commit_operation(
585 &self,
586 transaction: Self::BlockImportOperation,
587 ) -> sp_blockchain::Result<()>;
588
589 fn finalize_block(
593 &self,
594 hash: Block::Hash,
595 justification: Option<Justification>,
596 ) -> sp_blockchain::Result<()>;
597
598 fn append_justification(
602 &self,
603 hash: Block::Hash,
604 justification: Justification,
605 ) -> sp_blockchain::Result<()>;
606
607 fn blockchain(&self) -> &Self::Blockchain;
609
610 fn usage_info(&self) -> Option<UsageInfo>;
612
613 fn offchain_storage(&self) -> Option<Self::OffchainStorage>;
615
616 fn pin_block(&self, hash: Block::Hash) -> sp_blockchain::Result<()>;
620
621 fn unpin_block(&self, hash: Block::Hash);
623
624 fn have_state_at(&self, hash: Block::Hash, _number: NumberFor<Block>) -> bool {
626 self.state_at(hash, TrieCacheContext::Untrusted).is_ok()
627 }
628
629 fn state_at(
631 &self,
632 hash: Block::Hash,
633 trie_cache_context: TrieCacheContext,
634 ) -> sp_blockchain::Result<Self::State>;
635
636 fn revert(
644 &self,
645 n: NumberFor<Block>,
646 revert_finalized: bool,
647 ) -> sp_blockchain::Result<(NumberFor<Block>, HashSet<Block::Hash>)>;
648
649 fn remove_leaf_block(&self, hash: Block::Hash) -> sp_blockchain::Result<()>;
651
652 fn insert_aux<
654 'a,
655 'b: 'a,
656 'c: 'a,
657 I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
658 D: IntoIterator<Item = &'a &'b [u8]>,
659 >(
660 &self,
661 insert: I,
662 delete: D,
663 ) -> sp_blockchain::Result<()> {
664 AuxStore::insert_aux(self, insert, delete)
665 }
666 fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
668 AuxStore::get_aux(self, key)
669 }
670
671 fn get_import_lock(&self) -> &RwLock<()>;
678
679 fn requires_full_sync(&self) -> bool;
681}
682
683pub trait LocalBackend<Block: BlockT>: Backend<Block> {}