Newer
Older
// 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 <http://www.gnu.org/licenses/>.
//! The inclusion module is responsible for inclusion and availability of scheduled parachains
//! and parathreads.
//!
//! It is responsible for carrying candidates from being backable to being backed, and then from backed
//! to included.
use sp_std::prelude::*;
ValidatorId, CandidateCommitments, CandidateDescriptor, ValidatorIndex, Id as ParaId,
AvailabilityBitfield as AvailabilityBitfield, SignedAvailabilityBitfields, SigningContext,
BackedCandidate, CoreIndex, GroupIndex, CommittedCandidateReceipt,
decl_storage, decl_module, decl_error, decl_event, ensure, debug,
dispatch::DispatchResult, IterableStorageMap, weights::Weight, traits::Get,
};
use codec::{Encode, Decode};
use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
use sp_staking::SessionIndex;
use sp_runtime::{DispatchError, traits::{One, Saturating}};
use crate::{configuration, paras, scheduler::CoreAssignment};
/// A bitfield signed by a validator indicating that it is keeping its piece of the erasure-coding
/// for any backed candidates referred to by a `1` bit available.
///
/// The bitfield's signature should be checked at the point of submission. Afterwards it can be
/// dropped.
#[derive(Encode, Decode)]
#[cfg_attr(test, derive(Debug))]
pub struct AvailabilityBitfieldRecord<N> {
bitfield: AvailabilityBitfield, // one bit per core.
submitted_at: N, // for accounting, as meaning of bits may change over time.
}
/// A backed candidate pending availability.
// TODO: split this type and change this to hold a plain `CandidateReceipt`.
// https://github.com/paritytech/polkadot/issues/1357
#[derive(Encode, Decode, PartialEq)]
#[cfg_attr(test, derive(Debug))]
pub struct CandidatePendingAvailability<H, N> {
/// The availability core this is assigned to.
core: CoreIndex,
/// The candidate descriptor.
descriptor: CandidateDescriptor<H>,
/// The received availability votes. One bit per validator.
availability_votes: BitVec<BitOrderLsb0, u8>,
/// The block number of the relay-parent of the receipt.
relay_parent_number: N,
/// The block number of the relay-chain block this was backed in.
backed_in_number: N,
}
impl<H, N> CandidatePendingAvailability<H, N> {
/// Get the availability votes on the candidate.
pub(crate) fn availability_votes(&self) -> &BitVec<BitOrderLsb0, u8> {
&self.availability_votes
}
/// Get the relay-chain block number this was backed in.
pub(crate) fn backed_in_number(&self) -> &N {
&self.backed_in_number
}
/// Get the core index.
pub(crate) fn core_occupied(&self)-> CoreIndex {
self.core.clone()
}
}
pub trait Trait:
frame_system::Trait + paras::Trait + configuration::Trait
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
decl_storage! {
trait Store for Module<T: Trait> as ParaInclusion {
/// The latest bitfield for each validator, referred to by their index in the validator set.
AvailabilityBitfields: map hasher(twox_64_concat) ValidatorIndex
=> Option<AvailabilityBitfieldRecord<T::BlockNumber>>;
/// Candidates pending availability by `ParaId`.
PendingAvailability: map hasher(twox_64_concat) ParaId
=> Option<CandidatePendingAvailability<T::Hash, T::BlockNumber>>;
/// The commitments of candidates pending availability, by ParaId.
PendingAvailabilityCommitments: map hasher(twox_64_concat) ParaId
=> Option<CandidateCommitments>;
/// The current validators, by their parachain session keys.
Validators get(fn validators) config(validators): Vec<ValidatorId>;
/// The current session index.
CurrentSessionIndex get(fn session_index): SessionIndex;
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
}
}
decl_error! {
pub enum Error for Module<T: Trait> {
/// Availability bitfield has unexpected size.
WrongBitfieldSize,
/// Multiple bitfields submitted by same validator or validators out of order by index.
BitfieldDuplicateOrUnordered,
/// Validator index out of bounds.
ValidatorIndexOutOfBounds,
/// Invalid signature
InvalidBitfieldSignature,
/// Candidate submitted but para not scheduled.
UnscheduledCandidate,
/// Candidate scheduled despite pending candidate already existing for the para.
CandidateScheduledBeforeParaFree,
/// Candidate included with the wrong collator.
WrongCollator,
/// Scheduled cores out of order.
ScheduledOutOfOrder,
/// Code upgrade prematurely.
PrematureCodeUpgrade,
/// Candidate not in parent context.
CandidateNotInParentContext,
/// The bitfield contains a bit relating to an unassigned availability core.
UnoccupiedBitInBitfield,
/// Invalid group index in core assignment.
InvalidGroupIndex,
/// Insufficient (non-majority) backing.
InsufficientBacking,
/// Invalid (bad signature, unknown validator, etc.) backing.
InvalidBacking,
/// Collator did not sign PoV.
NotCollatorSigned,
asynchronous rob
committed
/// The validation data hash does not match expected.
ValidationDataHashMismatch,
/// Internal error only returned when compiled with debug assertions.
InternalError,
}
}
pub enum Event<T> where <T as frame_system::Trait>::Hash {
/// A candidate was backed. [candidate, head_data]
CandidateBacked(CandidateReceipt<Hash>, HeadData),
/// A candidate was included. [candidate, head_data]
CandidateIncluded(CandidateReceipt<Hash>, HeadData),
/// A candidate timed out. [candidate, head_data]
CandidateTimedOut(CandidateReceipt<Hash>, HeadData),
}
}
decl_module! {
/// The parachain-candidate inclusion module.
for enum Call where origin: <T as frame_system::Trait>::Origin
}
}
impl<T: Trait> Module<T> {
/// Block initialization logic, called by initializer.
pub(crate) fn initializer_initialize(_now: T::BlockNumber) -> Weight { 0 }
/// Block finalization logic, called by initializer.
pub(crate) fn initializer_finalize() { }
/// Handle an incoming session change.
pub(crate) fn initializer_on_new_session(
notification: &crate::initializer::SessionChangeNotification<T::BlockNumber>
) {
// unlike most drain methods, drained elements are not cleared on `Drop` of the iterator
// and require consumption.
for _ in <PendingAvailabilityCommitments>::drain() { }
for _ in <PendingAvailability<T>>::drain() { }
for _ in <AvailabilityBitfields<T>>::drain() { }
Validators::set(notification.validators.clone()); // substrate forces us to clone, stupidly.
CurrentSessionIndex::set(notification.session_index);
}
/// Process a set of incoming bitfields. Return a vec of cores freed by candidates
/// becoming available.
Loading full blame...