// Copyright 2020 Parity Technologies (UK) Ltd. // This file is part of Polkadot. // Polkadot is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Polkadot is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . //! Primitive types which are strictly necessary from a parachain-execution point //! of view. use sp_std::vec::Vec; use parity_scale_codec::{Encode, Decode, CompactAs}; use sp_core::{RuntimeDebug, TypeId}; use sp_runtime::traits::Hash as _; #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; #[cfg(feature = "std")] use sp_core::bytes; #[cfg(feature = "std")] use parity_util_mem::MallocSizeOf; use polkadot_core_primitives::{Hash, OutboundHrmpMessage}; /// Block number type used by the relay chain. pub use polkadot_core_primitives::BlockNumber as RelayChainBlockNumber; /// Parachain head data included in the chain. #[derive(PartialEq, Eq, Clone, PartialOrd, Ord, Encode, Decode, RuntimeDebug, derive_more::From)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Default, Hash, MallocSizeOf))] pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); #[cfg(feature = "std")] impl HeadData { /// Returns the hash of this head data. pub fn hash(&self) -> Hash { sp_runtime::traits::BlakeTwo256::hash(&self.0) } } /// Parachain validation code. #[derive(Default, PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, derive_more::From)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Hash, MallocSizeOf))] pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); impl ValidationCode { /// Get the blake2-256 hash of the validation code bytes. pub fn hash(&self) -> Hash { sp_runtime::traits::BlakeTwo256::hash(&self.0[..]) } } /// Parachain block data. /// /// Contains everything required to validate para-block, may contain block and witness data. #[derive(PartialEq, Eq, Clone, Encode, Decode, derive_more::From)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, MallocSizeOf))] pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Unique identifier of a parachain. #[derive( Clone, CompactAs, Copy, Decode, Default, Encode, Eq, Hash, Ord, PartialEq, PartialOrd, RuntimeDebug, )] #[cfg_attr(feature = "std", derive( serde::Serialize, serde::Deserialize, derive_more::Display, MallocSizeOf) )] pub struct Id(u32); impl TypeId for Id { const TYPE_ID: [u8; 4] = *b"para"; } impl From for u32 { fn from(x: Id) -> Self { x.0 } } impl From for Id { fn from(x: u32) -> Self { Id(x) } } impl From for Id { fn from(x: usize) -> Self { use sp_std::convert::TryInto; // can't panic, so need to truncate let x = x.try_into().unwrap_or(u32::MAX); Id(x) } } // When we added a second From impl for Id, type inference could no longer // determine which impl should apply for things like `5.into()`. It therefore // raised a bunch of errors in our test code, scattered throughout the // various modules' tests, that there is no impl of `From` (`i32` being // the default numeric type). // // We can't use `cfg(test)` here, because that configuration directive does not // propagate between crates, which would fail to fix tests in crates other than // this one. // // Instead, let's take advantage of the observation that what really matters for a // ParaId within a test context is that it is unique and constant. I believe that // there is no case where someone does `(-1).into()` anyway, but if they do, it // never matters whether the actual contained ID is `-1` or `4294967295`. Nobody // does arithmetic on a `ParaId`; doing so would be a bug. impl From for Id { fn from(x: i32) -> Self { Id(x as u32) } } const USER_INDEX_START: u32 = 1000; /// The ID of the first user (non-system) parachain. pub const LOWEST_USER_ID: Id = Id(USER_INDEX_START); impl Id { /// Create an `Id`. pub const fn new(id: u32) -> Self { Self(id) } } pub trait IsSystem { fn is_system(&self) -> bool; } impl IsSystem for Id { fn is_system(&self) -> bool { self.0 < USER_INDEX_START } } impl sp_std::ops::Add for Id { type Output = Self; fn add(self, other: u32) -> Self { Self(self.0 + other) } } #[derive(Clone, Copy, Default, Encode, Decode, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug)] pub struct Sibling(pub Id); impl From for Sibling { fn from(i: Id) -> Self { Self(i) } } impl From for Id { fn from(i: Sibling) -> Self { i.0 } } impl AsRef for Sibling { fn as_ref(&self) -> &Id { &self.0 } } impl TypeId for Sibling { const TYPE_ID: [u8; 4] = *b"sibl"; } impl From for u32 { fn from(x: Sibling) -> Self { x.0.into() } } impl From for Sibling { fn from(x: u32) -> Self { Sibling(x.into()) } } impl IsSystem for Sibling { fn is_system(&self) -> bool { IsSystem::is_system(&self.0) } } /// This type can be converted into and possibly from an AccountId (which itself is generic). pub trait AccountIdConversion: Sized { /// Convert into an account ID. This is infallible. fn into_account(&self) -> AccountId; /// Try to convert an account ID into this type. Might not succeed. fn try_from_account(a: &AccountId) -> Option; } // TODO: Remove all of this, move sp-runtime::AccountIdConversion to own crate and and use that. // #360 struct TrailingZeroInput<'a>(&'a [u8]); impl<'a> parity_scale_codec::Input for TrailingZeroInput<'a> { fn remaining_len(&mut self) -> Result, parity_scale_codec::Error> { Ok(None) } fn read(&mut self, into: &mut [u8]) -> Result<(), parity_scale_codec::Error> { let len = into.len().min(self.0.len()); into[..len].copy_from_slice(&self.0[..len]); for i in &mut into[len..] { *i = 0; } self.0 = &self.0[len..]; Ok(()) } } /// Format is b"para" ++ encode(parachain ID) ++ 00.... where 00... is indefinite trailing /// zeroes to fill AccountId. impl AccountIdConversion for Id { fn into_account(&self) -> T { (b"para", self).using_encoded(|b| T::decode(&mut TrailingZeroInput(b)) ).unwrap_or_default() } fn try_from_account(x: &T) -> Option { x.using_encoded(|d| { if &d[0..4] != b"para" { return None } let mut cursor = &d[4..]; let result = Decode::decode(&mut cursor).ok()?; if cursor.iter().all(|x| *x == 0) { Some(result) } else { None } }) } } /// A type that uniquely identifies an HRMP channel. An HRMP channel is established between two paras. /// In text, we use the notation `(A, B)` to specify a channel between A and B. The channels are /// unidirectional, meaning that `(A, B)` and `(B, A)` refer to different channels. The convention is /// that we use the first item tuple for the sender and the second for the recipient. Only one channel /// is allowed between two participants in one direction, i.e. there cannot be 2 different channels /// identified by `(A, B)`. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Encode, Decode, RuntimeDebug)] #[cfg_attr(feature = "std", derive(Hash))] pub struct HrmpChannelId { /// The para that acts as the sender in this channel. pub sender: Id, /// The para that acts as the recipient in this channel. pub recipient: Id, } /// A message from a parachain to its Relay Chain. pub type UpwardMessage = Vec; /// Validation parameters for evaluating the parachain validity function. // TODO: balance downloads (https://github.com/paritytech/polkadot/issues/220) #[derive(PartialEq, Eq, Decode, Clone)] #[cfg_attr(feature = "std", derive(Debug, Encode))] pub struct ValidationParams { /// Previous head-data. pub parent_head: HeadData, /// The collation body. pub block_data: BlockData, /// The current relay-chain block number. pub relay_parent_number: RelayChainBlockNumber, /// The relay-chain block's storage root. pub relay_parent_storage_root: Hash, } /// The result of parachain validation. // TODO: balance uploads (https://github.com/paritytech/polkadot/issues/220) #[derive(PartialEq, Eq, Clone, Encode)] #[cfg_attr(feature = "std", derive(Debug, Decode))] pub struct ValidationResult { /// New head data that should be included in the relay chain state. pub head_data: HeadData, /// An update to the validation code that should be scheduled in the relay chain. pub new_validation_code: Option, /// Upward messages send by the Parachain. pub upward_messages: Vec, /// Outbound horizontal messages sent by the parachain. pub horizontal_messages: Vec>, /// Number of downward messages that were processed by the Parachain. /// /// It is expected that the Parachain processes them from first to last. pub processed_downward_messages: u32, /// The mark which specifies the block number up to which all inbound HRMP messages are processed. pub hrmp_watermark: RelayChainBlockNumber, }