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