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