diff --git a/primitives/src/inclusion_inherent.rs b/primitives/src/inclusion_inherent.rs new file mode 100644 index 000000000000..ca3f5ec23a16 --- /dev/null +++ b/primitives/src/inclusion_inherent.rs @@ -0,0 +1,23 @@ +// Copyright 2017-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 . + +//! Inclusion Inherent primitives define types and constants which can be imported +//! without needing to import the entire inherent module. + +use inherents::InherentIdentifier; + +/// Unique identifier for the Inclusion Inherent +pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"inclusn0"; diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 9167d9910e37..24ed6e1eb37f 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -23,6 +23,7 @@ use runtime_primitives::{generic, MultiSignature}; pub use runtime_primitives::traits::{BlakeTwo256, Hash as HashT, Verify, IdentifyAccount}; +pub mod inclusion_inherent; pub mod parachain; pub use parity_scale_codec::Compact; diff --git a/primitives/src/parachain.rs b/primitives/src/parachain.rs index a24cb5b612de..52306174be5d 100644 --- a/primitives/src/parachain.rs +++ b/primitives/src/parachain.rs @@ -722,6 +722,12 @@ pub type SignedAvailabilityBitfield = Signed; #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)] pub struct SignedAvailabilityBitfields(pub Vec); +impl From> for SignedAvailabilityBitfields { + fn from(fields: Vec) -> SignedAvailabilityBitfields { + SignedAvailabilityBitfields(fields) + } +} + /// A backed (or backable, depending on context) candidate. // TODO: yes, this is roughly the same as AttestedCandidate. // After https://github.com/paritytech/polkadot/issues/1250 diff --git a/runtime/parachains/src/inclusion_inherent.rs b/runtime/parachains/src/inclusion_inherent.rs index 46fe1fee469e..ac092f6b4837 100644 --- a/runtime/parachains/src/inclusion_inherent.rs +++ b/runtime/parachains/src/inclusion_inherent.rs @@ -23,18 +23,23 @@ use sp_std::prelude::*; use primitives::{ + inclusion_inherent, parachain::{BackedCandidate, SignedAvailabilityBitfields}, }; use frame_support::{ - decl_storage, decl_module, decl_error, ensure, + decl_error, decl_module, decl_storage, ensure, dispatch::DispatchResult, weights::{DispatchClass, Weight}, traits::Get, }; use system::ensure_none; -use crate::{inclusion, scheduler::{self, FreedReason}}; +use crate::{ + inclusion, + scheduler::{self, FreedReason}, +}; +use inherents::{InherentIdentifier, InherentData, MakeFatalError, ProvideInherent}; -pub trait Trait: inclusion::Trait + scheduler::Trait { } +pub trait Trait: inclusion::Trait + scheduler::Trait {} decl_storage! { trait Store for Module as ParaInclusionInherent { @@ -118,3 +123,23 @@ decl_module! { } } } + +impl ProvideInherent for Module { + type Call = Call; + type Error = MakeFatalError<()>; + const INHERENT_IDENTIFIER: InherentIdentifier = inclusion_inherent::INHERENT_IDENTIFIER; + + fn create_inherent(data: &InherentData) -> Option { + data.get_data(&Self::INHERENT_IDENTIFIER) + .expect("inclusion inherent data failed to decode") + .map(|(signed_bitfields, backed_candidates): (SignedAvailabilityBitfields, Vec>)| { + // Sanity check: session changes can invalidate an inherent, and we _really_ don't want that to happen. + // See github.com/paritytech/polkadot/issues/1327 + if Self::inclusion(system::RawOrigin::None.into(), signed_bitfields.clone(), backed_candidates.clone()).is_ok() { + Call::inclusion(signed_bitfields, backed_candidates) + } else { + Call::inclusion(Vec::new().into(), Vec::new()) + } + }) + } +}