referrerpolicy=no-referrer-when-downgrade

polkadot_primitives/v9/
mod.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//! `V9` Primitives.
18
19use alloc::{
20	collections::{BTreeMap, BTreeSet, VecDeque},
21	vec,
22	vec::{IntoIter, Vec},
23};
24
25use bitvec::{field::BitField, prelude::*, slice::BitSlice};
26
27use codec::{Decode, DecodeWithMemTracking, Encode};
28use scale_info::TypeInfo;
29
30use core::{
31	marker::PhantomData,
32	slice::{Iter, IterMut},
33};
34
35#[cfg(feature = "test")]
36use sp_application_crypto::ByteArray;
37use sp_application_crypto::KeyTypeId;
38use sp_arithmetic::{
39	traits::{BaseArithmetic, Saturating},
40	Perbill,
41};
42
43use bounded_collections::BoundedVec;
44use serde::{Deserialize, Serialize};
45use sp_core::ConstU32;
46use sp_inherents::InherentIdentifier;
47
48// ==========
49// PUBLIC RE-EXPORTS
50// ==========
51
52pub use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
53pub use sp_consensus_slots::Slot;
54pub use sp_runtime::traits::{AppVerify, BlakeTwo256, Hash as HashT, Header as HeaderT};
55pub use sp_staking::SessionIndex;
56
57// Export some core primitives.
58pub use polkadot_core_primitives::v2::{
59	AccountId, AccountIndex, AccountPublic, Balance, Block, BlockId, BlockNumber, CandidateHash,
60	ChainId, DownwardMessage, Hash, Header, InboundDownwardMessage, InboundHrmpMessage, Moment,
61	Nonce, OutboundHrmpMessage, Remark, Signature, UncheckedExtrinsic,
62};
63
64// Export some polkadot-parachain primitives
65pub use polkadot_parachain_primitives::primitives::{
66	HeadData, HorizontalMessages, HrmpChannelId, Id, Id as ParaId, UpwardMessage, UpwardMessages,
67	ValidationCode, ValidationCodeHash, LOWEST_PUBLIC_ID,
68};
69
70/// Signed data.
71mod signed;
72pub use signed::{EncodeAs, Signed, UncheckedSigned};
73
74pub mod async_backing;
75pub mod executor_params;
76pub mod slashing;
77
78pub use async_backing::AsyncBackingParams;
79pub use executor_params::{
80	ExecutorHostFunction, ExecutorParam, ExecutorParamError, ExecutorParams, ExecutorParamsHash,
81	ExecutorParamsPrepHash,
82};
83
84mod metrics;
85pub use metrics::{
86	metric_definitions, RuntimeMetricLabel, RuntimeMetricLabelValue, RuntimeMetricLabelValues,
87	RuntimeMetricLabels, RuntimeMetricOp, RuntimeMetricUpdate,
88};
89
90/// The key type ID for a collator key.
91pub const COLLATOR_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"coll");
92const LOG_TARGET: &str = "runtime::primitives";
93
94mod collator_app {
95	use sp_application_crypto::{app_crypto, sr25519};
96	app_crypto!(sr25519, super::COLLATOR_KEY_TYPE_ID);
97}
98
99/// Identity that collators use.
100pub type CollatorId = collator_app::Public;
101
102/// A Parachain collator keypair.
103#[cfg(feature = "std")]
104pub type CollatorPair = collator_app::Pair;
105
106/// Signature on candidate's block data by a collator.
107pub type CollatorSignature = collator_app::Signature;
108
109/// The key type ID for a parachain validator key.
110pub const PARACHAIN_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"para");
111
112mod validator_app {
113	use sp_application_crypto::{app_crypto, sr25519};
114	app_crypto!(sr25519, super::PARACHAIN_KEY_TYPE_ID);
115}
116
117/// Identity that parachain validators use when signing validation messages.
118///
119/// For now we assert that parachain validator set is exactly equivalent to the authority set, and
120/// so we define it to be the same type as `SessionKey`. In the future it may have different crypto.
121pub type ValidatorId = validator_app::Public;
122
123/// Trait required for type specific indices e.g. `ValidatorIndex` and `GroupIndex`
124pub trait TypeIndex {
125	/// Returns the index associated to this value.
126	fn type_index(&self) -> usize;
127}
128
129/// Index of the validator is used as a lightweight replacement of the `ValidatorId` when
130/// appropriate.
131#[derive(
132	Eq,
133	Ord,
134	PartialEq,
135	PartialOrd,
136	Copy,
137	Clone,
138	Encode,
139	Decode,
140	DecodeWithMemTracking,
141	TypeInfo,
142	Debug,
143)]
144#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))]
145pub struct ValidatorIndex(pub u32);
146
147/// Index of an availability chunk.
148///
149/// The underlying type is identical to `ValidatorIndex`, because
150/// the number of chunks will always be equal to the number of validators.
151/// However, the chunk index held by a validator may not always be equal to its `ValidatorIndex`, so
152/// we use a separate type to make code easier to read.
153#[derive(Eq, Ord, PartialEq, PartialOrd, Copy, Clone, Encode, Decode, TypeInfo, Debug)]
154#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash))]
155pub struct ChunkIndex(pub u32);
156
157impl From<ChunkIndex> for ValidatorIndex {
158	fn from(c_index: ChunkIndex) -> Self {
159		ValidatorIndex(c_index.0)
160	}
161}
162
163impl From<ValidatorIndex> for ChunkIndex {
164	fn from(v_index: ValidatorIndex) -> Self {
165		ChunkIndex(v_index.0)
166	}
167}
168
169impl From<u32> for ChunkIndex {
170	fn from(n: u32) -> Self {
171		ChunkIndex(n)
172	}
173}
174
175// We should really get https://github.com/paritytech/polkadot/issues/2403 going ..
176impl From<u32> for ValidatorIndex {
177	fn from(n: u32) -> Self {
178		ValidatorIndex(n)
179	}
180}
181
182impl TypeIndex for ValidatorIndex {
183	fn type_index(&self) -> usize {
184		self.0 as usize
185	}
186}
187
188sp_application_crypto::with_pair! {
189	/// A Parachain validator keypair.
190	pub type ValidatorPair = validator_app::Pair;
191}
192
193/// Signature with which parachain validators sign blocks.
194///
195/// For now we assert that parachain validator set is exactly equivalent to the authority set, and
196/// so we define it to be the same type as `SessionKey`. In the future it may have different crypto.
197pub type ValidatorSignature = validator_app::Signature;
198
199/// A declarations of storage keys where an external observer can find some interesting data.
200pub mod well_known_keys {
201	use super::{HrmpChannelId, Id, WellKnownKey};
202	use alloc::vec::Vec;
203	use codec::Encode as _;
204	use hex_literal::hex;
205	use sp_io::hashing::twox_64;
206
207	// A note on generating these magic values below:
208	//
209	// The `StorageValue`, such as `ACTIVE_CONFIG` was obtained by calling:
210	//
211	//     ActiveConfig::<T>::hashed_key()
212	//
213	// The `StorageMap` values require `prefix`, and for example for `hrmp_egress_channel_index`,
214	// it could be obtained like:
215	//
216	//     HrmpEgressChannelsIndex::<T>::prefix_hash();
217	//
218
219	/// The current epoch index.
220	///
221	/// The storage item should be access as a `u64` encoded value.
222	pub const EPOCH_INDEX: &[u8] =
223		&hex!["1cb6f36e027abb2091cfb5110ab5087f38316cbf8fa0da822a20ac1c55bf1be3"];
224
225	/// The current relay chain block randomness
226	///
227	/// The storage item should be accessed as a `schnorrkel::Randomness` encoded value.
228	pub const CURRENT_BLOCK_RANDOMNESS: &[u8] =
229		&hex!["1cb6f36e027abb2091cfb5110ab5087fd077dfdb8adb10f78f10a5df8742c545"];
230
231	/// The randomness for one epoch ago
232	///
233	/// The storage item should be accessed as a `schnorrkel::Randomness` encoded value.
234	pub const ONE_EPOCH_AGO_RANDOMNESS: &[u8] =
235		&hex!["1cb6f36e027abb2091cfb5110ab5087f7ce678799d3eff024253b90e84927cc6"];
236
237	/// The randomness for two epochs ago
238	///
239	/// The storage item should be accessed as a `schnorrkel::Randomness` encoded value.
240	pub const TWO_EPOCHS_AGO_RANDOMNESS: &[u8] =
241		&hex!["1cb6f36e027abb2091cfb5110ab5087f7a414cb008e0e61e46722aa60abdd672"];
242
243	/// The current slot number.
244	///
245	/// The storage entry should be accessed as a `Slot` encoded value.
246	pub const CURRENT_SLOT: &[u8] =
247		&hex!["1cb6f36e027abb2091cfb5110ab5087f06155b3cd9a8c9e5e9a23fd5dc13a5ed"];
248
249	/// The currently active host configuration.
250	///
251	/// The storage entry should be accessed as an `AbridgedHostConfiguration` encoded value.
252	pub const ACTIVE_CONFIG: &[u8] =
253		&hex!["06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385"];
254
255	/// The authorities for the current epoch.
256	///
257	/// The storage entry should be accessed as an `Vec<(AuthorityId, BabeAuthorityWeight)>` encoded
258	/// value.
259	pub const AUTHORITIES: &[u8] =
260		&hex!["1cb6f36e027abb2091cfb5110ab5087f5e0621c4869aa60c02be9adcc98a0d1d"];
261
262	/// The authorities for the next epoch.
263	///
264	/// The storage entry should be accessed as an `Vec<(AuthorityId, BabeAuthorityWeight)>` encoded
265	/// value.
266	pub const NEXT_AUTHORITIES: &[u8] =
267		&hex!["1cb6f36e027abb2091cfb5110ab5087faacf00b9b41fda7a9268821c2a2b3e4c"];
268
269	/// Hash of the committed head data for a given registered para.
270	///
271	/// The storage entry stores wrapped `HeadData(Vec<u8>)`.
272	pub fn para_head(para_id: Id) -> Vec<u8> {
273		let prefix = hex!["cd710b30bd2eab0352ddcc26417aa1941b3c252fcb29d88eff4f3de5de4476c3"];
274
275		para_id.using_encoded(|para_id: &[u8]| {
276			prefix
277				.as_ref()
278				.iter()
279				.chain(twox_64(para_id).iter())
280				.chain(para_id.iter())
281				.cloned()
282				.collect()
283		})
284	}
285
286	/// The upward message dispatch queue for the given para id.
287	///
288	/// The storage entry stores a tuple of two values:
289	///
290	/// - `count: u32`, the number of messages currently in the queue for given para,
291	/// - `total_size: u32`, the total size of all messages in the queue.
292	#[deprecated = "Use `relay_dispatch_queue_remaining_capacity` instead"]
293	pub fn relay_dispatch_queue_size(para_id: Id) -> Vec<u8> {
294		let prefix = hex!["f5207f03cfdce586301014700e2c2593fad157e461d71fd4c1f936839a5f1f3e"];
295
296		para_id.using_encoded(|para_id: &[u8]| {
297			prefix
298				.as_ref()
299				.iter()
300				.chain(twox_64(para_id).iter())
301				.chain(para_id.iter())
302				.cloned()
303				.collect()
304		})
305	}
306
307	/// Type safe version of `relay_dispatch_queue_size`.
308	#[deprecated = "Use `relay_dispatch_queue_remaining_capacity` instead"]
309	pub fn relay_dispatch_queue_size_typed(para: Id) -> WellKnownKey<(u32, u32)> {
310		#[allow(deprecated)]
311		relay_dispatch_queue_size(para).into()
312	}
313
314	/// The upward message dispatch queue remaining capacity for the given para id.
315	///
316	/// The storage entry stores a tuple of two values:
317	///
318	/// - `count: u32`, the number of additional messages which may be enqueued for the given para,
319	/// - `total_size: u32`, the total size of additional messages which may be enqueued for the
320	/// given para.
321	pub fn relay_dispatch_queue_remaining_capacity(para_id: Id) -> WellKnownKey<(u32, u32)> {
322		(b":relay_dispatch_queue_remaining_capacity", para_id).encode().into()
323	}
324
325	/// The HRMP channel for the given identifier.
326	///
327	/// The storage entry should be accessed as an `AbridgedHrmpChannel` encoded value.
328	pub fn hrmp_channels(channel: HrmpChannelId) -> Vec<u8> {
329		let prefix = hex!["6a0da05ca59913bc38a8630590f2627cb6604cff828a6e3f579ca6c59ace013d"];
330
331		channel.using_encoded(|channel: &[u8]| {
332			prefix
333				.as_ref()
334				.iter()
335				.chain(twox_64(channel).iter())
336				.chain(channel.iter())
337				.cloned()
338				.collect()
339		})
340	}
341
342	/// The list of inbound channels for the given para.
343	///
344	/// The storage entry stores a `Vec<ParaId>`
345	pub fn hrmp_ingress_channel_index(para_id: Id) -> Vec<u8> {
346		let prefix = hex!["6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948"];
347
348		para_id.using_encoded(|para_id: &[u8]| {
349			prefix
350				.as_ref()
351				.iter()
352				.chain(twox_64(para_id).iter())
353				.chain(para_id.iter())
354				.cloned()
355				.collect()
356		})
357	}
358
359	/// The list of outbound channels for the given para.
360	///
361	/// The storage entry stores a `Vec<ParaId>`
362	pub fn hrmp_egress_channel_index(para_id: Id) -> Vec<u8> {
363		let prefix = hex!["6a0da05ca59913bc38a8630590f2627cf12b746dcf32e843354583c9702cc020"];
364
365		para_id.using_encoded(|para_id: &[u8]| {
366			prefix
367				.as_ref()
368				.iter()
369				.chain(twox_64(para_id).iter())
370				.chain(para_id.iter())
371				.cloned()
372				.collect()
373		})
374	}
375
376	/// The MQC head for the downward message queue of the given para. See more in the `Dmp` module.
377	///
378	/// The storage entry stores a `Hash`. This is polkadot hash which is at the moment
379	/// `blake2b-256`.
380	pub fn dmq_mqc_head(para_id: Id) -> Vec<u8> {
381		let prefix = hex!["63f78c98723ddc9073523ef3beefda0c4d7fefc408aac59dbfe80a72ac8e3ce5"];
382
383		para_id.using_encoded(|para_id: &[u8]| {
384			prefix
385				.as_ref()
386				.iter()
387				.chain(twox_64(para_id).iter())
388				.chain(para_id.iter())
389				.cloned()
390				.collect()
391		})
392	}
393
394	/// The signal that indicates whether the parachain should go-ahead with the proposed validation
395	/// code upgrade.
396	///
397	/// The storage entry stores a value of `UpgradeGoAhead` type.
398	pub fn upgrade_go_ahead_signal(para_id: Id) -> Vec<u8> {
399		let prefix = hex!["cd710b30bd2eab0352ddcc26417aa1949e94c040f5e73d9b7addd6cb603d15d3"];
400
401		para_id.using_encoded(|para_id: &[u8]| {
402			prefix
403				.as_ref()
404				.iter()
405				.chain(twox_64(para_id).iter())
406				.chain(para_id.iter())
407				.cloned()
408				.collect()
409		})
410	}
411
412	/// The signal that indicates whether the parachain is disallowed to signal an upgrade at this
413	/// relay-parent.
414	///
415	/// The storage entry stores a value of `UpgradeRestriction` type.
416	pub fn upgrade_restriction_signal(para_id: Id) -> Vec<u8> {
417		let prefix = hex!["cd710b30bd2eab0352ddcc26417aa194f27bbb460270642b5bcaf032ea04d56a"];
418
419		para_id.using_encoded(|para_id: &[u8]| {
420			prefix
421				.as_ref()
422				.iter()
423				.chain(twox_64(para_id).iter())
424				.chain(para_id.iter())
425				.cloned()
426				.collect()
427		})
428	}
429}
430
431/// Relay chain slot duration in milliseconds, which is the same
432/// value across all networks (e.g. Polkadot, Kusama, Westend, Rococo).
433pub const RELAY_CHAIN_SLOT_DURATION_MILLIS: u64 = 6000;
434
435/// Unique identifier for the Parachains Inherent
436pub const PARACHAINS_INHERENT_IDENTIFIER: InherentIdentifier = *b"parachn0";
437
438/// The key type ID for parachain assignment key.
439pub const ASSIGNMENT_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"asgn");
440
441/// Compressed or not the wasm blob can never be less than 9 bytes.
442pub const MIN_CODE_SIZE: u32 = 9;
443
444/// Maximum compressed code size we support right now.
445/// At the moment we have runtime upgrade on chain, which restricts scalability severely. If we want
446/// to have bigger values, we should fix that first.
447///
448/// Used for:
449/// * initial genesis for the Parachains configuration
450/// * checking updates to this stored runtime configuration do not exceed this limit
451// NOTE: This value is used in the runtime so be careful when changing it.
452pub const MAX_CODE_SIZE: u32 = 5 * 1024 * 1024;
453
454/// Maximum head data size we support right now.
455///
456/// Used for:
457/// * initial genesis for the Parachains configuration
458/// * checking updates to this stored runtime configuration do not exceed this limit
459// NOTE: This value is used in the runtime so be careful when changing it.
460pub const MAX_HEAD_DATA_SIZE: u32 = 1 * 1024 * 1024;
461
462/// Maximum PoV size we support right now.
463///
464/// Used for:
465/// * initial genesis for the Parachains configuration
466/// * checking updates to this stored runtime configuration do not exceed this limit
467/// * when detecting a PoV decompression bomb in the client
468// NOTE: This value is used in the runtime so be careful when changing it.
469pub const MAX_POV_SIZE: u32 = 10 * 1024 * 1024;
470
471/// Default queue size we use for the on-demand order book.
472///
473/// Can be adjusted in configuration.
474pub const ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE: u32 = 10_000;
475
476/// Maximum for maximum queue size.
477///
478/// We use this value for benchmarking.
479pub const ON_DEMAND_MAX_QUEUE_MAX_SIZE: u32 = 10_000;
480
481/// Backing votes threshold used from the host prior to runtime API version 6 and from the runtime
482/// prior to v9 configuration migration.
483pub const LEGACY_MIN_BACKING_VOTES: u32 = 2;
484
485/// Default value for `SchedulerParams.lookahead`
486pub const DEFAULT_SCHEDULING_LOOKAHEAD: u32 = 3;
487
488// The public key of a keypair used by a validator for determining assignments
489/// to approve included parachain candidates.
490mod assignment_app {
491	use sp_application_crypto::{app_crypto, sr25519};
492	app_crypto!(sr25519, super::ASSIGNMENT_KEY_TYPE_ID);
493}
494
495/// The public key of a keypair used by a validator for determining assignments
496/// to approve included parachain candidates.
497pub type AssignmentId = assignment_app::Public;
498
499sp_application_crypto::with_pair! {
500	/// The full keypair used by a validator for determining assignments to approve included
501	/// parachain candidates.
502	pub type AssignmentPair = assignment_app::Pair;
503}
504
505/// The index of the candidate in the list of candidates fully included as-of the block.
506pub type CandidateIndex = u32;
507
508/// The validation data provides information about how to create the inputs for validation of a
509/// candidate. This information is derived from the chain state and will vary from para to para,
510/// although some fields may be the same for every para.
511///
512/// Since this data is used to form inputs to the validation function, it needs to be persisted by
513/// the availability system to avoid dependence on availability of the relay-chain state.
514///
515/// Furthermore, the validation data acts as a way to authorize the additional data the collator
516/// needs to pass to the validation function. For example, the validation function can check whether
517/// the incoming messages (e.g. downward messages) were actually sent by using the data provided in
518/// the validation data using so called MQC heads.
519///
520/// Since the commitments of the validation function are checked by the relay-chain, secondary
521/// checkers can rely on the invariant that the relay-chain only includes para-blocks for which
522/// these checks have already been done. As such, there is no need for the validation data used to
523/// inform validators and collators about the checks the relay-chain will perform to be persisted by
524/// the availability system.
525///
526/// The `PersistedValidationData` should be relatively lightweight primarily because it is
527/// constructed during inclusion for each candidate and therefore lies on the critical path of
528/// inclusion.
529#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug)]
530#[cfg_attr(feature = "std", derive(Default))]
531pub struct PersistedValidationData<H = Hash, N = BlockNumber> {
532	/// The parent head-data.
533	pub parent_head: HeadData,
534	/// The relay-chain block number this is in the context of.
535	pub relay_parent_number: N,
536	/// The relay-chain block storage root this is in the context of.
537	pub relay_parent_storage_root: H,
538	/// The maximum legal size of a POV block, in bytes.
539	pub max_pov_size: u32,
540}
541
542impl<H: Encode, N: Encode> PersistedValidationData<H, N> {
543	/// Compute the blake2-256 hash of the persisted validation data.
544	pub fn hash(&self) -> Hash {
545		BlakeTwo256::hash_of(self)
546	}
547}
548
549/// Commitments made in a `CandidateReceipt`. Many of these are outputs of validation.
550#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug)]
551#[cfg_attr(feature = "std", derive(Default, Hash))]
552pub struct CandidateCommitments<N = BlockNumber> {
553	/// Messages destined to be interpreted by the Relay chain itself.
554	pub upward_messages: UpwardMessages,
555	/// Horizontal messages sent by the parachain.
556	pub horizontal_messages: HorizontalMessages,
557	/// New validation code.
558	pub new_validation_code: Option<ValidationCode>,
559	/// The head-data produced as a result of execution.
560	pub head_data: HeadData,
561	/// The number of messages processed from the DMQ.
562	pub processed_downward_messages: u32,
563	/// The mark which specifies the block number up to which all inbound HRMP messages are
564	/// processed.
565	pub hrmp_watermark: N,
566}
567
568impl CandidateCommitments {
569	/// Compute the blake2-256 hash of the commitments.
570	pub fn hash(&self) -> Hash {
571		BlakeTwo256::hash_of(self)
572	}
573}
574
575/// A bitfield concerning availability of backed candidates.
576///
577/// Every bit refers to an availability core index.
578#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
579pub struct AvailabilityBitfield(pub BitVec<u8, bitvec::order::Lsb0>);
580
581impl From<BitVec<u8, bitvec::order::Lsb0>> for AvailabilityBitfield {
582	fn from(inner: BitVec<u8, bitvec::order::Lsb0>) -> Self {
583		AvailabilityBitfield(inner)
584	}
585}
586
587/// A signed compact statement, suitable to be sent to the chain.
588pub type SignedStatement = Signed<CompactStatement>;
589/// A signed compact statement, with signature not yet checked.
590pub type UncheckedSignedStatement = UncheckedSigned<CompactStatement>;
591
592/// A bitfield signed by a particular validator about the availability of pending candidates.
593pub type SignedAvailabilityBitfield = Signed<AvailabilityBitfield>;
594/// A signed bitfield with signature not yet checked.
595pub type UncheckedSignedAvailabilityBitfield = UncheckedSigned<AvailabilityBitfield>;
596
597/// A set of signed availability bitfields. Should be sorted by validator index, ascending.
598pub type SignedAvailabilityBitfields = Vec<SignedAvailabilityBitfield>;
599/// A set of unchecked signed availability bitfields. Should be sorted by validator index,
600/// ascending.
601pub type UncheckedSignedAvailabilityBitfields = Vec<UncheckedSignedAvailabilityBitfield>;
602
603/// Verify the backing of the given candidate.
604///
605/// Provide a lookup from the index of a validator within the group assigned to this para,
606/// as opposed to the index of the validator within the overall validator set, as well as
607/// the number of validators in the group.
608///
609/// Also provide the signing context.
610///
611/// Returns either an error, indicating that one of the signatures was invalid or that the index
612/// was out-of-bounds, or the number of signatures checked.
613pub fn check_candidate_backing<H: AsRef<[u8]> + Clone + Encode + core::fmt::Debug>(
614	candidate_hash: CandidateHash,
615	validity_votes: &[ValidityAttestation],
616	validator_indices: &BitSlice<u8, bitvec::order::Lsb0>,
617	signing_context: &SigningContext<H>,
618	group_len: usize,
619	validator_lookup: impl Fn(usize) -> Option<ValidatorId>,
620) -> Result<usize, ()> {
621	if validator_indices.len() != group_len {
622		log::debug!(
623			target: LOG_TARGET,
624			"Check candidate backing: indices mismatch: group_len = {} , indices_len = {}",
625			group_len,
626			validator_indices.len(),
627		);
628		return Err(());
629	}
630
631	if validity_votes.len() > group_len {
632		log::debug!(
633			target: LOG_TARGET,
634			"Check candidate backing: Too many votes, expected: {}, found: {}",
635			group_len,
636			validity_votes.len(),
637		);
638		return Err(());
639	}
640
641	let mut signed = 0;
642	for ((val_in_group_idx, _), attestation) in validator_indices
643		.iter()
644		.enumerate()
645		.filter(|(_, signed)| **signed)
646		.zip(validity_votes.iter())
647	{
648		let validator_id = validator_lookup(val_in_group_idx).ok_or(())?;
649		let payload = attestation.signed_payload(candidate_hash, signing_context);
650		let sig = attestation.signature();
651
652		if sig.verify(&payload[..], &validator_id) {
653			signed += 1;
654		} else {
655			log::debug!(
656				target: LOG_TARGET,
657				"Check candidate backing: Invalid signature. validator_id = {:?}, validator_index = {} ",
658				validator_id,
659				val_in_group_idx,
660			);
661			return Err(());
662		}
663	}
664
665	if signed != validity_votes.len() {
666		log::error!(
667			target: LOG_TARGET,
668			"Check candidate backing: Too many signatures, expected = {}, found = {}",
669			validity_votes.len(),
670			signed,
671		);
672		return Err(());
673	}
674
675	Ok(signed)
676}
677
678/// The unique (during session) index of a core.
679#[derive(
680	Encode,
681	Decode,
682	DecodeWithMemTracking,
683	Default,
684	PartialOrd,
685	Ord,
686	Eq,
687	PartialEq,
688	Clone,
689	Copy,
690	TypeInfo,
691	Debug,
692)]
693#[cfg_attr(feature = "std", derive(Hash))]
694pub struct CoreIndex(pub u32);
695
696impl From<u32> for CoreIndex {
697	fn from(i: u32) -> CoreIndex {
698		CoreIndex(i)
699	}
700}
701
702impl TypeIndex for CoreIndex {
703	fn type_index(&self) -> usize {
704		self.0 as usize
705	}
706}
707
708/// The unique (during session) index of a validator group.
709#[derive(
710	Encode,
711	Decode,
712	DecodeWithMemTracking,
713	Default,
714	Clone,
715	Copy,
716	Debug,
717	PartialEq,
718	Eq,
719	TypeInfo,
720	PartialOrd,
721	Ord,
722)]
723#[cfg_attr(feature = "std", derive(Hash))]
724pub struct GroupIndex(pub u32);
725
726impl From<u32> for GroupIndex {
727	fn from(i: u32) -> GroupIndex {
728		GroupIndex(i)
729	}
730}
731
732impl TypeIndex for GroupIndex {
733	fn type_index(&self) -> usize {
734		self.0 as usize
735	}
736}
737
738/// A claim on authoring the next block for a given parathread (on-demand parachain).
739#[derive(Clone, Encode, Decode, TypeInfo, PartialEq, Debug)]
740pub struct ParathreadClaim(pub Id, pub Option<CollatorId>);
741
742/// An entry tracking a claim to ensure it does not pass the maximum number of retries.
743#[derive(Clone, Encode, Decode, TypeInfo, PartialEq, Debug)]
744pub struct ParathreadEntry {
745	/// The claim.
746	pub claim: ParathreadClaim,
747	/// Number of retries
748	pub retries: u32,
749}
750
751/// A helper data-type for tracking validator-group rotations.
752#[derive(Clone, Encode, Decode, TypeInfo, Debug)]
753#[cfg_attr(feature = "std", derive(PartialEq))]
754pub struct GroupRotationInfo<N = BlockNumber> {
755	/// The block number where the session started.
756	pub session_start_block: N,
757	/// How often groups rotate. 0 means never.
758	pub group_rotation_frequency: N,
759	/// The current block number.
760	pub now: N,
761}
762
763impl GroupRotationInfo {
764	/// Returns the index of the group needed to validate the core at the given index, assuming
765	/// the given number of cores.
766	///
767	/// `core_index` should be less than `cores`, which is capped at `u32::max()`.
768	pub fn group_for_core(&self, core_index: CoreIndex, cores: usize) -> GroupIndex {
769		if self.group_rotation_frequency == 0 {
770			return GroupIndex(core_index.0);
771		}
772		if cores == 0 {
773			return GroupIndex(0);
774		}
775
776		let cores = core::cmp::min(cores, u32::MAX as usize);
777		let blocks_since_start = self.now.saturating_sub(self.session_start_block);
778		let rotations = blocks_since_start / self.group_rotation_frequency;
779
780		// g = c + r mod cores
781
782		let idx = (core_index.0 as usize + rotations as usize) % cores;
783		GroupIndex(idx as u32)
784	}
785
786	/// Returns the index of the group assigned to the given core. This does no checking or
787	/// whether the group index is in-bounds.
788	///
789	/// `core_index` should be less than `cores`, which is capped at `u32::max()`.
790	pub fn core_for_group(&self, group_index: GroupIndex, cores: usize) -> CoreIndex {
791		if self.group_rotation_frequency == 0 {
792			return CoreIndex(group_index.0);
793		}
794		if cores == 0 {
795			return CoreIndex(0);
796		}
797
798		let cores = core::cmp::min(cores, u32::MAX as usize);
799		let blocks_since_start = self.now.saturating_sub(self.session_start_block);
800		let rotations = blocks_since_start / self.group_rotation_frequency;
801		let rotations = rotations % cores as u32;
802
803		// g = c + r mod cores
804		// c = g - r mod cores
805		// x = x + cores mod cores
806		// c = (g + cores) - r mod cores
807
808		let idx = (group_index.0 as usize + cores - rotations as usize) % cores;
809		CoreIndex(idx as u32)
810	}
811
812	/// Create a new `GroupRotationInfo` with one further rotation applied.
813	pub fn bump_rotation(&self) -> Self {
814		GroupRotationInfo {
815			session_start_block: self.session_start_block,
816			group_rotation_frequency: self.group_rotation_frequency,
817			now: self.next_rotation_at(),
818		}
819	}
820}
821
822impl<N: Saturating + BaseArithmetic + Copy> GroupRotationInfo<N> {
823	/// Returns the block number of the next rotation after the current block. If the current block
824	/// is 10 and the rotation frequency is 5, this should return 15.
825	pub fn next_rotation_at(&self) -> N {
826		let cycle_once = self.now + self.group_rotation_frequency;
827		cycle_once -
828			(cycle_once.saturating_sub(self.session_start_block) % self.group_rotation_frequency)
829	}
830
831	/// Returns the block number of the last rotation before or including the current block. If the
832	/// current block is 10 and the rotation frequency is 5, this should return 10.
833	pub fn last_rotation_at(&self) -> N {
834		self.now -
835			(self.now.saturating_sub(self.session_start_block) % self.group_rotation_frequency)
836	}
837}
838
839/// Information about a core which is currently occupied.
840#[derive(Clone, Encode, Decode, TypeInfo, Debug)]
841#[cfg_attr(feature = "std", derive(PartialEq))]
842pub struct ScheduledCore {
843	/// The ID of a para scheduled.
844	pub para_id: Id,
845	/// DEPRECATED: see: <https://github.com/paritytech/polkadot/issues/7575>
846	///
847	/// Will be removed in a future version.
848	pub collator: Option<CollatorId>,
849}
850
851/// An assumption being made about the state of an occupied core.
852#[derive(Clone, Copy, Encode, Decode, TypeInfo, Debug)]
853#[cfg_attr(feature = "std", derive(PartialEq, Eq, Hash))]
854pub enum OccupiedCoreAssumption {
855	/// The candidate occupying the core was made available and included to free the core.
856	#[codec(index = 0)]
857	Included,
858	/// The candidate occupying the core timed out and freed the core without advancing the para.
859	#[codec(index = 1)]
860	TimedOut,
861	/// The core was not occupied to begin with.
862	#[codec(index = 2)]
863	Free,
864}
865
866/// A vote of approval on a candidate.
867#[derive(Clone, Debug)]
868pub struct ApprovalVote(pub CandidateHash);
869
870impl ApprovalVote {
871	/// Yields the signing payload for this approval vote.
872	pub fn signing_payload(&self, session_index: SessionIndex) -> Vec<u8> {
873		const MAGIC: [u8; 4] = *b"APPR";
874
875		(MAGIC, &self.0, session_index).encode()
876	}
877}
878
879/// A vote of approval for multiple candidates.
880#[derive(Clone, Debug)]
881pub struct ApprovalVoteMultipleCandidates<'a>(pub &'a [CandidateHash]);
882
883impl<'a> ApprovalVoteMultipleCandidates<'a> {
884	/// Yields the signing payload for this approval vote.
885	pub fn signing_payload(&self, session_index: SessionIndex) -> Vec<u8> {
886		const MAGIC: [u8; 4] = *b"APPR";
887		// Make this backwards compatible with `ApprovalVote` so if we have just on candidate the
888		// signature will look the same.
889		// This gives us the nice benefit that old nodes can still check signatures when len is 1
890		// and the new node can check the signature coming from old nodes.
891		if self.0.len() == 1 {
892			(MAGIC, self.0.first().expect("QED: we just checked"), session_index).encode()
893		} else {
894			(MAGIC, &self.0, session_index).encode()
895		}
896	}
897}
898
899/// Approval voting configuration parameters
900#[derive(
901	Debug,
902	Copy,
903	Clone,
904	PartialEq,
905	Encode,
906	Decode,
907	DecodeWithMemTracking,
908	TypeInfo,
909	serde::Serialize,
910	serde::Deserialize,
911)]
912pub struct ApprovalVotingParams {
913	/// The maximum number of candidates `approval-voting` can vote for with
914	/// a single signatures.
915	///
916	/// Setting it to 1, means we send the approval as soon as we have it available.
917	pub max_approval_coalesce_count: u32,
918}
919
920impl Default for ApprovalVotingParams {
921	fn default() -> Self {
922		Self { max_approval_coalesce_count: 1 }
923	}
924}
925
926/// Custom validity errors used in Polkadot while validating transactions.
927#[repr(u8)]
928pub enum ValidityError {
929	/// The Ethereum signature is invalid.
930	InvalidEthereumSignature = 0,
931	/// The signer has no claim.
932	SignerHasNoClaim = 1,
933	/// No permission to execute the call.
934	NoPermission = 2,
935	/// An invalid statement was made for a claim.
936	InvalidStatement = 3,
937}
938
939impl From<ValidityError> for u8 {
940	fn from(err: ValidityError) -> Self {
941		err as u8
942	}
943}
944
945/// Abridged version of `HostConfiguration` (from the `Configuration` parachains host runtime
946/// module) meant to be used by a parachain or PDK such as cumulus.
947#[derive(Clone, Encode, Decode, Debug, TypeInfo)]
948#[cfg_attr(feature = "std", derive(PartialEq))]
949pub struct AbridgedHostConfiguration {
950	/// The maximum validation code size, in bytes.
951	pub max_code_size: u32,
952	/// The maximum head-data size, in bytes.
953	pub max_head_data_size: u32,
954	/// Total number of individual messages allowed in the parachain -> relay-chain message queue.
955	pub max_upward_queue_count: u32,
956	/// Total size of messages allowed in the parachain -> relay-chain message queue before which
957	/// no further messages may be added to it. If it exceeds this then the queue may contain only
958	/// a single message.
959	pub max_upward_queue_size: u32,
960	/// The maximum size of an upward message that can be sent by a candidate.
961	///
962	/// This parameter affects the size upper bound of the `CandidateCommitments`.
963	pub max_upward_message_size: u32,
964	/// The maximum number of messages that a candidate can contain.
965	///
966	/// This parameter affects the size upper bound of the `CandidateCommitments`.
967	pub max_upward_message_num_per_candidate: u32,
968	/// The maximum number of outbound HRMP messages can be sent by a candidate.
969	///
970	/// This parameter affects the upper bound of size of `CandidateCommitments`.
971	pub hrmp_max_message_num_per_candidate: u32,
972	/// The minimum period, in blocks, between which parachains can update their validation code.
973	pub validation_upgrade_cooldown: BlockNumber,
974	/// The delay, in blocks, before a validation upgrade is applied.
975	pub validation_upgrade_delay: BlockNumber,
976	/// Asynchronous backing parameters.
977	pub async_backing_params: AsyncBackingParams,
978}
979
980/// Abridged version of `HrmpChannel` (from the `Hrmp` parachains host runtime module) meant to be
981/// used by a parachain or PDK such as cumulus.
982#[derive(Clone, Encode, Decode, Debug, TypeInfo)]
983#[cfg_attr(feature = "std", derive(Default, PartialEq))]
984pub struct AbridgedHrmpChannel {
985	/// The maximum number of messages that can be pending in the channel at once.
986	pub max_capacity: u32,
987	/// The maximum total size of the messages that can be pending in the channel at once.
988	pub max_total_size: u32,
989	/// The maximum message size that could be put into the channel.
990	pub max_message_size: u32,
991	/// The current number of messages pending in the channel.
992	/// Invariant: should be less or equal to `max_capacity`.s`.
993	pub msg_count: u32,
994	/// The total size in bytes of all message payloads in the channel.
995	/// Invariant: should be less or equal to `max_total_size`.
996	pub total_size: u32,
997	/// A head of the Message Queue Chain for this channel. Each link in this chain has a form:
998	/// `(prev_head, B, H(M))`, where
999	/// - `prev_head`: is the previous value of `mqc_head` or zero if none.
1000	/// - `B`: is the [relay-chain] block number in which a message was appended
1001	/// - `H(M)`: is the hash of the message being appended.
1002	/// This value is initialized to a special value that consists of all zeroes which indicates
1003	/// that no messages were previously added.
1004	pub mqc_head: Option<Hash>,
1005}
1006
1007/// A possible upgrade restriction that prevents a parachain from performing an upgrade.
1008#[derive(Copy, Clone, Encode, Decode, PartialEq, Debug, TypeInfo)]
1009pub enum UpgradeRestriction {
1010	/// There is an upgrade restriction and there are no details about its specifics nor how long
1011	/// it could last.
1012	#[codec(index = 0)]
1013	Present,
1014}
1015
1016/// A struct that the relay-chain communicates to a parachain indicating what course of action the
1017/// parachain should take in the coordinated parachain validation code upgrade process.
1018///
1019/// This data type appears in the last step of the upgrade process. After the parachain observes it
1020/// and reacts to it the upgrade process concludes.
1021#[derive(Copy, Clone, Encode, Decode, PartialEq, Debug, TypeInfo)]
1022pub enum UpgradeGoAhead {
1023	/// Abort the upgrade process. There is something wrong with the validation code previously
1024	/// submitted by the parachain. This variant can also be used to prevent upgrades by the
1025	/// governance should an emergency emerge.
1026	///
1027	/// The expected reaction on this variant is that the parachain will admit this message and
1028	/// remove all the data about the pending upgrade. Depending on the nature of the problem (to
1029	/// be examined offchain for now), it can try to send another validation code or just retry
1030	/// later.
1031	#[codec(index = 0)]
1032	Abort,
1033	/// Apply the pending code change. The parablock that is built on a relay-parent that is
1034	/// descendant of the relay-parent where the parachain observed this signal must use the
1035	/// upgraded validation code.
1036	#[codec(index = 1)]
1037	GoAhead,
1038}
1039
1040/// Consensus engine id for polkadot v1 consensus engine.
1041pub const POLKADOT_ENGINE_ID: sp_runtime::ConsensusEngineId = *b"POL1";
1042
1043/// A consensus log item for polkadot validation. To be used with [`POLKADOT_ENGINE_ID`].
1044#[derive(Decode, Encode, Clone, PartialEq, Eq)]
1045pub enum ConsensusLog {
1046	/// A parachain upgraded its code.
1047	#[codec(index = 1)]
1048	ParaUpgradeCode(Id, ValidationCodeHash),
1049	/// A parachain scheduled a code upgrade.
1050	#[codec(index = 2)]
1051	ParaScheduleUpgradeCode(Id, ValidationCodeHash, BlockNumber),
1052	/// Governance requests to auto-approve every candidate included up to the given block
1053	/// number in the current chain, inclusive.
1054	#[codec(index = 3)]
1055	ForceApprove(BlockNumber),
1056	/// A signal to revert the block number in the same chain as the
1057	/// header this digest is part of and all of its descendants.
1058	///
1059	/// It is a no-op for a block to contain a revert digest targeting
1060	/// its own number or a higher number.
1061	///
1062	/// In practice, these are issued when on-chain logic has detected an
1063	/// invalid parachain block within its own chain, due to a dispute.
1064	#[codec(index = 4)]
1065	Revert(BlockNumber),
1066}
1067
1068impl ConsensusLog {
1069	/// Attempt to convert a reference to a generic digest item into a consensus log.
1070	pub fn from_digest_item(
1071		digest_item: &sp_runtime::DigestItem,
1072	) -> Result<Option<Self>, codec::Error> {
1073		match digest_item {
1074			sp_runtime::DigestItem::Consensus(id, encoded) if id == &POLKADOT_ENGINE_ID => {
1075				Ok(Some(Self::decode(&mut &encoded[..])?))
1076			},
1077			_ => Ok(None),
1078		}
1079	}
1080}
1081
1082impl From<ConsensusLog> for sp_runtime::DigestItem {
1083	fn from(c: ConsensusLog) -> sp_runtime::DigestItem {
1084		Self::Consensus(POLKADOT_ENGINE_ID, c.encode())
1085	}
1086}
1087
1088/// A statement about a candidate, to be used within the dispute resolution process.
1089///
1090/// Statements are either in favor of the candidate's validity or against it.
1091#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Debug, TypeInfo)]
1092pub enum DisputeStatement {
1093	/// A valid statement, of the given kind.
1094	#[codec(index = 0)]
1095	Valid(ValidDisputeStatementKind),
1096	/// An invalid statement, of the given kind.
1097	#[codec(index = 1)]
1098	Invalid(InvalidDisputeStatementKind),
1099}
1100
1101impl DisputeStatement {
1102	/// Get the payload data for this type of dispute statement.
1103	///
1104	/// Returns Error if the candidate_hash is not included in the list of signed
1105	/// candidate from ApprovalCheckingMultipleCandidate.
1106	pub fn payload_data(
1107		&self,
1108		candidate_hash: CandidateHash,
1109		session: SessionIndex,
1110	) -> Result<Vec<u8>, ()> {
1111		match self {
1112			DisputeStatement::Valid(ValidDisputeStatementKind::Explicit) => {
1113				Ok(ExplicitDisputeStatement { valid: true, candidate_hash, session }
1114					.signing_payload())
1115			},
1116			DisputeStatement::Valid(ValidDisputeStatementKind::BackingSeconded(
1117				inclusion_parent,
1118			)) => Ok(CompactStatement::Seconded(candidate_hash).signing_payload(&SigningContext {
1119				session_index: session,
1120				parent_hash: *inclusion_parent,
1121			})),
1122			DisputeStatement::Valid(ValidDisputeStatementKind::BackingValid(inclusion_parent)) => {
1123				Ok(CompactStatement::Valid(candidate_hash).signing_payload(&SigningContext {
1124					session_index: session,
1125					parent_hash: *inclusion_parent,
1126				}))
1127			},
1128			DisputeStatement::Valid(ValidDisputeStatementKind::ApprovalChecking) => {
1129				Ok(ApprovalVote(candidate_hash).signing_payload(session))
1130			},
1131			DisputeStatement::Valid(
1132				ValidDisputeStatementKind::ApprovalCheckingMultipleCandidates(candidate_hashes),
1133			) => {
1134				if candidate_hashes.contains(&candidate_hash) {
1135					Ok(ApprovalVoteMultipleCandidates(candidate_hashes).signing_payload(session))
1136				} else {
1137					Err(())
1138				}
1139			},
1140			DisputeStatement::Invalid(InvalidDisputeStatementKind::Explicit) => {
1141				Ok(ExplicitDisputeStatement { valid: false, candidate_hash, session }
1142					.signing_payload())
1143			},
1144		}
1145	}
1146
1147	/// Check the signature on a dispute statement.
1148	pub fn check_signature(
1149		&self,
1150		validator_public: &ValidatorId,
1151		candidate_hash: CandidateHash,
1152		session: SessionIndex,
1153		validator_signature: &ValidatorSignature,
1154	) -> Result<(), ()> {
1155		let payload = self.payload_data(candidate_hash, session)?;
1156
1157		if validator_signature.verify(&payload[..], &validator_public) {
1158			Ok(())
1159		} else {
1160			Err(())
1161		}
1162	}
1163
1164	/// Whether the statement indicates validity.
1165	pub fn indicates_validity(&self) -> bool {
1166		match *self {
1167			DisputeStatement::Valid(_) => true,
1168			DisputeStatement::Invalid(_) => false,
1169		}
1170	}
1171
1172	/// Whether the statement indicates invalidity.
1173	pub fn indicates_invalidity(&self) -> bool {
1174		match *self {
1175			DisputeStatement::Valid(_) => false,
1176			DisputeStatement::Invalid(_) => true,
1177		}
1178	}
1179
1180	/// Statement is backing statement.
1181	pub fn is_backing(&self) -> bool {
1182		match self {
1183			Self::Valid(s) => s.is_backing(),
1184			Self::Invalid(_) => false,
1185		}
1186	}
1187}
1188
1189/// Different kinds of statements of validity on  a candidate.
1190#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Debug, TypeInfo)]
1191pub enum ValidDisputeStatementKind {
1192	/// An explicit statement issued as part of a dispute.
1193	#[codec(index = 0)]
1194	Explicit,
1195	/// A seconded statement on a candidate from the backing phase.
1196	#[codec(index = 1)]
1197	BackingSeconded(Hash),
1198	/// A valid statement on a candidate from the backing phase.
1199	#[codec(index = 2)]
1200	BackingValid(Hash),
1201	/// An approval vote from the approval checking phase.
1202	#[codec(index = 3)]
1203	ApprovalChecking,
1204	/// An approval vote from the new version.
1205	/// We can't create this version until all nodes
1206	/// have been updated to support it and max_approval_coalesce_count
1207	/// is set to more than 1.
1208	#[codec(index = 4)]
1209	ApprovalCheckingMultipleCandidates(Vec<CandidateHash>),
1210}
1211
1212impl ValidDisputeStatementKind {
1213	/// Whether the statement is from the backing phase.
1214	pub fn is_backing(&self) -> bool {
1215		match self {
1216			ValidDisputeStatementKind::BackingSeconded(_) |
1217			ValidDisputeStatementKind::BackingValid(_) => true,
1218			ValidDisputeStatementKind::Explicit |
1219			ValidDisputeStatementKind::ApprovalChecking |
1220			ValidDisputeStatementKind::ApprovalCheckingMultipleCandidates(_) => false,
1221		}
1222	}
1223}
1224
1225/// Different kinds of statements of invalidity on a candidate.
1226#[derive(Encode, Decode, DecodeWithMemTracking, Copy, Clone, PartialEq, Debug, TypeInfo)]
1227pub enum InvalidDisputeStatementKind {
1228	/// An explicit statement issued as part of a dispute.
1229	#[codec(index = 0)]
1230	Explicit,
1231}
1232
1233/// An explicit statement on a candidate issued as part of a dispute.
1234#[derive(Clone, PartialEq, Debug)]
1235pub struct ExplicitDisputeStatement {
1236	/// Whether the candidate is valid
1237	pub valid: bool,
1238	/// The candidate hash.
1239	pub candidate_hash: CandidateHash,
1240	/// The session index of the candidate.
1241	pub session: SessionIndex,
1242}
1243
1244impl ExplicitDisputeStatement {
1245	/// Produce the payload used for signing this type of statement.
1246	pub fn signing_payload(&self) -> Vec<u8> {
1247		const MAGIC: [u8; 4] = *b"DISP";
1248
1249		(MAGIC, self.valid, self.candidate_hash, self.session).encode()
1250	}
1251}
1252
1253/// A set of statements about a specific candidate.
1254#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Debug, TypeInfo)]
1255pub struct DisputeStatementSet {
1256	/// The candidate referenced by this set.
1257	pub candidate_hash: CandidateHash,
1258	/// The session index of the candidate.
1259	pub session: SessionIndex,
1260	/// Statements about the candidate.
1261	pub statements: Vec<(DisputeStatement, ValidatorIndex, ValidatorSignature)>,
1262}
1263
1264impl From<CheckedDisputeStatementSet> for DisputeStatementSet {
1265	fn from(other: CheckedDisputeStatementSet) -> Self {
1266		other.0
1267	}
1268}
1269
1270impl AsRef<DisputeStatementSet> for DisputeStatementSet {
1271	fn as_ref(&self) -> &DisputeStatementSet {
1272		&self
1273	}
1274}
1275
1276/// A set of dispute statements.
1277pub type MultiDisputeStatementSet = Vec<DisputeStatementSet>;
1278
1279/// A _checked_ set of dispute statements.
1280#[derive(Clone, PartialEq, Debug, Encode)]
1281pub struct CheckedDisputeStatementSet(DisputeStatementSet);
1282
1283impl AsRef<DisputeStatementSet> for CheckedDisputeStatementSet {
1284	fn as_ref(&self) -> &DisputeStatementSet {
1285		&self.0
1286	}
1287}
1288
1289impl core::cmp::PartialEq<DisputeStatementSet> for CheckedDisputeStatementSet {
1290	fn eq(&self, other: &DisputeStatementSet) -> bool {
1291		self.0.eq(other)
1292	}
1293}
1294
1295impl CheckedDisputeStatementSet {
1296	/// Convert from an unchecked, the verification of correctness of the `unchecked` statement set
1297	/// _must_ be done before calling this function!
1298	pub fn unchecked_from_unchecked(unchecked: DisputeStatementSet) -> Self {
1299		Self(unchecked)
1300	}
1301}
1302
1303/// A set of _checked_ dispute statements.
1304pub type CheckedMultiDisputeStatementSet = Vec<CheckedDisputeStatementSet>;
1305
1306/// The entire state of a dispute.
1307#[derive(Encode, Decode, Clone, Debug, PartialEq, TypeInfo)]
1308pub struct DisputeState<N = BlockNumber> {
1309	/// A bitfield indicating all validators for the candidate.
1310	pub validators_for: BitVec<u8, bitvec::order::Lsb0>, // one bit per validator.
1311	/// A bitfield indicating all validators against the candidate.
1312	pub validators_against: BitVec<u8, bitvec::order::Lsb0>, // one bit per validator.
1313	/// The block number at which the dispute started on-chain.
1314	pub start: N,
1315	/// The block number at which the dispute concluded on-chain.
1316	pub concluded_at: Option<N>,
1317}
1318
1319/// An either implicit or explicit attestation to the validity of a parachain
1320/// candidate.
1321#[derive(Clone, Eq, PartialEq, Decode, DecodeWithMemTracking, Encode, Debug, TypeInfo)]
1322pub enum ValidityAttestation {
1323	/// Implicit validity attestation by issuing.
1324	/// This corresponds to issuance of a `Candidate` statement.
1325	#[codec(index = 1)]
1326	Implicit(ValidatorSignature),
1327	/// An explicit attestation. This corresponds to issuance of a
1328	/// `Valid` statement.
1329	#[codec(index = 2)]
1330	Explicit(ValidatorSignature),
1331}
1332
1333impl ValidityAttestation {
1334	/// Produce the underlying signed payload of the attestation, given the hash of the candidate,
1335	/// which should be known in context.
1336	pub fn to_compact_statement(&self, candidate_hash: CandidateHash) -> CompactStatement {
1337		// Explicit and implicit map directly from
1338		// `ValidityVote::Valid` and `ValidityVote::Issued`, and hence there is a
1339		// `1:1` relationship which enables the conversion.
1340		match *self {
1341			ValidityAttestation::Implicit(_) => CompactStatement::Seconded(candidate_hash),
1342			ValidityAttestation::Explicit(_) => CompactStatement::Valid(candidate_hash),
1343		}
1344	}
1345
1346	/// Get a reference to the signature.
1347	pub fn signature(&self) -> &ValidatorSignature {
1348		match *self {
1349			ValidityAttestation::Implicit(ref sig) => sig,
1350			ValidityAttestation::Explicit(ref sig) => sig,
1351		}
1352	}
1353
1354	/// Produce the underlying signed payload of the attestation, given the hash of the candidate,
1355	/// which should be known in context.
1356	pub fn signed_payload<H: Encode>(
1357		&self,
1358		candidate_hash: CandidateHash,
1359		signing_context: &SigningContext<H>,
1360	) -> Vec<u8> {
1361		match *self {
1362			ValidityAttestation::Implicit(_) => {
1363				(CompactStatement::Seconded(candidate_hash), signing_context).encode()
1364			},
1365			ValidityAttestation::Explicit(_) => {
1366				(CompactStatement::Valid(candidate_hash), signing_context).encode()
1367			},
1368		}
1369	}
1370}
1371
1372/// A type returned by runtime with current session index and a parent hash.
1373#[derive(Clone, Eq, PartialEq, Default, Decode, Encode, Debug)]
1374pub struct SigningContext<H = Hash> {
1375	/// Current session index.
1376	pub session_index: sp_staking::SessionIndex,
1377	/// Hash of the parent.
1378	pub parent_hash: H,
1379}
1380
1381const BACKING_STATEMENT_MAGIC: [u8; 4] = *b"BKNG";
1382
1383/// Statements that can be made about parachain candidates. These are the
1384/// actual values that are signed.
1385#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
1386#[cfg_attr(feature = "std", derive(Hash))]
1387pub enum CompactStatement {
1388	/// Proposal of a parachain candidate.
1389	Seconded(CandidateHash),
1390	/// State that a parachain candidate is valid.
1391	Valid(CandidateHash),
1392}
1393
1394impl CompactStatement {
1395	/// Yields the payload used for validator signatures on this kind
1396	/// of statement.
1397	pub fn signing_payload(&self, context: &SigningContext) -> Vec<u8> {
1398		(self, context).encode()
1399	}
1400
1401	/// Get the underlying candidate hash this references.
1402	pub fn candidate_hash(&self) -> &CandidateHash {
1403		match *self {
1404			CompactStatement::Seconded(ref h) | CompactStatement::Valid(ref h) => h,
1405		}
1406	}
1407}
1408
1409// Inner helper for codec on `CompactStatement`.
1410#[derive(Encode, Decode, TypeInfo)]
1411enum CompactStatementInner {
1412	#[codec(index = 1)]
1413	Seconded(CandidateHash),
1414	#[codec(index = 2)]
1415	Valid(CandidateHash),
1416}
1417
1418impl From<CompactStatement> for CompactStatementInner {
1419	fn from(s: CompactStatement) -> Self {
1420		match s {
1421			CompactStatement::Seconded(h) => CompactStatementInner::Seconded(h),
1422			CompactStatement::Valid(h) => CompactStatementInner::Valid(h),
1423		}
1424	}
1425}
1426
1427impl codec::Encode for CompactStatement {
1428	fn size_hint(&self) -> usize {
1429		// magic + discriminant + payload
1430		4 + 1 + 32
1431	}
1432
1433	fn encode_to<T: codec::Output + ?Sized>(&self, dest: &mut T) {
1434		dest.write(&BACKING_STATEMENT_MAGIC);
1435		CompactStatementInner::from(self.clone()).encode_to(dest)
1436	}
1437}
1438
1439impl codec::Decode for CompactStatement {
1440	fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
1441		let maybe_magic = <[u8; 4]>::decode(input)?;
1442		if maybe_magic != BACKING_STATEMENT_MAGIC {
1443			return Err(codec::Error::from("invalid magic string"));
1444		}
1445
1446		Ok(match CompactStatementInner::decode(input)? {
1447			CompactStatementInner::Seconded(h) => CompactStatement::Seconded(h),
1448			CompactStatementInner::Valid(h) => CompactStatement::Valid(h),
1449		})
1450	}
1451}
1452
1453/// `IndexedVec` struct indexed by type specific indices.
1454#[derive(Clone, Encode, Decode, Debug, TypeInfo)]
1455#[cfg_attr(feature = "std", derive(PartialEq))]
1456pub struct IndexedVec<K, V>(Vec<V>, PhantomData<fn(K) -> K>);
1457
1458impl<K, V> Default for IndexedVec<K, V> {
1459	fn default() -> Self {
1460		Self(vec![], PhantomData)
1461	}
1462}
1463
1464impl<K, V> From<Vec<V>> for IndexedVec<K, V> {
1465	fn from(validators: Vec<V>) -> Self {
1466		Self(validators, PhantomData)
1467	}
1468}
1469
1470impl<K, V> FromIterator<V> for IndexedVec<K, V> {
1471	fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
1472		Self(Vec::from_iter(iter), PhantomData)
1473	}
1474}
1475
1476impl<K, V> IndexedVec<K, V>
1477where
1478	V: Clone,
1479{
1480	/// Returns a reference to an element indexed using `K`.
1481	pub fn get(&self, index: K) -> Option<&V>
1482	where
1483		K: TypeIndex,
1484	{
1485		self.0.get(index.type_index())
1486	}
1487
1488	/// Returns a mutable reference to an element indexed using `K`.
1489	pub fn get_mut(&mut self, index: K) -> Option<&mut V>
1490	where
1491		K: TypeIndex,
1492	{
1493		self.0.get_mut(index.type_index())
1494	}
1495
1496	/// Returns number of elements in vector.
1497	pub fn len(&self) -> usize {
1498		self.0.len()
1499	}
1500
1501	/// Returns contained vector.
1502	pub fn to_vec(&self) -> Vec<V> {
1503		self.0.clone()
1504	}
1505
1506	/// Returns an iterator over the underlying vector.
1507	pub fn iter(&self) -> Iter<'_, V> {
1508		self.0.iter()
1509	}
1510
1511	/// Returns a mutable iterator over the underlying vector.
1512	pub fn iter_mut(&mut self) -> IterMut<'_, V> {
1513		self.0.iter_mut()
1514	}
1515
1516	/// Creates a consuming iterator.
1517	pub fn into_iter(self) -> IntoIter<V> {
1518		self.0.into_iter()
1519	}
1520
1521	/// Returns true if the underlying container is empty.
1522	pub fn is_empty(&self) -> bool {
1523		self.0.is_empty()
1524	}
1525}
1526
1527/// The maximum number of validators `f` which may safely be faulty.
1528///
1529/// The total number of validators is `n = 3f + e` where `e in { 1, 2, 3 }`.
1530pub const fn byzantine_threshold(n: usize) -> usize {
1531	n.saturating_sub(1) / 3
1532}
1533
1534/// The supermajority threshold of validators which represents a subset
1535/// guaranteed to have at least f+1 honest validators.
1536pub const fn supermajority_threshold(n: usize) -> usize {
1537	n - byzantine_threshold(n)
1538}
1539
1540/// Adjust the configured needed backing votes with the size of the backing group.
1541pub fn effective_minimum_backing_votes(
1542	group_len: usize,
1543	configured_minimum_backing_votes: u32,
1544) -> usize {
1545	core::cmp::min(group_len, configured_minimum_backing_votes as usize)
1546}
1547
1548/// Information about validator sets of a session.
1549///
1550/// NOTE: `SessionInfo` is frozen. Do not include new fields, consider creating a separate runtime
1551/// API. Reasoning and further outlook [here](https://github.com/paritytech/polkadot/issues/6586).
1552#[derive(Clone, Encode, Decode, Debug, TypeInfo)]
1553#[cfg_attr(feature = "std", derive(PartialEq))]
1554pub struct SessionInfo {
1555	/// **** New in v2 ******
1556	/// All the validators actively participating in parachain consensus.
1557	/// Indices are into the broader validator set.
1558	pub active_validator_indices: Vec<ValidatorIndex>,
1559	/// A secure random seed for the session, gathered from BABE.
1560	pub random_seed: [u8; 32],
1561	/// The amount of sessions to keep for disputes.
1562	pub dispute_period: SessionIndex,
1563
1564	/// **** Old fields *****
1565	/// Validators in canonical ordering.
1566	///
1567	/// NOTE: There might be more authorities in the current session, than `validators`
1568	/// participating in parachain consensus. See
1569	/// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148).
1570	///
1571	/// `SessionInfo::validators` will be limited to `max_validators` when set.
1572	pub validators: IndexedVec<ValidatorIndex, ValidatorId>,
1573	/// Validators' authority discovery keys for the session in canonical ordering.
1574	///
1575	/// NOTE: The first `validators.len()` entries will match the corresponding validators in
1576	/// `validators`, afterwards any remaining authorities can be found. This is any authorities
1577	/// not participating in parachain consensus - see
1578	/// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148)
1579	pub discovery_keys: Vec<AuthorityDiscoveryId>,
1580	/// The assignment keys for validators.
1581	///
1582	/// NOTE: There might be more authorities in the current session, than validators participating
1583	/// in parachain consensus. See
1584	/// [`max_validators`](https://github.com/paritytech/polkadot/blob/a52dca2be7840b23c19c153cf7e110b1e3e475f8/runtime/parachains/src/configuration.rs#L148).
1585	///
1586	/// Therefore:
1587	/// ```ignore
1588	/// 	assignment_keys.len() == validators.len() && validators.len() <= discovery_keys.len()
1589	/// ```
1590	pub assignment_keys: Vec<AssignmentId>,
1591	/// Validators in shuffled ordering - these are the validator groups as produced
1592	/// by the `Scheduler` module for the session and are typically referred to by
1593	/// `GroupIndex`.
1594	pub validator_groups: IndexedVec<GroupIndex, Vec<ValidatorIndex>>,
1595	/// The number of availability cores used by the protocol during this session.
1596	pub n_cores: u32,
1597	/// The zeroth delay tranche width.
1598	pub zeroth_delay_tranche_width: u32,
1599	/// The number of samples we do of `relay_vrf_modulo`.
1600	pub relay_vrf_modulo_samples: u32,
1601	/// The number of delay tranches in total.
1602	pub n_delay_tranches: u32,
1603	/// How many slots (BABE / SASSAFRAS) must pass before an assignment is considered a
1604	/// no-show.
1605	pub no_show_slots: u32,
1606	/// The number of validators needed to approve a block.
1607	pub needed_approvals: u32,
1608}
1609
1610/// A statement from the specified validator whether the given validation code passes PVF
1611/// pre-checking or not anchored to the given session index.
1612#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Debug, TypeInfo)]
1613pub struct PvfCheckStatement {
1614	/// `true` if the subject passed pre-checking and `false` otherwise.
1615	pub accept: bool,
1616	/// The validation code hash that was checked.
1617	pub subject: ValidationCodeHash,
1618	/// The index of a session during which this statement is considered valid.
1619	pub session_index: SessionIndex,
1620	/// The index of the validator from which this statement originates.
1621	pub validator_index: ValidatorIndex,
1622}
1623
1624impl PvfCheckStatement {
1625	/// Produce the payload used for signing this type of statement.
1626	///
1627	/// It is expected that it will be signed by the validator at `validator_index` in the
1628	/// `session_index`.
1629	pub fn signing_payload(&self) -> Vec<u8> {
1630		const MAGIC: [u8; 4] = *b"VCPC"; // for "validation code pre-checking"
1631		(MAGIC, self.accept, self.subject, self.session_index, self.validator_index).encode()
1632	}
1633}
1634
1635/// A well-known and typed storage key.
1636///
1637/// Allows for type-safe access to raw well-known storage keys.
1638pub struct WellKnownKey<T> {
1639	/// The raw storage key.
1640	pub key: Vec<u8>,
1641	_p: core::marker::PhantomData<T>,
1642}
1643
1644impl<T> From<Vec<u8>> for WellKnownKey<T> {
1645	fn from(key: Vec<u8>) -> Self {
1646		Self { key, _p: Default::default() }
1647	}
1648}
1649
1650impl<T> AsRef<[u8]> for WellKnownKey<T> {
1651	fn as_ref(&self) -> &[u8] {
1652		self.key.as_ref()
1653	}
1654}
1655
1656impl<T: Decode> WellKnownKey<T> {
1657	/// Gets the value or `None` if it does not exist or decoding failed.
1658	pub fn get(&self) -> Option<T> {
1659		sp_io::storage::get(&self.key)
1660			.and_then(|raw| codec::DecodeAll::decode_all(&mut raw.as_ref()).ok())
1661	}
1662}
1663
1664impl<T: Encode> WellKnownKey<T> {
1665	/// Sets the value.
1666	pub fn set(&self, value: T) {
1667		sp_io::storage::set(&self.key, &value.encode());
1668	}
1669}
1670
1671/// Type discriminator for PVF preparation.
1672#[derive(
1673	Encode,
1674	Decode,
1675	DecodeWithMemTracking,
1676	TypeInfo,
1677	Clone,
1678	Copy,
1679	Debug,
1680	PartialEq,
1681	Eq,
1682	Serialize,
1683	Deserialize,
1684)]
1685pub enum PvfPrepKind {
1686	/// For prechecking requests.
1687	Precheck,
1688
1689	/// For execution and heads-up requests.
1690	Prepare,
1691}
1692
1693/// Type discriminator for PVF execution.
1694#[derive(
1695	Encode,
1696	Decode,
1697	DecodeWithMemTracking,
1698	TypeInfo,
1699	Clone,
1700	Copy,
1701	Debug,
1702	PartialEq,
1703	Eq,
1704	Serialize,
1705	Deserialize,
1706)]
1707pub enum PvfExecKind {
1708	/// For backing requests.
1709	Backing,
1710	/// For approval and dispute request.
1711	Approval,
1712}
1713
1714/// Bit indices in the `HostConfiguration.node_features` that correspond to different node features.
1715pub type NodeFeatures = BitVec<u8, bitvec::order::Lsb0>;
1716
1717/// Module containing feature-specific bit indices into the `NodeFeatures` bitvec.
1718pub mod node_features {
1719	use crate::NodeFeatures;
1720
1721	/// A feature index used to identify a bit into the node_features array stored
1722	/// in the HostConfiguration.
1723	#[repr(u8)]
1724	#[derive(Clone, Copy)]
1725	pub enum FeatureIndex {
1726		/// Tells if tranch0 assignments could be sent in a single certificate.
1727		/// Reserved for: `<https://github.com/paritytech/polkadot-sdk/issues/628>`
1728		EnableAssignmentsV2 = 0,
1729		/// This feature enables the extension of `BackedCandidate::validator_indices` by 8 bits.
1730		/// The value stored there represents the assumed core index where the candidates
1731		/// are backed. This is needed for the elastic scaling MVP.
1732		ElasticScalingMVP = 1,
1733		/// Tells if the chunk mapping feature is enabled.
1734		/// Enables the implementation of
1735		/// [RFC-47](https://github.com/polkadot-fellows/RFCs/blob/main/text/0047-assignment-of-availability-chunks.md).
1736		/// Must not be enabled unless all validators and collators have stopped using `req_chunk`
1737		/// protocol version 1. If it is enabled, validators can start systematic chunk recovery.
1738		AvailabilityChunkMapping = 2,
1739		/// Enables node side support of `CoreIndex` committed candidate receipts.
1740		/// See [RFC-103](https://github.com/polkadot-fellows/RFCs/pull/103) for details.
1741		/// Only enable if at least 2/3 of nodes support the feature.
1742		CandidateReceiptV2 = 3,
1743		/// Enables support for scheduling information in the Candidate Descriptor.
1744		CandidateReceiptV3 = 4,
1745		/// First unassigned feature bit.
1746		/// Every time a new feature flag is assigned it should take this value.
1747		/// and this should be incremented.
1748		FirstUnassigned = 5,
1749	}
1750
1751	impl FeatureIndex {
1752		/// Check wheter the feature is enabled.
1753		pub fn is_set(self, node_features: &NodeFeatures) -> bool {
1754			node_features.get(self as usize).map(|v| *v).unwrap_or(false)
1755		}
1756	}
1757}
1758
1759/// Scheduler configuration parameters. All coretime/ondemand parameters are here.
1760#[derive(
1761	Debug,
1762	Copy,
1763	Clone,
1764	PartialEq,
1765	Encode,
1766	Decode,
1767	DecodeWithMemTracking,
1768	TypeInfo,
1769	serde::Serialize,
1770	serde::Deserialize,
1771)]
1772pub struct SchedulerParams<BlockNumber> {
1773	/// How often parachain groups should be rotated across parachains.
1774	///
1775	/// Must be non-zero.
1776	pub group_rotation_frequency: BlockNumber,
1777	/// Availability timeout for a block on a core, measured in blocks.
1778	///
1779	/// This is the maximum amount of blocks after a core became occupied that validators have time
1780	/// to make the block available.
1781	///
1782	/// This value only has effect on group rotations. If backers backed something at the end of
1783	/// their rotation, the occupied core affects the backing group that comes afterwards. We limit
1784	/// the effect one backing group can have on the next to `paras_availability_period` blocks.
1785	///
1786	/// Within a group rotation there is no timeout as backers are only affecting themselves.
1787	///
1788	/// Must be at least 1. With a value of 1, the previous group will not be able to negatively
1789	/// affect the following group at the expense of a tight availability timeline at group
1790	/// rotation boundaries.
1791	pub paras_availability_period: BlockNumber,
1792	/// The maximum number of validators to have per core.
1793	///
1794	/// `None` means no maximum.
1795	pub max_validators_per_core: Option<u32>,
1796	/// The amount of blocks ahead to schedule paras.
1797	pub lookahead: u32,
1798	/// How many cores are managed by the coretime chain.
1799	pub num_cores: u32,
1800	/// Deprecated and no longer used by the runtime.
1801	/// Removal is tracked by <https://github.com/paritytech/polkadot-sdk/issues/6067>.
1802	#[deprecated]
1803	pub max_availability_timeouts: u32,
1804	/// The maximum queue size of the pay as you go module.
1805	pub on_demand_queue_max_size: u32,
1806	/// The target utilization of the spot price queue in percentages.
1807	pub on_demand_target_queue_utilization: Perbill,
1808	/// How quickly the fee rises in reaction to increased utilization.
1809	/// The lower the number the slower the increase.
1810	pub on_demand_fee_variability: Perbill,
1811	/// The minimum amount needed to claim a slot in the spot pricing queue.
1812	pub on_demand_base_fee: Balance,
1813	/// Deprecated and no longer used by the runtime.
1814	/// Removal is tracked by <https://github.com/paritytech/polkadot-sdk/issues/6067>.
1815	#[deprecated]
1816	pub ttl: BlockNumber,
1817}
1818
1819impl<BlockNumber: Default + From<u32>> Default for SchedulerParams<BlockNumber> {
1820	#[allow(deprecated)]
1821	fn default() -> Self {
1822		Self {
1823			group_rotation_frequency: 1u32.into(),
1824			paras_availability_period: 1u32.into(),
1825			max_validators_per_core: Default::default(),
1826			lookahead: 1,
1827			num_cores: Default::default(),
1828			max_availability_timeouts: Default::default(),
1829			on_demand_queue_max_size: ON_DEMAND_DEFAULT_QUEUE_MAX_SIZE,
1830			on_demand_target_queue_utilization: Perbill::from_percent(25),
1831			on_demand_fee_variability: Perbill::from_percent(3),
1832			on_demand_base_fee: 10_000_000u128,
1833			ttl: 5u32.into(),
1834		}
1835	}
1836}
1837
1838/// A type representing the version of the candidate descriptor.
1839#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, TypeInfo, Debug, PartialOrd, Ord, Hash)]
1840pub enum CandidateDescriptorVersion {
1841	/// with deprecated collator id and collator signature.
1842	V1,
1843	/// First properly versioned candidate.
1844	///
1845	/// - Removes collator signature and collator id fields.
1846	/// - Introduces:
1847	/// -- A version field.
1848	/// -- session index field.
1849	/// -- core index field.
1850	V2,
1851	/// Candidate with scheduling info.
1852	V3,
1853	/// An unknown/not yet supported version.
1854	///
1855	/// Such a candidate must be dropped by the runtime and rejected by backers.
1856	Unknown,
1857}
1858
1859/// Error returned by [`CandidateDescriptorV2::check_version_acceptance`].
1860#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1861pub enum CandidateDescriptorVersionCheckError {
1862	/// Old-style and new-style version detection disagree, and this is not the
1863	/// expected V3 disagreement (old rules → V1, new rules → V3) with V3 enabled.
1864	Inconsistency,
1865	/// The descriptor is V3 but the V3 feature is not enabled.
1866	V3NotEnabled,
1867}
1868
1869// Manual Display impl required because this type is used in `no_std` runtime
1870// code (paras_inherent) where thiserror::Error is not available.
1871impl core::fmt::Display for CandidateDescriptorVersionCheckError {
1872	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1873		match self {
1874			Self::Inconsistency => {
1875				write!(f, "Descriptor version detection inconsistency (old vs new rules disagree)")
1876			},
1877			Self::V3NotEnabled => write!(f, "V3 candidate descriptor but V3 feature not enabled"),
1878		}
1879	}
1880}
1881
1882/// A unique descriptor of the candidate receipt.
1883#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo)]
1884pub struct CandidateDescriptorV2<H = Hash> {
1885	/// The ID of the para this is a candidate for.
1886	pub(super) para_id: ParaId,
1887	/// The hash of the relay-chain block this is executed in the context of.
1888	relay_parent: H,
1889	/// Version field. The raw value here is not exposed, instead it is used
1890	/// to determine the `CandidateDescriptorVersion`, see `fn version()`.
1891	/// For the current version this field is set to `0` and will be incremented
1892	/// by next versions.
1893	pub(super) version: u8,
1894	/// The core index where the candidate is backed.
1895	pub(super) core_index: u16,
1896	/// The session index of the candidate relay parent.
1897	session_index: SessionIndex,
1898	/// Offset from `session_index` to derive the scheduling session (introduced in v3).
1899	///
1900	/// Stored as a `u8` offset rather than a full `SessionIndex` to fit within the
1901	/// descriptor layout: `scheduling_session = session_index + scheduling_session_offset`.
1902	scheduling_session_offset: u8,
1903	/// Reserved bytes.
1904	reserved1: [u8; 24],
1905	/// The blake2-256 hash of the persisted validation data. This is extra data derived from
1906	/// relay-chain state which may vary based on bitfields included before the candidate.
1907	/// Thus it cannot be derived entirely from the relay-parent.
1908	persisted_validation_data_hash: Hash,
1909	/// The blake2-256 hash of the PoV.
1910	pov_hash: Hash,
1911	/// The root of a block's erasure encoding Merkle tree.
1912	erasure_root: Hash,
1913	/// The relay chain block determining scheduling.
1914	scheduling_parent: H, // Introduced in v3
1915	/// Reserved bytes.
1916	reserved2: [u8; 32],
1917	/// Hash of the para header that is being generated by this candidate.
1918	para_head: Hash,
1919	/// The blake2-256 hash of the validation code bytes.
1920	validation_code_hash: ValidationCodeHash,
1921}
1922
1923impl<H: AsRef<[u8]>> CandidateDescriptorV2<H> {
1924	/// Returns the candidate descriptor version.
1925	///
1926	/// NOTE: The candidate descriptor versioning is subtle for as long as we
1927	/// need to support the unversioned V1. The issue is that by default we
1928	/// assume a V1 descriptor - as soon as any of the reserved bytes are
1929	/// non-zero. Now if we introduce any new fields, then there will exist
1930	/// candidates where any old node will think that descriptors of that new
1931	/// version are actually V1 (non-zero contents), while upgraded nodes will
1932	/// either see v3 or an unknown version.
1933	///
1934	/// We solve this by completely gating v3 behavior behind the v3 node
1935	/// feature, which must only be enabled once enough validators have upgraded
1936	/// to support it. Any backers still running on the old version are
1937	/// protected by the relay chain runtime, which will drop any illegally
1938	/// (under v3) backed candidates.
1939	///
1940	/// For this to work we now also require a present UMP signal for any
1941	/// version higher or equal than V3. This is enforced by the runtime.
1942	///
1943	/// Via this, if an old node was presented a v3 candidate, which it would
1944	/// consider a V1, it would either detect itself that it is invalid, because
1945	/// of present UMP signals - which is illegal on v1 or the candidate would
1946	/// get rejected by the runtime, because for v3 UMP signals are mandatory.
1947	/// In both cases the backer wont't be slashed.
1948	///
1949	/// There are also candidates that would be treated as v1 by old nodes, but
1950	/// would result in an Unknown version on updated clients. For this
1951	/// scenario, also the runtime provides protection:
1952	///
1953	/// 1. Before the feature is enabled, all nodes will behave as if no v3
1954	/// would exist - all nodes would detect a V1.
1955	/// 2. After the upgrade, the runtime will also (in addition to upgraded
1956	/// nodes) detect an unknown version and no v1 and thus would drop it.
1957	///
1958	/// TL;DR: Yes old nodes will errorneously treat v3 candidates as v1, but we
1959	/// ensure via the relay chain runtime that this stays harmless for backers.
1960	/// V2 approval voters would get disabled, which means a super majority must
1961	/// have updated before enabling the v3 node feature.
1962	///
1963	/// Crucially for this to work: Behavior must not change before the node
1964	/// feature is present and enabled, together with new UMP signal
1965	/// requirements, the runtime can provide the necessary protection.
1966	///
1967	/// To ease future upgrades, we reduced the v1 check once v3 is enabled, so
1968	/// some actually unused bytes are available (don't affect the v1 version
1969	/// check).
1970	///
1971	/// Always uses the relaxed (v3-capable) detection logic. This means
1972	/// version detection is self-contained and does not require knowing
1973	/// whether the V3 node feature is enabled.
1974	///
1975	/// The safety invariant is maintained by the runtime and backing
1976	/// subsystem: they reject candidates where `version()` and
1977	/// `version_old_rules()` disagree when V3 is not yet enabled, and
1978	/// reject V3 candidates outright when V3 is not enabled.
1979	///
1980	/// During the V3 transition, approval checkers, dispute participants,
1981	/// and on-chain vote scrapers must use [`Self::version_for_candidate_validation`]
1982	/// (and the corresponding `scheduling_parent_for_candidate_validation` /
1983	/// `scheduling_session_for_candidate_validation`) instead of `version()`
1984	/// directly. This ensures they match old backer semantics before the V3
1985	/// node feature is confirmed enabled. See those methods for the full
1986	/// safety argument.
1987	pub fn version(&self) -> CandidateDescriptorVersion {
1988		self.v3_version()
1989	}
1990
1991	/// Detect the version using the pre-V3 (stricter) rules.
1992	///
1993	/// Under these rules, all reserved fields, `scheduling_parent`, and
1994	/// `scheduling_session_offset` must be zero for a descriptor to be
1995	/// considered V2. Any non-zero value in those fields causes V1
1996	/// detection. V3 descriptors appear as V1 under these rules.
1997	///
1998	/// Used together with `version()` in consistency checks: if the two
1999	/// methods disagree, the candidate is ambiguous and must be rejected
2000	/// when V3 is not enabled.
2001	pub fn version_old_rules(&self) -> CandidateDescriptorVersion {
2002		self.v2_version()
2003	}
2004
2005	/// Returns `true` if the old-style and new-style version detection agree.
2006	///
2007	/// When V3 is not enabled, both runtime and backing must reject candidates
2008	/// where this returns `false`, preventing ambiguous candidates from landing
2009	/// on-chain. Once V3 is enabled, disagreement is expected for V3 candidates
2010	/// (old rules see V1, new rules see V3) and this check is skipped.
2011	pub fn check_version_consistency(&self) -> bool {
2012		self.version() == self.version_old_rules()
2013	}
2014
2015	/// Validates that the descriptor version is acceptable given whether V3 is enabled.
2016	///
2017	/// Used by both the runtime (`check_descriptor_version_and_signals`) and the
2018	/// backing subsystem. Serves two distinct purposes:
2019	///
2020	/// 1. **V2 ambiguity protection (long-lived):** Old-style and new-style version detection must
2021	///    agree, unless the candidate is V3 and V3 is enabled (the expected disagreement: old rules
2022	///    see V1, new rules see V3). This prevents a crafted candidate from being treated as V2 (no
2023	///    mandatory UMP signals) by new nodes but as V1 by old nodes. Needed as long as V1 exists
2024	///    (maximum safety) or until we could have valiators not yet using the new rules.
2025	///
2026	/// 2. **V3 gating (transitional):** V3 candidates are rejected when V3 is not enabled.
2027	///
2028	/// Note: Consistent `Unknown` versions are not our concern here — they are caught upstream
2029	/// by the runtime (`check_descriptor_version_and_signals`) and the collator
2030	/// protocol (`descriptor_version_sanity_check`).
2031	pub fn check_version_acceptance(
2032		&self,
2033		v3_enabled: bool,
2034	) -> Result<(), CandidateDescriptorVersionCheckError> {
2035		let version = self.version();
2036
2037		// Version consistency: old and new detection must agree, unless this is the
2038		// expected V3 disagreement (old rules → V1, new rules → V3) with V3 enabled.
2039		let is_expected_v3_disagreement = version == CandidateDescriptorVersion::V3 && v3_enabled;
2040		if !self.check_version_consistency() && !is_expected_v3_disagreement {
2041			return Err(CandidateDescriptorVersionCheckError::Inconsistency);
2042		}
2043
2044		// V3 gating: reject V3 candidates before the feature is enabled.
2045		if version == CandidateDescriptorVersion::V3 && !v3_enabled {
2046			return Err(CandidateDescriptorVersionCheckError::V3NotEnabled);
2047		}
2048
2049		Ok(())
2050	}
2051
2052	fn v2_version(&self) -> CandidateDescriptorVersion {
2053		// V1 detected using the pre-v3 (stricter) check: all reserved and new
2054		// fields must be zero. Once v3 is enabled, the v1 check is relaxed in
2055		// `v3_version()` to free up more bytes for future use.
2056		let old_v1_detected = self.reserved2 != [0u8; 32] ||
2057			self.reserved1 != [0u8; 24] ||
2058			self.scheduling_session_offset != 0 ||
2059			self.scheduling_parent.as_ref() != &[0u8; 32];
2060
2061		if old_v1_detected {
2062			return CandidateDescriptorVersion::V1;
2063		}
2064
2065		match self.version {
2066			0 => CandidateDescriptorVersion::V2,
2067			_ => CandidateDescriptorVersion::Unknown,
2068		}
2069	}
2070}
2071
2072impl<H> CandidateDescriptorV2<H> {
2073	fn v3_version(&self) -> CandidateDescriptorVersion {
2074		// Reduce checked bits for v1 significantly to make more bytes easier
2075		// usable in future upgrades. 16 bytes is 32 hexadecimal digits which
2076		// must all be 0 by accident to cause any issues. Bitcoin hardest
2077		// difficulty so far has been 24 digits/12 bytes
2078		//
2079		// Impact if it still happened would also be fairly minimal: We would
2080		// drop a parachain block, which is not a big deal on v1, where we are
2081		// not aiming for perfect block confidence.
2082		let new_v1_detected = self.reserved1[0..16] != [0u8; 16];
2083
2084		if new_v1_detected {
2085			return CandidateDescriptorVersion::V1;
2086		}
2087		match self.version {
2088			0 => CandidateDescriptorVersion::V2,
2089			1 => CandidateDescriptorVersion::V3,
2090			_ => CandidateDescriptorVersion::Unknown,
2091		}
2092	}
2093}
2094
2095macro_rules! impl_getter {
2096	($field:ident, $type:ident) => {
2097		/// Returns the value of `$field` field.
2098		pub fn $field(&self) -> $type {
2099			self.$field
2100		}
2101	};
2102}
2103
2104impl<H: Copy + AsRef<[u8]>> CandidateDescriptorV2<H> {
2105	impl_getter!(erasure_root, Hash);
2106	impl_getter!(para_head, Hash);
2107	impl_getter!(relay_parent, H);
2108	impl_getter!(para_id, ParaId);
2109	impl_getter!(persisted_validation_data_hash, Hash);
2110	impl_getter!(pov_hash, Hash);
2111	impl_getter!(validation_code_hash, ValidationCodeHash);
2112
2113	#[cfg(feature = "test")]
2114	fn rebuild_collator_field(&self) -> CollatorId {
2115		let mut collator_id = Vec::with_capacity(32);
2116		let core_index: [u8; 2] = self.core_index.to_ne_bytes();
2117		let session_index: [u8; 4] = self.session_index.to_ne_bytes();
2118
2119		collator_id.push(self.version);
2120		collator_id.extend_from_slice(core_index.as_slice());
2121		collator_id.extend_from_slice(session_index.as_slice());
2122		collator_id.push(self.scheduling_session_offset);
2123		collator_id.extend_from_slice(self.reserved1.as_slice());
2124
2125		CollatorId::from_slice(&collator_id.as_slice())
2126			.expect("Slice size is exactly 32 bytes; qed")
2127	}
2128
2129	/// Returns the collator id if this is a v1 `CandidateDescriptor`
2130	#[cfg(feature = "test")]
2131	pub fn collator(&self) -> Option<CollatorId> {
2132		if self.version() == CandidateDescriptorVersion::V1 {
2133			Some(self.rebuild_collator_field())
2134		} else {
2135			None
2136		}
2137	}
2138
2139	#[cfg(feature = "test")]
2140	fn rebuild_signature_field(&self) -> CollatorSignature {
2141		let mut signature_bytes = Vec::with_capacity(64);
2142		signature_bytes.extend_from_slice(self.scheduling_parent.as_ref());
2143		signature_bytes.extend_from_slice(self.reserved2.as_slice());
2144
2145		CollatorSignature::from_slice(&signature_bytes)
2146			.expect("Slice size is exactly 64 bytes; qed")
2147	}
2148
2149	#[cfg(feature = "test")]
2150	#[doc(hidden)]
2151	pub fn rebuild_collator_field_for_tests(&self) -> CollatorId {
2152		self.rebuild_collator_field()
2153	}
2154
2155	#[cfg(feature = "test")]
2156	#[doc(hidden)]
2157	pub fn rebuild_signature_field_for_tests(&self) -> CollatorSignature {
2158		self.rebuild_signature_field()
2159	}
2160
2161	/// Returns the collator signature of `V1` candidate descriptors, `None` otherwise.
2162	#[cfg(feature = "test")]
2163	pub fn signature(&self) -> Option<CollatorSignature> {
2164		if self.version() == CandidateDescriptorVersion::V1 {
2165			return Some(self.rebuild_signature_field());
2166		}
2167
2168		None
2169	}
2170
2171	/// Returns the `core_index` of `V2` and `V3` candidate descriptors, `None` for `V1`.
2172	pub fn core_index(&self) -> Option<CoreIndex> {
2173		if self.version() == CandidateDescriptorVersion::V1 {
2174			return None;
2175		}
2176
2177		Some(CoreIndex(self.core_index as u32))
2178	}
2179
2180	/// Returns the `session_index` of `V2` and `V3` candidate descriptors, `None` for `V1`.
2181	pub fn session_index(&self) -> Option<SessionIndex> {
2182		if self.version() == CandidateDescriptorVersion::V1 {
2183			return None;
2184		}
2185
2186		Some(self.session_index)
2187	}
2188
2189	/// Return the scheduling parent of the descriptor.
2190	///
2191	///
2192	/// On v1 and v2 this function will return the relay parent as under these versions the relay
2193	/// parent is also the scheduling parent.
2194	pub fn scheduling_parent(&self) -> H {
2195		match self.version() {
2196			CandidateDescriptorVersion::V1 => self.relay_parent,
2197			CandidateDescriptorVersion::V2 => self.relay_parent,
2198			CandidateDescriptorVersion::V3 => self.scheduling_parent,
2199			CandidateDescriptorVersion::Unknown => self.relay_parent,
2200		}
2201	}
2202
2203	/// Return the scheduling session index of the descriptor.
2204	///
2205	///
2206	/// On v1: Return None.
2207	/// On v2: Return the session index as it equals the scheduling session on v2.
2208	/// On v3: Return the provided scheduling session index.
2209	pub fn scheduling_session(&self) -> Option<SessionIndex> {
2210		match self.version() {
2211			CandidateDescriptorVersion::V1 => None,
2212			CandidateDescriptorVersion::V2 => Some(self.session_index),
2213			CandidateDescriptorVersion::V3 => {
2214				Some(self.session_index.saturating_add(self.scheduling_session_offset as _))
2215			},
2216			CandidateDescriptorVersion::Unknown => None,
2217		}
2218	}
2219
2220	/// Version for use in candidate validation during the V3 transition period.
2221	///
2222	/// Before the `CandidateReceiptV3` node feature is observed, uses
2223	/// [`Self::version_old_rules`] to match old backer behavior. After the feature
2224	/// is seen, trusts [`Self::version`].
2225	///
2226	/// This prevents slashing honest old backers when a malicious collator crafts
2227	/// a pseudo-V3 descriptor that old nodes interpret as V1 but new nodes would
2228	/// interpret as V3 (different PVF inputs → dispute → 100% slash).
2229	///
2230	/// Safety argument: The node feature can only be enabled well after the runtime upgrade that
2231	/// adds `check_version_acceptance()` protection at inclusion time. Once the feature is seen,
2232	/// the runtime has long been upgraded and already rejecting pseudo-V3 candidates (candidates
2233	/// that are valid v1 under the old rules, but are v3 without UMP signals under the new
2234	/// rules), so no ambiguous candidates can exist on-chain.
2235	///
2236	/// Only needed during the V3 transition. Once V3 is universally deployed,
2237	/// callers can switch to [`Self::version`] directly.
2238	pub fn version_for_candidate_validation(
2239		&self,
2240		v3_ever_seen: bool,
2241	) -> CandidateDescriptorVersion {
2242		if v3_ever_seen {
2243			self.version()
2244		} else {
2245			self.version_old_rules()
2246		}
2247	}
2248
2249	/// Scheduling parent for use in candidate validation.
2250	///
2251	/// See [`Self::version_for_candidate_validation`] for the safety argument.
2252	pub fn scheduling_parent_for_candidate_validation(&self, v3_ever_seen: bool) -> H
2253	where
2254		H: Copy,
2255	{
2256		match self.version_for_candidate_validation(v3_ever_seen) {
2257			CandidateDescriptorVersion::V3 => self.scheduling_parent,
2258			_ => self.relay_parent,
2259		}
2260	}
2261
2262	/// Scheduling session for candidate validation.
2263	///
2264	/// See [`Self::version_for_candidate_validation`] for the safety argument.
2265	pub fn scheduling_session_for_candidate_validation(
2266		&self,
2267		v3_ever_seen: bool,
2268	) -> Option<SessionIndex> {
2269		match self.version_for_candidate_validation(v3_ever_seen) {
2270			CandidateDescriptorVersion::V1 => None,
2271			CandidateDescriptorVersion::V2 => Some(self.session_index),
2272			CandidateDescriptorVersion::V3 => {
2273				Some(self.session_index.saturating_add(self.scheduling_session_offset as _))
2274			},
2275			CandidateDescriptorVersion::Unknown => None,
2276		}
2277	}
2278
2279	/// Session index (relay parent session) for candidate validation.
2280	///
2281	/// See [`Self::version_for_candidate_validation`] for the safety argument.
2282	pub fn session_index_for_candidate_validation(
2283		&self,
2284		v3_ever_seen: bool,
2285	) -> Option<SessionIndex> {
2286		match self.version_for_candidate_validation(v3_ever_seen) {
2287			CandidateDescriptorVersion::V1 | CandidateDescriptorVersion::Unknown => None,
2288			CandidateDescriptorVersion::V2 | CandidateDescriptorVersion::V3 => {
2289				Some(self.session_index)
2290			},
2291		}
2292	}
2293}
2294
2295impl<H> core::fmt::Debug for CandidateDescriptorV2<H>
2296where
2297	H: core::fmt::Debug,
2298{
2299	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2300		// A bit imprecise, but should not matter in practice for debug output. (Keeps trait bounds
2301		// sane.)
2302		match self.v3_version() {
2303			CandidateDescriptorVersion::V1 => f
2304				.debug_struct("CandidateDescriptorV1")
2305				.field("para_id", &self.para_id)
2306				.field("relay_parent", &self.relay_parent)
2307				.field("persisted_validation_hash", &self.persisted_validation_data_hash)
2308				.field("pov_hash", &self.pov_hash)
2309				.field("erasure_root", &self.erasure_root)
2310				.field("para_head", &self.para_head)
2311				.field("validation_code_hash", &self.validation_code_hash)
2312				.finish(),
2313			CandidateDescriptorVersion::V2 => f
2314				.debug_struct("CandidateDescriptorV2")
2315				.field("para_id", &self.para_id)
2316				.field("relay_parent", &self.relay_parent)
2317				.field("core_index", &self.core_index)
2318				.field("session_index", &self.session_index)
2319				.field("persisted_validation_data_hash", &self.persisted_validation_data_hash)
2320				.field("pov_hash", &self.pov_hash)
2321				.field("erasure_root", &self.erasure_root)
2322				.field("para_head", &self.para_head)
2323				.field("validation_code_hash", &self.validation_code_hash)
2324				.finish(),
2325			CandidateDescriptorVersion::V3 => f
2326				.debug_struct("CandidateDescriptorV3")
2327				.field("para_id", &self.para_id)
2328				.field("relay_parent", &self.relay_parent)
2329				.field("core_index", &self.core_index)
2330				.field("session_index", &self.session_index)
2331				.field("scheduling_session_offset", &self.scheduling_session_offset)
2332				.field("persisted_validation_data_hash", &self.persisted_validation_data_hash)
2333				.field("pov_hash", &self.pov_hash)
2334				.field("erasure_root", &self.erasure_root)
2335				.field("scheduling_parent", &self.scheduling_parent)
2336				.field("para_head", &self.para_head)
2337				.field("validation_code_hash", &self.validation_code_hash)
2338				.finish(),
2339			CandidateDescriptorVersion::Unknown => {
2340				write!(f, "CandidateDescriptorV2(unknown version={})", self.version)
2341			},
2342		}
2343	}
2344}
2345
2346impl<H: Copy + AsRef<[u8]>> CandidateDescriptorV2<H> {
2347	/// Constructor for V2 candidate descriptor (scheduling_parent = zero).
2348	pub fn new(
2349		para_id: Id,
2350		relay_parent: H,
2351		core_index: CoreIndex,
2352		session_index: SessionIndex,
2353		persisted_validation_data_hash: Hash,
2354		pov_hash: Hash,
2355		erasure_root: Hash,
2356		para_head: Hash,
2357		validation_code_hash: ValidationCodeHash,
2358	) -> Self
2359	where
2360		H: Default,
2361	{
2362		Self {
2363			para_id,
2364			relay_parent,
2365			version: 0,
2366			core_index: core_index.0 as u16,
2367			session_index,
2368			scheduling_session_offset: 0,
2369			reserved1: [0; 24],
2370			persisted_validation_data_hash,
2371			pov_hash,
2372			erasure_root,
2373			scheduling_parent: H::default(),
2374			reserved2: [0; 32],
2375			para_head,
2376			validation_code_hash,
2377		}
2378	}
2379
2380	/// Constructor for V3 candidate descriptor with explicit scheduling_parent.
2381	///
2382	/// V3 descriptors are identified by `version == 1` and have a non-zero scheduling_parent
2383	/// field, which indicates the relay chain block that was used for scheduling (may differ
2384	/// from relay_parent). V3 descriptors require UMP signals to be present.
2385	pub fn new_v3(
2386		para_id: Id,
2387		relay_parent: H,
2388		core_index: CoreIndex,
2389		session_index: SessionIndex,
2390		scheduling_session_index: SessionIndex,
2391		persisted_validation_data_hash: Hash,
2392		pov_hash: Hash,
2393		erasure_root: Hash,
2394		para_head: Hash,
2395		validation_code_hash: ValidationCodeHash,
2396		scheduling_parent: H,
2397	) -> Self {
2398		Self {
2399			para_id,
2400			relay_parent,
2401			version: 1,
2402			core_index: core_index.0 as u16,
2403			session_index,
2404			scheduling_session_offset: scheduling_session_index
2405				.saturating_sub(session_index)
2406				.try_into()
2407				.expect("scheduling session offset should fit in u8"),
2408			reserved1: [0; 24],
2409			persisted_validation_data_hash,
2410			pov_hash,
2411			erasure_root,
2412			scheduling_parent,
2413			reserved2: [0; 32],
2414			para_head,
2415			validation_code_hash,
2416		}
2417	}
2418
2419	/// Constructor for a V1-like candidate descriptor with non-zero collator
2420	/// fields so that `version()` returns [`CandidateDescriptorVersion::V1`].
2421	pub fn new_v1(
2422		para_id: Id,
2423		relay_parent: H,
2424		persisted_validation_data_hash: Hash,
2425		pov_hash: Hash,
2426		erasure_root: Hash,
2427		para_head: Hash,
2428		validation_code_hash: ValidationCodeHash,
2429	) -> Self
2430	where
2431		H: Default,
2432	{
2433		Self {
2434			para_id,
2435			relay_parent,
2436			version: 0,
2437			core_index: 0,
2438			session_index: 0,
2439			scheduling_session_offset: 0,
2440			reserved1: [1u8; 24],
2441			persisted_validation_data_hash,
2442			pov_hash,
2443			erasure_root,
2444			scheduling_parent: H::default(),
2445			reserved2: [1u8; 32],
2446			para_head,
2447			validation_code_hash,
2448		}
2449	}
2450
2451	#[cfg(feature = "test")]
2452	#[doc(hidden)]
2453	pub fn new_from_raw(
2454		para_id: Id,
2455		relay_parent: H,
2456		version: u8,
2457		core_index: u16,
2458		session_index: SessionIndex,
2459		scheduling_session_offset: u8,
2460		reserved1: [u8; 24],
2461		persisted_validation_data_hash: Hash,
2462		pov_hash: Hash,
2463		erasure_root: Hash,
2464		scheduling_parent: H,
2465		reserved2: [u8; 32],
2466		para_head: Hash,
2467		validation_code_hash: ValidationCodeHash,
2468	) -> Self {
2469		Self {
2470			para_id,
2471			relay_parent,
2472			version,
2473			core_index,
2474			session_index,
2475			scheduling_session_offset,
2476			reserved1,
2477			persisted_validation_data_hash,
2478			pov_hash,
2479			erasure_root,
2480			scheduling_parent,
2481			reserved2,
2482			para_head,
2483			validation_code_hash,
2484		}
2485	}
2486}
2487
2488/// A trait to allow changing the descriptor field values in tests.
2489#[cfg(feature = "test")]
2490pub trait MutateDescriptorV2<H> {
2491	/// Set the relay parent of the descriptor.
2492	fn set_relay_parent(&mut self, relay_parent: H);
2493	/// Set the `ParaId` of the descriptor.
2494	fn set_para_id(&mut self, para_id: Id);
2495	/// Set the PoV hash of the descriptor.
2496	fn set_pov_hash(&mut self, pov_hash: Hash);
2497	/// Set the raw version field of the descriptor.
2498	fn set_version(&mut self, version: u8);
2499	/// Set the PVD of the descriptor.
2500	fn set_persisted_validation_data_hash(&mut self, persisted_validation_data_hash: Hash);
2501	/// Set the validation code hash of the descriptor.
2502	fn set_validation_code_hash(&mut self, validation_code_hash: ValidationCodeHash);
2503	/// Set the erasure root of the descriptor.
2504	fn set_erasure_root(&mut self, erasure_root: Hash);
2505	/// Set the para head of the descriptor.
2506	fn set_para_head(&mut self, para_head: Hash);
2507	/// Set the core index of the descriptor.
2508	fn set_core_index(&mut self, core_index: CoreIndex);
2509	/// Set the session index of the descriptor.
2510	fn set_session_index(&mut self, session_index: SessionIndex);
2511	/// Set the reserved2 field of the descriptor.
2512	fn set_reserved2(&mut self, reserved2: [u8; 32]);
2513	/// Set the scheduling parent of the descriptor.
2514	fn set_scheduling_parent(&mut self, scheduling_parent: H);
2515	/// Set the scheduling session offset of the descriptor.
2516	fn set_scheduling_session_offset(&mut self, offset: u8);
2517}
2518
2519#[cfg(feature = "test")]
2520impl<H> MutateDescriptorV2<H> for CandidateDescriptorV2<H> {
2521	fn set_para_id(&mut self, para_id: Id) {
2522		self.para_id = para_id;
2523	}
2524
2525	fn set_relay_parent(&mut self, relay_parent: H) {
2526		self.relay_parent = relay_parent;
2527	}
2528
2529	fn set_pov_hash(&mut self, pov_hash: Hash) {
2530		self.pov_hash = pov_hash;
2531	}
2532
2533	fn set_version(&mut self, version: u8) {
2534		self.version = version;
2535	}
2536
2537	fn set_core_index(&mut self, core_index: CoreIndex) {
2538		self.core_index = core_index.0 as u16;
2539	}
2540
2541	fn set_session_index(&mut self, session_index: SessionIndex) {
2542		self.session_index = session_index;
2543	}
2544
2545	fn set_persisted_validation_data_hash(&mut self, persisted_validation_data_hash: Hash) {
2546		self.persisted_validation_data_hash = persisted_validation_data_hash;
2547	}
2548
2549	fn set_validation_code_hash(&mut self, validation_code_hash: ValidationCodeHash) {
2550		self.validation_code_hash = validation_code_hash;
2551	}
2552
2553	fn set_erasure_root(&mut self, erasure_root: Hash) {
2554		self.erasure_root = erasure_root;
2555	}
2556
2557	fn set_para_head(&mut self, para_head: Hash) {
2558		self.para_head = para_head;
2559	}
2560
2561	fn set_reserved2(&mut self, reserved2: [u8; 32]) {
2562		self.reserved2 = reserved2;
2563	}
2564
2565	fn set_scheduling_parent(&mut self, scheduling_parent: H) {
2566		self.scheduling_parent = scheduling_parent;
2567	}
2568
2569	fn set_scheduling_session_offset(&mut self, offset: u8) {
2570		self.scheduling_session_offset = offset;
2571	}
2572}
2573
2574/// A candidate-receipt at version 2.
2575#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug)]
2576pub struct CandidateReceiptV2<H = Hash> {
2577	/// The descriptor of the candidate.
2578	pub descriptor: CandidateDescriptorV2<H>,
2579	/// The hash of the encoded commitments made as a result of candidate execution.
2580	pub commitments_hash: Hash,
2581}
2582
2583/// A candidate-receipt with commitments directly included.
2584#[derive(PartialEq, Eq, Clone, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug)]
2585pub struct CommittedCandidateReceiptV2<H = Hash> {
2586	/// The descriptor of the candidate.
2587	pub descriptor: CandidateDescriptorV2<H>,
2588	/// The commitments of the candidate receipt.
2589	pub commitments: CandidateCommitments,
2590}
2591
2592/// An event concerning a candidate.
2593#[derive(Clone, Encode, Decode, TypeInfo, Debug)]
2594#[cfg_attr(feature = "std", derive(PartialEq))]
2595pub enum CandidateEvent<H = Hash> {
2596	/// This candidate receipt was backed in the most recent block.
2597	/// This includes the core index the candidate is now occupying.
2598	#[codec(index = 0)]
2599	CandidateBacked(CandidateReceiptV2<H>, HeadData, CoreIndex, GroupIndex),
2600	/// This candidate receipt was included and became a parablock at the most recent block.
2601	/// This includes the core index the candidate was occupying as well as the group responsible
2602	/// for backing the candidate.
2603	#[codec(index = 1)]
2604	CandidateIncluded(CandidateReceiptV2<H>, HeadData, CoreIndex, GroupIndex),
2605	/// This candidate receipt was not made available in time and timed out.
2606	/// This includes the core index the candidate was occupying.
2607	#[codec(index = 2)]
2608	CandidateTimedOut(CandidateReceiptV2<H>, HeadData, CoreIndex),
2609}
2610
2611impl<H> CandidateReceiptV2<H> {
2612	/// Get a reference to the candidate descriptor.
2613	pub fn descriptor(&self) -> &CandidateDescriptorV2<H> {
2614		&self.descriptor
2615	}
2616
2617	/// Computes the blake2-256 hash of the receipt.
2618	pub fn hash(&self) -> CandidateHash
2619	where
2620		H: Encode,
2621	{
2622		CandidateHash(BlakeTwo256::hash_of(self))
2623	}
2624}
2625
2626impl<H: Clone> CommittedCandidateReceiptV2<H> {
2627	/// Transforms this into a plain `CandidateReceipt`.
2628	pub fn to_plain(&self) -> CandidateReceiptV2<H> {
2629		CandidateReceiptV2 {
2630			descriptor: self.descriptor.clone(),
2631			commitments_hash: self.commitments.hash(),
2632		}
2633	}
2634
2635	/// Computes the hash of the committed candidate receipt.
2636	///
2637	/// This computes the canonical hash, not the hash of the directly encoded data.
2638	/// Thus this is a shortcut for `candidate.to_plain().hash()`.
2639	pub fn hash(&self) -> CandidateHash
2640	where
2641		H: Encode,
2642	{
2643		self.to_plain().hash()
2644	}
2645
2646	/// Does this committed candidate receipt corresponds to the given [`CandidateReceiptV2`]?
2647	pub fn corresponds_to(&self, receipt: &CandidateReceiptV2<H>) -> bool
2648	where
2649		H: PartialEq,
2650	{
2651		receipt.descriptor == self.descriptor && receipt.commitments_hash == self.commitments.hash()
2652	}
2653}
2654
2655impl PartialOrd for CommittedCandidateReceiptV2 {
2656	fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
2657		Some(self.cmp(other))
2658	}
2659}
2660
2661impl Ord for CommittedCandidateReceiptV2 {
2662	fn cmp(&self, other: &Self) -> core::cmp::Ordering {
2663		self.descriptor
2664			.para_id
2665			.cmp(&other.descriptor.para_id)
2666			.then_with(|| self.commitments.head_data.cmp(&other.commitments.head_data))
2667	}
2668}
2669
2670/// A strictly increasing sequence number, typically this would be the least significant byte of the
2671/// block number.
2672#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug, Copy)]
2673pub struct CoreSelector(pub u8);
2674
2675impl From<u8> for CoreSelector {
2676	fn from(value: u8) -> Self {
2677		Self(value)
2678	}
2679}
2680
2681/// An offset in the relay chain claim queue.
2682#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug, Copy)]
2683pub struct ClaimQueueOffset(pub u8);
2684
2685impl From<u8> for ClaimQueueOffset {
2686	fn from(value: u8) -> Self {
2687		Self(value)
2688	}
2689}
2690
2691/// Signals that a parachain can send to the relay chain via the UMP queue.
2692#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug)]
2693pub enum UMPSignal {
2694	/// A message sent by a parachain to select the core the candidate is committed to.
2695	/// Relay chain validators, in particular backers, use the `CoreSelector` and
2696	/// `ClaimQueueOffset` to compute the index of the core the candidate has committed to.
2697	SelectCore(CoreSelector, ClaimQueueOffset),
2698	/// A message sent by a parachain to promote the reputation of a given peerid.
2699	ApprovedPeer(ApprovedPeerId),
2700}
2701
2702/// The default claim queue offset to be used if it's not configured/accessible in the parachain
2703/// runtime
2704pub const DEFAULT_CLAIM_QUEUE_OFFSET: u8 = 0;
2705
2706/// Approved PeerId type. PeerIds in polkadot should typically be 32 bytes long but for identity
2707/// multihash can go up to 64. Cannot reuse the PeerId type definition from the networking code as
2708/// it's too generic and extensible.
2709pub type ApprovedPeerId = BoundedVec<u8, ConstU32<64>>;
2710
2711#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug, Default)]
2712/// User-friendly representation of a candidate's UMP signals.
2713pub struct CandidateUMPSignals {
2714	pub(super) select_core: Option<(CoreSelector, ClaimQueueOffset)>,
2715	pub(super) approved_peer: Option<ApprovedPeerId>,
2716}
2717
2718impl CandidateUMPSignals {
2719	/// Get the core selector UMP signal.
2720	pub fn core_selector(&self) -> Option<(CoreSelector, ClaimQueueOffset)> {
2721		self.select_core
2722	}
2723
2724	/// Get a reference to the approved peer UMP signal.
2725	pub fn approved_peer(&self) -> Option<&ApprovedPeerId> {
2726		self.approved_peer.as_ref()
2727	}
2728
2729	/// Returns `true` if UMP signals are empty.
2730	pub fn is_empty(&self) -> bool {
2731		self.select_core.is_none() && self.approved_peer.is_none()
2732	}
2733
2734	fn try_decode_signal(
2735		&mut self,
2736		buffer: &mut impl codec::Input,
2737	) -> Result<(), CommittedCandidateReceiptError> {
2738		match UMPSignal::decode(buffer)
2739			.map_err(|_| CommittedCandidateReceiptError::UmpSignalDecode)?
2740		{
2741			UMPSignal::ApprovedPeer(approved_peer_id) if self.approved_peer.is_none() => {
2742				self.approved_peer = Some(approved_peer_id);
2743			},
2744			UMPSignal::SelectCore(core_selector, cq_offset) if self.select_core.is_none() => {
2745				self.select_core = Some((core_selector, cq_offset));
2746			},
2747			_ => {
2748				// This means that we got duplicate UMP signals.
2749				return Err(CommittedCandidateReceiptError::DuplicateUMPSignal);
2750			},
2751		};
2752
2753		Ok(())
2754	}
2755
2756	#[cfg(feature = "test")]
2757	#[doc(hidden)]
2758	pub fn dummy(
2759		select_core: Option<(CoreSelector, ClaimQueueOffset)>,
2760		approved_peer: Option<ApprovedPeerId>,
2761	) -> Self {
2762		Self { select_core, approved_peer }
2763	}
2764}
2765
2766/// Separator between `XCM` and `UMPSignal`.
2767pub const UMP_SEPARATOR: Vec<u8> = vec![];
2768
2769/// Utility function for skipping the ump signals.
2770pub fn skip_ump_signals<'a>(
2771	upward_messages: impl Iterator<Item = &'a Vec<u8>>,
2772) -> impl Iterator<Item = &'a Vec<u8>> {
2773	upward_messages.take_while(|message| *message != &UMP_SEPARATOR)
2774}
2775
2776impl CandidateCommitments {
2777	/// Returns the ump signals of this candidate, if any, or an error if they violate the expected
2778	/// format.
2779	pub fn ump_signals(&self) -> Result<CandidateUMPSignals, CommittedCandidateReceiptError> {
2780		let mut res = CandidateUMPSignals::default();
2781
2782		let mut signals_iter =
2783			self.upward_messages.iter().skip_while(|message| *message != &UMP_SEPARATOR);
2784
2785		if signals_iter.next().is_none() {
2786			// No UMP separator
2787			return Ok(res);
2788		}
2789
2790		// Process first signal
2791		let Some(first_signal) = signals_iter.next() else { return Ok(res) };
2792		res.try_decode_signal(&mut first_signal.as_slice())?;
2793
2794		// Process second signal
2795		let Some(second_signal) = signals_iter.next() else { return Ok(res) };
2796		res.try_decode_signal(&mut second_signal.as_slice())?;
2797
2798		// At most two signals are allowed
2799		if signals_iter.next().is_some() {
2800			return Err(CommittedCandidateReceiptError::TooManyUMPSignals);
2801		}
2802
2803		Ok(res)
2804	}
2805}
2806
2807/// CommittedCandidateReceiptError construction errors.
2808#[derive(PartialEq, Eq, Clone, Encode, Decode, TypeInfo, Debug)]
2809#[cfg_attr(feature = "std", derive(thiserror::Error))]
2810pub enum CommittedCandidateReceiptError {
2811	/// The specified core index is invalid.
2812	#[cfg_attr(feature = "std", error("The specified core index is invalid"))]
2813	InvalidCoreIndex,
2814	/// The core index in commitments doesn't match the one in descriptor
2815	#[cfg_attr(
2816		feature = "std",
2817		error("The core index in commitments ({commitments:?}) doesn't match the one in descriptor ({descriptor:?})")
2818	)]
2819	CoreIndexMismatch {
2820		/// The core index as found in the descriptor.
2821		descriptor: CoreIndex,
2822		/// The core index as found in the commitments.
2823		commitments: CoreIndex,
2824	},
2825	/// The core selector or claim queue offset is invalid.
2826	#[cfg_attr(feature = "std", error("The core selector or claim queue offset is invalid"))]
2827	InvalidSelectedCore,
2828	#[cfg_attr(feature = "std", error("Could not decode UMP signal"))]
2829	/// Could not decode UMP signal.
2830	UmpSignalDecode,
2831	/// The parachain is not assigned to any core at specified claim queue offset.
2832	#[cfg_attr(
2833		feature = "std",
2834		error("The parachain is not assigned to any core at specified claim queue offset")
2835	)]
2836	NoAssignment,
2837	/// Unknown version.
2838	#[cfg_attr(feature = "std", error("Unknown internal version"))]
2839	UnknownVersion(u8),
2840	/// The allowed number of `UMPSignal` messages in the queue was exceeded.
2841	#[cfg_attr(feature = "std", error("Too many UMP signals"))]
2842	TooManyUMPSignals,
2843	/// Duplicated UMP signal.
2844	#[cfg_attr(feature = "std", error("Duplicate UMP signal"))]
2845	DuplicateUMPSignal,
2846	/// If the parachain runtime started sending ump signals, v1 descriptors are no longer
2847	/// allowed.
2848	#[cfg_attr(feature = "std", error("Version 1 receipt does not support ump signals"))]
2849	UMPSignalWithV1Descriptor,
2850	/// Starting with v3 ump signals are mandatory.
2851	///
2852	/// This is to avoid nodes only understanding v1 and v2 to getting tricked
2853	/// into backing a candidate that looks like a valid v1 to them, but is
2854	/// actually an invalid v3.
2855	///
2856	/// This is prevented by the runtime rejecting v3 candidates without ump
2857	/// signals. Therefore a candidate that was erroneously backed as v1, while
2858	/// it actually was a v3 would get rejected by the runtime due to missing
2859	/// signals, thus preventing the backer from getting slashed. This is given,
2860	/// because v1 and v2 only nodes would not back a v1 candidate with UMP
2861	/// signals, as that is seen as invalid by them already.
2862	#[cfg_attr(feature = "std", error("Version 3 receipt requires ump signals"))]
2863	NoUMPSignalWithV3Descriptor,
2864}
2865
2866impl<H: Copy + AsRef<[u8]>> CommittedCandidateReceiptV2<H> {
2867	/// Performs checks on the UMP signals and returns them.
2868	///
2869	/// Also checks if descriptor core index is equal to the committed core index.
2870	///
2871	/// Params:
2872	/// - `cores_per_para` is a claim queue snapshot at the candidate's relay parent, stored as
2873	/// a mapping between `ParaId` and the cores assigned per depth.
2874	///
2875	/// NOTE: This must only be called in the runtime and backing - never in approval voting nor
2876	/// disputes! At least not as long as nodes exist which don't understand v3 candidate
2877	/// descriptors. Not checking there is fine, because it is checked by the runtime - if it can be
2878	/// disputed, it has been checked already!
2879	pub fn parse_ump_signals(
2880		&self,
2881		cores_per_para: &TransposedClaimQueue,
2882	) -> Result<CandidateUMPSignals, CommittedCandidateReceiptError> {
2883		let signals = self.commitments.ump_signals()?;
2884
2885		match self.descriptor.version() {
2886			CandidateDescriptorVersion::V1 => {
2887				// If the parachain runtime started sending ump signals, v1 descriptors are no
2888				// longer allowed.
2889				if !signals.is_empty() {
2890					return Err(CommittedCandidateReceiptError::UMPSignalWithV1Descriptor);
2891				} else {
2892					// Nothing else to check for v1 descriptors.
2893					return Ok(CandidateUMPSignals::default());
2894				}
2895			},
2896			CandidateDescriptorVersion::V2 => {},
2897			CandidateDescriptorVersion::Unknown => {
2898				return Err(CommittedCandidateReceiptError::UnknownVersion(self.descriptor.version))
2899			},
2900			_ if signals.is_empty() => {
2901				// V3 and above require UMP signals.
2902				return Err(CommittedCandidateReceiptError::NoUMPSignalWithV3Descriptor);
2903			},
2904			_ => {},
2905		}
2906
2907		// Check the core index
2908		let (maybe_core_index_selector, cq_offset) = signals
2909			.core_selector()
2910			.map(|(selector, offset)| (Some(selector), offset))
2911			.unwrap_or_else(|| (None, ClaimQueueOffset(DEFAULT_CLAIM_QUEUE_OFFSET)));
2912
2913		self.check_core_index(cores_per_para, maybe_core_index_selector, cq_offset)?;
2914
2915		// Nothing to further check for the approved peer. If everything passed so far, return the
2916		// signals.
2917		Ok(signals)
2918	}
2919
2920	/// Checks if descriptor core index is equal to the committed core index.
2921	/// Input `cores_per_para` is a claim queue snapshot at the candidate's relay parent, stored as
2922	/// a mapping between `ParaId` and the cores assigned per depth.
2923	fn check_core_index(
2924		&self,
2925		cores_per_para: &TransposedClaimQueue,
2926		maybe_core_index_selector: Option<CoreSelector>,
2927		cq_offset: ClaimQueueOffset,
2928	) -> Result<(), CommittedCandidateReceiptError> {
2929		let assigned_cores = cores_per_para
2930			.get(&self.descriptor.para_id())
2931			.ok_or(CommittedCandidateReceiptError::NoAssignment)?
2932			.get(&cq_offset.0)
2933			.ok_or(CommittedCandidateReceiptError::NoAssignment)?;
2934
2935		if assigned_cores.is_empty() {
2936			return Err(CommittedCandidateReceiptError::NoAssignment);
2937		}
2938
2939		let descriptor_core_index = CoreIndex(self.descriptor.core_index as u32);
2940
2941		let core_index_selector = if let Some(core_index_selector) = maybe_core_index_selector {
2942			// We have a committed core selector, we can use it.
2943			core_index_selector
2944		} else if assigned_cores.len() > 1 {
2945			// We got more than one assigned core and no core selector. Special care is needed.
2946			if !assigned_cores.contains(&descriptor_core_index) {
2947				// core index in the descriptor is not assigned to the para. Error.
2948				return Err(CommittedCandidateReceiptError::InvalidCoreIndex);
2949			} else {
2950				// the descriptor core index is indeed assigned to the para. This is the most we can
2951				// check for now
2952				return Ok(());
2953			}
2954		} else {
2955			// No core selector but there's only one assigned core, use it.
2956			CoreSelector(0)
2957		};
2958
2959		let core_index = assigned_cores
2960			.iter()
2961			.nth(core_index_selector.0 as usize % assigned_cores.len())
2962			.ok_or(CommittedCandidateReceiptError::InvalidSelectedCore)
2963			.copied()?;
2964
2965		if core_index != descriptor_core_index {
2966			return Err(CommittedCandidateReceiptError::CoreIndexMismatch {
2967				descriptor: descriptor_core_index,
2968				commitments: core_index,
2969			});
2970		}
2971
2972		Ok(())
2973	}
2974}
2975
2976/// A backed (or backable, depending on context) candidate.
2977#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Eq, Debug, TypeInfo)]
2978pub struct BackedCandidate<H = Hash> {
2979	/// The candidate referred to.
2980	candidate: CommittedCandidateReceiptV2<H>,
2981	/// The validity votes themselves, expressed as signatures.
2982	validity_votes: Vec<ValidityAttestation>,
2983	/// The indices of the validators within the group, expressed as a bitfield. May be extended
2984	/// beyond the backing group size to contain the assigned core index, if ElasticScalingMVP is
2985	/// enabled.
2986	validator_indices: BitVec<u8, bitvec::order::Lsb0>,
2987}
2988
2989/// Parachains inherent-data passed into the runtime by a block author
2990#[derive(Encode, Decode, DecodeWithMemTracking, Clone, PartialEq, Debug, TypeInfo)]
2991pub struct InherentData<HDR: HeaderT = Header> {
2992	/// Signed bitfields by validators about availability.
2993	pub bitfields: UncheckedSignedAvailabilityBitfields,
2994	/// Backed candidates for inclusion in the block.
2995	pub backed_candidates: Vec<BackedCandidate<HDR::Hash>>,
2996	/// Sets of dispute votes for inclusion,
2997	pub disputes: MultiDisputeStatementSet,
2998	/// The parent block header. Used for checking state proofs.
2999	pub parent_header: HDR,
3000}
3001
3002impl<H> BackedCandidate<H> {
3003	/// Constructor
3004	pub fn new(
3005		candidate: CommittedCandidateReceiptV2<H>,
3006		validity_votes: Vec<ValidityAttestation>,
3007		validator_indices: BitVec<u8, bitvec::order::Lsb0>,
3008		core_index: CoreIndex,
3009	) -> Self {
3010		let mut instance = Self { candidate, validity_votes, validator_indices };
3011		instance.inject_core_index(core_index);
3012		instance
3013	}
3014
3015	/// Get a reference to the committed candidate receipt of the candidate.
3016	pub fn candidate(&self) -> &CommittedCandidateReceiptV2<H> {
3017		&self.candidate
3018	}
3019
3020	/// Get a mutable reference to the committed candidate receipt of the candidate.
3021	/// Only for testing.
3022	#[cfg(feature = "test")]
3023	pub fn candidate_mut(&mut self) -> &mut CommittedCandidateReceiptV2<H> {
3024		&mut self.candidate
3025	}
3026	/// Get a reference to the descriptor of the candidate.
3027	pub fn descriptor(&self) -> &CandidateDescriptorV2<H> {
3028		&self.candidate.descriptor
3029	}
3030
3031	/// Get a mutable reference to the descriptor of the candidate. Only for testing.
3032	#[cfg(feature = "test")]
3033	pub fn descriptor_mut(&mut self) -> &mut CandidateDescriptorV2<H> {
3034		&mut self.candidate.descriptor
3035	}
3036
3037	/// Get a reference to the validity votes of the candidate.
3038	pub fn validity_votes(&self) -> &[ValidityAttestation] {
3039		&self.validity_votes
3040	}
3041
3042	/// Get a mutable reference to validity votes of the para.
3043	pub fn validity_votes_mut(&mut self) -> &mut Vec<ValidityAttestation> {
3044		&mut self.validity_votes
3045	}
3046
3047	/// Compute this candidate's hash.
3048	pub fn hash(&self) -> CandidateHash
3049	where
3050		H: Clone + Encode,
3051	{
3052		self.candidate.to_plain().hash()
3053	}
3054
3055	/// Get this candidate's receipt.
3056	pub fn receipt(&self) -> CandidateReceiptV2<H>
3057	where
3058		H: Clone,
3059	{
3060		self.candidate.to_plain()
3061	}
3062
3063	/// Get a copy of the raw validator indices.
3064	#[cfg(feature = "test")]
3065	pub fn raw_validator_indices(&self) -> BitVec<u8, bitvec::order::Lsb0> {
3066		self.validator_indices.clone()
3067	}
3068
3069	/// Get a copy of the validator indices and the assumed core index, if any.
3070	pub fn validator_indices_and_core_index(
3071		&self,
3072	) -> (&BitSlice<u8, bitvec::order::Lsb0>, Option<CoreIndex>) {
3073		// `BackedCandidate::validity_indices` are extended to store a 8 bit core index.
3074		let core_idx_offset = self.validator_indices.len().saturating_sub(8);
3075		if core_idx_offset > 0 {
3076			let (validator_indices_slice, core_idx_slice) =
3077				self.validator_indices.split_at(core_idx_offset);
3078			return (validator_indices_slice, Some(CoreIndex(core_idx_slice.load::<u8>() as u32)));
3079		}
3080
3081		(&self.validator_indices, None)
3082	}
3083
3084	/// Inject a core index in the validator_indices bitvec.
3085	fn inject_core_index(&mut self, core_index: CoreIndex) {
3086		let core_index_to_inject: BitVec<u8, bitvec::order::Lsb0> =
3087			BitVec::from_vec(vec![core_index.0 as u8]);
3088		self.validator_indices.extend(core_index_to_inject);
3089	}
3090
3091	/// Update the validator indices and core index in the candidate.
3092	pub fn set_validator_indices_and_core_index(
3093		&mut self,
3094		new_indices: BitVec<u8, bitvec::order::Lsb0>,
3095		maybe_core_index: Option<CoreIndex>,
3096	) {
3097		self.validator_indices = new_indices;
3098
3099		if let Some(core_index) = maybe_core_index {
3100			self.inject_core_index(core_index);
3101		}
3102	}
3103}
3104
3105/// Scraped runtime backing votes and resolved disputes.
3106#[derive(Clone, Encode, Decode, Debug, TypeInfo)]
3107#[cfg_attr(feature = "std", derive(PartialEq))]
3108pub struct ScrapedOnChainVotes<H: Encode + Decode = Hash> {
3109	/// The session in which the block was included.
3110	pub session: SessionIndex,
3111	/// Set of backing validators for each candidate, represented by its candidate
3112	/// receipt.
3113	pub backing_validators_per_candidate:
3114		Vec<(CandidateReceiptV2<H>, Vec<(ValidatorIndex, ValidityAttestation)>)>,
3115	/// On-chain-recorded set of disputes.
3116	/// Note that the above `backing_validators` are
3117	/// unrelated to the backers of the disputes candidates.
3118	pub disputes: MultiDisputeStatementSet,
3119}
3120
3121/// Information about a core which is currently occupied.
3122#[derive(Clone, Encode, Decode, TypeInfo, Debug)]
3123#[cfg_attr(feature = "std", derive(PartialEq))]
3124pub struct OccupiedCore<H = Hash, N = BlockNumber> {
3125	// NOTE: this has no ParaId as it can be deduced from the candidate descriptor.
3126	/// If this core is freed by availability, this is the assignment that is next up on this
3127	/// core, if any. None if there is nothing queued for this core.
3128	pub next_up_on_available: Option<ScheduledCore>,
3129	/// The relay-chain block number this began occupying the core at.
3130	pub occupied_since: N,
3131	/// The relay-chain block this will time-out at, if any.
3132	pub time_out_at: N,
3133	/// If this core is freed by being timed-out, this is the assignment that is next up on this
3134	/// core. None if there is nothing queued for this core or there is no possibility of timing
3135	/// out.
3136	pub next_up_on_time_out: Option<ScheduledCore>,
3137	/// A bitfield with 1 bit for each validator in the set. `1` bits mean that the corresponding
3138	/// validators has attested to availability on-chain. A 2/3+ majority of `1` bits means that
3139	/// this will be available.
3140	pub availability: BitVec<u8, bitvec::order::Lsb0>,
3141	/// The group assigned to distribute availability pieces of this candidate.
3142	pub group_responsible: GroupIndex,
3143	/// The hash of the candidate occupying the core.
3144	pub candidate_hash: CandidateHash,
3145	/// The descriptor of the candidate occupying the core.
3146	pub candidate_descriptor: CandidateDescriptorV2<H>,
3147}
3148
3149impl<H, N> OccupiedCore<H, N> {
3150	/// Get the Para currently occupying this core.
3151	pub fn para_id(&self) -> Id {
3152		self.candidate_descriptor.para_id
3153	}
3154}
3155
3156/// The state of a particular availability core.
3157#[derive(Clone, Encode, Decode, TypeInfo, Debug)]
3158#[cfg_attr(feature = "std", derive(PartialEq))]
3159pub enum CoreState<H = Hash, N = BlockNumber> {
3160	/// The core is currently occupied.
3161	#[codec(index = 0)]
3162	Occupied(OccupiedCore<H, N>),
3163	/// The core is currently free, with a para scheduled and given the opportunity
3164	/// to occupy.
3165	///
3166	/// If a particular Collator is required to author this block, that is also present in this
3167	/// variant.
3168	#[codec(index = 1)]
3169	Scheduled(ScheduledCore),
3170	/// The core is currently free and there is nothing scheduled. This can be the case for
3171	/// parathread cores when there are no parathread blocks queued. Parachain cores will never be
3172	/// left idle.
3173	#[codec(index = 2)]
3174	Free,
3175}
3176
3177impl<N> CoreState<N> {
3178	/// Returns the scheduled `ParaId` for the core or `None` if nothing is scheduled.
3179	///
3180	/// This function is deprecated. `ClaimQueue` should be used to obtain the scheduled `ParaId`s
3181	/// for each core.
3182	#[deprecated(
3183		note = "`para_id` will be removed. Use `ClaimQueue` to query the scheduled `para_id` instead."
3184	)]
3185	pub fn para_id(&self) -> Option<Id> {
3186		match self {
3187			Self::Occupied(ref core) => core.next_up_on_available.as_ref().map(|n| n.para_id),
3188			Self::Scheduled(core) => Some(core.para_id),
3189			Self::Free => None,
3190		}
3191	}
3192
3193	/// Is this core state `Self::Occupied`?
3194	pub fn is_occupied(&self) -> bool {
3195		matches!(self, Self::Occupied(_))
3196	}
3197}
3198
3199/// The claim queue mapped by parachain id.
3200pub type TransposedClaimQueue = BTreeMap<ParaId, BTreeMap<u8, BTreeSet<CoreIndex>>>;
3201
3202/// Returns a mapping between the para id and the core indices assigned at different
3203/// depths in the claim queue.
3204pub fn transpose_claim_queue(
3205	claim_queue: BTreeMap<CoreIndex, VecDeque<Id>>,
3206) -> TransposedClaimQueue {
3207	let mut per_para_claim_queue = BTreeMap::new();
3208
3209	for (core, paras) in claim_queue {
3210		// Iterate paras assigned to this core at each depth.
3211		for (depth, para) in paras.into_iter().enumerate() {
3212			let depths: &mut BTreeMap<u8, BTreeSet<CoreIndex>> =
3213				per_para_claim_queue.entry(para).or_insert_with(|| Default::default());
3214
3215			depths.entry(depth as u8).or_default().insert(core);
3216		}
3217	}
3218
3219	per_para_claim_queue
3220}
3221
3222// Approval Slashes primitives
3223/// Supercedes the old 'SlashingOffenceKind' enum.
3224#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, DecodeWithMemTracking, TypeInfo, Debug)]
3225pub enum DisputeOffenceKind {
3226	/// A severe offence when a validator backed an invalid block
3227	/// (backing only)
3228	#[codec(index = 0)]
3229	ForInvalidBacked,
3230	/// A minor offence when a validator disputed a valid block.
3231	/// (approval checking and dispute vote only)
3232	#[codec(index = 1)]
3233	AgainstValid,
3234	/// A medium offence when a validator approved an invalid block
3235	/// (approval checking and dispute vote only)
3236	#[codec(index = 2)]
3237	ForInvalidApproved,
3238}
3239
3240/// impl for a conversion from SlashingOffenceKind to DisputeOffenceKind
3241/// This creates DisputeOffenceKind that never contains ForInvalidApproved since it was not
3242/// supported in the past
3243impl From<super::v9::slashing::SlashingOffenceKind> for DisputeOffenceKind {
3244	fn from(value: super::v9::slashing::SlashingOffenceKind) -> Self {
3245		match value {
3246			super::v9::slashing::SlashingOffenceKind::ForInvalid => Self::ForInvalidBacked,
3247			super::v9::slashing::SlashingOffenceKind::AgainstValid => Self::AgainstValid,
3248		}
3249	}
3250}
3251
3252/// impl for a tryFrom conversion from DisputeOffenceKind to SlashingOffenceKind
3253impl TryFrom<DisputeOffenceKind> for super::v9::slashing::SlashingOffenceKind {
3254	type Error = ();
3255
3256	fn try_from(value: DisputeOffenceKind) -> Result<Self, Self::Error> {
3257		match value {
3258			DisputeOffenceKind::ForInvalidBacked => Ok(Self::ForInvalid),
3259			DisputeOffenceKind::AgainstValid => Ok(Self::AgainstValid),
3260			DisputeOffenceKind::ForInvalidApproved => Err(()),
3261		}
3262	}
3263}
3264
3265#[cfg(test)]
3266/// Basic tests
3267pub mod tests {
3268	use super::*;
3269
3270	#[test]
3271	fn group_rotation_info_calculations() {
3272		let info =
3273			GroupRotationInfo { session_start_block: 10u32, now: 15, group_rotation_frequency: 5 };
3274
3275		assert_eq!(info.next_rotation_at(), 20);
3276		assert_eq!(info.last_rotation_at(), 15);
3277	}
3278
3279	#[test]
3280	fn group_for_core_is_core_for_group() {
3281		for cores in 1..=256 {
3282			for rotations in 0..(cores * 2) {
3283				let info = GroupRotationInfo {
3284					session_start_block: 0u32,
3285					now: rotations,
3286					group_rotation_frequency: 1,
3287				};
3288
3289				for core in 0..cores {
3290					let group = info.group_for_core(CoreIndex(core), cores as usize);
3291					assert_eq!(info.core_for_group(group, cores as usize).0, core);
3292				}
3293			}
3294		}
3295	}
3296
3297	#[test]
3298	fn test_byzantine_threshold() {
3299		assert_eq!(byzantine_threshold(0), 0);
3300		assert_eq!(byzantine_threshold(1), 0);
3301		assert_eq!(byzantine_threshold(2), 0);
3302		assert_eq!(byzantine_threshold(3), 0);
3303		assert_eq!(byzantine_threshold(4), 1);
3304		assert_eq!(byzantine_threshold(5), 1);
3305		assert_eq!(byzantine_threshold(6), 1);
3306		assert_eq!(byzantine_threshold(7), 2);
3307	}
3308
3309	#[test]
3310	fn test_supermajority_threshold() {
3311		assert_eq!(supermajority_threshold(0), 0);
3312		assert_eq!(supermajority_threshold(1), 1);
3313		assert_eq!(supermajority_threshold(2), 2);
3314		assert_eq!(supermajority_threshold(3), 3);
3315		assert_eq!(supermajority_threshold(4), 3);
3316		assert_eq!(supermajority_threshold(5), 4);
3317		assert_eq!(supermajority_threshold(6), 5);
3318		assert_eq!(supermajority_threshold(7), 5);
3319	}
3320
3321	#[test]
3322	fn balance_bigger_than_usize() {
3323		let zero_b: Balance = 0;
3324		let zero_u: usize = 0;
3325
3326		assert!(zero_b.leading_zeros() >= zero_u.leading_zeros());
3327	}
3328
3329	fn make_v2_descriptor() -> CandidateDescriptorV2 {
3330		CandidateDescriptorV2::new(
3331			Id::from(1u32),
3332			Hash::repeat_byte(1),
3333			CoreIndex(0),
3334			1,
3335			Hash::repeat_byte(2),
3336			Hash::repeat_byte(3),
3337			Hash::repeat_byte(4),
3338			Hash::repeat_byte(5),
3339			ValidationCodeHash::from(Hash::repeat_byte(6)),
3340		)
3341	}
3342
3343	fn make_v3_descriptor() -> CandidateDescriptorV2 {
3344		CandidateDescriptorV2::new_v3(
3345			Id::from(1u32),
3346			Hash::repeat_byte(1),
3347			CoreIndex(0),
3348			1, // session_index
3349			1, // scheduling_session_index
3350			Hash::repeat_byte(2),
3351			Hash::repeat_byte(3),
3352			Hash::repeat_byte(4),
3353			Hash::repeat_byte(5),
3354			ValidationCodeHash::from(Hash::repeat_byte(6)),
3355			Hash::repeat_byte(7), // scheduling_parent
3356		)
3357	}
3358
3359	#[test]
3360	fn check_version_acceptance_v1_consistent() {
3361		// A V1 descriptor (created from old-style with non-zero collator fields)
3362		// Both old and new rules agree → passes regardless of v3_enabled.
3363		let mut desc = make_v2_descriptor();
3364		// Put non-zero bytes in first 16 bytes of reserved1 to trigger V1 in both
3365		// old and new detection.
3366		desc.reserved1[0] = 0xFF;
3367
3368		assert_eq!(desc.version(), CandidateDescriptorVersion::V1);
3369		assert_eq!(desc.version_old_rules(), CandidateDescriptorVersion::V1);
3370		assert!(desc.check_version_consistency());
3371
3372		assert!(desc.check_version_acceptance(false).is_ok());
3373		assert!(desc.check_version_acceptance(true).is_ok());
3374	}
3375
3376	#[test]
3377	fn check_version_acceptance_v2_consistent() {
3378		// A clean V2 descriptor: both rules agree → passes always.
3379		let desc = make_v2_descriptor();
3380
3381		assert_eq!(desc.version(), CandidateDescriptorVersion::V2);
3382		assert_eq!(desc.version_old_rules(), CandidateDescriptorVersion::V2);
3383		assert!(desc.check_version_consistency());
3384
3385		assert!(desc.check_version_acceptance(false).is_ok());
3386		assert!(desc.check_version_acceptance(true).is_ok());
3387	}
3388
3389	#[test]
3390	fn check_version_acceptance_v3_when_enabled() {
3391		// V3 descriptor with v3_enabled=true → passes.
3392		let desc = make_v3_descriptor();
3393
3394		assert_eq!(desc.version(), CandidateDescriptorVersion::V3);
3395		assert_eq!(desc.version_old_rules(), CandidateDescriptorVersion::V1);
3396		assert!(!desc.check_version_consistency());
3397
3398		assert!(desc.check_version_acceptance(true).is_ok());
3399	}
3400
3401	#[test]
3402	fn check_version_acceptance_v3_when_disabled() {
3403		// V3 descriptor with v3_enabled=false → rejected.
3404		// The consistency check fires first (old rules see V1, new rules see V3,
3405		// and V3 disagreement is not expected when v3_enabled=false).
3406		let desc = make_v3_descriptor();
3407
3408		assert_eq!(desc.version(), CandidateDescriptorVersion::V3);
3409		assert_eq!(
3410			desc.check_version_acceptance(false),
3411			Err(CandidateDescriptorVersionCheckError::Inconsistency)
3412		);
3413	}
3414
3415	#[test]
3416	fn check_version_acceptance_ambiguous_rejected() {
3417		// Craft descriptor where old rules see V1, new rules see V2.
3418		// reserved1[16..24] non-zero, reserved1[0..16] all zero, version=0.
3419		let mut desc = make_v2_descriptor();
3420		desc.reserved1[16] = 0xFF; // triggers old V1 check but not new
3421
3422		assert_eq!(desc.version(), CandidateDescriptorVersion::V2);
3423		assert_eq!(desc.version_old_rules(), CandidateDescriptorVersion::V1);
3424		assert!(!desc.check_version_consistency());
3425
3426		// Rejected regardless of v3_enabled.
3427		assert_eq!(
3428			desc.check_version_acceptance(false),
3429			Err(CandidateDescriptorVersionCheckError::Inconsistency)
3430		);
3431		assert_eq!(
3432			desc.check_version_acceptance(true),
3433			Err(CandidateDescriptorVersionCheckError::Inconsistency)
3434		);
3435	}
3436
3437	#[test]
3438	fn check_version_consistency_v3_expected_disagreement() {
3439		// V3 descriptor: version() returns V3, version_old_rules() returns V1.
3440		// check_version_consistency() is false — but this is expected.
3441		let desc = make_v3_descriptor();
3442
3443		assert_eq!(desc.version(), CandidateDescriptorVersion::V3);
3444		assert_eq!(desc.version_old_rules(), CandidateDescriptorVersion::V1);
3445		assert!(!desc.check_version_consistency());
3446		// Accepted when V3 is enabled.
3447		assert!(desc.check_version_acceptance(true).is_ok());
3448	}
3449
3450	#[test]
3451	fn v3_feature_activation_changes_descriptor_interpretation() {
3452		let desc = make_v3_descriptor();
3453
3454		// Sanity: the descriptor IS V3 under new rules but looks like V1 under old rules.
3455		assert_eq!(desc.version(), CandidateDescriptorVersion::V3);
3456		assert_eq!(desc.version_old_rules(), CandidateDescriptorVersion::V1);
3457
3458		// Before V3 activation: descriptor is treated as V1 — relay_parent is used.
3459		assert_eq!(desc.version_for_candidate_validation(false), CandidateDescriptorVersion::V1,);
3460		assert_eq!(
3461			desc.scheduling_parent_for_candidate_validation(false),
3462			Hash::repeat_byte(1), // relay_parent
3463		);
3464		assert_eq!(
3465			desc.scheduling_session_for_candidate_validation(false),
3466			None,
3467			"V1 has no embedded session — must be fetched from runtime",
3468		);
3469
3470		// After V3 activation: descriptor is correctly identified as V3.
3471		assert_eq!(desc.version_for_candidate_validation(true), CandidateDescriptorVersion::V3,);
3472		assert_eq!(
3473			desc.scheduling_parent_for_candidate_validation(true),
3474			Hash::repeat_byte(7), // scheduling_parent
3475		);
3476		assert_eq!(
3477			desc.scheduling_session_for_candidate_validation(true),
3478			Some(1), // session_index from descriptor, offset=0
3479		);
3480	}
3481
3482	#[test]
3483	fn check_version_acceptance_ambiguous_scheduling_parent_nonzero() {
3484		// Descriptor with scheduling_parent non-zero but version=0.
3485		// Old rules: V1 (scheduling_parent non-zero triggers old_v1_detected).
3486		// New rules: V2 (only checks reserved1[0..16], which is zero).
3487		let mut desc = make_v2_descriptor();
3488		desc.scheduling_parent = Hash::repeat_byte(0xAB);
3489
3490		assert_eq!(desc.version(), CandidateDescriptorVersion::V2);
3491		assert_eq!(desc.version_old_rules(), CandidateDescriptorVersion::V1);
3492		assert!(!desc.check_version_consistency());
3493
3494		assert_eq!(
3495			desc.check_version_acceptance(false),
3496			Err(CandidateDescriptorVersionCheckError::Inconsistency)
3497		);
3498		assert_eq!(
3499			desc.check_version_acceptance(true),
3500			Err(CandidateDescriptorVersionCheckError::Inconsistency)
3501		);
3502	}
3503}