polkadot_node_subsystem_types/
runtime_client.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17use async_trait::async_trait;
18use polkadot_primitives::{
19	async_backing, runtime_api::ParachainHost, slashing, ApprovalVotingParams, Block, BlockNumber,
20	CandidateCommitments, CandidateEvent, CandidateHash, CommittedCandidateReceipt, CoreIndex,
21	CoreState, DisputeState, ExecutorParams, GroupRotationInfo, Hash, Header, Id,
22	InboundDownwardMessage, InboundHrmpMessage, NodeFeatures, OccupiedCoreAssumption,
23	PersistedValidationData, PvfCheckStatement, ScrapedOnChainVotes, SessionIndex, SessionInfo,
24	ValidationCode, ValidationCodeHash, ValidatorId, ValidatorIndex, ValidatorSignature,
25};
26use sc_client_api::{AuxStore, HeaderBackend};
27use sc_transaction_pool_api::OffchainTransactionPoolFactory;
28use sp_api::{ApiError, ApiExt, ProvideRuntimeApi};
29use sp_authority_discovery::AuthorityDiscoveryApi;
30use sp_blockchain::{BlockStatus, Info};
31use sp_consensus_babe::{BabeApi, Epoch};
32use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
33use std::{
34	collections::{BTreeMap, VecDeque},
35	sync::Arc,
36};
37
38/// Offers header utilities.
39///
40/// This is a async wrapper trait for ['HeaderBackend'] to be used with the
41/// `ChainApiSubsystem`.
42// This trait was introduced to suit the needs of collators. Depending on their operating mode, they
43// might not have a client of the relay chain that can supply a synchronous HeaderBackend
44// implementation.
45#[async_trait]
46pub trait ChainApiBackend: Send + Sync {
47	/// Get block header. Returns `None` if block is not found.
48	async fn header(&self, hash: Hash) -> sp_blockchain::Result<Option<Header>>;
49	/// Get blockchain info.
50	async fn info(&self) -> sp_blockchain::Result<Info<Block>>;
51	/// Get block number by hash. Returns `None` if the header is not in the chain.
52	async fn number(
53		&self,
54		hash: Hash,
55	) -> sp_blockchain::Result<Option<<Header as HeaderT>::Number>>;
56	/// Get block hash by number. Returns `None` if the header is not in the chain.
57	async fn hash(&self, number: NumberFor<Block>) -> sp_blockchain::Result<Option<Hash>>;
58}
59
60#[async_trait]
61impl<T> ChainApiBackend for T
62where
63	T: HeaderBackend<Block>,
64{
65	/// Get block header. Returns `None` if block is not found.
66	async fn header(&self, hash: Hash) -> sp_blockchain::Result<Option<Header>> {
67		HeaderBackend::header(self, hash)
68	}
69
70	/// Get blockchain info.
71	async fn info(&self) -> sp_blockchain::Result<Info<Block>> {
72		Ok(HeaderBackend::info(self))
73	}
74
75	/// Get block number by hash. Returns `None` if the header is not in the chain.
76	async fn number(
77		&self,
78		hash: Hash,
79	) -> sp_blockchain::Result<Option<<Header as HeaderT>::Number>> {
80		HeaderBackend::number(self, hash)
81	}
82
83	/// Get block hash by number. Returns `None` if the header is not in the chain.
84	async fn hash(&self, number: NumberFor<Block>) -> sp_blockchain::Result<Option<Hash>> {
85		HeaderBackend::hash(self, number)
86	}
87}
88
89/// Exposes all runtime calls that are used by the runtime API subsystem.
90#[async_trait]
91pub trait RuntimeApiSubsystemClient {
92	/// Parachain host API version
93	async fn api_version_parachain_host(&self, at: Hash) -> Result<Option<u32>, ApiError>;
94
95	// === ParachainHost API ===
96
97	/// Get the current validators.
98	async fn validators(&self, at: Hash) -> Result<Vec<ValidatorId>, ApiError>;
99
100	/// Returns the validator groups and rotation info localized based on the hypothetical child
101	///  of a block whose state  this is invoked on. Note that `now` in the `GroupRotationInfo`
102	/// should be the successor of the number of the block.
103	async fn validator_groups(
104		&self,
105		at: Hash,
106	) -> Result<(Vec<Vec<ValidatorIndex>>, GroupRotationInfo<BlockNumber>), ApiError>;
107
108	/// Yields information on all availability cores as relevant to the child block.
109	/// Cores are either free or occupied. Free cores can have paras assigned to them.
110	async fn availability_cores(
111		&self,
112		at: Hash,
113	) -> Result<Vec<CoreState<Hash, BlockNumber>>, ApiError>;
114
115	/// Yields the persisted validation data for the given `ParaId` along with an assumption that
116	/// should be used if the para currently occupies a core.
117	///
118	/// Returns `None` if either the para is not registered or the assumption is `Freed`
119	/// and the para already occupies a core.
120	async fn persisted_validation_data(
121		&self,
122		at: Hash,
123		para_id: Id,
124		assumption: OccupiedCoreAssumption,
125	) -> Result<Option<PersistedValidationData<Hash, BlockNumber>>, ApiError>;
126
127	/// Returns the persisted validation data for the given `ParaId` along with the corresponding
128	/// validation code hash. Instead of accepting assumption about the para, matches the validation
129	/// data hash against an expected one and yields `None` if they're not equal.
130	async fn assumed_validation_data(
131		&self,
132		at: Hash,
133		para_id: Id,
134		expected_persisted_validation_data_hash: Hash,
135	) -> Result<Option<(PersistedValidationData<Hash, BlockNumber>, ValidationCodeHash)>, ApiError>;
136
137	/// Checks if the given validation outputs pass the acceptance criteria.
138	async fn check_validation_outputs(
139		&self,
140		at: Hash,
141		para_id: Id,
142		outputs: CandidateCommitments,
143	) -> Result<bool, ApiError>;
144
145	/// Returns the session index expected at a child of the block.
146	///
147	/// This can be used to instantiate a `SigningContext`.
148	async fn session_index_for_child(&self, at: Hash) -> Result<SessionIndex, ApiError>;
149
150	/// Fetch the validation code used by a para, making the given `OccupiedCoreAssumption`.
151	///
152	/// Returns `None` if either the para is not registered or the assumption is `Freed`
153	/// and the para already occupies a core.
154	async fn validation_code(
155		&self,
156		at: Hash,
157		para_id: Id,
158		assumption: OccupiedCoreAssumption,
159	) -> Result<Option<ValidationCode>, ApiError>;
160
161	/// Get the receipt of a candidate pending availability. This returns `Some` for any paras
162	/// assigned to occupied cores in `availability_cores` and `None` otherwise.
163	async fn candidate_pending_availability(
164		&self,
165		at: Hash,
166		para_id: Id,
167	) -> Result<Option<CommittedCandidateReceipt<Hash>>, ApiError>;
168
169	/// Get a vector of events concerning candidates that occurred within a block.
170	async fn candidate_events(&self, at: Hash) -> Result<Vec<CandidateEvent<Hash>>, ApiError>;
171
172	/// Get all the pending inbound messages in the downward message queue for a para.
173	async fn dmq_contents(
174		&self,
175		at: Hash,
176		recipient: Id,
177	) -> Result<Vec<InboundDownwardMessage<BlockNumber>>, ApiError>;
178
179	/// Get the contents of all channels addressed to the given recipient. Channels that have no
180	/// messages in them are also included.
181	async fn inbound_hrmp_channels_contents(
182		&self,
183		at: Hash,
184		recipient: Id,
185	) -> Result<BTreeMap<Id, Vec<InboundHrmpMessage<BlockNumber>>>, ApiError>;
186
187	/// Get the validation code from its hash.
188	async fn validation_code_by_hash(
189		&self,
190		at: Hash,
191		hash: ValidationCodeHash,
192	) -> Result<Option<ValidationCode>, ApiError>;
193
194	/// Scrape dispute relevant from on-chain, backing votes and resolved disputes.
195	async fn on_chain_votes(&self, at: Hash)
196		-> Result<Option<ScrapedOnChainVotes<Hash>>, ApiError>;
197
198	/***** Added in v2 **** */
199
200	/// Get the session info for the given session, if stored.
201	///
202	/// NOTE: This function is only available since parachain host version 2.
203	async fn session_info(
204		&self,
205		at: Hash,
206		index: SessionIndex,
207	) -> Result<Option<SessionInfo>, ApiError>;
208
209	/// Submits a PVF pre-checking statement into the transaction pool.
210	///
211	/// NOTE: This function is only available since parachain host version 2.
212	async fn submit_pvf_check_statement(
213		&self,
214		at: Hash,
215		stmt: PvfCheckStatement,
216		signature: ValidatorSignature,
217	) -> Result<(), ApiError>;
218
219	/// Returns code hashes of PVFs that require pre-checking by validators in the active set.
220	///
221	/// NOTE: This function is only available since parachain host version 2.
222	async fn pvfs_require_precheck(&self, at: Hash) -> Result<Vec<ValidationCodeHash>, ApiError>;
223
224	/// Fetch the hash of the validation code used by a para, making the given
225	/// `OccupiedCoreAssumption`.
226	///
227	/// NOTE: This function is only available since parachain host version 2.
228	async fn validation_code_hash(
229		&self,
230		at: Hash,
231		para_id: Id,
232		assumption: OccupiedCoreAssumption,
233	) -> Result<Option<ValidationCodeHash>, ApiError>;
234
235	/***** Added in v3 **** */
236
237	/// Returns all onchain disputes.
238	/// This is a staging method! Do not use on production runtimes!
239	async fn disputes(
240		&self,
241		at: Hash,
242	) -> Result<Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)>, ApiError>;
243
244	/// Returns a list of validators that lost a past session dispute and need to be slashed.
245	///
246	/// WARNING: This is a staging method! Do not use on production runtimes!
247	async fn unapplied_slashes(
248		&self,
249		at: Hash,
250	) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, ApiError>;
251
252	/// Returns a merkle proof of a validator session key in a past session.
253	///
254	/// WARNING: This is a staging method! Do not use on production runtimes!
255	async fn key_ownership_proof(
256		&self,
257		at: Hash,
258		validator_id: ValidatorId,
259	) -> Result<Option<slashing::OpaqueKeyOwnershipProof>, ApiError>;
260
261	/// Submits an unsigned extrinsic to slash validators who lost a dispute about
262	/// a candidate of a past session.
263	///
264	/// WARNING: This is a staging method! Do not use on production runtimes!
265	async fn submit_report_dispute_lost(
266		&self,
267		at: Hash,
268		dispute_proof: slashing::DisputeProof,
269		key_ownership_proof: slashing::OpaqueKeyOwnershipProof,
270	) -> Result<Option<()>, ApiError>;
271
272	// === BABE API ===
273
274	/// Returns information regarding the current epoch.
275	async fn current_epoch(&self, at: Hash) -> Result<Epoch, ApiError>;
276
277	// === AuthorityDiscovery API ===
278
279	/// Retrieve authority identifiers of the current and next authority set.
280	async fn authorities(
281		&self,
282		at: Hash,
283	) -> std::result::Result<Vec<sp_authority_discovery::AuthorityId>, ApiError>;
284
285	/// Get the execution environment parameter set by parent hash, if stored
286	async fn session_executor_params(
287		&self,
288		at: Hash,
289		session_index: SessionIndex,
290	) -> Result<Option<ExecutorParams>, ApiError>;
291
292	// === v6 ===
293	/// Get the minimum number of backing votes.
294	async fn minimum_backing_votes(
295		&self,
296		at: Hash,
297		session_index: SessionIndex,
298	) -> Result<u32, ApiError>;
299
300	// === v7: Asynchronous backing API ===
301
302	/// Returns candidate's acceptance limitations for asynchronous backing for a relay parent.
303	async fn async_backing_params(
304		&self,
305		at: Hash,
306	) -> Result<polkadot_primitives::AsyncBackingParams, ApiError>;
307
308	/// Returns the state of parachain backing for a given para.
309	/// This is a staging method! Do not use on production runtimes!
310	async fn para_backing_state(
311		&self,
312		at: Hash,
313		para_id: Id,
314	) -> Result<Option<async_backing::BackingState>, ApiError>;
315
316	// === v8 ===
317
318	/// Gets the disabled validators at a specific block height
319	async fn disabled_validators(&self, at: Hash) -> Result<Vec<ValidatorIndex>, ApiError>;
320
321	// === v9 ===
322	/// Get the node features.
323	async fn node_features(&self, at: Hash) -> Result<NodeFeatures, ApiError>;
324
325	// == v10: Approval voting params ==
326	/// Approval voting configuration parameters
327	async fn approval_voting_params(
328		&self,
329		at: Hash,
330		session_index: SessionIndex,
331	) -> Result<ApprovalVotingParams, ApiError>;
332
333	// == v11: Claim queue ==
334	/// Fetch the `ClaimQueue` from scheduler pallet
335	async fn claim_queue(&self, at: Hash) -> Result<BTreeMap<CoreIndex, VecDeque<Id>>, ApiError>;
336
337	// == v11: Elastic scaling support ==
338	/// Get the receipts of all candidates pending availability for a `ParaId`.
339	async fn candidates_pending_availability(
340		&self,
341		at: Hash,
342		para_id: Id,
343	) -> Result<Vec<CommittedCandidateReceipt<Hash>>, ApiError>;
344}
345
346/// Default implementation of [`RuntimeApiSubsystemClient`] using the client.
347pub struct DefaultSubsystemClient<Client> {
348	client: Arc<Client>,
349	offchain_transaction_pool_factory: OffchainTransactionPoolFactory<Block>,
350}
351
352impl<Client> DefaultSubsystemClient<Client> {
353	/// Create new instance.
354	pub fn new(
355		client: Arc<Client>,
356		offchain_transaction_pool_factory: OffchainTransactionPoolFactory<Block>,
357	) -> Self {
358		Self { client, offchain_transaction_pool_factory }
359	}
360}
361
362#[async_trait]
363impl<Client> RuntimeApiSubsystemClient for DefaultSubsystemClient<Client>
364where
365	Client: ProvideRuntimeApi<Block> + Send + Sync,
366	Client::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
367{
368	async fn validators(&self, at: Hash) -> Result<Vec<ValidatorId>, ApiError> {
369		self.client.runtime_api().validators(at)
370	}
371
372	async fn validator_groups(
373		&self,
374		at: Hash,
375	) -> Result<(Vec<Vec<ValidatorIndex>>, GroupRotationInfo<BlockNumber>), ApiError> {
376		self.client.runtime_api().validator_groups(at)
377	}
378
379	async fn availability_cores(
380		&self,
381		at: Hash,
382	) -> Result<Vec<CoreState<Hash, BlockNumber>>, ApiError> {
383		self.client
384			.runtime_api()
385			.availability_cores(at)
386			.map(|cores| cores.into_iter().map(|core| core.into()).collect::<Vec<_>>())
387	}
388
389	async fn persisted_validation_data(
390		&self,
391		at: Hash,
392		para_id: Id,
393		assumption: OccupiedCoreAssumption,
394	) -> Result<Option<PersistedValidationData<Hash, BlockNumber>>, ApiError> {
395		self.client.runtime_api().persisted_validation_data(at, para_id, assumption)
396	}
397
398	async fn assumed_validation_data(
399		&self,
400		at: Hash,
401		para_id: Id,
402		expected_persisted_validation_data_hash: Hash,
403	) -> Result<Option<(PersistedValidationData<Hash, BlockNumber>, ValidationCodeHash)>, ApiError>
404	{
405		self.client.runtime_api().assumed_validation_data(
406			at,
407			para_id,
408			expected_persisted_validation_data_hash,
409		)
410	}
411
412	async fn check_validation_outputs(
413		&self,
414		at: Hash,
415		para_id: Id,
416		outputs: CandidateCommitments,
417	) -> Result<bool, ApiError> {
418		self.client.runtime_api().check_validation_outputs(at, para_id, outputs)
419	}
420
421	async fn session_index_for_child(&self, at: Hash) -> Result<SessionIndex, ApiError> {
422		self.client.runtime_api().session_index_for_child(at)
423	}
424
425	async fn validation_code(
426		&self,
427		at: Hash,
428		para_id: Id,
429		assumption: OccupiedCoreAssumption,
430	) -> Result<Option<ValidationCode>, ApiError> {
431		self.client.runtime_api().validation_code(at, para_id, assumption)
432	}
433
434	async fn candidate_pending_availability(
435		&self,
436		at: Hash,
437		para_id: Id,
438	) -> Result<Option<CommittedCandidateReceipt<Hash>>, ApiError> {
439		self.client
440			.runtime_api()
441			.candidate_pending_availability(at, para_id)
442			.map(|maybe_candidate| maybe_candidate.map(|candidate| candidate.into()))
443	}
444
445	async fn candidates_pending_availability(
446		&self,
447		at: Hash,
448		para_id: Id,
449	) -> Result<Vec<CommittedCandidateReceipt<Hash>>, ApiError> {
450		self.client
451			.runtime_api()
452			.candidates_pending_availability(at, para_id)
453			.map(|candidates| {
454				candidates.into_iter().map(|candidate| candidate.into()).collect::<Vec<_>>()
455			})
456	}
457
458	async fn candidate_events(&self, at: Hash) -> Result<Vec<CandidateEvent<Hash>>, ApiError> {
459		self.client
460			.runtime_api()
461			.candidate_events(at)
462			.map(|events| events.into_iter().map(|event| event.into()).collect::<Vec<_>>())
463	}
464
465	async fn dmq_contents(
466		&self,
467		at: Hash,
468		recipient: Id,
469	) -> Result<Vec<InboundDownwardMessage<BlockNumber>>, ApiError> {
470		self.client.runtime_api().dmq_contents(at, recipient)
471	}
472
473	async fn inbound_hrmp_channels_contents(
474		&self,
475		at: Hash,
476		recipient: Id,
477	) -> Result<BTreeMap<Id, Vec<InboundHrmpMessage<BlockNumber>>>, ApiError> {
478		self.client.runtime_api().inbound_hrmp_channels_contents(at, recipient)
479	}
480
481	async fn validation_code_by_hash(
482		&self,
483		at: Hash,
484		hash: ValidationCodeHash,
485	) -> Result<Option<ValidationCode>, ApiError> {
486		self.client.runtime_api().validation_code_by_hash(at, hash)
487	}
488
489	async fn on_chain_votes(
490		&self,
491		at: Hash,
492	) -> Result<Option<ScrapedOnChainVotes<Hash>>, ApiError> {
493		self.client
494			.runtime_api()
495			.on_chain_votes(at)
496			.map(|maybe_votes| maybe_votes.map(|votes| votes.into()))
497	}
498
499	async fn session_executor_params(
500		&self,
501		at: Hash,
502		session_index: SessionIndex,
503	) -> Result<Option<ExecutorParams>, ApiError> {
504		self.client.runtime_api().session_executor_params(at, session_index)
505	}
506
507	async fn session_info(
508		&self,
509		at: Hash,
510		index: SessionIndex,
511	) -> Result<Option<SessionInfo>, ApiError> {
512		self.client.runtime_api().session_info(at, index)
513	}
514
515	async fn submit_pvf_check_statement(
516		&self,
517		at: Hash,
518		stmt: PvfCheckStatement,
519		signature: ValidatorSignature,
520	) -> Result<(), ApiError> {
521		let mut runtime_api = self.client.runtime_api();
522
523		runtime_api.register_extension(
524			self.offchain_transaction_pool_factory.offchain_transaction_pool(at),
525		);
526
527		runtime_api.submit_pvf_check_statement(at, stmt, signature)
528	}
529
530	async fn pvfs_require_precheck(&self, at: Hash) -> Result<Vec<ValidationCodeHash>, ApiError> {
531		self.client.runtime_api().pvfs_require_precheck(at)
532	}
533
534	async fn validation_code_hash(
535		&self,
536		at: Hash,
537		para_id: Id,
538		assumption: OccupiedCoreAssumption,
539	) -> Result<Option<ValidationCodeHash>, ApiError> {
540		self.client.runtime_api().validation_code_hash(at, para_id, assumption)
541	}
542
543	async fn current_epoch(&self, at: Hash) -> Result<Epoch, ApiError> {
544		self.client.runtime_api().current_epoch(at)
545	}
546
547	async fn authorities(
548		&self,
549		at: Hash,
550	) -> std::result::Result<Vec<sp_authority_discovery::AuthorityId>, ApiError> {
551		self.client.runtime_api().authorities(at)
552	}
553
554	async fn api_version_parachain_host(&self, at: Hash) -> Result<Option<u32>, ApiError> {
555		self.client.runtime_api().api_version::<dyn ParachainHost<Block>>(at)
556	}
557
558	async fn disputes(
559		&self,
560		at: Hash,
561	) -> Result<Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)>, ApiError> {
562		self.client.runtime_api().disputes(at)
563	}
564
565	async fn unapplied_slashes(
566		&self,
567		at: Hash,
568	) -> Result<Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)>, ApiError> {
569		self.client.runtime_api().unapplied_slashes(at)
570	}
571
572	async fn key_ownership_proof(
573		&self,
574		at: Hash,
575		validator_id: ValidatorId,
576	) -> Result<Option<slashing::OpaqueKeyOwnershipProof>, ApiError> {
577		self.client.runtime_api().key_ownership_proof(at, validator_id)
578	}
579
580	async fn submit_report_dispute_lost(
581		&self,
582		at: Hash,
583		dispute_proof: slashing::DisputeProof,
584		key_ownership_proof: slashing::OpaqueKeyOwnershipProof,
585	) -> Result<Option<()>, ApiError> {
586		let mut runtime_api = self.client.runtime_api();
587
588		runtime_api.register_extension(
589			self.offchain_transaction_pool_factory.offchain_transaction_pool(at),
590		);
591
592		runtime_api.submit_report_dispute_lost(at, dispute_proof, key_ownership_proof)
593	}
594
595	async fn minimum_backing_votes(
596		&self,
597		at: Hash,
598		_session_index: SessionIndex,
599	) -> Result<u32, ApiError> {
600		self.client.runtime_api().minimum_backing_votes(at)
601	}
602
603	async fn para_backing_state(
604		&self,
605		at: Hash,
606		para_id: Id,
607	) -> Result<Option<async_backing::BackingState>, ApiError> {
608		self.client
609			.runtime_api()
610			.para_backing_state(at, para_id)
611			.map(|maybe_backing_state| {
612				maybe_backing_state.map(|backing_state| backing_state.into())
613			})
614	}
615
616	async fn async_backing_params(
617		&self,
618		at: Hash,
619	) -> Result<async_backing::AsyncBackingParams, ApiError> {
620		self.client.runtime_api().async_backing_params(at)
621	}
622
623	async fn node_features(&self, at: Hash) -> Result<NodeFeatures, ApiError> {
624		self.client.runtime_api().node_features(at)
625	}
626
627	async fn disabled_validators(&self, at: Hash) -> Result<Vec<ValidatorIndex>, ApiError> {
628		self.client.runtime_api().disabled_validators(at)
629	}
630
631	/// Approval voting configuration parameters
632	async fn approval_voting_params(
633		&self,
634		at: Hash,
635		_session_index: SessionIndex,
636	) -> Result<ApprovalVotingParams, ApiError> {
637		self.client.runtime_api().approval_voting_params(at)
638	}
639
640	async fn claim_queue(&self, at: Hash) -> Result<BTreeMap<CoreIndex, VecDeque<Id>>, ApiError> {
641		self.client.runtime_api().claim_queue(at)
642	}
643}
644
645impl<Client, Block> HeaderBackend<Block> for DefaultSubsystemClient<Client>
646where
647	Client: HeaderBackend<Block>,
648	Block: sp_runtime::traits::Block,
649{
650	fn header(
651		&self,
652		hash: Block::Hash,
653	) -> sc_client_api::blockchain::Result<Option<Block::Header>> {
654		self.client.header(hash)
655	}
656
657	fn info(&self) -> Info<Block> {
658		self.client.info()
659	}
660
661	fn status(&self, hash: Block::Hash) -> sc_client_api::blockchain::Result<BlockStatus> {
662		self.client.status(hash)
663	}
664
665	fn number(
666		&self,
667		hash: Block::Hash,
668	) -> sc_client_api::blockchain::Result<Option<<<Block as BlockT>::Header as HeaderT>::Number>>
669	{
670		self.client.number(hash)
671	}
672
673	fn hash(
674		&self,
675		number: NumberFor<Block>,
676	) -> sc_client_api::blockchain::Result<Option<Block::Hash>> {
677		self.client.hash(number)
678	}
679}
680
681impl<Client> AuxStore for DefaultSubsystemClient<Client>
682where
683	Client: AuxStore,
684{
685	fn insert_aux<
686		'a,
687		'b: 'a,
688		'c: 'a,
689		I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
690		D: IntoIterator<Item = &'a &'b [u8]>,
691	>(
692		&self,
693		insert: I,
694		delete: D,
695	) -> sp_blockchain::Result<()> {
696		self.client.insert_aux(insert, delete)
697	}
698
699	fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
700		self.client.get_aux(key)
701	}
702}