polkadot_node_core_runtime_api/
lib.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
17//! Implements the Runtime API Subsystem
18//!
19//! This provides a clean, ownerless wrapper around the parachain-related runtime APIs. This crate
20//! can also be used to cache responses from heavy runtime APIs.
21
22#![deny(unused_crate_dependencies)]
23#![warn(missing_docs)]
24
25use polkadot_node_subsystem::{
26	errors::RuntimeApiError,
27	messages::{RuntimeApiMessage, RuntimeApiRequest as Request},
28	overseer, FromOrchestra, OverseerSignal, SpawnedSubsystem, SubsystemError, SubsystemResult,
29};
30use polkadot_node_subsystem_types::RuntimeApiSubsystemClient;
31use polkadot_primitives::Hash;
32
33use cache::{RequestResult, RequestResultCache};
34use futures::{channel::oneshot, prelude::*, select, stream::FuturesUnordered};
35use std::sync::Arc;
36
37mod cache;
38
39mod metrics;
40use self::metrics::Metrics;
41
42#[cfg(test)]
43mod tests;
44
45const LOG_TARGET: &str = "parachain::runtime-api";
46
47/// The number of maximum runtime API requests can be executed in parallel.
48/// Further requests will backpressure the bounded channel.
49const MAX_PARALLEL_REQUESTS: usize = 4;
50
51/// The name of the blocking task that executes a runtime API request.
52const API_REQUEST_TASK_NAME: &str = "polkadot-runtime-api-request";
53
54/// The `RuntimeApiSubsystem`. See module docs for more details.
55pub struct RuntimeApiSubsystem<Client> {
56	client: Arc<Client>,
57	metrics: Metrics,
58	spawn_handle: Box<dyn overseer::gen::Spawner>,
59	/// All the active runtime API requests that are currently being executed.
60	active_requests: FuturesUnordered<oneshot::Receiver<Option<RequestResult>>>,
61	/// Requests results cache
62	requests_cache: RequestResultCache,
63}
64
65impl<Client> RuntimeApiSubsystem<Client> {
66	/// Create a new Runtime API subsystem wrapping the given client and metrics.
67	pub fn new(
68		client: Arc<Client>,
69		metrics: Metrics,
70		spawner: impl overseer::gen::Spawner + 'static,
71	) -> Self {
72		RuntimeApiSubsystem {
73			client,
74			metrics,
75			spawn_handle: Box::new(spawner),
76			active_requests: Default::default(),
77			requests_cache: RequestResultCache::default(),
78		}
79	}
80}
81
82#[overseer::subsystem(RuntimeApi, error = SubsystemError, prefix = self::overseer)]
83impl<Client, Context> RuntimeApiSubsystem<Client>
84where
85	Client: RuntimeApiSubsystemClient + Send + Sync + 'static,
86{
87	fn start(self, ctx: Context) -> SpawnedSubsystem {
88		SpawnedSubsystem { future: run(ctx, self).boxed(), name: "runtime-api-subsystem" }
89	}
90}
91
92impl<Client> RuntimeApiSubsystem<Client>
93where
94	Client: RuntimeApiSubsystemClient + Send + 'static + Sync,
95{
96	fn store_cache(&mut self, result: RequestResult) {
97		use RequestResult::*;
98
99		match result {
100			Authorities(relay_parent, authorities) =>
101				self.requests_cache.cache_authorities(relay_parent, authorities),
102			Validators(relay_parent, validators) =>
103				self.requests_cache.cache_validators(relay_parent, validators),
104			MinimumBackingVotes(session_index, minimum_backing_votes) => self
105				.requests_cache
106				.cache_minimum_backing_votes(session_index, minimum_backing_votes),
107			ValidatorGroups(relay_parent, groups) =>
108				self.requests_cache.cache_validator_groups(relay_parent, groups),
109			AvailabilityCores(relay_parent, cores) =>
110				self.requests_cache.cache_availability_cores(relay_parent, cores),
111			PersistedValidationData(relay_parent, para_id, assumption, data) => self
112				.requests_cache
113				.cache_persisted_validation_data((relay_parent, para_id, assumption), data),
114			AssumedValidationData(
115				_relay_parent,
116				para_id,
117				expected_persisted_validation_data_hash,
118				data,
119			) => self.requests_cache.cache_assumed_validation_data(
120				(para_id, expected_persisted_validation_data_hash),
121				data,
122			),
123			CheckValidationOutputs(relay_parent, para_id, commitments, b) => self
124				.requests_cache
125				.cache_check_validation_outputs((relay_parent, para_id, commitments), b),
126			SessionIndexForChild(relay_parent, session_index) =>
127				self.requests_cache.cache_session_index_for_child(relay_parent, session_index),
128			ValidationCode(relay_parent, para_id, assumption, code) => self
129				.requests_cache
130				.cache_validation_code((relay_parent, para_id, assumption), code),
131			ValidationCodeByHash(_relay_parent, validation_code_hash, code) =>
132				self.requests_cache.cache_validation_code_by_hash(validation_code_hash, code),
133			CandidatePendingAvailability(relay_parent, para_id, candidate) => self
134				.requests_cache
135				.cache_candidate_pending_availability((relay_parent, para_id), candidate),
136			CandidatesPendingAvailability(relay_parent, para_id, candidates) => self
137				.requests_cache
138				.cache_candidates_pending_availability((relay_parent, para_id), candidates),
139			CandidateEvents(relay_parent, events) =>
140				self.requests_cache.cache_candidate_events(relay_parent, events),
141			SessionExecutorParams(_relay_parent, session_index, index) =>
142				self.requests_cache.cache_session_executor_params(session_index, index),
143			SessionInfo(_relay_parent, session_index, info) =>
144				if let Some(info) = info {
145					self.requests_cache.cache_session_info(session_index, info);
146				},
147			DmqContents(relay_parent, para_id, messages) =>
148				self.requests_cache.cache_dmq_contents((relay_parent, para_id), messages),
149			InboundHrmpChannelsContents(relay_parent, para_id, contents) => self
150				.requests_cache
151				.cache_inbound_hrmp_channel_contents((relay_parent, para_id), contents),
152			CurrentBabeEpoch(relay_parent, epoch) =>
153				self.requests_cache.cache_current_babe_epoch(relay_parent, epoch),
154			FetchOnChainVotes(relay_parent, scraped) =>
155				self.requests_cache.cache_on_chain_votes(relay_parent, scraped),
156			PvfsRequirePrecheck(relay_parent, pvfs) =>
157				self.requests_cache.cache_pvfs_require_precheck(relay_parent, pvfs),
158			SubmitPvfCheckStatement(()) => {},
159			ValidationCodeHash(relay_parent, para_id, assumption, hash) => self
160				.requests_cache
161				.cache_validation_code_hash((relay_parent, para_id, assumption), hash),
162			Version(relay_parent, version) =>
163				self.requests_cache.cache_version(relay_parent, version),
164			Disputes(relay_parent, disputes) =>
165				self.requests_cache.cache_disputes(relay_parent, disputes),
166			UnappliedSlashes(relay_parent, unapplied_slashes) =>
167				self.requests_cache.cache_unapplied_slashes(relay_parent, unapplied_slashes),
168			KeyOwnershipProof(relay_parent, validator_id, key_ownership_proof) => self
169				.requests_cache
170				.cache_key_ownership_proof((relay_parent, validator_id), key_ownership_proof),
171			ApprovalVotingParams(_relay_parent, session_index, params) =>
172				self.requests_cache.cache_approval_voting_params(session_index, params),
173			SubmitReportDisputeLost(_) => {},
174			DisabledValidators(relay_parent, disabled_validators) =>
175				self.requests_cache.cache_disabled_validators(relay_parent, disabled_validators),
176			ParaBackingState(relay_parent, para_id, constraints) => self
177				.requests_cache
178				.cache_para_backing_state((relay_parent, para_id), constraints),
179			AsyncBackingParams(relay_parent, params) =>
180				self.requests_cache.cache_async_backing_params(relay_parent, params),
181			NodeFeatures(session_index, params) =>
182				self.requests_cache.cache_node_features(session_index, params),
183			ClaimQueue(relay_parent, sender) => {
184				self.requests_cache.cache_claim_queue(relay_parent, sender);
185			},
186			BackingConstraints(relay_parent, para_id, constraints) => self
187				.requests_cache
188				.cache_backing_constraints((relay_parent, para_id), constraints),
189			SchedulingLookahead(session_index, scheduling_lookahead) => self
190				.requests_cache
191				.cache_scheduling_lookahead(session_index, scheduling_lookahead),
192			ValidationCodeBombLimit(session_index, limit) =>
193				self.requests_cache.cache_validation_code_bomb_limit(session_index, limit),
194		}
195	}
196
197	fn query_cache(&mut self, relay_parent: Hash, request: Request) -> Option<Request> {
198		macro_rules! query {
199			// Just query by relay parent
200			($cache_api_name:ident (), $sender:expr) => {{
201				let sender = $sender;
202				if let Some(value) = self.requests_cache.$cache_api_name(&relay_parent) {
203					let _ = sender.send(Ok(value.clone()));
204					self.metrics.on_cached_request();
205					None
206				} else {
207					Some(sender)
208				}
209			}};
210			// Query by relay parent + additional parameters
211			($cache_api_name:ident ($($param:expr),+), $sender:expr) => {{
212				let sender = $sender;
213				if let Some(value) = self.requests_cache.$cache_api_name((relay_parent.clone(), $($param.clone()),+)) {
214					self.metrics.on_cached_request();
215					let _ = sender.send(Ok(value.clone()));
216					None
217				} else {
218					Some(sender)
219				}
220			}}
221		}
222
223		match request {
224			Request::Version(sender) =>
225				query!(version(), sender).map(|sender| Request::Version(sender)),
226			Request::Authorities(sender) =>
227				query!(authorities(), sender).map(|sender| Request::Authorities(sender)),
228			Request::Validators(sender) =>
229				query!(validators(), sender).map(|sender| Request::Validators(sender)),
230			Request::ValidatorGroups(sender) =>
231				query!(validator_groups(), sender).map(|sender| Request::ValidatorGroups(sender)),
232			Request::AvailabilityCores(sender) => query!(availability_cores(), sender)
233				.map(|sender| Request::AvailabilityCores(sender)),
234			Request::PersistedValidationData(para, assumption, sender) =>
235				query!(persisted_validation_data(para, assumption), sender)
236					.map(|sender| Request::PersistedValidationData(para, assumption, sender)),
237			Request::AssumedValidationData(
238				para,
239				expected_persisted_validation_data_hash,
240				sender,
241			) => query!(
242				assumed_validation_data(para, expected_persisted_validation_data_hash),
243				sender
244			)
245			.map(|sender| {
246				Request::AssumedValidationData(
247					para,
248					expected_persisted_validation_data_hash,
249					sender,
250				)
251			}),
252			Request::CheckValidationOutputs(para, commitments, sender) =>
253				query!(check_validation_outputs(para, commitments), sender)
254					.map(|sender| Request::CheckValidationOutputs(para, commitments, sender)),
255			Request::SessionIndexForChild(sender) => query!(session_index_for_child(), sender)
256				.map(|sender| Request::SessionIndexForChild(sender)),
257			Request::ValidationCode(para, assumption, sender) =>
258				query!(validation_code(para, assumption), sender)
259					.map(|sender| Request::ValidationCode(para, assumption, sender)),
260			Request::ValidationCodeByHash(validation_code_hash, sender) =>
261				query!(validation_code_by_hash(validation_code_hash), sender)
262					.map(|sender| Request::ValidationCodeByHash(validation_code_hash, sender)),
263			Request::CandidatePendingAvailability(para, sender) =>
264				query!(candidate_pending_availability(para), sender)
265					.map(|sender| Request::CandidatePendingAvailability(para, sender)),
266			Request::CandidatesPendingAvailability(para, sender) =>
267				query!(candidates_pending_availability(para), sender)
268					.map(|sender| Request::CandidatesPendingAvailability(para, sender)),
269			Request::CandidateEvents(sender) =>
270				query!(candidate_events(), sender).map(|sender| Request::CandidateEvents(sender)),
271			Request::SessionExecutorParams(session_index, sender) => {
272				if let Some(executor_params) =
273					self.requests_cache.session_executor_params(session_index)
274				{
275					self.metrics.on_cached_request();
276					let _ = sender.send(Ok(executor_params.clone()));
277					None
278				} else {
279					Some(Request::SessionExecutorParams(session_index, sender))
280				}
281			},
282			Request::SessionInfo(index, sender) => {
283				if let Some(info) = self.requests_cache.session_info(index) {
284					self.metrics.on_cached_request();
285					let _ = sender.send(Ok(Some(info.clone())));
286					None
287				} else {
288					Some(Request::SessionInfo(index, sender))
289				}
290			},
291			Request::DmqContents(id, sender) =>
292				query!(dmq_contents(id), sender).map(|sender| Request::DmqContents(id, sender)),
293			Request::InboundHrmpChannelsContents(id, sender) =>
294				query!(inbound_hrmp_channels_contents(id), sender)
295					.map(|sender| Request::InboundHrmpChannelsContents(id, sender)),
296			Request::CurrentBabeEpoch(sender) =>
297				query!(current_babe_epoch(), sender).map(|sender| Request::CurrentBabeEpoch(sender)),
298			Request::FetchOnChainVotes(sender) =>
299				query!(on_chain_votes(), sender).map(|sender| Request::FetchOnChainVotes(sender)),
300			Request::PvfsRequirePrecheck(sender) => query!(pvfs_require_precheck(), sender)
301				.map(|sender| Request::PvfsRequirePrecheck(sender)),
302			request @ Request::SubmitPvfCheckStatement(_, _, _) => {
303				// This request is side-effecting and thus cannot be cached.
304				Some(request)
305			},
306			Request::ValidationCodeHash(para, assumption, sender) =>
307				query!(validation_code_hash(para, assumption), sender)
308					.map(|sender| Request::ValidationCodeHash(para, assumption, sender)),
309			Request::Disputes(sender) =>
310				query!(disputes(), sender).map(|sender| Request::Disputes(sender)),
311			Request::UnappliedSlashes(sender) =>
312				query!(unapplied_slashes(), sender).map(|sender| Request::UnappliedSlashes(sender)),
313			Request::KeyOwnershipProof(validator_id, sender) =>
314				query!(key_ownership_proof(validator_id), sender)
315					.map(|sender| Request::KeyOwnershipProof(validator_id, sender)),
316			Request::SubmitReportDisputeLost(dispute_proof, key_ownership_proof, sender) =>
317				query!(submit_report_dispute_lost(dispute_proof, key_ownership_proof), sender).map(
318					|sender| {
319						Request::SubmitReportDisputeLost(dispute_proof, key_ownership_proof, sender)
320					},
321				),
322			Request::ApprovalVotingParams(session_index, sender) =>
323				query!(approval_voting_params(session_index), sender)
324					.map(|sender| Request::ApprovalVotingParams(session_index, sender)),
325			Request::DisabledValidators(sender) => query!(disabled_validators(), sender)
326				.map(|sender| Request::DisabledValidators(sender)),
327			Request::ParaBackingState(para, sender) => query!(para_backing_state(para), sender)
328				.map(|sender| Request::ParaBackingState(para, sender)),
329			Request::AsyncBackingParams(sender) => query!(async_backing_params(), sender)
330				.map(|sender| Request::AsyncBackingParams(sender)),
331			Request::MinimumBackingVotes(index, sender) => {
332				if let Some(value) = self.requests_cache.minimum_backing_votes(index) {
333					self.metrics.on_cached_request();
334					let _ = sender.send(Ok(value));
335					None
336				} else {
337					Some(Request::MinimumBackingVotes(index, sender))
338				}
339			},
340			Request::NodeFeatures(index, sender) => {
341				if let Some(value) = self.requests_cache.node_features(index) {
342					self.metrics.on_cached_request();
343					let _ = sender.send(Ok(value.clone()));
344					None
345				} else {
346					Some(Request::NodeFeatures(index, sender))
347				}
348			},
349			Request::ClaimQueue(sender) =>
350				query!(claim_queue(), sender).map(|sender| Request::ClaimQueue(sender)),
351			Request::BackingConstraints(para, sender) => query!(backing_constraints(para), sender)
352				.map(|sender| Request::BackingConstraints(para, sender)),
353			Request::SchedulingLookahead(index, sender) => {
354				if let Some(value) = self.requests_cache.scheduling_lookahead(index) {
355					self.metrics.on_cached_request();
356					let _ = sender.send(Ok(value));
357					None
358				} else {
359					Some(Request::SchedulingLookahead(index, sender))
360				}
361			},
362			Request::ValidationCodeBombLimit(index, sender) => {
363				if let Some(value) = self.requests_cache.validation_code_bomb_limit(index) {
364					self.metrics.on_cached_request();
365					let _ = sender.send(Ok(value));
366					None
367				} else {
368					Some(Request::ValidationCodeBombLimit(index, sender))
369				}
370			},
371		}
372	}
373
374	/// Spawn a runtime API request.
375	fn spawn_request(&mut self, relay_parent: Hash, request: Request) {
376		let client = self.client.clone();
377		let metrics = self.metrics.clone();
378		let (sender, receiver) = oneshot::channel();
379
380		// TODO: make the cache great again https://github.com/paritytech/polkadot/issues/5546
381		let request = match self.query_cache(relay_parent, request) {
382			Some(request) => request,
383			None => return,
384		};
385
386		let request = async move {
387			let result = make_runtime_api_request(client, metrics, relay_parent, request).await;
388			let _ = sender.send(result);
389		}
390		.boxed();
391
392		self.spawn_handle
393			.spawn_blocking(API_REQUEST_TASK_NAME, Some("runtime-api"), request);
394		self.active_requests.push(receiver);
395	}
396
397	/// Poll the active runtime API requests.
398	async fn poll_requests(&mut self) {
399		// If there are no active requests, this future should be pending forever.
400		if self.active_requests.len() == 0 {
401			return futures::pending!();
402		}
403
404		// If there are active requests, this will always resolve to `Some(_)` when a request is
405		// finished.
406		if let Some(Ok(Some(result))) = self.active_requests.next().await {
407			self.store_cache(result);
408		}
409	}
410
411	/// Returns true if our `active_requests` queue is full.
412	fn is_busy(&self) -> bool {
413		self.active_requests.len() >= MAX_PARALLEL_REQUESTS
414	}
415}
416
417#[overseer::contextbounds(RuntimeApi, prefix = self::overseer)]
418async fn run<Client, Context>(
419	mut ctx: Context,
420	mut subsystem: RuntimeApiSubsystem<Client>,
421) -> SubsystemResult<()>
422where
423	Client: RuntimeApiSubsystemClient + Send + Sync + 'static,
424{
425	loop {
426		// Let's add some back pressure when the subsystem is running at `MAX_PARALLEL_REQUESTS`.
427		// This can never block forever, because `active_requests` is owned by this task and any
428		// mutations happen either in `poll_requests` or `spawn_request` - so if `is_busy` returns
429		// true, then even if all of the requests finish before us calling `poll_requests` the
430		// `active_requests` length remains invariant.
431		if subsystem.is_busy() {
432			// Since we are not using any internal waiting queues, we need to wait for exactly
433			// one request to complete before we can read the next one from the overseer channel.
434			let _ = subsystem.poll_requests().await;
435		}
436
437		select! {
438			req = ctx.recv().fuse() => match req? {
439				FromOrchestra::Signal(OverseerSignal::Conclude) => return Ok(()),
440				FromOrchestra::Signal(OverseerSignal::ActiveLeaves(_)) => {},
441				FromOrchestra::Signal(OverseerSignal::BlockFinalized(..)) => {},
442				FromOrchestra::Communication { msg } => match msg {
443					RuntimeApiMessage::Request(relay_parent, request) => {
444						subsystem.spawn_request(relay_parent, request);
445					},
446				}
447			},
448			_ = subsystem.poll_requests().fuse() => {},
449		}
450	}
451}
452
453async fn make_runtime_api_request<Client>(
454	client: Arc<Client>,
455	metrics: Metrics,
456	relay_parent: Hash,
457	request: Request,
458) -> Option<RequestResult>
459where
460	Client: RuntimeApiSubsystemClient + 'static,
461{
462	let _timer = metrics.time_make_runtime_api_request();
463
464	macro_rules! query {
465		($req_variant:ident, $api_name:ident ($($param:expr),*), ver = $version:expr, $sender:expr) => {{
466			query!($req_variant, $api_name($($param),*), ver = $version, $sender, result = ( relay_parent $(, $param )* ) )
467		}};
468		($req_variant:ident, $api_name:ident ($($param:expr),*), ver = $version:expr, $sender:expr, result = ( $($results:expr),* ) ) => {{
469			let sender = $sender;
470			let version: u32 = $version; // enforce type for the version expression
471			let runtime_version = client.api_version_parachain_host(relay_parent).await
472				.unwrap_or_else(|e| {
473					gum::warn!(
474						target: LOG_TARGET,
475						api = ?stringify!($api_name),
476						"cannot query the runtime API version: {}",
477						e,
478					);
479					Some(0)
480				})
481				.unwrap_or_else(|| {
482					gum::warn!(
483						target: LOG_TARGET,
484						"no runtime version is reported"
485					);
486					0
487				});
488
489			let res = if runtime_version >= version {
490				client.$api_name(relay_parent $(, $param.clone() )*).await
491					.map_err(|e| RuntimeApiError::Execution {
492						runtime_api_name: stringify!($api_name),
493						source: std::sync::Arc::new(e),
494					})
495			} else {
496				Err(RuntimeApiError::NotSupported {
497					runtime_api_name: stringify!($api_name),
498				})
499			};
500			metrics.on_request(res.is_ok());
501			let _ = sender.send(res.clone());
502
503			res.ok().map(|res| RequestResult::$req_variant($( $results, )* res))
504		}}
505	}
506
507	match request {
508		Request::Version(sender) => {
509			let runtime_version = match client.api_version_parachain_host(relay_parent).await {
510				Ok(Some(v)) => Ok(v),
511				Ok(None) => Err(RuntimeApiError::NotSupported { runtime_api_name: "api_version" }),
512				Err(e) => Err(RuntimeApiError::Execution {
513					runtime_api_name: "api_version",
514					source: std::sync::Arc::new(e),
515				}),
516			};
517
518			let _ = sender.send(runtime_version.clone());
519			runtime_version.ok().map(|v| RequestResult::Version(relay_parent, v))
520		},
521
522		Request::Authorities(sender) => query!(Authorities, authorities(), ver = 1, sender),
523		Request::Validators(sender) => query!(Validators, validators(), ver = 1, sender),
524		Request::ValidatorGroups(sender) => {
525			query!(ValidatorGroups, validator_groups(), ver = 1, sender)
526		},
527		Request::AvailabilityCores(sender) => {
528			query!(AvailabilityCores, availability_cores(), ver = 1, sender)
529		},
530		Request::PersistedValidationData(para, assumption, sender) => query!(
531			PersistedValidationData,
532			persisted_validation_data(para, assumption),
533			ver = 1,
534			sender
535		),
536		Request::AssumedValidationData(para, expected_persisted_validation_data_hash, sender) => {
537			query!(
538				AssumedValidationData,
539				assumed_validation_data(para, expected_persisted_validation_data_hash),
540				ver = 1,
541				sender
542			)
543		},
544		Request::CheckValidationOutputs(para, commitments, sender) => query!(
545			CheckValidationOutputs,
546			check_validation_outputs(para, commitments),
547			ver = 1,
548			sender
549		),
550		Request::SessionIndexForChild(sender) => {
551			query!(SessionIndexForChild, session_index_for_child(), ver = 1, sender)
552		},
553		Request::ValidationCode(para, assumption, sender) => {
554			query!(ValidationCode, validation_code(para, assumption), ver = 1, sender)
555		},
556		Request::ValidationCodeByHash(validation_code_hash, sender) => query!(
557			ValidationCodeByHash,
558			validation_code_by_hash(validation_code_hash),
559			ver = 1,
560			sender
561		),
562		Request::CandidatePendingAvailability(para, sender) => query!(
563			CandidatePendingAvailability,
564			candidate_pending_availability(para),
565			ver = 1,
566			sender
567		),
568		Request::CandidatesPendingAvailability(para, sender) => query!(
569			CandidatesPendingAvailability,
570			candidates_pending_availability(para),
571			ver = Request::CANDIDATES_PENDING_AVAILABILITY_RUNTIME_REQUIREMENT,
572			sender
573		),
574		Request::CandidateEvents(sender) => {
575			query!(CandidateEvents, candidate_events(), ver = 1, sender)
576		},
577		Request::SessionInfo(index, sender) => {
578			query!(SessionInfo, session_info(index), ver = 2, sender)
579		},
580		Request::SessionExecutorParams(session_index, sender) => query!(
581			SessionExecutorParams,
582			session_executor_params(session_index),
583			ver = Request::EXECUTOR_PARAMS_RUNTIME_REQUIREMENT,
584			sender
585		),
586		Request::DmqContents(id, sender) => query!(DmqContents, dmq_contents(id), ver = 1, sender),
587		Request::InboundHrmpChannelsContents(id, sender) => {
588			query!(InboundHrmpChannelsContents, inbound_hrmp_channels_contents(id), ver = 1, sender)
589		},
590		Request::CurrentBabeEpoch(sender) => {
591			query!(CurrentBabeEpoch, current_epoch(), ver = 1, sender)
592		},
593		Request::FetchOnChainVotes(sender) => {
594			query!(FetchOnChainVotes, on_chain_votes(), ver = 1, sender)
595		},
596		Request::SubmitPvfCheckStatement(stmt, signature, sender) => {
597			query!(
598				SubmitPvfCheckStatement,
599				submit_pvf_check_statement(stmt, signature),
600				ver = 2,
601				sender,
602				result = ()
603			)
604		},
605		Request::PvfsRequirePrecheck(sender) => {
606			query!(PvfsRequirePrecheck, pvfs_require_precheck(), ver = 2, sender)
607		},
608		Request::ValidationCodeHash(para, assumption, sender) => {
609			query!(ValidationCodeHash, validation_code_hash(para, assumption), ver = 2, sender)
610		},
611		Request::Disputes(sender) => {
612			query!(Disputes, disputes(), ver = Request::DISPUTES_RUNTIME_REQUIREMENT, sender)
613		},
614		Request::UnappliedSlashes(sender) => query!(
615			UnappliedSlashes,
616			unapplied_slashes(),
617			ver = Request::UNAPPLIED_SLASHES_RUNTIME_REQUIREMENT,
618			sender
619		),
620		Request::KeyOwnershipProof(validator_id, sender) => query!(
621			KeyOwnershipProof,
622			key_ownership_proof(validator_id),
623			ver = Request::KEY_OWNERSHIP_PROOF_RUNTIME_REQUIREMENT,
624			sender
625		),
626		Request::ApprovalVotingParams(session_index, sender) => {
627			query!(
628				ApprovalVotingParams,
629				approval_voting_params(session_index),
630				ver = Request::APPROVAL_VOTING_PARAMS_REQUIREMENT,
631				sender
632			)
633		},
634		Request::SubmitReportDisputeLost(dispute_proof, key_ownership_proof, sender) => query!(
635			SubmitReportDisputeLost,
636			submit_report_dispute_lost(dispute_proof, key_ownership_proof),
637			ver = Request::SUBMIT_REPORT_DISPUTE_LOST_RUNTIME_REQUIREMENT,
638			sender,
639			result = ()
640		),
641		Request::MinimumBackingVotes(index, sender) => query!(
642			MinimumBackingVotes,
643			minimum_backing_votes(index),
644			ver = Request::MINIMUM_BACKING_VOTES_RUNTIME_REQUIREMENT,
645			sender,
646			result = (index)
647		),
648		Request::DisabledValidators(sender) => query!(
649			DisabledValidators,
650			disabled_validators(),
651			ver = Request::DISABLED_VALIDATORS_RUNTIME_REQUIREMENT,
652			sender
653		),
654		Request::ParaBackingState(para, sender) => {
655			query!(
656				ParaBackingState,
657				para_backing_state(para),
658				ver = Request::ASYNC_BACKING_STATE_RUNTIME_REQUIREMENT,
659				sender
660			)
661		},
662		Request::AsyncBackingParams(sender) => {
663			query!(
664				AsyncBackingParams,
665				async_backing_params(),
666				ver = Request::ASYNC_BACKING_STATE_RUNTIME_REQUIREMENT,
667				sender
668			)
669		},
670		Request::NodeFeatures(index, sender) => query!(
671			NodeFeatures,
672			node_features(),
673			ver = Request::NODE_FEATURES_RUNTIME_REQUIREMENT,
674			sender,
675			result = (index)
676		),
677		Request::ClaimQueue(sender) => query!(
678			ClaimQueue,
679			claim_queue(),
680			ver = Request::CLAIM_QUEUE_RUNTIME_REQUIREMENT,
681			sender
682		),
683		Request::BackingConstraints(para, sender) => {
684			query!(
685				BackingConstraints,
686				backing_constraints(para),
687				ver = Request::CONSTRAINTS_RUNTIME_REQUIREMENT,
688				sender
689			)
690		},
691		Request::SchedulingLookahead(index, sender) => query!(
692			SchedulingLookahead,
693			scheduling_lookahead(),
694			ver = Request::SCHEDULING_LOOKAHEAD_RUNTIME_REQUIREMENT,
695			sender,
696			result = (index)
697		),
698		Request::ValidationCodeBombLimit(index, sender) => query!(
699			ValidationCodeBombLimit,
700			validation_code_bomb_limit(),
701			ver = Request::VALIDATION_CODE_BOMB_LIMIT_RUNTIME_REQUIREMENT,
702			sender,
703			result = (index)
704		),
705	}
706}