referrerpolicy=no-referrer-when-downgrade

polkadot_parachain_primitives/
primitives.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Primitive types which are strictly necessary from a parachain-execution point
18//! of view.
19
20use alloc::vec::Vec;
21
22use bounded_collections::{BoundedVec, ConstU32};
23use codec::{CompactAs, Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
24use scale_info::TypeInfo;
25use serde::{Deserialize, Serialize};
26use sp_core::{bytes, TypeId};
27use sp_runtime::traits::Hash as _;
28use sp_weights::Weight;
29
30use polkadot_core_primitives::{Hash, OutboundHrmpMessage};
31
32/// Block number type used by the relay chain.
33pub use polkadot_core_primitives::BlockNumber as RelayChainBlockNumber;
34
35/// Parachain head data included in the chain.
36#[derive(
37	PartialEq,
38	Eq,
39	Clone,
40	PartialOrd,
41	Ord,
42	Encode,
43	Decode,
44	DecodeWithMemTracking,
45	derive_more::From,
46	TypeInfo,
47	Serialize,
48	Deserialize,
49)]
50#[cfg_attr(feature = "std", derive(Hash, Default))]
51pub struct HeadData(#[serde(with = "bytes")] pub Vec<u8>);
52
53impl core::fmt::Debug for HeadData {
54	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55		write!(f, "HeadData({})", array_bytes::bytes2hex("0x", &self.0))
56	}
57}
58
59impl HeadData {
60	/// Returns the hash of this head data.
61	pub fn hash(&self) -> Hash {
62		sp_runtime::traits::BlakeTwo256::hash(&self.0)
63	}
64}
65
66impl codec::EncodeLike<HeadData> for alloc::vec::Vec<u8> {}
67
68/// Parachain validation code.
69#[derive(
70	PartialEq,
71	Eq,
72	Clone,
73	Encode,
74	Decode,
75	DecodeWithMemTracking,
76	derive_more::From,
77	TypeInfo,
78	Serialize,
79	Deserialize,
80)]
81#[cfg_attr(feature = "std", derive(Hash))]
82pub struct ValidationCode(#[serde(with = "bytes")] pub Vec<u8>);
83
84impl core::fmt::Debug for ValidationCode {
85	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
86		write!(f, "ValidationCode({})", array_bytes::bytes2hex("0x", &self.0))
87	}
88}
89
90impl ValidationCode {
91	/// Get the blake2-256 hash of the validation code bytes.
92	pub fn hash(&self) -> ValidationCodeHash {
93		ValidationCodeHash(sp_runtime::traits::BlakeTwo256::hash(&self.0[..]))
94	}
95}
96
97/// Unit type wrapper around [`type@Hash`] that represents the blake2-256 hash
98/// of validation code in particular.
99///
100/// This type is produced by [`ValidationCode::hash`].
101///
102/// This type makes it easy to enforce that a hash is a validation code hash on the type level.
103#[derive(
104	Clone,
105	Copy,
106	Encode,
107	Decode,
108	DecodeWithMemTracking,
109	Hash,
110	Eq,
111	PartialEq,
112	PartialOrd,
113	Ord,
114	TypeInfo,
115)]
116pub struct ValidationCodeHash(Hash);
117
118impl core::fmt::Display for ValidationCodeHash {
119	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
120		self.0.fmt(f)
121	}
122}
123
124impl core::fmt::Debug for ValidationCodeHash {
125	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
126		write!(f, "{:?}", self.0)
127	}
128}
129
130impl AsRef<[u8]> for ValidationCodeHash {
131	fn as_ref(&self) -> &[u8] {
132		self.0.as_ref()
133	}
134}
135
136impl From<Hash> for ValidationCodeHash {
137	fn from(hash: Hash) -> ValidationCodeHash {
138		ValidationCodeHash(hash)
139	}
140}
141
142impl From<[u8; 32]> for ValidationCodeHash {
143	fn from(hash: [u8; 32]) -> ValidationCodeHash {
144		ValidationCodeHash(hash.into())
145	}
146}
147
148impl core::fmt::LowerHex for ValidationCodeHash {
149	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
150		core::fmt::LowerHex::fmt(&self.0, f)
151	}
152}
153
154/// Parachain block data.
155///
156/// Contains everything required to validate para-block, may contain block and witness data.
157#[derive(PartialEq, Eq, Clone, Encode, Decode, derive_more::From, TypeInfo, Debug)]
158#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
159pub struct BlockData(#[cfg_attr(feature = "std", serde(with = "bytes"))] pub Vec<u8>);
160
161/// Unique identifier of a parachain.
162#[derive(
163	Clone,
164	CompactAs,
165	Copy,
166	Decode,
167	DecodeWithMemTracking,
168	Default,
169	Encode,
170	Eq,
171	Hash,
172	MaxEncodedLen,
173	Ord,
174	PartialEq,
175	PartialOrd,
176	serde::Serialize,
177	serde::Deserialize,
178	TypeInfo,
179)]
180#[cfg_attr(feature = "std", derive(derive_more::Display))]
181pub struct Id(u32);
182
183impl core::fmt::Debug for Id {
184	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
185		self.0.fmt(f)
186	}
187}
188
189impl codec::EncodeLike<u32> for Id {}
190impl codec::EncodeLike<Id> for u32 {}
191
192impl TypeId for Id {
193	const TYPE_ID: [u8; 4] = *b"para";
194}
195
196impl From<Id> for u32 {
197	fn from(x: Id) -> Self {
198		x.0
199	}
200}
201
202impl From<u32> for Id {
203	fn from(x: u32) -> Self {
204		Id(x)
205	}
206}
207
208#[cfg(any(feature = "std", feature = "runtime-benchmarks"))]
209impl From<usize> for Id {
210	fn from(x: usize) -> Self {
211		// can't panic, so need to truncate
212		let x = x.try_into().unwrap_or(u32::MAX);
213		Id(x)
214	}
215}
216
217// When we added a second From impl for Id, type inference could no longer
218// determine which impl should apply for things like `5.into()`. It therefore
219// raised a bunch of errors in our test code, scattered throughout the
220// various modules' tests, that there is no impl of `From<i32>` (`i32` being
221// the default numeric type).
222//
223// We can't use `cfg(test)` here, because that configuration directive does not
224// propagate between crates, which would fail to fix tests in crates other than
225// this one.
226//
227// Instead, let's take advantage of the observation that what really matters for a
228// ParaId within a test context is that it is unique and constant. I believe that
229// there is no case where someone does `(-1).into()` anyway, but if they do, it
230// never matters whether the actual contained ID is `-1` or `4294967295`. Nobody
231// does arithmetic on a `ParaId`; doing so would be a bug.
232impl From<i32> for Id {
233	fn from(x: i32) -> Self {
234		Id(x as u32)
235	}
236}
237
238// System parachain ID is considered `< 2000`.
239const SYSTEM_INDEX_END: u32 = 1999;
240const PUBLIC_INDEX_START: u32 = 2000;
241
242/// The ID of the first publicly registrable parachain.
243pub const LOWEST_PUBLIC_ID: Id = Id(PUBLIC_INDEX_START);
244
245impl Id {
246	/// Create an `Id`.
247	pub const fn new(id: u32) -> Self {
248		Self(id)
249	}
250}
251
252/// Determine if a parachain is a system parachain or not.
253pub trait IsSystem {
254	/// Returns `true` if a parachain is a system parachain, `false` otherwise.
255	fn is_system(&self) -> bool;
256}
257
258impl IsSystem for Id {
259	fn is_system(&self) -> bool {
260		self.0 <= SYSTEM_INDEX_END
261	}
262}
263
264impl core::ops::Add<u32> for Id {
265	type Output = Self;
266
267	fn add(self, other: u32) -> Self {
268		Self(self.0 + other)
269	}
270}
271
272impl core::ops::Sub<u32> for Id {
273	type Output = Self;
274
275	fn sub(self, other: u32) -> Self {
276		Self(self.0 - other)
277	}
278}
279
280#[derive(Clone, Copy, Default, Encode, Decode, Eq, PartialEq, Ord, PartialOrd, Debug, TypeInfo)]
281pub struct Sibling(pub Id);
282
283impl From<Id> for Sibling {
284	fn from(i: Id) -> Self {
285		Self(i)
286	}
287}
288
289impl From<Sibling> for Id {
290	fn from(i: Sibling) -> Self {
291		i.0
292	}
293}
294
295impl AsRef<Id> for Sibling {
296	fn as_ref(&self) -> &Id {
297		&self.0
298	}
299}
300
301impl TypeId for Sibling {
302	const TYPE_ID: [u8; 4] = *b"sibl";
303}
304
305impl From<Sibling> for u32 {
306	fn from(x: Sibling) -> Self {
307		x.0.into()
308	}
309}
310
311impl From<u32> for Sibling {
312	fn from(x: u32) -> Self {
313		Sibling(x.into())
314	}
315}
316
317impl IsSystem for Sibling {
318	fn is_system(&self) -> bool {
319		IsSystem::is_system(&self.0)
320	}
321}
322
323/// A type that uniquely identifies an HRMP channel. An HRMP channel is established between two
324/// paras. In text, we use the notation `(A, B)` to specify a channel between A and B. The channels
325/// are unidirectional, meaning that `(A, B)` and `(B, A)` refer to different channels. The
326/// convention is that we use the first item tuple for the sender and the second for the recipient.
327/// Only one channel is allowed between two participants in one direction, i.e. there cannot be 2
328/// different channels identified by `(A, B)`. A channel with the same para id in sender and
329/// recipient is invalid. That is, however, not enforced.
330#[derive(
331	Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo,
332)]
333#[cfg_attr(feature = "std", derive(Hash))]
334pub struct HrmpChannelId {
335	/// The para that acts as the sender in this channel.
336	pub sender: Id,
337	/// The para that acts as the recipient in this channel.
338	pub recipient: Id,
339}
340
341impl HrmpChannelId {
342	/// Returns true if the given id corresponds to either the sender or the recipient.
343	pub fn is_participant(&self, id: Id) -> bool {
344		id == self.sender || id == self.recipient
345	}
346}
347
348/// A message from a parachain to its Relay Chain.
349pub type UpwardMessage = Vec<u8>;
350
351/// Something that should be called when a downward message is received.
352pub trait DmpMessageHandler {
353	/// Handle some incoming DMP messages (note these are individual XCM messages).
354	///
355	/// Also, process messages up to some `max_weight`.
356	fn handle_dmp_messages(
357		iter: impl Iterator<Item = (RelayChainBlockNumber, Vec<u8>)>,
358		max_weight: Weight,
359	) -> Weight;
360}
361impl DmpMessageHandler for () {
362	fn handle_dmp_messages(
363		iter: impl Iterator<Item = (RelayChainBlockNumber, Vec<u8>)>,
364		_max_weight: Weight,
365	) -> Weight {
366		iter.for_each(drop);
367		Weight::zero()
368	}
369}
370
371/// The aggregate XCMP message format.
372#[derive(
373	Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo, Debug, MaxEncodedLen,
374)]
375pub enum XcmpMessageFormat {
376	/// Encoded `VersionedXcm` messages, all concatenated.
377	ConcatenatedVersionedXcm,
378	/// Encoded `Vec<u8>` messages, all concatenated.
379	ConcatenatedEncodedBlob,
380	/// One or more channel control signals; these should be interpreted immediately upon receipt
381	/// from the relay-chain.
382	Signals,
383	/// Double encoded `VersionedXcm` messages, all concatenated.
384	ConcatenatedOpaqueVersionedXcm,
385}
386
387/// Something that should be called for each batch of messages received over XCMP.
388pub trait XcmpMessageHandler {
389	/// Handle some incoming XCMP messages (note these are the big one-per-block aggregate
390	/// messages).
391	///
392	/// Also, process messages up to some `max_weight`.
393	fn handle_xcmp_messages<'a, I: Iterator<Item = (Id, RelayChainBlockNumber, &'a [u8])>>(
394		iter: I,
395		max_weight: Weight,
396	) -> Weight;
397}
398impl XcmpMessageHandler for () {
399	fn handle_xcmp_messages<'a, I: Iterator<Item = (Id, RelayChainBlockNumber, &'a [u8])>>(
400		iter: I,
401		_max_weight: Weight,
402	) -> Weight {
403		for _ in iter {}
404		Weight::zero()
405	}
406}
407
408/// Validation parameters for evaluating the parachain validity function.
409// TODO: balance downloads (https://github.com/paritytech/polkadot/issues/220)
410#[derive(PartialEq, Eq, Decode, Clone)]
411#[cfg_attr(feature = "std", derive(Debug, Encode))]
412pub struct ValidationParams {
413	/// Previous head-data.
414	pub parent_head: HeadData,
415	/// The collation body.
416	pub block_data: BlockData,
417	/// The current relay-chain block number.
418	pub relay_parent_number: RelayChainBlockNumber,
419	/// The relay-chain block's storage root.
420	pub relay_parent_storage_root: Hash,
421}
422
423/// Maximum number of HRMP messages allowed per candidate.
424///
425/// We also use this as a generous limit, which still prevents possible memory exhaustion, from
426/// malicious parachains that may otherwise return a huge amount of messages in `ValidationResult`.
427pub const MAX_HORIZONTAL_MESSAGE_NUM: u32 = 16 * 1024;
428/// Maximum number of UMP messages allowed per candidate.
429///
430/// We also use this as a generous limit, which still prevents possible memory exhaustion, from
431/// malicious parachains that may otherwise return a huge amount of messages in `ValidationResult`.
432pub const MAX_UPWARD_MESSAGE_NUM: u32 = 16 * 1024;
433
434pub type UpwardMessages = BoundedVec<UpwardMessage, ConstU32<MAX_UPWARD_MESSAGE_NUM>>;
435
436pub type HorizontalMessages =
437	BoundedVec<OutboundHrmpMessage<Id>, ConstU32<MAX_HORIZONTAL_MESSAGE_NUM>>;
438
439/// The result of parachain validation.
440// TODO: balance uploads (https://github.com/paritytech/polkadot/issues/220)
441#[derive(PartialEq, Eq, Clone, Encode)]
442#[cfg_attr(feature = "std", derive(Debug, Decode))]
443pub struct ValidationResult {
444	/// New head data that should be included in the relay chain state.
445	pub head_data: HeadData,
446	/// An update to the validation code that should be scheduled in the relay chain.
447	pub new_validation_code: Option<ValidationCode>,
448	/// Upward messages send by the Parachain.
449	pub upward_messages: UpwardMessages,
450	/// Outbound horizontal messages sent by the parachain.
451	pub horizontal_messages: HorizontalMessages,
452	/// Number of downward messages that were processed by the Parachain.
453	///
454	/// It is expected that the Parachain processes them from first to last.
455	pub processed_downward_messages: u32,
456	/// The mark which specifies the block number up to which all inbound HRMP messages are
457	/// processed.
458	pub hrmp_watermark: RelayChainBlockNumber,
459}
460
461#[cfg(test)]
462mod tests {
463	use super::*;
464
465	#[test]
466	fn para_id_debug() {
467		let id = Id::new(42);
468		assert_eq!(format!("{:?}", id), "42");
469	}
470}