referrerpolicy=no-referrer-when-downgrade

sc_service/client/
client.rs

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