From b4fb14bc521d270096b28df0d752cc174e934cb0 Mon Sep 17 00:00:00 2001 From: Peter Goodspeed-Niklaus Date: Thu, 5 Mar 2020 09:19:03 +0100 Subject: [PATCH] WIP: Add current_relay_block to ValidationParams, resolve circular dep Resolving the circular dependency was relatively simple: just move a bunch of parachain-specific stuff from the parachain package into the primitives package, then fix up the Cargo manifests. Then, publicly import all the stuff which was moved so that we don't break any external packages which depend on parachain. We have a deprecation notice on that `pub use` statement because downstream consumers should depend on items in the right place. Unfortunately, it doesn't actually do anything due to https://github.com/rust-lang/rust/issues/47236. Still, we'll leave it in against the day that bug gets fixed. Adding current_relay_block to ValidationParams is only part of the work, of course: we now need to go back to where that struct is instantiated, and insert it there, tracing it back until we get to some kind of relay chain instance from which we can get the actual current value and insert it appropriately. --- parachain/Cargo.toml | 2 + parachain/src/lib.rs | 164 +++--------------------------------- primitives/Cargo.toml | 7 +- primitives/src/parachain.rs | 159 ++++++++++++++++++++++++++++++++-- 4 files changed, 171 insertions(+), 161 deletions(-) diff --git a/parachain/Cargo.toml b/parachain/Cargo.toml index 85948c302244..a0104dc6f803 100644 --- a/parachain/Cargo.toml +++ b/parachain/Cargo.toml @@ -18,6 +18,7 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "cumulus-bra lazy_static = { version = "1.4.0", optional = true } parking_lot = { version = "0.10.0", optional = true } log = { version = "0.4.8", optional = true } +polkadot-primitives = { path = "../primitives", default-features = false } [target.'cfg(not(target_os = "unknown"))'.dependencies] shared_memory = { version = "0.10.0", optional = true } @@ -44,4 +45,5 @@ std = [ "sp-externalities", "sc-executor", "sp-io", + "polkadot-primitives/std", ] diff --git a/parachain/src/lib.rs b/parachain/src/lib.rs index d1324140d78f..5367a01c0a1c 100644 --- a/parachain/src/lib.rs +++ b/parachain/src/lib.rs @@ -50,12 +50,21 @@ mod wasm_api; use rstd::vec::Vec; -use codec::{Encode, Decode, CompactAs}; -use sp_core::{RuntimeDebug, TypeId}; +use codec::{Encode, Decode}; #[cfg(all(not(feature = "std"), feature = "wasm-api"))] pub use wasm_api::*; +#[deprecated(note="moved to primitives package")] +pub use polkadot_primitives::{BlockNumber, parachain::{ + AccountIdConversion, + Id, + IncomingMessage, + LOWEST_USER_ID, + ParachainDispatchOrigin, + UpwardMessage, +}}; + /// Validation parameters for evaluating the parachain validity function. // TODO: balance downloads (https://github.com/paritytech/polkadot/issues/220) #[derive(PartialEq, Eq, Decode)] @@ -65,6 +74,8 @@ pub struct ValidationParams { pub block_data: Vec, /// Previous head-data. pub parent_head: Vec, + /// Number of the current relay chain block. + pub current_relay_block: BlockNumber, } /// The result of parachain validation. @@ -75,152 +86,3 @@ pub struct ValidationResult { /// New head data that should be included in the relay chain state. pub head_data: 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))] -pub struct Id(u32); - -impl TypeId for Id { - const TYPE_ID: [u8; 4] = *b"para"; -} - -/// Type for determining the active set of parachains. -pub trait ActiveThreads { - /// Return the current ordered set of `Id`s of active parathreads. - fn active_threads() -> Vec; -} - -impl From for u32 { - fn from(x: Id) -> Self { x.0 } -} - -impl From for Id { - fn from(x: u32) -> Self { Id(x) } -} - -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) - } - - /// Returns `true` if this parachain runs with system-level privileges. - pub fn is_system(&self) -> bool { self.0 < USER_INDEX_START } -} - -impl rstd::ops::Add for Id { - type Output = Self; - - fn add(self, other: u32) -> Self { - Self(self.0 + other) - } -} - -// TODO: Remove all of this, move sp-runtime::AccountIdConversion to own crate and and use that. -// #360 -struct TrailingZeroInput<'a>(&'a [u8]); -impl<'a> codec::Input for TrailingZeroInput<'a> { - fn remaining_len(&mut self) -> Result, codec::Error> { - Ok(None) - } - - fn read(&mut self, into: &mut [u8]) -> Result<(), 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(()) - } -} - -/// 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; -} - -/// 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 - } - }) - } -} - -/// Which origin a parachain's message to the relay chain should be dispatched from. -#[derive(Clone, PartialEq, Eq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug))] -#[repr(u8)] -pub enum ParachainDispatchOrigin { - /// As a simple `Origin::Signed`, using `ParaId::account_id` as its value. This is good when - /// interacting with standard modules such as `balances`. - Signed, - /// As the special `Origin::Parachain(ParaId)`. This is good when interacting with parachain- - /// aware modules which need to succinctly verify that the origin is a parachain. - Parachain, - /// As the simple, superuser `Origin::Root`. This can only be done on specially permissioned - /// parachains. - Root, -} - -impl rstd::convert::TryFrom for ParachainDispatchOrigin { - type Error = (); - fn try_from(x: u8) -> core::result::Result { - const SIGNED: u8 = ParachainDispatchOrigin::Signed as u8; - const PARACHAIN: u8 = ParachainDispatchOrigin::Parachain as u8; - Ok(match x { - SIGNED => ParachainDispatchOrigin::Signed, - PARACHAIN => ParachainDispatchOrigin::Parachain, - _ => return Err(()), - }) - } -} - -/// A message from a parachain to its Relay Chain. -#[derive(Clone, PartialEq, Eq, Encode, Decode, sp_runtime_interface::pass_by::PassByCodec)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct UpwardMessage { - /// The origin for the message to be sent from. - pub origin: ParachainDispatchOrigin, - /// The message data. - pub data: Vec, -} - -/// An incoming message. -#[derive(PartialEq, Eq, Decode)] -#[cfg_attr(feature = "std", derive(Debug, Encode))] -pub struct IncomingMessage { - /// The source parachain. - pub source: Id, - /// The data of the message. - pub data: Vec, -} diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 98861c5afc0b..db9beee34309 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -11,13 +11,13 @@ primitives = { package = "sp-core", git = "https://github.com/paritytech/substra inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false } application-crypto = { package = "sp-application-crypto", git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false } +sp-runtime-interface = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false } sp-version = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false } rstd = { package = "sp-std", git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false } runtime_primitives = { package = "sp-runtime", git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false } -polkadot-parachain = { path = "../parachain", default-features = false } trie = { package = "sp-trie", git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false } bitvec = { version = "0.15.2", default-features = false, features = ["alloc"] } -babe = { package = "pallet-babe", git = "https://github.com/paritytech/substrate", branch = "cumulus-branch", default-features = false } +derive_more = { version = "0.99.2" } [dev-dependencies] sp-serializer = { git = "https://github.com/paritytech/substrate", branch = "cumulus-branch" } @@ -31,11 +31,10 @@ std = [ "inherents/std", "trie/std", "sp-api/std", + "sp-runtime-interface/std", "rstd/std", "sp-version/std", "runtime_primitives/std", "serde", - "polkadot-parachain/std", "bitvec/std", - "babe/std" ] diff --git a/primitives/src/parachain.rs b/primitives/src/parachain.rs index 045f99d62319..faa9f083bbe4 100644 --- a/primitives/src/parachain.rs +++ b/primitives/src/parachain.rs @@ -18,7 +18,7 @@ use rstd::prelude::*; use rstd::cmp::Ordering; -use parity_scale_codec::{Encode, Decode}; +use parity_scale_codec::{Encode, Decode, CompactAs}; use bitvec::vec::BitVec; use super::{Hash, Balance}; @@ -27,17 +27,13 @@ use serde::{Serialize, Deserialize}; #[cfg(feature = "std")] use primitives::bytes; -use primitives::RuntimeDebug; +use primitives::{RuntimeDebug, TypeId}; use inherents::InherentIdentifier; use application_crypto::KeyTypeId; #[cfg(feature = "std")] use trie::TrieConfiguration; -pub use polkadot_parachain::{ - Id, ParachainDispatchOrigin, LOWEST_USER_ID, UpwardMessage, -}; - /// The key type ID for a collator key. pub const COLLATOR_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"coll"); @@ -465,6 +461,157 @@ pub mod id { pub const PARACHAIN_HOST: ApiId = *b"parahost"; } +/// 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))] +pub struct Id(u32); + +impl TypeId for Id { + const TYPE_ID: [u8; 4] = *b"para"; +} + +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) + } + + /// Returns `true` if this parachain runs with system-level privileges. + pub fn is_system(&self) -> bool { self.0 < USER_INDEX_START } +} + +impl rstd::ops::Add for Id { + type Output = Self; + + fn add(self, other: u32) -> Self { + Self(self.0 + other) + } +} + +/// Type for determining the active set of parachains. +pub trait ActiveThreads { + /// Return the current ordered set of `Id`s of active parathreads. + fn active_threads() -> Vec; +} + +impl From for u32 { + fn from(x: Id) -> Self { x.0 } +} + +impl From for Id { + fn from(x: u32) -> Self { Id(x) } +} + +// 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(()) + } +} + +/// 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; +} + +/// 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 + } + }) + } +} + + +/// Which origin a parachain's message to the relay chain should be dispatched from. +#[derive(Clone, PartialEq, Eq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +#[repr(u8)] +pub enum ParachainDispatchOrigin { + /// As a simple `Origin::Signed`, using `ParaId::account_id` as its value. This is good when + /// interacting with standard modules such as `balances`. + Signed, + /// As the special `Origin::Parachain(ParaId)`. This is good when interacting with parachain- + /// aware modules which need to succinctly verify that the origin is a parachain. + Parachain, + /// As the simple, superuser `Origin::Root`. This can only be done on specially permissioned + /// parachains. + Root, +} + +impl rstd::convert::TryFrom for ParachainDispatchOrigin { + type Error = (); + fn try_from(x: u8) -> core::result::Result { + const SIGNED: u8 = ParachainDispatchOrigin::Signed as u8; + const PARACHAIN: u8 = ParachainDispatchOrigin::Parachain as u8; + Ok(match x { + SIGNED => ParachainDispatchOrigin::Signed, + PARACHAIN => ParachainDispatchOrigin::Parachain, + _ => return Err(()), + }) + } +} + +/// A message from a parachain to its Relay Chain. +#[derive(Clone, PartialEq, Eq, Encode, Decode, sp_runtime_interface::pass_by::PassByCodec)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct UpwardMessage { + /// The origin for the message to be sent from. + pub origin: ParachainDispatchOrigin, + /// The message data. + pub data: Vec, +} + +/// An incoming message. +#[derive(PartialEq, Eq, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Encode))] +pub struct IncomingMessage { + /// The source parachain. + pub source: Id, + /// The data of the message. + pub data: Vec, +} + + #[cfg(test)] mod tests { use super::*;