pezkuwi_primitives/v9/
mod.rs

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