Skip to main content

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