// 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 = >::decode(value).unwrap_or(None); Some(StoredPendingChange { scheduled_at: old.scheduled_at, delay: old.delay, next_authorities: old.next_authorities, forced, }) } } decl_event!( pub enum Event where ::SessionKey { /// New authority set has been applied. NewAuthorities(Vec<(SessionKey, u64)>), } ); decl_storage! { trait Store for Module as GrandpaFinality { // Pending change: (signaled at, scheduled change). PendingChange get(pending_change): Option>; // next block number where we can force a change. NextForced get(next_forced): Option; } add_extra_genesis { config(authorities): Vec<(T::SessionKey, u64)>; build(|storage: &mut primitives::StorageOverlay, _: &mut primitives::ChildrenStorageOverlay, config: &GenesisConfig| { use codec::{Encode, KeyedVec}; let auth_count = config.authorities.len() as u32; config.authorities.iter().enumerate().for_each(|(i, v)| { storage.insert((i as u32).to_keyed_vec( crate::fg_primitives::well_known_keys::AUTHORITY_PREFIX), v.encode() ); }); storage.insert( crate::fg_primitives::well_known_keys::AUTHORITY_COUNT.to_vec(), auth_count.encode(), ); }); } } decl_module! { pub struct Module for enum Call where origin: T::Origin { fn deposit_event() = default; /// Report some misbehavior. fn report_misbehavior(origin, _report: Vec) { ensure_signed(origin)?; // FIXME: https://github.com/paritytech/substrate/issues/1112 } fn on_finalize(block_number: T::BlockNumber) { if let Some(pending_change) = >::get() { if block_number == pending_change.scheduled_at { if let Some(median) = pending_change.forced { Self::deposit_log(RawLog::ForcedAuthoritiesChangeSignal( median, pending_change.delay, pending_change.next_authorities.clone(), )); } else { Self::deposit_log(RawLog::AuthoritiesChangeSignal( pending_change.delay, pending_change.next_authorities.clone(), )); } } if block_number == pending_change.scheduled_at + pending_change.delay { Self::deposit_event( RawEvent::NewAuthorities(pending_change.next_authorities.clone()) ); >::set_items(pending_change.next_authorities); >::kill(); } } } } } impl Module { /// Get the current set of authorities, along with their respective weights. pub fn grandpa_authorities() -> Vec<(T::SessionKey, u64)> { >::items() } /// Schedule a change in the authorities. /// /// The change will be applied at the end of execution of the block /// `in_blocks` after the current block. This value may be 0, in which /// case the change is applied at the end of the current block. /// /// If the `forced` parameter is defined, this indicates that the current /// set has been synchronously determined to be offline and that after /// `in_blocks` the given change should be applied. The given block number /// indicates the median last finalized block number and it should be used /// as the canon block when starting the new grandpa voter. /// /// No change should be signaled while any change is pending. Returns /// an error if a change is already pending. pub fn schedule_change( next_authorities: Vec<(T::SessionKey, u64)>, in_blocks: T::BlockNumber, forced: Option, ) -> Result { use primitives::traits::As; if Self::pending_change().is_none() { let scheduled_at = system::ChainContext::::default().current_height(); if let Some(_) = forced { if Self::next_forced().map_or(false, |next| next > scheduled_at) { return Err("Cannot signal forced change so soon after last."); } // only allow the next forced change when twice the window has passed since // this one. >::put(scheduled_at + in_blocks * T::BlockNumber::sa(2)); } >::put(StoredPendingChange { delay: in_blocks, scheduled_at, next_authorities, forced, }); Ok(()) } else { Err("Attempt to signal GRANDPA change with one already pending.") } } /// Deposit one of this module's logs. fn deposit_log(log: Log) { >::deposit_log(::Log::from(log).into()); } } impl Module where AuthorityId: core::convert::From<::SessionKey> { /// See if the digest contains any standard scheduled change. pub fn scrape_digest_change(log: &Log) -> Option> { as GrandpaChangeSignal>::as_signal(log) } /// See if the digest contains any forced scheduled change. pub fn scrape_digest_forced_change(log: &Log) -> Option<(T::BlockNumber, ScheduledChange)> { as GrandpaChangeSignal>::as_forced_signal(log) } } /// Helper for authorities being synchronized with the general session authorities. /// /// This is not the only way to manage an authority set for GRANDPA, but it is /// a convenient one. When this is used, no other mechanism for altering authority /// sets should be. pub struct SyncedAuthorities(::rstd::marker::PhantomData); // FIXME: remove when https://github.com/rust-lang/rust/issues/26925 is fixed impl Default for SyncedAuthorities { fn default() -> Self { SyncedAuthorities(::rstd::marker::PhantomData) } } impl session::OnSessionChange for SyncedAuthorities where T: Trait + consensus::Trait::SessionKey>, ::Log: From::SessionKey>> { fn on_session_change(_: X, _: bool) { use primitives::traits::Zero; let next_authorities = >::authorities() .into_iter() .map(|key| (key, 1)) // evenly-weighted. .collect::::SessionKey, u64)>>(); // instant changes let last_authorities = >::grandpa_authorities(); if next_authorities != last_authorities { let _ = >::schedule_change(next_authorities, Zero::zero(), None); } } } impl finality_tracker::OnFinalizationStalled for SyncedAuthorities where T: Trait + consensus::Trait::SessionKey>, ::Log: From::SessionKey>>, T: finality_tracker::Trait, { fn on_stalled(further_wait: T::BlockNumber) { // when we record old authority sets, we can use `finality_tracker::median` // to figure out _who_ failed. until then, we can't meaningfully guard // against `next == last` the way that normal session changes do. let next_authorities = >::authorities() .into_iter() .map(|key| (key, 1)) // evenly-weighted. .collect::::SessionKey, u64)>>(); let median = >::median(); // schedule a change for `further_wait` blocks. let _ = >::schedule_change(next_authorities, further_wait, Some(median)); } }