// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see .
//! GRANDPA Consensus module for runtime.
//!
//! This manages the GRANDPA authority set ready for the native code.
//! These authorities are only for GRANDPA finality, not for consensus overall.
//!
//! In the future, it will also handle misbehavior reports, and on-chain
//! finality notifications.
//!
//! For full integration with GRANDPA, the `GrandpaApi` should be implemented.
//! The necessary items are re-exported via the `fg_primitives` crate.
#![cfg_attr(not(feature = "std"), no_std)]
// re-export since this is necessary for `impl_apis` in runtime.
pub use substrate_finality_grandpa_primitives as fg_primitives;
#[cfg(feature = "std")]
use serde_derive::Serialize;
use rstd::prelude::*;
use parity_codec as codec;
use codec::{Encode, Decode};
use fg_primitives::ScheduledChange;
use srml_support::{Parameter, decl_event, decl_storage, decl_module};
use srml_support::dispatch::Result;
use srml_support::storage::StorageValue;
use srml_support::storage::unhashed::StorageVec;
use primitives::traits::CurrentHeight;
use substrate_primitives::ed25519;
use system::ensure_signed;
use primitives::traits::MaybeSerializeDebug;
use ed25519::Public as AuthorityId;
mod mock;
mod tests;
struct AuthorityStorageVec(rstd::marker::PhantomData);
impl StorageVec for AuthorityStorageVec {
type Item = (S, u64);
const PREFIX: &'static [u8] = crate::fg_primitives::well_known_keys::AUTHORITY_PREFIX;
}
/// The log type of this crate, projected from module trait type.
pub type Log = RawLog<
::BlockNumber,
::SessionKey,
>;
/// Logs which can be scanned by GRANDPA for authorities change events.
pub trait GrandpaChangeSignal {
/// Try to cast the log entry as a contained signal.
fn as_signal(&self) -> Option>;
/// Try to cast the log entry as a contained forced signal.
fn as_forced_signal(&self) -> Option<(N, ScheduledChange)>;
}
/// A logs in this module.
#[cfg_attr(feature = "std", derive(Serialize, Debug))]
#[derive(Encode, Decode, PartialEq, Eq, Clone)]
pub enum RawLog {
/// Authorities set change has been signaled. Contains the new set of authorities
/// and the delay in blocks _to finalize_ before applying.
AuthoritiesChangeSignal(N, Vec<(SessionKey, u64)>),
/// A forced authorities set change. Contains in this order: the median last
/// finalized block when the change was signaled, the delay in blocks _to import_
/// before applying and the new set of authorities.
ForcedAuthoritiesChangeSignal(N, N, Vec<(SessionKey, u64)>),
}
impl RawLog {
/// Try to cast the log entry as a contained signal.
pub fn as_signal(&self) -> Option<(N, &[(SessionKey, u64)])> {
match *self {
RawLog::AuthoritiesChangeSignal(ref delay, ref signal) => Some((delay.clone(), signal)),
RawLog::ForcedAuthoritiesChangeSignal(_, _, _) => None,
}
}
/// Try to cast the log entry as a contained forced signal.
pub fn as_forced_signal(&self) -> Option<(N, N, &[(SessionKey, u64)])> {
match *self {
RawLog::ForcedAuthoritiesChangeSignal(ref median, ref delay, ref signal) => Some((median.clone(), delay.clone(), signal)),
RawLog::AuthoritiesChangeSignal(_, _) => None,
}
}
}
impl GrandpaChangeSignal for RawLog
where N: Clone, SessionKey: Clone + Into,
{
fn as_signal(&self) -> Option> {
RawLog::as_signal(self).map(|(delay, next_authorities)| ScheduledChange {
delay,
next_authorities: next_authorities.iter()
.cloned()
.map(|(k, w)| (k.into(), w))
.collect(),
})
}
fn as_forced_signal(&self) -> Option<(N, ScheduledChange)> {
RawLog::as_forced_signal(self).map(|(median, delay, next_authorities)| (median, ScheduledChange {
delay,
next_authorities: next_authorities.iter()
.cloned()
.map(|(k, w)| (k.into(), w))
.collect(),
}))
}
}
pub trait Trait: system::Trait {
/// Type for all log entries of this module.
type Log: From> + Into>;
/// The session key type used by authorities.
type SessionKey: Parameter + Default + MaybeSerializeDebug;
/// The event type of this module.
type Event: From> + Into<::Event>;
}
/// A stored pending change, old format.
// TODO: remove shim
// https://github.com/paritytech/substrate/issues/1614
#[derive(Encode, Decode)]
pub struct OldStoredPendingChange {
/// The block number this was scheduled at.
pub scheduled_at: N,
/// The delay in blocks until it will be applied.
pub delay: N,
/// The next authority set.
pub next_authorities: Vec<(SessionKey, u64)>,
}
/// A stored pending change.
#[derive(Encode)]
pub struct StoredPendingChange {
/// The block number this was scheduled at.
pub scheduled_at: N,
/// The delay in blocks until it will be applied.
pub delay: N,
/// The next authority set.
pub next_authorities: Vec<(SessionKey, u64)>,
/// If defined it means the change was forced and the given block number
/// indicates the median last finalized block when the change was signaled.
pub forced: Option,
}
impl Decode for StoredPendingChange {
fn decode(value: &mut I) -> Option {
let old = OldStoredPendingChange::decode(value)?;
let forced =