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