// 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 .
//! Message types for the overseer and subsystems.
//!
//! These messages are intended to define the protocol by which different subsystems communicate with each
//! other and signals that they receive from an overseer to coordinate their work.
//! This is intended for use with the `polkadot-overseer` crate.
//!
//! Subsystems' APIs are defined separately from their implementation, leading to easier mocking.
use futures::channel::{mpsc, oneshot};
use polkadot_primitives::v1::{
Hash, CommittedCandidateReceipt,
CandidateReceipt, PoV, ErasureChunk, BackedCandidate, Id as ParaId,
SignedAvailabilityBitfield, ValidatorId, ValidationCode, ValidatorIndex,
CoreAssignment, CoreOccupied, CandidateDescriptor,
ValidatorSignature, OmittedValidationData, AvailableData, GroupRotationInfo,
CoreState, LocalValidationData, GlobalValidationData, OccupiedCoreAssumption,
CandidateEvent, SessionIndex, BlockNumber,
};
use polkadot_node_primitives::{
MisbehaviorReport, SignedFullStatement, View, ProtocolId, ValidationResult,
};
use std::sync::Arc;
pub use sc_network::{ObservedRole, ReputationChange, PeerId};
/// A notification of a new backed candidate.
#[derive(Debug)]
pub struct NewBackedCandidate(pub BackedCandidate);
/// Messages received by the Candidate Selection subsystem.
#[derive(Debug)]
pub enum CandidateSelectionMessage {
/// We recommended a particular candidate to be seconded, but it was invalid; penalize the collator.
/// The hash is the relay parent.
Invalid(Hash, CandidateReceipt),
}
impl CandidateSelectionMessage {
/// If the current variant contains the relay parent hash, return it.
pub fn relay_parent(&self) -> Option {
match self {
Self::Invalid(hash, _) => Some(*hash),
}
}
}
/// Messages received by the Candidate Backing subsystem.
#[derive(Debug)]
pub enum CandidateBackingMessage {
/// Requests a set of backable candidates that could be backed in a child of the given
/// relay-parent, referenced by its hash.
GetBackedCandidates(Hash, oneshot::Sender>),
/// Note that the Candidate Backing subsystem should second the given candidate in the context of the
/// given relay-parent (ref. by hash). This candidate must be validated.
Second(Hash, CandidateReceipt, PoV),
/// Note a validator's statement about a particular candidate. Disagreements about validity must be escalated
/// to a broader check by Misbehavior Arbitration. Agreements are simply tallied until a quorum is reached.
Statement(Hash, SignedFullStatement),
}
impl CandidateBackingMessage {
/// If the current variant contains the relay parent hash, return it.
pub fn relay_parent(&self) -> Option {
match self {
Self::GetBackedCandidates(hash, _) => Some(*hash),
Self::Second(hash, _, _) => Some(*hash),
Self::Statement(hash, _) => Some(*hash),
}
}
}
/// Blanket error for validation failing.
#[derive(Debug)]
pub struct ValidationFailed;
/// Messages received by the Validation subsystem.
///
/// ## Validation Requests
///
/// Validation requests made to the subsystem should return an error only on internal error.
/// Otherwise, they should return either `Ok(ValidationResult::Valid(_))`
/// or `Ok(ValidationResult::Invalid)`.
#[derive(Debug)]
pub enum CandidateValidationMessage {
/// Validate a candidate with provided parameters using relay-chain state.
///
/// This will implicitly attempt to gather the `OmittedValidationData` and `ValidationCode`
/// from the runtime API of the chain, based on the `relay_parent`
/// of the `CandidateDescriptor`.
///
/// If there is no state available which can provide this data or the core for
/// the para is not free at the relay-parent, an error is returned.
ValidateFromChainState(
CandidateDescriptor,
Arc,
oneshot::Sender>,
),
/// Validate a candidate with provided, exhaustive parameters for validation.
///
/// Explicitly provide the `OmittedValidationData` and `ValidationCode` so this can do full
/// validation without needing to access the state of the relay-chain.
ValidateFromExhaustive(
OmittedValidationData,
ValidationCode,
CandidateDescriptor,
Arc,
oneshot::Sender>,
),
}
impl CandidateValidationMessage {
/// If the current variant contains the relay parent hash, return it.
pub fn relay_parent(&self) -> Option {
match self {
Self::ValidateFromChainState(_, _, _) => None,
Self::ValidateFromExhaustive(_, _, _, _, _) => None,
}
}
}
/// Events from network.
#[derive(Debug, Clone)]
pub enum NetworkBridgeEvent {
/// A peer has connected.
PeerConnected(PeerId, ObservedRole),
/// A peer has disconnected.
PeerDisconnected(PeerId),
/// Peer has sent a message.
PeerMessage(PeerId, Vec),
/// Peer's `View` has changed.
PeerViewChange(PeerId, View),
/// Our `View` has changed.
OurViewChange(View),
}
/// Messages received by the network bridge subsystem.
#[derive(Debug)]
pub enum NetworkBridgeMessage {
/// Register an event producer on startup.
RegisterEventProducer(ProtocolId, fn(NetworkBridgeEvent) -> AllMessages),
/// Report a peer for their actions.
ReportPeer(PeerId, ReputationChange),
/// Send a message to multiple peers.
SendMessage(Vec, ProtocolId, Vec),
}
impl NetworkBridgeMessage {
/// If the current variant contains the relay parent hash, return it.
pub fn relay_parent(&self) -> Option {
match self {
Self::RegisterEventProducer(_, _) => None,
Self::ReportPeer(_, _) => None,
Self::SendMessage(_, _, _) => None,
}
}
}
/// Availability Distribution Message.
#[derive(Debug)]
pub enum AvailabilityDistributionMessage {
/// Distribute an availability chunk to other validators.
DistributeChunk(Hash, ErasureChunk),
/// Fetch an erasure chunk from networking by candidate hash and chunk index.
FetchChunk(Hash, u32),
/// Event from the network bridge.
NetworkBridgeUpdate(NetworkBridgeEvent),
}
impl AvailabilityDistributionMessage {
/// If the current variant contains the relay parent hash, return it.
pub fn relay_parent(&self) -> Option {
match self {
Self::DistributeChunk(hash, _) => Some(*hash),
Self::FetchChunk(hash, _) => Some(*hash),
Self::NetworkBridgeUpdate(_) => None,
}
}
}
/// Bitfield distribution message.
#[derive(Debug)]
pub enum BitfieldDistributionMessage {
/// Distribute a bitfield via gossip to other validators.
DistributeBitfield(Hash, SignedAvailabilityBitfield),
/// Event from the network bridge.
NetworkBridgeUpdate(NetworkBridgeEvent),
}
impl BitfieldDistributionMessage {
/// If the current variant contains the relay parent hash, return it.
pub fn relay_parent(&self) -> Option {
match self {
Self::DistributeBitfield(hash, _) => Some(*hash),
Self::NetworkBridgeUpdate(_) => None,
}
}
}
/// Bitfield signing message.
///
/// Currently non-instantiable.
#[derive(Debug)]
pub enum BitfieldSigningMessage {}
impl BitfieldSigningMessage {
/// If the current variant contains the relay parent hash, return it.
pub fn relay_parent(&self) -> Option {
None
}
}
/// Availability store subsystem message.
#[derive(Debug)]
pub enum AvailabilityStoreMessage {
/// Query a `AvailableData` from the AV store.
QueryAvailableData(Hash, oneshot::Sender