1use std::collections::{HashMap, HashSet};
22
23use parking_lot::RwLock;
24
25use sp_api::CallContext;
26use sp_consensus::BlockOrigin;
27use sp_core::{offchain::OffchainStorage, H256};
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
165#[derive(Default, Debug, Clone)]
167pub struct PrefetchedIndexedTransactions {
168 pub ops: Vec<IndexOperation>,
170
171 pub renew_payloads: HashMap<H256, Vec<u8>>,
173}
174
175pub trait BlockImportOperation<Block: BlockT> {
179 type State: StateBackend<HashingFor<Block>>;
181
182 fn state(&self) -> sp_blockchain::Result<Option<&Self::State>>;
186
187 fn set_block_data(
197 &mut self,
198 header: Block::Header,
199 body: Option<Vec<Block::Extrinsic>>,
200 justifications: Option<Justifications>,
201 state: NewBlockState,
202 register_as_leaf: bool,
203 ) -> sp_blockchain::Result<()>;
204
205 fn update_db_storage(
207 &mut self,
208 update: BackendTransaction<HashingFor<Block>>,
209 ) -> sp_blockchain::Result<()>;
210
211 fn set_genesis_state(
214 &mut self,
215 storage: Storage,
216 commit: bool,
217 state_version: StateVersion,
218 ) -> sp_blockchain::Result<Block::Hash>;
219
220 fn reset_storage(
222 &mut self,
223 storage: Storage,
224 state_version: StateVersion,
225 ) -> sp_blockchain::Result<Block::Hash>;
226
227 fn update_storage(
229 &mut self,
230 update: StorageCollection,
231 child_update: ChildStorageCollection,
232 ) -> sp_blockchain::Result<()>;
233
234 fn update_offchain_storage(
236 &mut self,
237 _offchain_update: OffchainChangesCollection,
238 ) -> sp_blockchain::Result<()> {
239 Ok(())
240 }
241
242 fn insert_aux<I>(&mut self, ops: I) -> sp_blockchain::Result<()>
246 where
247 I: IntoIterator<Item = (Vec<u8>, Option<Vec<u8>>)>;
248
249 fn mark_finalized(
252 &mut self,
253 hash: Block::Hash,
254 justification: Option<Justification>,
255 ) -> sp_blockchain::Result<()>;
256
257 fn mark_head(&mut self, hash: Block::Hash) -> sp_blockchain::Result<()>;
260
261 fn update_transaction_index(&mut self, index: Vec<IndexOperation>)
263 -> sp_blockchain::Result<()>;
264
265 fn set_renew_payloads(&mut self, payloads: HashMap<H256, Vec<u8>>)
268 -> sp_blockchain::Result<()>;
269
270 fn set_create_gap(&mut self, create_gap: bool);
272}
273
274pub trait LockImportRun<Block: BlockT, B: Backend<Block>> {
276 fn lock_import_and_run<R, Err, F>(&self, f: F) -> Result<R, Err>
278 where
279 F: FnOnce(&mut ClientImportOperation<Block, B>) -> Result<R, Err>,
280 Err: From<sp_blockchain::Error>;
281}
282
283pub trait Finalizer<Block: BlockT, B: Backend<Block>> {
285 fn apply_finality(
295 &self,
296 operation: &mut ClientImportOperation<Block, B>,
297 block: Block::Hash,
298 justification: Option<Justification>,
299 notify: bool,
300 ) -> sp_blockchain::Result<()>;
301
302 fn finalize_block(
316 &self,
317 block: Block::Hash,
318 justification: Option<Justification>,
319 notify: bool,
320 ) -> sp_blockchain::Result<()>;
321}
322
323pub trait AuxStore {
329 fn insert_aux<
333 'a,
334 'b: 'a,
335 'c: 'a,
336 I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
337 D: IntoIterator<Item = &'a &'b [u8]>,
338 >(
339 &self,
340 insert: I,
341 delete: D,
342 ) -> sp_blockchain::Result<()>;
343
344 fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>>;
346}
347
348pub struct KeysIter<State, Block>
350where
351 State: StateBackend<HashingFor<Block>>,
352 Block: BlockT,
353{
354 inner: <State as StateBackend<HashingFor<Block>>>::RawIter,
355 state: State,
356}
357
358impl<State, Block> KeysIter<State, Block>
359where
360 State: StateBackend<HashingFor<Block>>,
361 Block: BlockT,
362{
363 pub fn new(
365 state: State,
366 prefix: Option<&StorageKey>,
367 start_at: Option<&StorageKey>,
368 ) -> Result<Self, State::Error> {
369 let mut args = IterArgs::default();
370 args.prefix = prefix.as_ref().map(|prefix| prefix.0.as_slice());
371 args.start_at = start_at.as_ref().map(|start_at| start_at.0.as_slice());
372 args.start_at_exclusive = true;
373
374 Ok(Self { inner: state.raw_iter(args)?, state })
375 }
376
377 pub fn new_child(
379 state: State,
380 child_info: ChildInfo,
381 prefix: Option<&StorageKey>,
382 start_at: Option<&StorageKey>,
383 ) -> Result<Self, State::Error> {
384 let mut args = IterArgs::default();
385 args.prefix = prefix.as_ref().map(|prefix| prefix.0.as_slice());
386 args.start_at = start_at.as_ref().map(|start_at| start_at.0.as_slice());
387 args.child_info = Some(child_info);
388 args.start_at_exclusive = true;
389
390 Ok(Self { inner: state.raw_iter(args)?, state })
391 }
392}
393
394impl<State, Block> Iterator for KeysIter<State, Block>
395where
396 Block: BlockT,
397 State: StateBackend<HashingFor<Block>>,
398{
399 type Item = StorageKey;
400
401 fn next(&mut self) -> Option<Self::Item> {
402 self.inner.next_key(&self.state)?.ok().map(StorageKey)
403 }
404}
405
406pub struct PairsIter<State, Block>
408where
409 State: StateBackend<HashingFor<Block>>,
410 Block: BlockT,
411{
412 inner: <State as StateBackend<HashingFor<Block>>>::RawIter,
413 state: State,
414}
415
416impl<State, Block> Iterator for PairsIter<State, Block>
417where
418 Block: BlockT,
419 State: StateBackend<HashingFor<Block>>,
420{
421 type Item = (StorageKey, StorageData);
422
423 fn next(&mut self) -> Option<Self::Item> {
424 self.inner
425 .next_pair(&self.state)?
426 .ok()
427 .map(|(key, value)| (StorageKey(key), StorageData(value)))
428 }
429}
430
431impl<State, Block> PairsIter<State, Block>
432where
433 State: StateBackend<HashingFor<Block>>,
434 Block: BlockT,
435{
436 pub fn new(
438 state: State,
439 prefix: Option<&StorageKey>,
440 start_at: Option<&StorageKey>,
441 ) -> Result<Self, State::Error> {
442 let mut args = IterArgs::default();
443 args.prefix = prefix.as_ref().map(|prefix| prefix.0.as_slice());
444 args.start_at = start_at.as_ref().map(|start_at| start_at.0.as_slice());
445 args.start_at_exclusive = true;
446
447 Ok(Self { inner: state.raw_iter(args)?, state })
448 }
449}
450
451pub trait StorageProvider<Block: BlockT, B: Backend<Block>> {
453 fn storage(
455 &self,
456 hash: Block::Hash,
457 key: &StorageKey,
458 ) -> sp_blockchain::Result<Option<StorageData>>;
459
460 fn storage_hash(
462 &self,
463 hash: Block::Hash,
464 key: &StorageKey,
465 ) -> sp_blockchain::Result<Option<Block::Hash>>;
466
467 fn storage_keys(
470 &self,
471 hash: Block::Hash,
472 prefix: Option<&StorageKey>,
473 start_key: Option<&StorageKey>,
474 ) -> sp_blockchain::Result<KeysIter<B::State, Block>>;
475
476 fn storage_pairs(
479 &self,
480 hash: <Block as BlockT>::Hash,
481 prefix: Option<&StorageKey>,
482 start_key: Option<&StorageKey>,
483 ) -> sp_blockchain::Result<PairsIter<B::State, Block>>;
484
485 fn child_storage(
488 &self,
489 hash: Block::Hash,
490 child_info: &ChildInfo,
491 key: &StorageKey,
492 ) -> sp_blockchain::Result<Option<StorageData>>;
493
494 fn child_storage_keys(
497 &self,
498 hash: Block::Hash,
499 child_info: ChildInfo,
500 prefix: Option<&StorageKey>,
501 start_key: Option<&StorageKey>,
502 ) -> sp_blockchain::Result<KeysIter<B::State, Block>>;
503
504 fn child_storage_hash(
507 &self,
508 hash: Block::Hash,
509 child_info: &ChildInfo,
510 key: &StorageKey,
511 ) -> sp_blockchain::Result<Option<Block::Hash>>;
512
513 fn closest_merkle_value(
515 &self,
516 hash: Block::Hash,
517 key: &StorageKey,
518 ) -> sp_blockchain::Result<Option<MerkleValue<Block::Hash>>>;
519
520 fn child_closest_merkle_value(
522 &self,
523 hash: Block::Hash,
524 child_info: &ChildInfo,
525 key: &StorageKey,
526 ) -> sp_blockchain::Result<Option<MerkleValue<Block::Hash>>>;
527}
528
529#[derive(Debug, Clone, Copy)]
533pub enum TrieCacheContext {
534 Trusted,
542 Untrusted,
546}
547
548impl From<CallContext> for TrieCacheContext {
549 fn from(call_context: CallContext) -> Self {
550 match call_context {
551 CallContext::Onchain { .. } => TrieCacheContext::Trusted,
552 CallContext::Offchain => TrieCacheContext::Untrusted,
553 }
554 }
555}
556
557pub trait Backend<Block: BlockT>: AuxStore + Send + Sync {
580 type BlockImportOperation: BlockImportOperation<Block, State = Self::State>;
582 type Blockchain: BlockchainBackend<Block>;
584 type State: StateBackend<HashingFor<Block>>
586 + Send
587 + AsTrieBackend<
588 HashingFor<Block>,
589 TrieBackendStorage = <Self::State as StateBackend<HashingFor<Block>>>::TrieBackendStorage,
590 >;
591 type OffchainStorage: OffchainStorage;
593
594 fn begin_operation(&self) -> sp_blockchain::Result<Self::BlockImportOperation>;
598
599 fn begin_state_operation(
601 &self,
602 operation: &mut Self::BlockImportOperation,
603 block: Block::Hash,
604 ) -> sp_blockchain::Result<()>;
605
606 fn commit_operation(
608 &self,
609 transaction: Self::BlockImportOperation,
610 ) -> sp_blockchain::Result<()>;
611
612 fn finalize_block(
616 &self,
617 hash: Block::Hash,
618 justification: Option<Justification>,
619 ) -> sp_blockchain::Result<()>;
620
621 fn append_justification(
625 &self,
626 hash: Block::Hash,
627 justification: Justification,
628 ) -> sp_blockchain::Result<()>;
629
630 fn blockchain(&self) -> &Self::Blockchain;
632
633 fn usage_info(&self) -> Option<UsageInfo>;
635
636 fn offchain_storage(&self) -> Option<Self::OffchainStorage>;
638
639 fn pin_block(&self, hash: Block::Hash) -> sp_blockchain::Result<()>;
643
644 fn unpin_block(&self, hash: Block::Hash);
646
647 fn have_state_at(&self, hash: Block::Hash, _number: NumberFor<Block>) -> bool {
649 self.state_at(hash, TrieCacheContext::Untrusted).is_ok()
650 }
651
652 fn state_at(
654 &self,
655 hash: Block::Hash,
656 trie_cache_context: TrieCacheContext,
657 ) -> sp_blockchain::Result<Self::State>;
658
659 fn revert(
667 &self,
668 n: NumberFor<Block>,
669 revert_finalized: bool,
670 ) -> sp_blockchain::Result<(NumberFor<Block>, HashSet<Block::Hash>)>;
671
672 fn remove_leaf_block(&self, hash: Block::Hash) -> sp_blockchain::Result<()>;
674
675 fn insert_aux<
677 'a,
678 'b: 'a,
679 'c: 'a,
680 I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
681 D: IntoIterator<Item = &'a &'b [u8]>,
682 >(
683 &self,
684 insert: I,
685 delete: D,
686 ) -> sp_blockchain::Result<()> {
687 AuxStore::insert_aux(self, insert, delete)
688 }
689 fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
691 AuxStore::get_aux(self, key)
692 }
693
694 fn get_import_lock(&self) -> &RwLock<()>;
701
702 fn requires_full_sync(&self) -> bool;
704}
705
706pub trait LocalBackend<Block: BlockT>: Backend<Block> {}