1use std::collections::HashSet;
22
23use parking_lot::RwLock;
24
25use sp_consensus::BlockOrigin;
26use sp_core::offchain::OffchainStorage;
27use sp_runtime::{
28 traits::{Block as BlockT, HashingFor, NumberFor},
29 Justification, Justifications, StateVersion, Storage,
30};
31use sp_state_machine::{
32 backend::AsTrieBackend, ChildStorageCollection, IndexOperation, IterArgs,
33 OffchainChangesCollection, StorageCollection, StorageIterator,
34};
35use sp_storage::{ChildInfo, StorageData, StorageKey};
36pub use sp_trie::MerkleValue;
37
38use crate::{blockchain::Backend as BlockchainBackend, UsageInfo};
39
40pub use sp_state_machine::{Backend as StateBackend, BackendTransaction, KeyValueStates};
41
42pub type StateBackendFor<B, Block> = <B as Backend<Block>>::State;
44
45#[derive(Debug, Clone, Copy)]
47pub enum ImportNotificationAction {
48 RecentBlock,
50 EveryBlock,
52 Both,
54 None,
56}
57
58pub struct ImportSummary<Block: BlockT> {
63 pub hash: Block::Hash,
65 pub origin: BlockOrigin,
67 pub header: Block::Header,
69 pub is_new_best: bool,
71 pub storage_changes: Option<(StorageCollection, ChildStorageCollection)>,
73 pub tree_route: Option<sp_blockchain::TreeRoute<Block>>,
77 pub import_notification_action: ImportNotificationAction,
79}
80
81pub struct FinalizeSummary<Block: BlockT> {
86 pub header: Block::Header,
88 pub finalized: Vec<Block::Hash>,
91 pub stale_heads: Vec<Block::Hash>,
93}
94
95pub struct ClientImportOperation<Block: BlockT, B: Backend<Block>> {
97 pub op: B::BlockImportOperation,
99 pub notify_imported: Option<ImportSummary<Block>>,
101 pub notify_finalized: Option<FinalizeSummary<Block>>,
103}
104
105pub fn apply_aux<'a, 'b: 'a, 'c: 'a, B, Block, D, I>(
107 operation: &mut ClientImportOperation<Block, B>,
108 insert: I,
109 delete: D,
110) -> sp_blockchain::Result<()>
111where
112 Block: BlockT,
113 B: Backend<Block>,
114 I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
115 D: IntoIterator<Item = &'a &'b [u8]>,
116{
117 operation.op.insert_aux(
118 insert
119 .into_iter()
120 .map(|(k, v)| (k.to_vec(), Some(v.to_vec())))
121 .chain(delete.into_iter().map(|k| (k.to_vec(), None))),
122 )
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127pub enum NewBlockState {
128 Normal,
130 Best,
132 Final,
134}
135
136impl NewBlockState {
137 pub fn is_best(self) -> bool {
139 match self {
140 NewBlockState::Best | NewBlockState::Final => true,
141 NewBlockState::Normal => false,
142 }
143 }
144
145 pub fn is_final(self) -> bool {
147 match self {
148 NewBlockState::Final => true,
149 NewBlockState::Best | NewBlockState::Normal => false,
150 }
151 }
152}
153
154pub trait BlockImportOperation<Block: BlockT> {
158 type State: StateBackend<HashingFor<Block>>;
160
161 fn state(&self) -> sp_blockchain::Result<Option<&Self::State>>;
165
166 fn set_block_data(
168 &mut self,
169 header: Block::Header,
170 body: Option<Vec<Block::Extrinsic>>,
171 indexed_body: Option<Vec<Vec<u8>>>,
172 justifications: Option<Justifications>,
173 state: NewBlockState,
174 ) -> sp_blockchain::Result<()>;
175
176 fn update_db_storage(
178 &mut self,
179 update: BackendTransaction<HashingFor<Block>>,
180 ) -> sp_blockchain::Result<()>;
181
182 fn set_genesis_state(
185 &mut self,
186 storage: Storage,
187 commit: bool,
188 state_version: StateVersion,
189 ) -> sp_blockchain::Result<Block::Hash>;
190
191 fn reset_storage(
193 &mut self,
194 storage: Storage,
195 state_version: StateVersion,
196 ) -> sp_blockchain::Result<Block::Hash>;
197
198 fn update_storage(
200 &mut self,
201 update: StorageCollection,
202 child_update: ChildStorageCollection,
203 ) -> sp_blockchain::Result<()>;
204
205 fn update_offchain_storage(
207 &mut self,
208 _offchain_update: OffchainChangesCollection,
209 ) -> sp_blockchain::Result<()> {
210 Ok(())
211 }
212
213 fn insert_aux<I>(&mut self, ops: I) -> sp_blockchain::Result<()>
217 where
218 I: IntoIterator<Item = (Vec<u8>, Option<Vec<u8>>)>;
219
220 fn mark_finalized(
223 &mut self,
224 hash: Block::Hash,
225 justification: Option<Justification>,
226 ) -> sp_blockchain::Result<()>;
227
228 fn mark_head(&mut self, hash: Block::Hash) -> sp_blockchain::Result<()>;
231
232 fn update_transaction_index(&mut self, index: Vec<IndexOperation>)
234 -> sp_blockchain::Result<()>;
235
236 fn set_create_gap(&mut self, create_gap: bool);
238}
239
240pub trait LockImportRun<Block: BlockT, B: Backend<Block>> {
242 fn lock_import_and_run<R, Err, F>(&self, f: F) -> Result<R, Err>
244 where
245 F: FnOnce(&mut ClientImportOperation<Block, B>) -> Result<R, Err>,
246 Err: From<sp_blockchain::Error>;
247}
248
249pub trait Finalizer<Block: BlockT, B: Backend<Block>> {
251 fn apply_finality(
261 &self,
262 operation: &mut ClientImportOperation<Block, B>,
263 block: Block::Hash,
264 justification: Option<Justification>,
265 notify: bool,
266 ) -> sp_blockchain::Result<()>;
267
268 fn finalize_block(
282 &self,
283 block: Block::Hash,
284 justification: Option<Justification>,
285 notify: bool,
286 ) -> sp_blockchain::Result<()>;
287}
288
289pub trait AuxStore {
295 fn insert_aux<
299 'a,
300 'b: 'a,
301 'c: 'a,
302 I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
303 D: IntoIterator<Item = &'a &'b [u8]>,
304 >(
305 &self,
306 insert: I,
307 delete: D,
308 ) -> sp_blockchain::Result<()>;
309
310 fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>>;
312}
313
314pub struct KeysIter<State, Block>
316where
317 State: StateBackend<HashingFor<Block>>,
318 Block: BlockT,
319{
320 inner: <State as StateBackend<HashingFor<Block>>>::RawIter,
321 state: State,
322}
323
324impl<State, Block> KeysIter<State, Block>
325where
326 State: StateBackend<HashingFor<Block>>,
327 Block: BlockT,
328{
329 pub fn new(
331 state: State,
332 prefix: Option<&StorageKey>,
333 start_at: Option<&StorageKey>,
334 ) -> Result<Self, State::Error> {
335 let mut args = IterArgs::default();
336 args.prefix = prefix.as_ref().map(|prefix| prefix.0.as_slice());
337 args.start_at = start_at.as_ref().map(|start_at| start_at.0.as_slice());
338 args.start_at_exclusive = true;
339
340 Ok(Self { inner: state.raw_iter(args)?, state })
341 }
342
343 pub fn new_child(
345 state: State,
346 child_info: ChildInfo,
347 prefix: Option<&StorageKey>,
348 start_at: Option<&StorageKey>,
349 ) -> Result<Self, State::Error> {
350 let mut args = IterArgs::default();
351 args.prefix = prefix.as_ref().map(|prefix| prefix.0.as_slice());
352 args.start_at = start_at.as_ref().map(|start_at| start_at.0.as_slice());
353 args.child_info = Some(child_info);
354 args.start_at_exclusive = true;
355
356 Ok(Self { inner: state.raw_iter(args)?, state })
357 }
358}
359
360impl<State, Block> Iterator for KeysIter<State, Block>
361where
362 Block: BlockT,
363 State: StateBackend<HashingFor<Block>>,
364{
365 type Item = StorageKey;
366
367 fn next(&mut self) -> Option<Self::Item> {
368 self.inner.next_key(&self.state)?.ok().map(StorageKey)
369 }
370}
371
372pub struct PairsIter<State, Block>
374where
375 State: StateBackend<HashingFor<Block>>,
376 Block: BlockT,
377{
378 inner: <State as StateBackend<HashingFor<Block>>>::RawIter,
379 state: State,
380}
381
382impl<State, Block> Iterator for PairsIter<State, Block>
383where
384 Block: BlockT,
385 State: StateBackend<HashingFor<Block>>,
386{
387 type Item = (StorageKey, StorageData);
388
389 fn next(&mut self) -> Option<Self::Item> {
390 self.inner
391 .next_pair(&self.state)?
392 .ok()
393 .map(|(key, value)| (StorageKey(key), StorageData(value)))
394 }
395}
396
397impl<State, Block> PairsIter<State, Block>
398where
399 State: StateBackend<HashingFor<Block>>,
400 Block: BlockT,
401{
402 pub fn new(
404 state: State,
405 prefix: Option<&StorageKey>,
406 start_at: Option<&StorageKey>,
407 ) -> Result<Self, State::Error> {
408 let mut args = IterArgs::default();
409 args.prefix = prefix.as_ref().map(|prefix| prefix.0.as_slice());
410 args.start_at = start_at.as_ref().map(|start_at| start_at.0.as_slice());
411 args.start_at_exclusive = true;
412
413 Ok(Self { inner: state.raw_iter(args)?, state })
414 }
415}
416
417pub trait StorageProvider<Block: BlockT, B: Backend<Block>> {
419 fn storage(
421 &self,
422 hash: Block::Hash,
423 key: &StorageKey,
424 ) -> sp_blockchain::Result<Option<StorageData>>;
425
426 fn storage_hash(
428 &self,
429 hash: Block::Hash,
430 key: &StorageKey,
431 ) -> sp_blockchain::Result<Option<Block::Hash>>;
432
433 fn storage_keys(
436 &self,
437 hash: Block::Hash,
438 prefix: Option<&StorageKey>,
439 start_key: Option<&StorageKey>,
440 ) -> sp_blockchain::Result<KeysIter<B::State, Block>>;
441
442 fn storage_pairs(
445 &self,
446 hash: <Block as BlockT>::Hash,
447 prefix: Option<&StorageKey>,
448 start_key: Option<&StorageKey>,
449 ) -> sp_blockchain::Result<PairsIter<B::State, Block>>;
450
451 fn child_storage(
454 &self,
455 hash: Block::Hash,
456 child_info: &ChildInfo,
457 key: &StorageKey,
458 ) -> sp_blockchain::Result<Option<StorageData>>;
459
460 fn child_storage_keys(
463 &self,
464 hash: Block::Hash,
465 child_info: ChildInfo,
466 prefix: Option<&StorageKey>,
467 start_key: Option<&StorageKey>,
468 ) -> sp_blockchain::Result<KeysIter<B::State, Block>>;
469
470 fn child_storage_hash(
473 &self,
474 hash: Block::Hash,
475 child_info: &ChildInfo,
476 key: &StorageKey,
477 ) -> sp_blockchain::Result<Option<Block::Hash>>;
478
479 fn closest_merkle_value(
481 &self,
482 hash: Block::Hash,
483 key: &StorageKey,
484 ) -> sp_blockchain::Result<Option<MerkleValue<Block::Hash>>>;
485
486 fn child_closest_merkle_value(
488 &self,
489 hash: Block::Hash,
490 child_info: &ChildInfo,
491 key: &StorageKey,
492 ) -> sp_blockchain::Result<Option<MerkleValue<Block::Hash>>>;
493}
494
495pub trait Backend<Block: BlockT>: AuxStore + Send + Sync {
518 type BlockImportOperation: BlockImportOperation<Block, State = Self::State>;
520 type Blockchain: BlockchainBackend<Block>;
522 type State: StateBackend<HashingFor<Block>>
524 + Send
525 + AsTrieBackend<
526 HashingFor<Block>,
527 TrieBackendStorage = <Self::State as StateBackend<HashingFor<Block>>>::TrieBackendStorage,
528 >;
529 type OffchainStorage: OffchainStorage;
531
532 fn begin_operation(&self) -> sp_blockchain::Result<Self::BlockImportOperation>;
536
537 fn begin_state_operation(
539 &self,
540 operation: &mut Self::BlockImportOperation,
541 block: Block::Hash,
542 ) -> sp_blockchain::Result<()>;
543
544 fn commit_operation(
546 &self,
547 transaction: Self::BlockImportOperation,
548 ) -> sp_blockchain::Result<()>;
549
550 fn finalize_block(
554 &self,
555 hash: Block::Hash,
556 justification: Option<Justification>,
557 ) -> sp_blockchain::Result<()>;
558
559 fn append_justification(
563 &self,
564 hash: Block::Hash,
565 justification: Justification,
566 ) -> sp_blockchain::Result<()>;
567
568 fn blockchain(&self) -> &Self::Blockchain;
570
571 fn usage_info(&self) -> Option<UsageInfo>;
573
574 fn offchain_storage(&self) -> Option<Self::OffchainStorage>;
576
577 fn pin_block(&self, hash: Block::Hash) -> sp_blockchain::Result<()>;
581
582 fn unpin_block(&self, hash: Block::Hash);
584
585 fn have_state_at(&self, hash: Block::Hash, _number: NumberFor<Block>) -> bool {
587 self.state_at(hash).is_ok()
588 }
589
590 fn state_at(&self, hash: Block::Hash) -> sp_blockchain::Result<Self::State>;
592
593 fn revert(
601 &self,
602 n: NumberFor<Block>,
603 revert_finalized: bool,
604 ) -> sp_blockchain::Result<(NumberFor<Block>, HashSet<Block::Hash>)>;
605
606 fn remove_leaf_block(&self, hash: Block::Hash) -> sp_blockchain::Result<()>;
608
609 fn insert_aux<
611 'a,
612 'b: 'a,
613 'c: 'a,
614 I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
615 D: IntoIterator<Item = &'a &'b [u8]>,
616 >(
617 &self,
618 insert: I,
619 delete: D,
620 ) -> sp_blockchain::Result<()> {
621 AuxStore::insert_aux(self, insert, delete)
622 }
623 fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
625 AuxStore::get_aux(self, key)
626 }
627
628 fn get_import_lock(&self) -> &RwLock<()>;
635
636 fn requires_full_sync(&self) -> bool;
638}
639
640pub trait LocalBackend<Block: BlockT>: Backend<Block> {}