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