1#![deny(missing_docs)]
24
25use std::pin::Pin;
26
27use bounded_vec::BoundedVec;
28use codec::{Decode, Encode, Error as CodecError, Input};
29use futures::Future;
30use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
31
32use polkadot_primitives::{
33	BlakeTwo256, BlockNumber, CandidateCommitments, CandidateHash, ChunkIndex, CollatorPair,
34	CommittedCandidateReceiptError, CommittedCandidateReceiptV2 as CommittedCandidateReceipt,
35	CompactStatement, CoreIndex, EncodeAs, Hash, HashT, HeadData, Id as ParaId,
36	PersistedValidationData, SessionIndex, Signed, UncheckedSigned, ValidationCode,
37	ValidationCodeHash, MAX_CODE_SIZE, MAX_POV_SIZE,
38};
39pub use sp_consensus_babe::{
40	AllowedSlots as BabeAllowedSlots, BabeEpochConfiguration, Epoch as BabeEpoch,
41	Randomness as BabeRandomness,
42};
43
44pub use polkadot_parachain_primitives::primitives::{
45	BlockData, HorizontalMessages, UpwardMessages,
46};
47
48pub mod approval;
49
50pub mod disputes;
52pub use disputes::{
53	dispute_is_inactive, CandidateVotes, DisputeMessage, DisputeMessageCheckError, DisputeStatus,
54	InvalidDisputeVote, SignedDisputeStatement, Timestamp, UncheckedDisputeMessage,
55	ValidDisputeVote, ACTIVE_DURATION_SECS,
56};
57
58pub const NODE_VERSION: &'static str = "1.19.2";
64
65const MERKLE_NODE_MAX_SIZE: usize = 512 + 100;
69const MERKLE_PROOF_MAX_DEPTH: usize = 8;
71
72#[deprecated(
74	note = "`VALIDATION_CODE_BOMB_LIMIT` will be removed. Use `validation_code_bomb_limit`
75	runtime API to retrieve the value from the runtime"
76)]
77pub const VALIDATION_CODE_BOMB_LIMIT: usize = (MAX_CODE_SIZE * 4u32) as usize;
78
79pub const POV_BOMB_LIMIT: usize = (MAX_POV_SIZE * 4u32) as usize;
81
82pub const DISPUTE_CANDIDATE_LIFETIME_AFTER_FINALIZATION: BlockNumber = 10;
104
105pub const MAX_FINALITY_LAG: u32 = 500;
109
110#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
117pub struct SessionWindowSize(SessionIndex);
118
119#[macro_export]
120macro_rules! new_session_window_size {
122	(0) => {
123		compile_error!("Must be non zero");
124	};
125	(0_u32) => {
126		compile_error!("Must be non zero");
127	};
128	(0 as u32) => {
129		compile_error!("Must be non zero");
130	};
131	(0 as _) => {
132		compile_error!("Must be non zero");
133	};
134	($l:literal) => {
135		SessionWindowSize::unchecked_new($l as _)
136	};
137}
138
139pub const DISPUTE_WINDOW: SessionWindowSize = new_session_window_size!(6);
144
145impl SessionWindowSize {
146	pub fn get(self) -> SessionIndex {
148		self.0
149	}
150
151	#[doc(hidden)]
156	pub const fn unchecked_new(size: SessionIndex) -> Self {
157		Self(size)
158	}
159}
160
161pub type BlockWeight = u32;
163
164#[derive(Clone, PartialEq, Eq, Encode, Decode)]
171pub enum Statement {
172	#[codec(index = 1)]
174	Seconded(CommittedCandidateReceipt),
175	#[codec(index = 2)]
177	Valid(CandidateHash),
178}
179
180impl std::fmt::Debug for Statement {
181	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
182		match self {
183			Statement::Seconded(seconded) => write!(f, "Seconded: {:?}", seconded.descriptor),
184			Statement::Valid(hash) => write!(f, "Valid: {:?}", hash),
185		}
186	}
187}
188
189impl Statement {
190	pub fn candidate_hash(&self) -> CandidateHash {
195		match *self {
196			Statement::Valid(ref h) => *h,
197			Statement::Seconded(ref c) => c.hash(),
198		}
199	}
200
201	pub fn to_compact(&self) -> CompactStatement {
204		match *self {
205			Statement::Seconded(ref c) => CompactStatement::Seconded(c.hash()),
206			Statement::Valid(hash) => CompactStatement::Valid(hash),
207		}
208	}
209
210	pub fn supply_pvd(self, pvd: PersistedValidationData) -> StatementWithPVD {
212		match self {
213			Statement::Seconded(c) => StatementWithPVD::Seconded(c, pvd),
214			Statement::Valid(hash) => StatementWithPVD::Valid(hash),
215		}
216	}
217}
218
219impl From<&'_ Statement> for CompactStatement {
220	fn from(stmt: &Statement) -> Self {
221		stmt.to_compact()
222	}
223}
224
225impl EncodeAs<CompactStatement> for Statement {
226	fn encode_as(&self) -> Vec<u8> {
227		self.to_compact().encode()
228	}
229}
230
231#[derive(Clone, PartialEq, Eq)]
234pub enum StatementWithPVD {
235	Seconded(CommittedCandidateReceipt, PersistedValidationData),
237	Valid(CandidateHash),
239}
240
241impl std::fmt::Debug for StatementWithPVD {
242	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
243		match self {
244			StatementWithPVD::Seconded(seconded, _) =>
245				write!(f, "Seconded: {:?}", seconded.descriptor),
246			StatementWithPVD::Valid(hash) => write!(f, "Valid: {:?}", hash),
247		}
248	}
249}
250
251impl StatementWithPVD {
252	pub fn candidate_hash(&self) -> CandidateHash {
257		match *self {
258			StatementWithPVD::Valid(ref h) => *h,
259			StatementWithPVD::Seconded(ref c, _) => c.hash(),
260		}
261	}
262
263	pub fn to_compact(&self) -> CompactStatement {
266		match *self {
267			StatementWithPVD::Seconded(ref c, _) => CompactStatement::Seconded(c.hash()),
268			StatementWithPVD::Valid(hash) => CompactStatement::Valid(hash),
269		}
270	}
271
272	pub fn drop_pvd(self) -> Statement {
274		match self {
275			StatementWithPVD::Seconded(c, _) => Statement::Seconded(c),
276			StatementWithPVD::Valid(c_h) => Statement::Valid(c_h),
277		}
278	}
279
280	pub fn drop_pvd_from_signed(signed: SignedFullStatementWithPVD) -> SignedFullStatement {
283		signed
284			.convert_to_superpayload_with(|s| s.drop_pvd())
285			.expect("persisted_validation_data doesn't affect encode_as; qed")
286	}
287
288	pub fn signed_to_compact(signed: SignedFullStatementWithPVD) -> Signed<CompactStatement> {
291		signed
292			.convert_to_superpayload_with(|s| s.to_compact())
293			.expect("doesn't affect encode_as; qed")
294	}
295}
296
297impl From<&'_ StatementWithPVD> for CompactStatement {
298	fn from(stmt: &StatementWithPVD) -> Self {
299		stmt.to_compact()
300	}
301}
302
303impl EncodeAs<CompactStatement> for StatementWithPVD {
304	fn encode_as(&self) -> Vec<u8> {
305		self.to_compact().encode()
306	}
307}
308
309pub type SignedFullStatement = Signed<Statement, CompactStatement>;
316
317pub type UncheckedSignedFullStatement = UncheckedSigned<Statement, CompactStatement>;
319
320pub type SignedFullStatementWithPVD = Signed<StatementWithPVD, CompactStatement>;
326
327#[derive(Debug)]
329pub enum InvalidCandidate {
330	ExecutionError(String),
332	InvalidOutputs,
334	Timeout,
336	ParamsTooLarge(u64),
338	CodeTooLarge(u64),
340	PoVDecompressionFailure,
342	BadReturn,
344	BadParent,
346	PoVHashMismatch,
348	BadSignature,
350	ParaHeadHashMismatch,
352	CodeHashMismatch,
354	CommitmentsHashMismatch,
356	InvalidSessionIndex,
358	InvalidUMPSignals(CommittedCandidateReceiptError),
360}
361
362#[derive(Debug)]
364pub enum ValidationResult {
365	Valid(CandidateCommitments, PersistedValidationData),
368	Invalid(InvalidCandidate),
370}
371
372#[derive(PartialEq, Eq, Clone, Encode, Decode, Debug)]
374pub struct PoV {
375	pub block_data: BlockData,
377}
378
379impl PoV {
380	pub fn hash(&self) -> Hash {
382		BlakeTwo256::hash_of(self)
383	}
384}
385
386#[derive(Clone, Encode, Decode)]
388#[cfg(not(target_os = "unknown"))]
389pub enum MaybeCompressedPoV {
390	Raw(PoV),
392	Compressed(PoV),
394}
395
396#[cfg(not(target_os = "unknown"))]
397impl std::fmt::Debug for MaybeCompressedPoV {
398	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
399		let (variant, size) = match self {
400			MaybeCompressedPoV::Raw(pov) => ("Raw", pov.block_data.0.len()),
401			MaybeCompressedPoV::Compressed(pov) => ("Compressed", pov.block_data.0.len()),
402		};
403
404		write!(f, "{} PoV ({} bytes)", variant, size)
405	}
406}
407
408#[cfg(not(target_os = "unknown"))]
409impl MaybeCompressedPoV {
410	pub fn into_compressed(self) -> PoV {
414		match self {
415			Self::Raw(raw) => maybe_compress_pov(raw),
416			Self::Compressed(compressed) => compressed,
417		}
418	}
419}
420
421#[derive(Debug, Clone, Encode, Decode)]
428#[cfg(not(target_os = "unknown"))]
429pub struct Collation<BlockNumber = polkadot_primitives::BlockNumber> {
430	pub upward_messages: UpwardMessages,
432	pub horizontal_messages: HorizontalMessages,
434	pub new_validation_code: Option<ValidationCode>,
436	pub head_data: HeadData,
438	pub proof_of_validity: MaybeCompressedPoV,
440	pub processed_downward_messages: u32,
442	pub hrmp_watermark: BlockNumber,
445}
446
447#[derive(Debug)]
449#[cfg(not(target_os = "unknown"))]
450pub struct CollationSecondedSignal {
451	pub relay_parent: Hash,
453	pub statement: SignedFullStatement,
457}
458
459#[cfg(not(target_os = "unknown"))]
461pub struct CollationResult {
462	pub collation: Collation,
464	pub result_sender: Option<futures::channel::oneshot::Sender<CollationSecondedSignal>>,
470}
471
472#[cfg(not(target_os = "unknown"))]
473impl CollationResult {
474	pub fn into_inner(
476		self,
477	) -> (Collation, Option<futures::channel::oneshot::Sender<CollationSecondedSignal>>) {
478		(self.collation, self.result_sender)
479	}
480}
481
482#[cfg(not(target_os = "unknown"))]
490pub type CollatorFn = Box<
491	dyn Fn(
492			Hash,
493			&PersistedValidationData,
494		) -> Pin<Box<dyn Future<Output = Option<CollationResult>> + Send>>
495		+ Send
496		+ Sync,
497>;
498
499#[cfg(not(target_os = "unknown"))]
501pub struct CollationGenerationConfig {
502	pub key: CollatorPair,
504	pub collator: Option<CollatorFn>,
509	pub para_id: ParaId,
511}
512
513#[cfg(not(target_os = "unknown"))]
514impl std::fmt::Debug for CollationGenerationConfig {
515	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
516		write!(f, "CollationGenerationConfig {{ ... }}")
517	}
518}
519
520#[derive(Debug)]
522pub struct SubmitCollationParams {
523	pub relay_parent: Hash,
525	pub collation: Collation,
527	pub parent_head: HeadData,
529	pub validation_code_hash: ValidationCodeHash,
531	pub result_sender: Option<futures::channel::oneshot::Sender<CollationSecondedSignal>>,
537	pub core_index: CoreIndex,
539}
540
541#[derive(Clone, Encode, Decode, PartialEq, Eq, Debug)]
543pub struct AvailableData {
544	pub pov: std::sync::Arc<PoV>,
546	pub validation_data: PersistedValidationData,
548}
549
550#[derive(PartialEq, Eq, Clone, Debug, Hash)]
552pub struct Proof(BoundedVec<BoundedVec<u8, 1, MERKLE_NODE_MAX_SIZE>, 1, MERKLE_PROOF_MAX_DEPTH>);
553
554impl Proof {
555	pub fn iter(&self) -> impl Iterator<Item = &[u8]> {
557		self.0.iter().map(|v| v.as_slice())
558	}
559
560	pub fn dummy_proof() -> Proof {
564		Proof(BoundedVec::from_vec(vec![BoundedVec::from_vec(vec![0]).unwrap()]).unwrap())
565	}
566}
567
568#[derive(thiserror::Error, Debug)]
570pub enum MerkleProofError {
571	#[error("Merkle max proof depth exceeded {0} > {} .", MERKLE_PROOF_MAX_DEPTH)]
572	MerkleProofDepthExceeded(usize),
574
575	#[error("Merkle node max size exceeded {0} > {} .", MERKLE_NODE_MAX_SIZE)]
576	MerkleProofNodeSizeExceeded(usize),
578}
579
580impl TryFrom<Vec<Vec<u8>>> for Proof {
581	type Error = MerkleProofError;
582
583	fn try_from(input: Vec<Vec<u8>>) -> Result<Self, Self::Error> {
584		if input.len() > MERKLE_PROOF_MAX_DEPTH {
585			return Err(Self::Error::MerkleProofDepthExceeded(input.len()))
586		}
587		let mut out = Vec::new();
588		for element in input.into_iter() {
589			let length = element.len();
590			let data: BoundedVec<u8, 1, MERKLE_NODE_MAX_SIZE> = BoundedVec::from_vec(element)
591				.map_err(|_| Self::Error::MerkleProofNodeSizeExceeded(length))?;
592			out.push(data);
593		}
594		Ok(Proof(BoundedVec::from_vec(out).expect("Buffer size is deterined above. qed")))
595	}
596}
597
598impl Decode for Proof {
599	fn decode<I: Input>(value: &mut I) -> Result<Self, CodecError> {
600		let temp: Vec<Vec<u8>> = Decode::decode(value)?;
601		let mut out = Vec::new();
602		for element in temp.into_iter() {
603			let bounded_temp: Result<BoundedVec<u8, 1, MERKLE_NODE_MAX_SIZE>, CodecError> =
604				BoundedVec::from_vec(element)
605					.map_err(|_| "Inner node exceeds maximum node size.".into());
606			out.push(bounded_temp?);
607		}
608		BoundedVec::from_vec(out)
609			.map(Self)
610			.map_err(|_| "Merkle proof depth exceeds maximum trie depth".into())
611	}
612}
613
614impl Encode for Proof {
615	fn size_hint(&self) -> usize {
616		MERKLE_NODE_MAX_SIZE * MERKLE_PROOF_MAX_DEPTH
617	}
618
619	fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
620		let temp = self.0.iter().map(|v| v.as_vec()).collect::<Vec<_>>();
621		temp.using_encoded(f)
622	}
623}
624
625impl Serialize for Proof {
626	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
627	where
628		S: Serializer,
629	{
630		serializer.serialize_bytes(&self.encode())
631	}
632}
633
634impl<'de> Deserialize<'de> for Proof {
635	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
636	where
637		D: Deserializer<'de>,
638	{
639		let s = Vec::<u8>::deserialize(deserializer)?;
641		let mut slice = s.as_slice();
642		Decode::decode(&mut slice).map_err(de::Error::custom)
643	}
644}
645
646#[derive(PartialEq, Eq, Clone, Encode, Decode, Serialize, Deserialize, Debug, Hash)]
648pub struct ErasureChunk {
649	pub chunk: Vec<u8>,
651	pub index: ChunkIndex,
653	pub proof: Proof,
655}
656
657impl ErasureChunk {
658	pub fn proof(&self) -> &Proof {
660		&self.proof
661	}
662}
663
664#[cfg(not(target_os = "unknown"))]
666pub fn maybe_compress_pov(pov: PoV) -> PoV {
667	let PoV { block_data: BlockData(raw) } = pov;
668	let raw = sp_maybe_compressed_blob::compress(&raw, POV_BOMB_LIMIT).unwrap_or(raw);
669
670	let pov = PoV { block_data: BlockData(raw) };
671	pov
672}