referrerpolicy=no-referrer-when-downgrade

sc_service/client/
client.rs

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