Skip to main content

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