1use super::{
22 block_rules::{BlockRules, LookupResult as BlockLookupResult},
23 CodeProvider,
24};
25use crate::client::notification_pinning::NotificationPinningWorker;
26use codec::Encode;
27use log::{debug, info, trace, warn};
28use parking_lot::{Mutex, RwLock};
29use prometheus_endpoint::Registry;
30use rand::Rng;
31use sc_chain_spec::{resolve_state_version_from_wasm, BuildGenesisBlock};
32use sc_client_api::{
33 backend::{
34 self, apply_aux, BlockImportOperation, ClientImportOperation, FinalizeSummary, Finalizer,
35 ImportNotificationAction, ImportSummary, LockImportRun, NewBlockState, StorageProvider,
36 },
37 client::{
38 BadBlocks, BlockBackend, BlockImportNotification, BlockOf, BlockchainEvents, ClientInfo,
39 FinalityNotification, FinalityNotifications, ForkBlocks, ImportNotifications,
40 PreCommitActions, ProvideUncles,
41 },
42 execution_extensions::ExecutionExtensions,
43 notifications::{StorageEventStream, StorageNotifications},
44 CallExecutor, ExecutorProvider, KeysIter, OnFinalityAction, OnImportAction, PairsIter,
45 PrefetchedIndexedTransactions, ProofProvider, StaleBlock, TrieCacheContext, UnpinWorkerMessage,
46 UsageProvider,
47};
48use sc_consensus::{
49 BlockCheckParams, BlockImportParams, ForkChoiceStrategy, ImportResult, StateAction,
50};
51use sc_executor::RuntimeVersion;
52use sc_telemetry::{telemetry, TelemetryHandle, SUBSTRATE_INFO};
53use sp_api::{
54 ApiExt, ApiRef, CallApiAt, CallApiAtParams, ConstructRuntimeApi, Core as CoreApi,
55 ProvideRuntimeApi,
56};
57use sp_blockchain::{
58 self as blockchain, Backend as ChainBackend, CachedHeaderMetadata, Error,
59 HeaderBackend as ChainHeaderBackend, HeaderMetadata, Info as BlockchainInfo,
60};
61use sp_consensus::{BlockOrigin, BlockStatus, Error as ConsensusError};
62
63use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender};
64use sp_core::{
65 storage::{ChildInfo, ChildType, PrefixedStorageKey, StorageChild, StorageData, StorageKey},
66 traits::{CallContext, SpawnNamed},
67 H256,
68};
69use sp_runtime::{
70 generic::{BlockId, SignedBlock},
71 traits::{
72 Block as BlockT, BlockIdTo, Hash as HashT, HashingFor, Header as HeaderT, NumberFor, One,
73 SaturatedConversion, Zero,
74 },
75 Justification, Justifications, StateVersion,
76};
77use sp_state_machine::{
78 prove_child_read, prove_range_read_with_child_with_size, prove_read,
79 read_range_proof_check_with_child_on_proving_backend, Backend as StateBackend,
80 ChildStorageCollection, KeyValueStates, KeyValueStorageLevel, StorageCollection,
81 MAX_NESTED_TRIE_DEPTH,
82};
83use sp_trie::{proof_size_extension::ProofSizeExt, CompactProof, MerkleValue, StorageProof};
84use std::{
85 collections::{HashMap, HashSet},
86 marker::PhantomData,
87 path::PathBuf,
88 sync::Arc,
89 time::Duration,
90};
91
92use super::call_executor::LocalCallExecutor;
93use sp_core::traits::CodeExecutor;
94
95fn check_extrinsics_root<Block: BlockT>(
100 header: &Block::Header,
101 body: &[Block::Extrinsic],
102) -> sp_blockchain::Result<()> {
103 let extrinsics = body.iter().map(Encode::encode).collect::<Vec<_>>();
104 let expected = *header.extrinsics_root();
105 let v0_root = HashingFor::<Block>::ordered_trie_root(extrinsics.clone(), StateVersion::V0);
106
107 if v0_root == expected ||
108 HashingFor::<Block>::ordered_trie_root(extrinsics, StateVersion::V1) == expected
109 {
110 return Ok(());
111 }
112
113 Err(Error::ExtrinsicRootInvalid {
114 received: format!("{v0_root:?}"),
115 expected: format!("{expected:?}"),
116 })
117}
118
119type NotificationSinks<T> = Mutex<Vec<TracingUnboundedSender<T>>>;
120
121pub struct Client<B, E, Block, RA>
123where
124 Block: BlockT,
125{
126 backend: Arc<B>,
127 executor: E,
128 storage_notifications: StorageNotifications<Block>,
129 import_notification_sinks: NotificationSinks<BlockImportNotification<Block>>,
130 every_import_notification_sinks: NotificationSinks<BlockImportNotification<Block>>,
131 finality_notification_sinks: NotificationSinks<FinalityNotification<Block>>,
132 import_actions: Mutex<Vec<OnImportAction<Block>>>,
135 finality_actions: Mutex<Vec<OnFinalityAction<Block>>>,
138 importing_block: RwLock<Option<Block::Hash>>,
140 block_rules: BlockRules<Block>,
141 config: ClientConfig<Block>,
142 telemetry: Option<TelemetryHandle>,
143 unpin_worker_sender: TracingUnboundedSender<UnpinWorkerMessage<Block>>,
144 code_provider: CodeProvider<Block, B, E>,
145 _phantom: PhantomData<RA>,
146}
147
148enum PrePostHeader<H> {
151 Same(H),
153 Different(H, H),
155}
156
157impl<H> PrePostHeader<H> {
158 fn post(&self) -> &H {
161 match *self {
162 PrePostHeader::Same(ref h) => h,
163 PrePostHeader::Different(_, ref h) => h,
164 }
165 }
166
167 fn into_post(self) -> H {
170 match self {
171 PrePostHeader::Same(h) => h,
172 PrePostHeader::Different(_, h) => h,
173 }
174 }
175}
176
177enum PrepareStorageChangesResult<Block: BlockT> {
178 Discard(ImportResult),
179 Import(Option<sc_consensus::StorageChanges<Block>>),
180}
181#[derive(Debug, Clone)]
183pub struct ClientConfig<Block: BlockT> {
184 pub offchain_worker_enabled: bool,
186 pub offchain_indexing_api: bool,
188 pub wasm_runtime_overrides: Option<PathBuf>,
190 pub no_genesis: bool,
192 pub wasm_runtime_substitutes: HashMap<NumberFor<Block>, Vec<u8>>,
195 pub enable_import_proof_recording: bool,
197}
198
199impl<Block: BlockT> Default for ClientConfig<Block> {
200 fn default() -> Self {
201 Self {
202 offchain_worker_enabled: false,
203 offchain_indexing_api: false,
204 wasm_runtime_overrides: None,
205 no_genesis: false,
206 wasm_runtime_substitutes: HashMap::new(),
207 enable_import_proof_recording: false,
208 }
209 }
210}
211
212pub fn new_with_backend<B, E, Block, G, RA>(
215 backend: Arc<B>,
216 executor: E,
217 genesis_block_builder: G,
218 spawn_handle: Box<dyn SpawnNamed>,
219 prometheus_registry: Option<Registry>,
220 telemetry: Option<TelemetryHandle>,
221 config: ClientConfig<Block>,
222) -> sp_blockchain::Result<Client<B, LocalCallExecutor<Block, B, E>, Block, RA>>
223where
224 E: CodeExecutor + sc_executor::RuntimeVersionOf,
225 G: BuildGenesisBlock<
226 Block,
227 BlockImportOperation = <B as backend::Backend<Block>>::BlockImportOperation,
228 >,
229 Block: BlockT,
230 B: backend::LocalBackend<Block> + 'static,
231{
232 let extensions = ExecutionExtensions::new(None, Arc::new(executor.clone()));
233
234 let call_executor =
235 LocalCallExecutor::new(backend.clone(), executor, config.clone(), extensions)?;
236
237 Client::new(
238 backend,
239 call_executor,
240 spawn_handle,
241 genesis_block_builder,
242 Default::default(),
243 Default::default(),
244 prometheus_registry,
245 telemetry,
246 config,
247 )
248}
249
250impl<B, E, Block, RA> BlockOf for Client<B, E, Block, RA>
251where
252 B: backend::Backend<Block>,
253 E: CallExecutor<Block>,
254 Block: BlockT,
255{
256 type Type = Block;
257}
258
259impl<B, E, Block, RA> LockImportRun<Block, B> for Client<B, E, Block, RA>
260where
261 B: backend::Backend<Block>,
262 E: CallExecutor<Block>,
263 Block: BlockT,
264{
265 fn lock_import_and_run<R, Err, F>(&self, f: F) -> Result<R, Err>
266 where
267 F: FnOnce(&mut ClientImportOperation<Block, B>) -> Result<R, Err>,
268 Err: From<sp_blockchain::Error>,
269 {
270 let inner = || {
271 let _import_lock = self.backend.get_import_lock().write();
272
273 let mut op = ClientImportOperation {
274 op: self.backend.begin_operation()?,
275 notify_imported: None,
276 notify_finalized: None,
277 };
278
279 let r = f(&mut op)?;
280
281 let ClientImportOperation { mut op, notify_imported, notify_finalized } = op;
282
283 let finality_notification = notify_finalized.map(|summary| {
284 FinalityNotification::from_summary(summary, self.unpin_worker_sender.clone())
285 });
286
287 let (import_notification, storage_changes, import_notification_action) =
288 match notify_imported {
289 Some(mut summary) => {
290 let import_notification_action = summary.import_notification_action;
291 let storage_changes = summary.storage_changes.take();
292 (
293 Some(BlockImportNotification::from_summary(
294 summary,
295 self.unpin_worker_sender.clone(),
296 )),
297 storage_changes,
298 import_notification_action,
299 )
300 },
301 None => (None, None, ImportNotificationAction::None),
302 };
303
304 if let Some(ref notification) = finality_notification {
305 for action in self.finality_actions.lock().iter_mut() {
306 op.insert_aux(action(notification))?;
307 }
308 }
309 if let Some(ref notification) = import_notification {
310 for action in self.import_actions.lock().iter_mut() {
311 op.insert_aux(action(notification))?;
312 }
313 }
314
315 self.backend.commit_operation(op)?;
316
317 if let Some(ref notification) = finality_notification {
321 if let Err(err) = self.backend.pin_block(notification.hash) {
322 debug!(
323 "Unable to pin block for finality notification. hash: {}, Error: {}",
324 notification.hash, err
325 );
326 } else {
327 let _ = self
328 .unpin_worker_sender
329 .unbounded_send(UnpinWorkerMessage::AnnouncePin(notification.hash))
330 .map_err(|e| {
331 log::error!(
332 "Unable to send AnnouncePin worker message for finality: {e}"
333 )
334 });
335 }
336 }
337
338 if let Some(ref notification) = import_notification {
339 if let Err(err) = self.backend.pin_block(notification.hash) {
340 debug!(
341 "Unable to pin block for import notification. hash: {}, Error: {}",
342 notification.hash, err
343 );
344 } else {
345 let _ = self
346 .unpin_worker_sender
347 .unbounded_send(UnpinWorkerMessage::AnnouncePin(notification.hash))
348 .map_err(|e| {
349 log::error!("Unable to send AnnouncePin worker message for import: {e}")
350 });
351 };
352 }
353
354 self.notify_finalized(finality_notification)?;
355 self.notify_imported(import_notification, import_notification_action, storage_changes)?;
356
357 Ok(r)
358 };
359
360 let result = inner();
361 *self.importing_block.write() = None;
362
363 result
364 }
365}
366
367impl<B, E, Block, RA> LockImportRun<Block, B> for &Client<B, E, Block, RA>
368where
369 Block: BlockT,
370 B: backend::Backend<Block>,
371 E: CallExecutor<Block>,
372{
373 fn lock_import_and_run<R, Err, F>(&self, f: F) -> Result<R, Err>
374 where
375 F: FnOnce(&mut ClientImportOperation<Block, B>) -> Result<R, Err>,
376 Err: From<sp_blockchain::Error>,
377 {
378 (**self).lock_import_and_run(f)
379 }
380}
381
382impl<B, E, Block, RA> Client<B, E, Block, RA>
383where
384 B: backend::Backend<Block>,
385 E: CallExecutor<Block>,
386 Block: BlockT,
387 Block::Header: Clone,
388{
389 pub fn new<G>(
391 backend: Arc<B>,
392 executor: E,
393 spawn_handle: Box<dyn SpawnNamed>,
394 genesis_block_builder: G,
395 fork_blocks: ForkBlocks<Block>,
396 bad_blocks: BadBlocks<Block>,
397 prometheus_registry: Option<Registry>,
398 telemetry: Option<TelemetryHandle>,
399 config: ClientConfig<Block>,
400 ) -> sp_blockchain::Result<Self>
401 where
402 G: BuildGenesisBlock<
403 Block,
404 BlockImportOperation = <B as backend::Backend<Block>>::BlockImportOperation,
405 >,
406 E: Clone,
407 B: 'static,
408 {
409 let info = backend.blockchain().info();
410 if info.finalized_state.is_none() {
411 let (genesis_block, mut op) = genesis_block_builder.build_genesis_block()?;
412 info!(
413 "🔨 Initializing Genesis block/state (state: {}, header-hash: {})",
414 genesis_block.header().state_root(),
415 genesis_block.header().hash()
416 );
417 let block_state = if info.best_hash == Default::default() {
420 NewBlockState::Final
421 } else {
422 NewBlockState::Normal
423 };
424 let (header, body) = genesis_block.deconstruct();
425 op.set_block_data(header, Some(body), None, block_state, true)?;
426 backend.commit_operation(op)?;
427 }
428
429 let (unpin_worker_sender, rx) = tracing_unbounded::<UnpinWorkerMessage<Block>>(
430 "notification-pinning-worker-channel",
431 10_000,
432 );
433 let unpin_worker = NotificationPinningWorker::new(rx, backend.clone());
434 spawn_handle.spawn("notification-pinning-worker", None, Box::pin(unpin_worker.run()));
435 let code_provider = CodeProvider::new(&config, executor.clone(), backend.clone())?;
436
437 Ok(Client {
438 backend,
439 executor,
440 storage_notifications: StorageNotifications::new(prometheus_registry),
441 import_notification_sinks: Default::default(),
442 every_import_notification_sinks: Default::default(),
443 finality_notification_sinks: Default::default(),
444 import_actions: Default::default(),
445 finality_actions: Default::default(),
446 importing_block: Default::default(),
447 block_rules: BlockRules::new(fork_blocks, bad_blocks),
448 config,
449 telemetry,
450 unpin_worker_sender,
451 code_provider,
452 _phantom: Default::default(),
453 })
454 }
455
456 pub fn import_notification_sinks(&self) -> &NotificationSinks<BlockImportNotification<Block>> {
459 &self.import_notification_sinks
460 }
461
462 pub fn finality_notification_sinks(&self) -> &NotificationSinks<FinalityNotification<Block>> {
465 &self.finality_notification_sinks
466 }
467
468 pub fn state_at(&self, hash: Block::Hash) -> sp_blockchain::Result<B::State> {
470 self.backend.state_at(hash, TrieCacheContext::Untrusted)
471 }
472
473 pub fn code_at(&self, hash: Block::Hash) -> sp_blockchain::Result<Vec<u8>> {
477 self.code_provider.code_at_ignoring_overrides(hash)
478 }
479
480 pub fn runtime_version_at(
482 &self,
483 hash: Block::Hash,
484 call_context: CallContext,
485 ) -> sp_blockchain::Result<RuntimeVersion> {
486 CallExecutor::runtime_version(&self.executor, hash, call_context)
487 }
488
489 fn apply_block(
491 &self,
492 operation: &mut ClientImportOperation<Block, B>,
493 import_block: BlockImportParams<Block>,
494 storage_changes: Option<sc_consensus::StorageChanges<Block>>,
495 ) -> sp_blockchain::Result<ImportResult>
496 where
497 Self: ProvideRuntimeApi<Block>,
498 <Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block> + ApiExt<Block>,
499 {
500 let BlockImportParams {
501 origin,
502 header,
503 justifications,
504 post_digests,
505 body,
506 finalized,
507 auxiliary,
508 fork_choice,
509 intermediates,
510 import_existing,
511 create_gap,
512 prefetched_indexed_transactions,
513 ..
514 } = import_block;
515
516 if !intermediates.is_empty() {
517 return Err(Error::IncompletePipeline);
518 }
519
520 let PrefetchedIndexedTransactions { ops: prefetched_index_ops, renew_payloads } =
521 prefetched_indexed_transactions;
522 operation.op.set_renew_payloads(renew_payloads)?;
523 operation.op.update_transaction_index(prefetched_index_ops)?;
524
525 let fork_choice = fork_choice.ok_or(Error::IncompletePipeline)?;
526
527 let import_headers = if post_digests.is_empty() {
528 PrePostHeader::Same(header)
529 } else {
530 let mut post_header = header.clone();
531 for item in post_digests {
532 post_header.digest_mut().push(item);
533 }
534 PrePostHeader::Different(header, post_header)
535 };
536
537 let hash = import_headers.post().hash();
538 let height = (*import_headers.post().number()).saturated_into::<u64>();
539
540 *self.importing_block.write() = Some(hash);
541
542 operation.op.set_create_gap(create_gap);
543
544 let result = self.execute_and_import_block(
545 operation,
546 origin,
547 hash,
548 import_headers,
549 justifications,
550 body,
551 storage_changes,
552 finalized,
553 auxiliary,
554 fork_choice,
555 import_existing,
556 );
557
558 if let Ok(ImportResult::Imported(ref aux)) = result {
559 if aux.is_new_best {
560 if origin != BlockOrigin::NetworkInitialSync || rand::thread_rng().gen_bool(0.1) {
564 telemetry!(
565 self.telemetry;
566 SUBSTRATE_INFO;
567 "block.import";
568 "height" => height,
569 "best" => ?hash,
570 "origin" => ?origin
571 );
572 }
573 }
574 }
575
576 result
577 }
578
579 fn execute_and_import_block(
580 &self,
581 operation: &mut ClientImportOperation<Block, B>,
582 origin: BlockOrigin,
583 hash: Block::Hash,
584 import_headers: PrePostHeader<Block::Header>,
585 justifications: Option<Justifications>,
586 body: Option<Vec<Block::Extrinsic>>,
587 storage_changes: Option<sc_consensus::StorageChanges<Block>>,
588 finalized: bool,
589 aux: Vec<(Vec<u8>, Option<Vec<u8>>)>,
590 fork_choice: ForkChoiceStrategy,
591 import_existing: bool,
592 ) -> sp_blockchain::Result<ImportResult>
593 where
594 Self: ProvideRuntimeApi<Block>,
595 <Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block> + ApiExt<Block>,
596 {
597 let parent_hash = *import_headers.post().parent_hash();
598 let status = self.backend.blockchain().status(hash)?;
599 let parent_exists =
600 self.backend.blockchain().status(parent_hash)? == blockchain::BlockStatus::InChain;
601
602 match (import_existing, status) {
603 (false, blockchain::BlockStatus::InChain) => return Ok(ImportResult::AlreadyInChain),
604 (false, blockchain::BlockStatus::Unknown) => {},
605 (true, blockchain::BlockStatus::InChain) => {},
606 (true, blockchain::BlockStatus::Unknown) => {},
607 }
608
609 let info = self.backend.blockchain().info();
610 let gap_block =
611 info.block_gap.map_or(false, |gap| *import_headers.post().number() == gap.start);
612
613 if status == blockchain::BlockStatus::Unknown &&
616 *import_headers.post().number() <= info.finalized_number &&
617 !gap_block
618 {
619 return Err(sp_blockchain::Error::NotInFinalizedChain);
620 }
621
622 let make_notifications = match origin {
626 BlockOrigin::NetworkBroadcast | BlockOrigin::Own | BlockOrigin::ConsensusBroadcast => {
627 true
628 },
629 BlockOrigin::Genesis |
630 BlockOrigin::NetworkInitialSync |
631 BlockOrigin::File |
632 BlockOrigin::WarpSync |
633 BlockOrigin::GapSync => false,
634 };
635
636 let storage_changes = match storage_changes {
637 Some(sc_consensus::StorageChanges::Changes(storage_changes)) => {
638 self.backend.begin_state_operation(&mut operation.op, parent_hash)?;
639 let (main_sc, child_sc, offchain_sc, tx, _, tx_index) =
640 storage_changes.into_inner();
641
642 if self.config.offchain_indexing_api {
643 operation.op.update_offchain_storage(offchain_sc)?;
644 }
645
646 operation.op.update_db_storage(tx)?;
647 operation.op.update_storage(main_sc.clone(), child_sc.clone())?;
648 operation.op.update_transaction_index(tx_index)?;
649
650 Some((main_sc, child_sc))
651 },
652 Some(sc_consensus::StorageChanges::Import(changes)) => {
653 let mut storage = sp_storage::Storage::default();
654 for state in changes.state.0.into_iter() {
655 if state.parent_storage_keys.is_empty() && state.state_root.is_empty() {
656 for (key, value) in state.key_values.into_iter() {
657 storage.top.insert(key, value);
658 }
659 } else {
660 for parent_storage in state.parent_storage_keys {
661 let storage_key = PrefixedStorageKey::new_ref(&parent_storage);
662 let storage_key = match ChildType::from_prefixed_key(storage_key) {
663 Some((ChildType::ParentKeyId, storage_key)) => storage_key,
664 None => {
665 return Err(Error::Backend(
666 "Invalid child storage key.".to_string(),
667 ))
668 },
669 };
670 let entry = storage
671 .children_default
672 .entry(storage_key.to_vec())
673 .or_insert_with(|| StorageChild {
674 data: Default::default(),
675 child_info: ChildInfo::new_default(storage_key),
676 });
677 for (key, value) in state.key_values.iter() {
678 entry.data.insert(key.clone(), value.clone());
679 }
680 }
681 }
682 }
683
684 let state_version = resolve_state_version_from_wasm::<_, HashingFor<Block>>(
687 &storage,
688 &self.executor,
689 )?;
690 let state_root = operation.op.reset_storage(storage, state_version)?;
691 if state_root != *import_headers.post().state_root() {
692 warn!("Error importing state: State root mismatch.");
695 return Err(Error::InvalidStateRoot);
696 }
697 None
698 },
699 None => None,
700 };
701
702 if finalized && parent_exists && info.finalized_hash != parent_hash {
705 self.apply_finality_with_block_hash(
706 operation,
707 parent_hash,
708 None,
709 &info,
710 make_notifications,
711 )?;
712 }
713
714 let is_new_best = !gap_block &&
715 (finalized ||
716 match fork_choice {
717 ForkChoiceStrategy::LongestChain => {
718 import_headers.post().number() > &info.best_number
719 },
720 ForkChoiceStrategy::Custom(v) => v,
721 });
722
723 let leaf_state = if finalized {
724 NewBlockState::Final
725 } else if is_new_best {
726 NewBlockState::Best
727 } else {
728 NewBlockState::Normal
729 };
730
731 let register_as_leaf = origin != BlockOrigin::WarpSync;
734
735 let tree_route = if is_new_best && info.best_hash != parent_hash && parent_exists {
736 let route_from_best =
737 sp_blockchain::tree_route(self.backend.blockchain(), info.best_hash, parent_hash)?;
738 Some(route_from_best)
739 } else {
740 None
741 };
742
743 trace!(
744 "Imported {}, (#{}), best={}, origin={:?}",
745 hash,
746 import_headers.post().number(),
747 is_new_best,
748 origin,
749 );
750
751 operation.op.set_block_data(
752 import_headers.post().clone(),
753 body,
754 justifications,
755 leaf_state,
756 register_as_leaf,
757 )?;
758
759 operation.op.insert_aux(aux)?;
760
761 let should_notify_every_block = !self.every_import_notification_sinks.lock().is_empty();
762
763 let should_notify_recent_block = make_notifications || tree_route.is_some();
766
767 if should_notify_every_block || should_notify_recent_block {
768 let header = import_headers.into_post();
769 if finalized && should_notify_recent_block {
770 let mut summary = match operation.notify_finalized.take() {
771 Some(mut summary) => {
772 summary.header = header.clone();
773 summary.finalized.push(hash);
774 summary
775 },
776 None => FinalizeSummary {
777 header: header.clone(),
778 finalized: vec![hash],
779 stale_blocks: Vec::new(),
780 },
781 };
782
783 if parent_exists {
784 let stale_heads = self.backend.blockchain().displaced_leaves_after_finalizing(
786 hash,
787 *header.number(),
788 parent_hash,
789 )?;
790
791 summary.stale_blocks.extend(stale_heads.displaced_blocks.into_iter().map(
792 |b| StaleBlock {
793 hash: b,
794 is_head: stale_heads.displaced_leaves.iter().any(|(_, h)| *h == b),
795 },
796 ));
797 }
798 operation.notify_finalized = Some(summary);
799 }
800
801 let import_notification_action = if should_notify_every_block {
802 if should_notify_recent_block {
803 ImportNotificationAction::Both
804 } else {
805 ImportNotificationAction::EveryBlock
806 }
807 } else {
808 ImportNotificationAction::RecentBlock
809 };
810
811 operation.notify_imported = Some(ImportSummary {
812 hash,
813 origin,
814 header,
815 is_new_best,
816 storage_changes,
817 tree_route,
818 import_notification_action,
819 })
820 }
821
822 Ok(ImportResult::imported(is_new_best))
823 }
824
825 fn prepare_block_storage_changes(
831 &self,
832 import_block: &mut BlockImportParams<Block>,
833 ) -> sp_blockchain::Result<PrepareStorageChangesResult<Block>>
834 where
835 Self: ProvideRuntimeApi<Block>,
836 <Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block> + ApiExt<Block>,
837 {
838 let parent_hash = import_block.header.parent_hash();
839 let state_action = std::mem::replace(&mut import_block.state_action, StateAction::Skip);
840 let (enact_state, storage_changes) = match (self.block_status(*parent_hash)?, state_action)
841 {
842 (BlockStatus::KnownBad, _) => {
843 return Ok(PrepareStorageChangesResult::Discard(ImportResult::KnownBad))
844 },
845 (
846 BlockStatus::InChainPruned,
847 StateAction::ApplyChanges(sc_consensus::StorageChanges::Changes(_)),
848 ) => return Ok(PrepareStorageChangesResult::Discard(ImportResult::MissingState)),
849 (_, StateAction::ApplyChanges(changes)) => (true, Some(changes)),
850 (_, StateAction::Skip) => (false, None),
851 (BlockStatus::Unknown, _) => {
852 return Ok(PrepareStorageChangesResult::Discard(ImportResult::UnknownParent))
853 },
854 (BlockStatus::InChainPruned, StateAction::Execute) => {
855 return Ok(PrepareStorageChangesResult::Discard(ImportResult::MissingState))
856 },
857 (BlockStatus::InChainPruned, StateAction::ExecuteIfPossible) => (false, None),
858 (_, StateAction::Execute) => (true, None),
859 (_, StateAction::ExecuteIfPossible) => (true, None),
860 };
861
862 let execute = enact_state && storage_changes.is_none();
864 if let (false, Some(body)) = (execute, &import_block.body) {
865 check_extrinsics_root::<Block>(&import_block.header, body)?;
866 }
867
868 let storage_changes = match (enact_state, storage_changes, &import_block.body) {
869 (true, changes @ Some(_), _) => changes,
872 (true, None, Some(ref body)) => {
875 let mut runtime_api = self.runtime_api();
876 let call_context = CallContext::Onchain { import: true };
877 runtime_api.set_call_context(call_context);
878
879 if self.config.enable_import_proof_recording {
880 runtime_api.record_proof();
881 let recorder = runtime_api
882 .proof_recorder()
883 .expect("Proof recording is enabled in the line above; qed.");
884 runtime_api.register_extension(ProofSizeExt::new(recorder));
885 }
886
887 runtime_api.execute_block(
888 *parent_hash,
889 Block::new(import_block.header.clone(), body.clone()).into(),
890 )?;
891
892 let state = self.backend.state_at(*parent_hash, call_context.into())?;
893 let gen_storage_changes = runtime_api
894 .into_storage_changes(&state, *parent_hash)
895 .map_err(sp_blockchain::Error::Storage)?;
896
897 if import_block.header.state_root() != &gen_storage_changes.transaction_storage_root
898 {
899 return Err(Error::InvalidStateRoot);
900 }
901 Some(sc_consensus::StorageChanges::Changes(gen_storage_changes))
902 },
903 (true, None, None) => None,
905 (false, _, _) => None,
907 };
908
909 Ok(PrepareStorageChangesResult::Import(storage_changes))
910 }
911
912 fn apply_finality_with_block_hash(
913 &self,
914 operation: &mut ClientImportOperation<Block, B>,
915 hash: Block::Hash,
916 justification: Option<Justification>,
917 info: &BlockchainInfo<Block>,
918 notify: bool,
919 ) -> sp_blockchain::Result<()> {
920 if hash == info.finalized_hash {
921 warn!(
922 "Possible safety violation: attempted to re-finalize last finalized block {:?} ",
923 hash,
924 );
925 return Ok(());
926 }
927
928 let route_from_finalized =
930 sp_blockchain::tree_route(self.backend.blockchain(), info.finalized_hash, hash)?;
931
932 if let Some(retracted) = route_from_finalized.retracted().get(0) {
933 warn!(
934 "Safety violation: attempted to revert finalized block {:?} which is not in the \
935 same chain as last finalized {:?}",
936 retracted, info.finalized_hash
937 );
938
939 return Err(sp_blockchain::Error::NotInFinalizedChain);
940 }
941
942 let block_number = self
947 .backend
948 .blockchain()
949 .number(hash)?
950 .ok_or(Error::MissingHeader(format!("{hash:?}")))?;
951 if self.backend.blockchain().leaves()?.len() > 1 || info.best_number < block_number {
952 let route_from_best =
953 sp_blockchain::tree_route(self.backend.blockchain(), info.best_hash, hash)?;
954
955 if route_from_best.common_block().hash != hash {
958 operation.op.mark_head(hash)?;
965 }
966 }
967
968 let enacted = route_from_finalized.enacted();
969 assert!(enacted.len() > 0);
970 for finalize_new in &enacted[..enacted.len() - 1] {
971 operation.op.mark_finalized(finalize_new.hash, None)?;
972 }
973
974 assert_eq!(enacted.last().map(|e| e.hash), Some(hash));
975 operation.op.mark_finalized(hash, justification)?;
976
977 if notify {
978 let finalized =
979 route_from_finalized.enacted().iter().map(|elem| elem.hash).collect::<Vec<_>>();
980
981 let header = self
982 .backend
983 .blockchain()
984 .header(hash)?
985 .expect("Block to finalize expected to be onchain; qed");
986 let block_number = *header.number();
987
988 let mut stale_blocks = Vec::new();
990
991 let stale_heads = self.backend.blockchain().displaced_leaves_after_finalizing(
992 hash,
993 block_number,
994 *header.parent_hash(),
995 )?;
996
997 stale_blocks.extend(stale_heads.displaced_blocks.into_iter().map(|b| StaleBlock {
998 hash: b,
999 is_head: stale_heads.displaced_leaves.iter().any(|(_, h)| *h == b),
1000 }));
1001
1002 operation.notify_finalized = Some(FinalizeSummary { header, finalized, stale_blocks });
1003 }
1004
1005 Ok(())
1006 }
1007
1008 fn notify_finalized(
1009 &self,
1010 notification: Option<FinalityNotification<Block>>,
1011 ) -> sp_blockchain::Result<()> {
1012 let mut sinks = self.finality_notification_sinks.lock();
1013
1014 let notification = match notification {
1015 Some(notify_finalized) => notify_finalized,
1016 None => {
1017 sinks.retain(|sink| !sink.is_closed());
1021 return Ok(());
1022 },
1023 };
1024
1025 telemetry!(
1026 self.telemetry;
1027 SUBSTRATE_INFO;
1028 "notify.finalized";
1029 "height" => format!("{}", notification.header.number()),
1030 "best" => ?notification.hash,
1031 );
1032
1033 sinks.retain(|sink| sink.unbounded_send(notification.clone()).is_ok());
1034
1035 Ok(())
1036 }
1037
1038 fn notify_imported(
1039 &self,
1040 notification: Option<BlockImportNotification<Block>>,
1041 import_notification_action: ImportNotificationAction,
1042 storage_changes: Option<(StorageCollection, ChildStorageCollection)>,
1043 ) -> sp_blockchain::Result<()> {
1044 let notification = match notification {
1045 Some(notify_import) => notify_import,
1046 None => {
1047 self.import_notification_sinks.lock().retain(|sink| !sink.is_closed());
1054
1055 self.every_import_notification_sinks.lock().retain(|sink| !sink.is_closed());
1056
1057 return Ok(());
1058 },
1059 };
1060
1061 let trigger_storage_changes_notification = || {
1062 if let Some(storage_changes) = storage_changes {
1063 self.storage_notifications.trigger(
1065 ¬ification.hash,
1066 storage_changes.0.into_iter(),
1067 storage_changes.1.into_iter().map(|(sk, v)| (sk, v.into_iter())),
1068 );
1069 }
1070 };
1071
1072 match import_notification_action {
1073 ImportNotificationAction::Both => {
1074 trigger_storage_changes_notification();
1075 self.import_notification_sinks
1076 .lock()
1077 .retain(|sink| sink.unbounded_send(notification.clone()).is_ok());
1078
1079 self.every_import_notification_sinks
1080 .lock()
1081 .retain(|sink| sink.unbounded_send(notification.clone()).is_ok());
1082 },
1083 ImportNotificationAction::RecentBlock => {
1084 trigger_storage_changes_notification();
1085 self.import_notification_sinks
1086 .lock()
1087 .retain(|sink| sink.unbounded_send(notification.clone()).is_ok());
1088
1089 self.every_import_notification_sinks.lock().retain(|sink| !sink.is_closed());
1090 },
1091 ImportNotificationAction::EveryBlock => {
1092 self.every_import_notification_sinks
1093 .lock()
1094 .retain(|sink| sink.unbounded_send(notification.clone()).is_ok());
1095
1096 self.import_notification_sinks.lock().retain(|sink| !sink.is_closed());
1097 },
1098 ImportNotificationAction::None => {
1099 self.import_notification_sinks.lock().retain(|sink| !sink.is_closed());
1103
1104 self.every_import_notification_sinks.lock().retain(|sink| !sink.is_closed());
1105 },
1106 }
1107
1108 Ok(())
1109 }
1110
1111 pub fn revert(&self, n: NumberFor<Block>) -> sp_blockchain::Result<NumberFor<Block>> {
1115 let (number, _) = self.backend.revert(n, false)?;
1116 Ok(number)
1117 }
1118
1119 pub fn unsafe_revert(
1129 &mut self,
1130 n: NumberFor<Block>,
1131 blacklist: bool,
1132 ) -> sp_blockchain::Result<NumberFor<Block>> {
1133 let (number, reverted) = self.backend.revert(n, true)?;
1134 if blacklist {
1135 for b in reverted {
1136 self.block_rules.mark_bad(b);
1137 }
1138 }
1139 Ok(number)
1140 }
1141
1142 pub fn chain_info(&self) -> BlockchainInfo<Block> {
1144 self.backend.blockchain().info()
1145 }
1146
1147 pub fn block_status(&self, hash: Block::Hash) -> sp_blockchain::Result<BlockStatus> {
1149 if self
1151 .importing_block
1152 .read()
1153 .as_ref()
1154 .map_or(false, |importing| &hash == importing)
1155 {
1156 return Ok(BlockStatus::Queued);
1157 }
1158
1159 let hash_and_number = self.backend.blockchain().number(hash)?.map(|n| (hash, n));
1160 match hash_and_number {
1161 Some((hash, number)) => {
1162 if self.backend.have_state_at(hash, number) {
1163 Ok(BlockStatus::InChainWithState)
1164 } else {
1165 Ok(BlockStatus::InChainPruned)
1166 }
1167 },
1168 None => Ok(BlockStatus::Unknown),
1169 }
1170 }
1171
1172 pub fn header(
1174 &self,
1175 hash: Block::Hash,
1176 ) -> sp_blockchain::Result<Option<<Block as BlockT>::Header>> {
1177 self.backend.blockchain().header(hash)
1178 }
1179
1180 pub fn body(
1182 &self,
1183 hash: Block::Hash,
1184 ) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
1185 self.backend.blockchain().body(hash)
1186 }
1187
1188 pub fn uncles(
1190 &self,
1191 target_hash: Block::Hash,
1192 max_generation: NumberFor<Block>,
1193 ) -> sp_blockchain::Result<Vec<Block::Hash>> {
1194 let load_header = |hash: Block::Hash| -> sp_blockchain::Result<Block::Header> {
1195 self.backend
1196 .blockchain()
1197 .header(hash)?
1198 .ok_or_else(|| Error::UnknownBlock(format!("{:?}", hash)))
1199 };
1200
1201 let genesis_hash = self.backend.blockchain().info().genesis_hash;
1202 if genesis_hash == target_hash {
1203 return Ok(Vec::new());
1204 }
1205
1206 let mut current_hash = target_hash;
1207 let mut current = load_header(current_hash)?;
1208 let mut ancestor_hash = *current.parent_hash();
1209 let mut ancestor = load_header(ancestor_hash)?;
1210 let mut uncles = Vec::new();
1211
1212 let mut generation: NumberFor<Block> = Zero::zero();
1213 while generation < max_generation {
1214 let children = self.backend.blockchain().children(ancestor_hash)?;
1215 uncles.extend(children.into_iter().filter(|h| h != ¤t_hash));
1216 current_hash = ancestor_hash;
1217
1218 if genesis_hash == current_hash {
1219 break;
1220 }
1221
1222 current = ancestor;
1223 ancestor_hash = *current.parent_hash();
1224 ancestor = load_header(ancestor_hash)?;
1225 generation += One::one();
1226 }
1227 trace!("Collected {} uncles", uncles.len());
1228 Ok(uncles)
1229 }
1230}
1231
1232impl<B, E, Block, RA> UsageProvider<Block> for Client<B, E, Block, RA>
1233where
1234 B: backend::Backend<Block>,
1235 E: CallExecutor<Block>,
1236 Block: BlockT,
1237{
1238 fn usage_info(&self) -> ClientInfo<Block> {
1240 ClientInfo { chain: self.chain_info(), usage: self.backend.usage_info() }
1241 }
1242}
1243
1244impl<B, E, Block, RA> ProofProvider<Block> for Client<B, E, Block, RA>
1245where
1246 B: backend::Backend<Block>,
1247 E: CallExecutor<Block>,
1248 Block: BlockT,
1249{
1250 fn read_proof(
1251 &self,
1252 hash: Block::Hash,
1253 keys: &mut dyn Iterator<Item = &[u8]>,
1254 ) -> sp_blockchain::Result<StorageProof> {
1255 self.state_at(hash)
1256 .and_then(|state| prove_read(state, keys).map_err(Into::into))
1257 }
1258
1259 fn read_child_proof(
1260 &self,
1261 hash: Block::Hash,
1262 child_info: &ChildInfo,
1263 keys: &mut dyn Iterator<Item = &[u8]>,
1264 ) -> sp_blockchain::Result<StorageProof> {
1265 self.state_at(hash)
1266 .and_then(|state| prove_child_read(state, child_info, keys).map_err(Into::into))
1267 }
1268
1269 fn execution_proof(
1270 &self,
1271 hash: Block::Hash,
1272 method: &str,
1273 call_data: &[u8],
1274 timeout: Option<Duration>,
1275 ) -> sp_blockchain::Result<(Vec<u8>, StorageProof)> {
1276 self.executor.prove_execution(hash, method, call_data, timeout)
1277 }
1278
1279 fn read_proof_collection(
1280 &self,
1281 hash: Block::Hash,
1282 start_key: &[Vec<u8>],
1283 size_limit: usize,
1284 ) -> sp_blockchain::Result<(CompactProof, u32)> {
1285 let state = self.state_at(hash)?;
1286 let root = state.storage_root(std::iter::empty(), StateVersion::V0).0;
1288
1289 let (proof, count) = prove_range_read_with_child_with_size::<_, HashingFor<Block>>(
1290 state, size_limit, start_key,
1291 )?;
1292 let proof = proof
1293 .into_compact_proof::<HashingFor<Block>>(root)
1294 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?;
1295 Ok((proof, count))
1296 }
1297
1298 fn storage_collection(
1299 &self,
1300 hash: Block::Hash,
1301 start_key: &[Vec<u8>],
1302 size_limit: usize,
1303 ) -> sp_blockchain::Result<Vec<(KeyValueStorageLevel, bool)>> {
1304 if start_key.len() > MAX_NESTED_TRIE_DEPTH {
1305 return Err(Error::Backend("Invalid start key.".to_string()));
1306 }
1307 let state = self.state_at(hash)?;
1308 let child_info = |storage_key: &Vec<u8>| -> sp_blockchain::Result<ChildInfo> {
1309 let storage_key = PrefixedStorageKey::new_ref(storage_key);
1310 match ChildType::from_prefixed_key(storage_key) {
1311 Some((ChildType::ParentKeyId, storage_key)) => {
1312 Ok(ChildInfo::new_default(storage_key))
1313 },
1314 None => Err(Error::Backend("Invalid child storage key.".to_string())),
1315 }
1316 };
1317 let mut current_child = if start_key.len() == 2 {
1318 let start_key = start_key.get(0).expect("checked len");
1319 if let Some(child_root) = state
1320 .storage(start_key)
1321 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
1322 {
1323 Some((child_info(start_key)?, child_root))
1324 } else {
1325 return Err(Error::Backend("Invalid root start key.".to_string()));
1326 }
1327 } else {
1328 None
1329 };
1330 let mut current_key = start_key.last().map(Clone::clone).unwrap_or_default();
1331 let mut total_size = 0;
1332 let mut result = vec![(
1333 KeyValueStorageLevel {
1334 state_root: Vec::new(),
1335 key_values: Vec::new(),
1336 parent_storage_keys: Vec::new(),
1337 },
1338 false,
1339 )];
1340
1341 let mut child_roots = HashSet::new();
1342 loop {
1343 let mut entries = Vec::new();
1344 let mut complete = true;
1345 let mut switch_child_key = None;
1346 while let Some(next_key) = if let Some(child) = current_child.as_ref() {
1347 state
1348 .next_child_storage_key(&child.0, ¤t_key)
1349 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
1350 } else {
1351 state
1352 .next_storage_key(¤t_key)
1353 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
1354 } {
1355 let value = if let Some(child) = current_child.as_ref() {
1356 state
1357 .child_storage(&child.0, next_key.as_ref())
1358 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
1359 .unwrap_or_default()
1360 } else {
1361 state
1362 .storage(next_key.as_ref())
1363 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
1364 .unwrap_or_default()
1365 };
1366 let size = value.len() + next_key.len();
1367 if total_size + size > size_limit && !entries.is_empty() {
1368 complete = false;
1369 break;
1370 }
1371 total_size += size;
1372
1373 if current_child.is_none() &&
1374 sp_core::storage::well_known_keys::is_child_storage_key(next_key.as_slice()) &&
1375 !child_roots.contains(value.as_slice())
1376 {
1377 child_roots.insert(value.clone());
1378 switch_child_key = Some((next_key.clone(), value.clone()));
1379 entries.push((next_key.clone(), value));
1380 break;
1381 }
1382 entries.push((next_key.clone(), value));
1383 current_key = next_key;
1384 }
1385 if let Some((child, child_root)) = switch_child_key.take() {
1386 result[0].0.key_values.extend(entries.into_iter());
1387 current_child = Some((child_info(&child)?, child_root));
1388 current_key = Vec::new();
1389 } else if let Some((child, child_root)) = current_child.take() {
1390 current_key = child.into_prefixed_storage_key().into_inner();
1391 result.push((
1392 KeyValueStorageLevel {
1393 state_root: child_root,
1394 key_values: entries,
1395 parent_storage_keys: Vec::new(),
1396 },
1397 complete,
1398 ));
1399 if !complete {
1400 break;
1401 }
1402 } else {
1403 result[0].0.key_values.extend(entries.into_iter());
1404 result[0].1 = complete;
1405 break;
1406 }
1407 }
1408 Ok(result)
1409 }
1410
1411 fn verify_range_proof(
1412 &self,
1413 root: Block::Hash,
1414 proof: CompactProof,
1415 start_key: &[Vec<u8>],
1416 ) -> sp_blockchain::Result<(KeyValueStates, usize)> {
1417 let mut db = sp_state_machine::MemoryDB::<HashingFor<Block>>::new(&[]);
1418 sp_trie::decode_compact::<sp_state_machine::LayoutV0<HashingFor<Block>>, _, _>(
1420 &mut db,
1421 proof.iter_compact_encoded_nodes(),
1422 &root,
1423 )
1424 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?;
1425 let proving_backend = sp_state_machine::TrieBackendBuilder::new(db, root).build();
1426 let state = read_range_proof_check_with_child_on_proving_backend::<HashingFor<Block>>(
1427 &proving_backend,
1428 start_key,
1429 )?;
1430
1431 Ok(state)
1432 }
1433}
1434
1435impl<B, E, Block, RA> ExecutorProvider<Block> for Client<B, E, Block, RA>
1436where
1437 B: backend::Backend<Block>,
1438 E: CallExecutor<Block>,
1439 Block: BlockT,
1440{
1441 type Executor = E;
1442
1443 fn executor(&self) -> &Self::Executor {
1444 &self.executor
1445 }
1446
1447 fn execution_extensions(&self) -> &ExecutionExtensions<Block> {
1448 self.executor.execution_extensions()
1449 }
1450}
1451
1452impl<B, E, Block, RA> StorageProvider<Block, B> for Client<B, E, Block, RA>
1453where
1454 B: backend::Backend<Block>,
1455 E: CallExecutor<Block>,
1456 Block: BlockT,
1457{
1458 fn storage_keys(
1459 &self,
1460 hash: <Block as BlockT>::Hash,
1461 prefix: Option<&StorageKey>,
1462 start_key: Option<&StorageKey>,
1463 ) -> sp_blockchain::Result<KeysIter<B::State, Block>> {
1464 let state = self.state_at(hash)?;
1465 KeysIter::new(state, prefix, start_key)
1466 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))
1467 }
1468
1469 fn child_storage_keys(
1470 &self,
1471 hash: <Block as BlockT>::Hash,
1472 child_info: ChildInfo,
1473 prefix: Option<&StorageKey>,
1474 start_key: Option<&StorageKey>,
1475 ) -> sp_blockchain::Result<KeysIter<B::State, Block>> {
1476 let state = self.state_at(hash)?;
1477 KeysIter::new_child(state, child_info, prefix, start_key)
1478 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))
1479 }
1480
1481 fn storage_pairs(
1482 &self,
1483 hash: <Block as BlockT>::Hash,
1484 prefix: Option<&StorageKey>,
1485 start_key: Option<&StorageKey>,
1486 ) -> sp_blockchain::Result<PairsIter<B::State, Block>> {
1487 let state = self.state_at(hash)?;
1488 PairsIter::new(state, prefix, start_key)
1489 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))
1490 }
1491
1492 fn storage(
1493 &self,
1494 hash: Block::Hash,
1495 key: &StorageKey,
1496 ) -> sp_blockchain::Result<Option<StorageData>> {
1497 Ok(self
1498 .state_at(hash)?
1499 .storage(&key.0)
1500 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
1501 .map(StorageData))
1502 }
1503
1504 fn storage_hash(
1505 &self,
1506 hash: <Block as BlockT>::Hash,
1507 key: &StorageKey,
1508 ) -> sp_blockchain::Result<Option<Block::Hash>> {
1509 self.state_at(hash)?
1510 .storage_hash(&key.0)
1511 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))
1512 }
1513
1514 fn child_storage(
1515 &self,
1516 hash: <Block as BlockT>::Hash,
1517 child_info: &ChildInfo,
1518 key: &StorageKey,
1519 ) -> sp_blockchain::Result<Option<StorageData>> {
1520 Ok(self
1521 .state_at(hash)?
1522 .child_storage(child_info, &key.0)
1523 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?
1524 .map(StorageData))
1525 }
1526
1527 fn child_storage_hash(
1528 &self,
1529 hash: <Block as BlockT>::Hash,
1530 child_info: &ChildInfo,
1531 key: &StorageKey,
1532 ) -> sp_blockchain::Result<Option<Block::Hash>> {
1533 self.state_at(hash)?
1534 .child_storage_hash(child_info, &key.0)
1535 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))
1536 }
1537
1538 fn closest_merkle_value(
1539 &self,
1540 hash: <Block as BlockT>::Hash,
1541 key: &StorageKey,
1542 ) -> blockchain::Result<Option<MerkleValue<<Block as BlockT>::Hash>>> {
1543 self.state_at(hash)?
1544 .closest_merkle_value(&key.0)
1545 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))
1546 }
1547
1548 fn child_closest_merkle_value(
1549 &self,
1550 hash: <Block as BlockT>::Hash,
1551 child_info: &ChildInfo,
1552 key: &StorageKey,
1553 ) -> blockchain::Result<Option<MerkleValue<<Block as BlockT>::Hash>>> {
1554 self.state_at(hash)?
1555 .child_closest_merkle_value(child_info, &key.0)
1556 .map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))
1557 }
1558}
1559
1560impl<B, E, Block, RA> HeaderMetadata<Block> for Client<B, E, Block, RA>
1561where
1562 B: backend::Backend<Block>,
1563 E: CallExecutor<Block>,
1564 Block: BlockT,
1565{
1566 type Error = sp_blockchain::Error;
1567
1568 fn header_metadata(
1569 &self,
1570 hash: Block::Hash,
1571 ) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
1572 self.backend.blockchain().header_metadata(hash)
1573 }
1574
1575 fn insert_header_metadata(&self, hash: Block::Hash, metadata: CachedHeaderMetadata<Block>) {
1576 self.backend.blockchain().insert_header_metadata(hash, metadata)
1577 }
1578
1579 fn remove_header_metadata(&self, hash: Block::Hash) {
1580 self.backend.blockchain().remove_header_metadata(hash)
1581 }
1582}
1583
1584impl<B, E, Block, RA> ProvideUncles<Block> for Client<B, E, Block, RA>
1585where
1586 B: backend::Backend<Block>,
1587 E: CallExecutor<Block>,
1588 Block: BlockT,
1589{
1590 fn uncles(
1591 &self,
1592 target_hash: Block::Hash,
1593 max_generation: NumberFor<Block>,
1594 ) -> sp_blockchain::Result<Vec<Block::Header>> {
1595 Ok(Client::uncles(self, target_hash, max_generation)?
1596 .into_iter()
1597 .filter_map(|hash| Client::header(self, hash).unwrap_or(None))
1598 .collect())
1599 }
1600}
1601
1602impl<B, E, Block, RA> ChainHeaderBackend<Block> for Client<B, E, Block, RA>
1603where
1604 B: backend::Backend<Block>,
1605 E: CallExecutor<Block> + Send + Sync,
1606 Block: BlockT,
1607 RA: Send + Sync,
1608{
1609 fn header(&self, hash: Block::Hash) -> sp_blockchain::Result<Option<Block::Header>> {
1610 self.backend.blockchain().header(hash)
1611 }
1612
1613 fn info(&self) -> blockchain::Info<Block> {
1614 self.backend.blockchain().info()
1615 }
1616
1617 fn status(&self, hash: Block::Hash) -> sp_blockchain::Result<blockchain::BlockStatus> {
1618 self.backend.blockchain().status(hash)
1619 }
1620
1621 fn number(
1622 &self,
1623 hash: Block::Hash,
1624 ) -> sp_blockchain::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
1625 self.backend.blockchain().number(hash)
1626 }
1627
1628 fn hash(&self, number: NumberFor<Block>) -> sp_blockchain::Result<Option<Block::Hash>> {
1629 self.backend.blockchain().hash(number)
1630 }
1631}
1632
1633impl<B, E, Block, RA> BlockIdTo<Block> for Client<B, E, Block, RA>
1634where
1635 B: backend::Backend<Block>,
1636 E: CallExecutor<Block> + Send + Sync,
1637 Block: BlockT,
1638 RA: Send + Sync,
1639{
1640 type Error = Error;
1641
1642 fn to_hash(&self, block_id: &BlockId<Block>) -> sp_blockchain::Result<Option<Block::Hash>> {
1643 self.block_hash_from_id(block_id)
1644 }
1645
1646 fn to_number(
1647 &self,
1648 block_id: &BlockId<Block>,
1649 ) -> sp_blockchain::Result<Option<NumberFor<Block>>> {
1650 self.block_number_from_id(block_id)
1651 }
1652}
1653
1654impl<B, E, Block, RA> ChainHeaderBackend<Block> for &Client<B, E, Block, RA>
1655where
1656 B: backend::Backend<Block>,
1657 E: CallExecutor<Block> + Send + Sync,
1658 Block: BlockT,
1659 RA: Send + Sync,
1660{
1661 fn header(&self, hash: Block::Hash) -> sp_blockchain::Result<Option<Block::Header>> {
1662 self.backend.blockchain().header(hash)
1663 }
1664
1665 fn info(&self) -> blockchain::Info<Block> {
1666 self.backend.blockchain().info()
1667 }
1668
1669 fn status(&self, hash: Block::Hash) -> sp_blockchain::Result<blockchain::BlockStatus> {
1670 (**self).status(hash)
1671 }
1672
1673 fn number(
1674 &self,
1675 hash: Block::Hash,
1676 ) -> sp_blockchain::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>> {
1677 (**self).number(hash)
1678 }
1679
1680 fn hash(&self, number: NumberFor<Block>) -> sp_blockchain::Result<Option<Block::Hash>> {
1681 (**self).hash(number)
1682 }
1683}
1684
1685impl<B, E, Block, RA> ProvideRuntimeApi<Block> for Client<B, E, Block, RA>
1686where
1687 B: backend::Backend<Block>,
1688 E: CallExecutor<Block, Backend = B> + Send + Sync,
1689 Block: BlockT,
1690 RA: ConstructRuntimeApi<Block, Self> + Send + Sync,
1691{
1692 type Api = <RA as ConstructRuntimeApi<Block, Self>>::RuntimeApi;
1693
1694 fn runtime_api(&self) -> ApiRef<'_, Self::Api> {
1695 RA::construct_runtime_api(self)
1696 }
1697}
1698
1699impl<B, E, Block, RA> CallApiAt<Block> for Client<B, E, Block, RA>
1700where
1701 B: backend::Backend<Block>,
1702 E: CallExecutor<Block, Backend = B> + Send + Sync,
1703 Block: BlockT,
1704 RA: Send + Sync,
1705{
1706 type StateBackend = B::State;
1707
1708 fn call_api_at(&self, params: CallApiAtParams<Block>) -> Result<Vec<u8>, sp_api::ApiError> {
1709 self.executor
1710 .contextual_call(
1711 params.at,
1712 params.function,
1713 ¶ms.arguments,
1714 params.overlayed_changes,
1715 params.recorder,
1716 params.call_context,
1717 params.extensions,
1718 )
1719 .map_err(Into::into)
1720 }
1721
1722 fn runtime_version_at(
1723 &self,
1724 hash: Block::Hash,
1725 call_context: CallContext,
1726 ) -> Result<RuntimeVersion, sp_api::ApiError> {
1727 CallExecutor::runtime_version(&self.executor, hash, call_context).map_err(Into::into)
1728 }
1729
1730 fn state_at(&self, at: Block::Hash) -> Result<Self::StateBackend, sp_api::ApiError> {
1731 self.state_at(at).map_err(Into::into)
1732 }
1733
1734 fn initialize_extensions(
1735 &self,
1736 at: Block::Hash,
1737 extensions: &mut sp_externalities::Extensions,
1738 ) -> Result<(), sp_api::ApiError> {
1739 let block_number = self.expect_block_number_from_id(&BlockId::Hash(at))?;
1740
1741 extensions.merge(self.executor.execution_extensions().extensions(at, block_number));
1742
1743 Ok(())
1744 }
1745}
1746
1747#[async_trait::async_trait]
1751impl<B, E, Block, RA> sc_consensus::BlockImport<Block> for &Client<B, E, Block, RA>
1752where
1753 B: backend::Backend<Block>,
1754 E: CallExecutor<Block> + Send + Sync,
1755 Block: BlockT,
1756 Client<B, E, Block, RA>: ProvideRuntimeApi<Block>,
1757 <Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api: CoreApi<Block> + ApiExt<Block>,
1758 RA: Sync + Send,
1759{
1760 type Error = ConsensusError;
1761
1762 async fn import_block(
1771 &self,
1772 mut import_block: BlockImportParams<Block>,
1773 ) -> Result<ImportResult, Self::Error> {
1774 let span = tracing::span!(tracing::Level::DEBUG, "import_block");
1775 let _enter = span.enter();
1776
1777 let storage_changes =
1778 match self.prepare_block_storage_changes(&mut import_block).map_err(|e| {
1779 warn!("Block prepare storage changes error: {}", e);
1780 ConsensusError::ClientImport(e.to_string())
1781 })? {
1782 PrepareStorageChangesResult::Discard(res) => return Ok(res),
1783 PrepareStorageChangesResult::Import(storage_changes) => storage_changes,
1784 };
1785
1786 self.lock_import_and_run(|operation| {
1787 self.apply_block(operation, import_block, storage_changes)
1788 })
1789 .map_err(|e| {
1790 warn!("Block import error: {}", e);
1791 ConsensusError::ClientImport(e.to_string())
1792 })
1793 }
1794
1795 async fn check_block(
1797 &self,
1798 block: BlockCheckParams<Block>,
1799 ) -> Result<ImportResult, Self::Error> {
1800 let BlockCheckParams {
1801 hash,
1802 number,
1803 parent_hash,
1804 allow_missing_state,
1805 import_existing,
1806 allow_missing_parent,
1807 } = block;
1808
1809 match self.block_rules.lookup(number, &hash) {
1812 BlockLookupResult::KnownBad => {
1813 trace!("Rejecting known bad block: #{} {:?}", number, hash);
1814 return Ok(ImportResult::KnownBad);
1815 },
1816 BlockLookupResult::Expected(expected_hash) => {
1817 trace!(
1818 "Rejecting block from known invalid fork. Got {:?}, expected: {:?} at height {}",
1819 hash,
1820 expected_hash,
1821 number
1822 );
1823 return Ok(ImportResult::KnownBad);
1824 },
1825 BlockLookupResult::NotSpecial => {},
1826 }
1827
1828 match self
1831 .block_status(hash)
1832 .map_err(|e| ConsensusError::ClientImport(e.to_string()))?
1833 {
1834 BlockStatus::InChainWithState | BlockStatus::Queued => {
1835 return Ok(ImportResult::AlreadyInChain)
1836 },
1837 BlockStatus::InChainPruned if !import_existing => {
1838 return Ok(ImportResult::AlreadyInChain)
1839 },
1840 BlockStatus::InChainPruned => {},
1841 BlockStatus::Unknown => {},
1842 BlockStatus::KnownBad => return Ok(ImportResult::KnownBad),
1843 }
1844
1845 match self
1846 .block_status(parent_hash)
1847 .map_err(|e| ConsensusError::ClientImport(e.to_string()))?
1848 {
1849 BlockStatus::InChainWithState | BlockStatus::Queued => {},
1850 BlockStatus::Unknown if allow_missing_parent => {},
1851 BlockStatus::Unknown => return Ok(ImportResult::UnknownParent),
1852 BlockStatus::InChainPruned if allow_missing_state => {},
1853 BlockStatus::InChainPruned => return Ok(ImportResult::MissingState),
1854 BlockStatus::KnownBad => return Ok(ImportResult::KnownBad),
1855 }
1856
1857 Ok(ImportResult::imported(false))
1858 }
1859}
1860
1861#[async_trait::async_trait]
1862impl<B, E, Block, RA> sc_consensus::BlockImport<Block> for Client<B, E, Block, RA>
1863where
1864 B: backend::Backend<Block>,
1865 E: CallExecutor<Block> + Send + Sync,
1866 Block: BlockT,
1867 Self: ProvideRuntimeApi<Block>,
1868 <Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block> + ApiExt<Block>,
1869 RA: Sync + Send,
1870{
1871 type Error = ConsensusError;
1872
1873 async fn check_block(
1874 &self,
1875 block: BlockCheckParams<Block>,
1876 ) -> Result<ImportResult, Self::Error> {
1877 (&self).check_block(block).await
1878 }
1879
1880 async fn import_block(
1881 &self,
1882 import_block: BlockImportParams<Block>,
1883 ) -> Result<ImportResult, Self::Error> {
1884 (&self).import_block(import_block).await
1885 }
1886}
1887
1888impl<B, E, Block, RA> Finalizer<Block, B> for Client<B, E, Block, RA>
1889where
1890 B: backend::Backend<Block>,
1891 E: CallExecutor<Block>,
1892 Block: BlockT,
1893{
1894 fn apply_finality(
1895 &self,
1896 operation: &mut ClientImportOperation<Block, B>,
1897 hash: Block::Hash,
1898 justification: Option<Justification>,
1899 notify: bool,
1900 ) -> sp_blockchain::Result<()> {
1901 let info = self.backend.blockchain().info();
1902 self.apply_finality_with_block_hash(operation, hash, justification, &info, notify)
1903 }
1904
1905 fn finalize_block(
1906 &self,
1907 hash: Block::Hash,
1908 justification: Option<Justification>,
1909 notify: bool,
1910 ) -> sp_blockchain::Result<()> {
1911 self.lock_import_and_run(|operation| {
1912 self.apply_finality(operation, hash, justification, notify)
1913 })
1914 }
1915}
1916
1917impl<B, E, Block, RA> Finalizer<Block, B> for &Client<B, E, Block, RA>
1918where
1919 B: backend::Backend<Block>,
1920 E: CallExecutor<Block>,
1921 Block: BlockT,
1922{
1923 fn apply_finality(
1924 &self,
1925 operation: &mut ClientImportOperation<Block, B>,
1926 hash: Block::Hash,
1927 justification: Option<Justification>,
1928 notify: bool,
1929 ) -> sp_blockchain::Result<()> {
1930 (**self).apply_finality(operation, hash, justification, notify)
1931 }
1932
1933 fn finalize_block(
1934 &self,
1935 hash: Block::Hash,
1936 justification: Option<Justification>,
1937 notify: bool,
1938 ) -> sp_blockchain::Result<()> {
1939 (**self).finalize_block(hash, justification, notify)
1940 }
1941}
1942
1943impl<B, E, Block, RA> PreCommitActions<Block> for Client<B, E, Block, RA>
1944where
1945 Block: BlockT,
1946{
1947 fn register_import_action(&self, action: OnImportAction<Block>) {
1948 self.import_actions.lock().push(action);
1949 }
1950
1951 fn register_finality_action(&self, action: OnFinalityAction<Block>) {
1952 self.finality_actions.lock().push(action);
1953 }
1954}
1955
1956impl<B, E, Block, RA> BlockchainEvents<Block> for Client<B, E, Block, RA>
1957where
1958 E: CallExecutor<Block>,
1959 Block: BlockT,
1960{
1961 fn import_notification_stream(&self) -> ImportNotifications<Block> {
1963 let (sink, stream) = tracing_unbounded("mpsc_import_notification_stream", 100_000);
1964 self.import_notification_sinks.lock().push(sink);
1965 stream
1966 }
1967
1968 fn every_import_notification_stream(&self) -> ImportNotifications<Block> {
1969 let (sink, stream) = tracing_unbounded("mpsc_every_import_notification_stream", 100_000);
1970 self.every_import_notification_sinks.lock().push(sink);
1971 stream
1972 }
1973
1974 fn finality_notification_stream(&self) -> FinalityNotifications<Block> {
1975 let (sink, stream) = tracing_unbounded("mpsc_finality_notification_stream", 100_000);
1976 self.finality_notification_sinks.lock().push(sink);
1977 stream
1978 }
1979
1980 fn storage_changes_notification_stream(
1982 &self,
1983 filter_keys: Option<&[StorageKey]>,
1984 child_filter_keys: Option<&[(StorageKey, Option<Vec<StorageKey>>)]>,
1985 ) -> sp_blockchain::Result<StorageEventStream<Block::Hash>> {
1986 Ok(self.storage_notifications.listen(filter_keys, child_filter_keys))
1987 }
1988}
1989
1990impl<B, E, Block, RA> BlockBackend<Block> for Client<B, E, Block, RA>
1991where
1992 B: backend::Backend<Block>,
1993 E: CallExecutor<Block>,
1994 Block: BlockT,
1995{
1996 fn block_body(
1997 &self,
1998 hash: Block::Hash,
1999 ) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
2000 self.body(hash)
2001 }
2002
2003 fn block(&self, hash: Block::Hash) -> sp_blockchain::Result<Option<SignedBlock<Block>>> {
2004 Ok(match (self.header(hash)?, self.body(hash)?, self.justifications(hash)?) {
2005 (Some(header), Some(extrinsics), justifications) => {
2006 Some(SignedBlock { block: Block::new(header, extrinsics), justifications })
2007 },
2008 _ => None,
2009 })
2010 }
2011
2012 fn block_status(&self, hash: Block::Hash) -> sp_blockchain::Result<BlockStatus> {
2013 Client::block_status(self, hash)
2014 }
2015
2016 fn justifications(&self, hash: Block::Hash) -> sp_blockchain::Result<Option<Justifications>> {
2017 self.backend.blockchain().justifications(hash)
2018 }
2019
2020 fn block_hash(&self, number: NumberFor<Block>) -> sp_blockchain::Result<Option<Block::Hash>> {
2021 self.backend.blockchain().hash(number)
2022 }
2023
2024 fn indexed_transaction(&self, hash: H256) -> sp_blockchain::Result<Option<Vec<u8>>> {
2025 self.backend.blockchain().indexed_transaction(hash)
2026 }
2027
2028 fn has_indexed_transaction(&self, hash: H256) -> sp_blockchain::Result<bool> {
2029 self.backend.blockchain().has_indexed_transaction(hash)
2030 }
2031
2032 fn block_indexed_hashes(&self, hash: Block::Hash) -> sp_blockchain::Result<Option<Vec<H256>>> {
2033 self.backend.blockchain().block_indexed_hashes(hash)
2034 }
2035
2036 fn block_indexed_body(&self, hash: Block::Hash) -> sp_blockchain::Result<Option<Vec<Vec<u8>>>> {
2037 self.backend.blockchain().block_indexed_body(hash)
2038 }
2039
2040 fn requires_full_sync(&self) -> bool {
2041 self.backend.requires_full_sync()
2042 }
2043}
2044
2045impl<B, E, Block, RA> backend::AuxStore for Client<B, E, Block, RA>
2046where
2047 B: backend::Backend<Block>,
2048 E: CallExecutor<Block>,
2049 Block: BlockT,
2050 Self: ProvideRuntimeApi<Block>,
2051 <Self as ProvideRuntimeApi<Block>>::Api: CoreApi<Block>,
2052{
2053 fn insert_aux<
2055 'a,
2056 'b: 'a,
2057 'c: 'a,
2058 I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
2059 D: IntoIterator<Item = &'a &'b [u8]>,
2060 >(
2061 &self,
2062 insert: I,
2063 delete: D,
2064 ) -> sp_blockchain::Result<()> {
2065 self.lock_import_and_run(|operation| apply_aux(operation, insert, delete))
2070 }
2071 fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
2073 backend::AuxStore::get_aux(&*self.backend, key)
2074 }
2075}
2076
2077impl<B, E, Block, RA> backend::AuxStore for &Client<B, E, Block, RA>
2078where
2079 B: backend::Backend<Block>,
2080 E: CallExecutor<Block>,
2081 Block: BlockT,
2082 Client<B, E, Block, RA>: ProvideRuntimeApi<Block>,
2083 <Client<B, E, Block, RA> as ProvideRuntimeApi<Block>>::Api: CoreApi<Block>,
2084{
2085 fn insert_aux<
2086 'a,
2087 'b: 'a,
2088 'c: 'a,
2089 I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
2090 D: IntoIterator<Item = &'a &'b [u8]>,
2091 >(
2092 &self,
2093 insert: I,
2094 delete: D,
2095 ) -> sp_blockchain::Result<()> {
2096 (**self).insert_aux(insert, delete)
2097 }
2098
2099 fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
2100 (**self).get_aux(key)
2101 }
2102}
2103
2104impl<BE, E, B, RA> sp_consensus::block_validation::Chain<B> for Client<BE, E, B, RA>
2105where
2106 BE: backend::Backend<B>,
2107 E: CallExecutor<B>,
2108 B: BlockT,
2109{
2110 fn block_status(
2111 &self,
2112 hash: B::Hash,
2113 ) -> Result<BlockStatus, Box<dyn std::error::Error + Send>> {
2114 Client::block_status(self, hash).map_err(|e| Box::new(e) as Box<_>)
2115 }
2116}
2117
2118impl<BE, E, B, RA> sp_transaction_storage_proof::IndexedBody<B> for Client<BE, E, B, RA>
2119where
2120 BE: backend::Backend<B>,
2121 E: CallExecutor<B>,
2122 B: BlockT,
2123{
2124 fn block_indexed_body(
2125 &self,
2126 number: NumberFor<B>,
2127 ) -> Result<Option<Vec<Vec<u8>>>, sp_transaction_storage_proof::Error> {
2128 let hash = match self
2129 .backend
2130 .blockchain()
2131 .block_hash_from_id(&BlockId::Number(number))
2132 .map_err(|e| sp_transaction_storage_proof::Error::Application(Box::new(e)))?
2133 {
2134 Some(hash) => hash,
2135 None => return Ok(None),
2136 };
2137
2138 self.backend
2139 .blockchain()
2140 .block_indexed_body(hash)
2141 .map_err(|e| sp_transaction_storage_proof::Error::Application(Box::new(e)))
2142 }
2143
2144 fn number(
2145 &self,
2146 hash: B::Hash,
2147 ) -> Result<Option<NumberFor<B>>, sp_transaction_storage_proof::Error> {
2148 self.backend
2149 .blockchain()
2150 .number(hash)
2151 .map_err(|e| sp_transaction_storage_proof::Error::Application(Box::new(e)))
2152 }
2153}