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