// Copyright 2018-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 .
use std::collections::VecDeque;
use std::iter::FromIterator;
use std::sync::Arc;
use std::time::{Duration, Instant};
use log::{debug, warn, info};
use parity_codec::{Decode, Encode};
use futures::prelude::*;
use tokio_timer::Delay;
use parking_lot::RwLock;
use client::{
backend::Backend, BlockchainEvents, CallExecutor, Client, error::Error as ClientError
};
use grandpa::{
BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState,
voter, voter_set::VoterSet,
};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{
Block as BlockT, Header as HeaderT, NumberFor, One, Zero, BlockNumberToHash,
};
use substrate_primitives::{Blake2Hasher, ed25519, H256, Pair};
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
use crate::{
CommandOrError, Commit, Config, Error, Network, Precommit, Prevote,
PrimaryPropose, SignedMessage, NewAuthoritySet, VoterCommand,
};
use consensus_common::SelectChain;
use crate::authorities::{AuthoritySet, SharedAuthoritySet};
use crate::consensus_changes::SharedConsensusChanges;
use crate::justification::GrandpaJustification;
use crate::until_imported::UntilVoteTargetImported;
use fg_primitives::{AuthorityId, AuthoritySignature};
type HistoricalVotes = grandpa::HistoricalVotes<
::Hash,
NumberFor,
AuthoritySignature,
AuthorityId,
>;
/// Data about a completed round. The set of votes that is stored must be
/// minimal, i.e. at most one equivocation is stored per voter.
#[derive(Debug, Clone, Decode, Encode, PartialEq)]
pub struct CompletedRound {
/// The round number.
pub number: u64,
/// The round state (prevote ghost, estimate, finalized, etc.)
pub state: RoundState>,
/// The target block base used for voting in the round.
pub base: (Block::Hash, NumberFor),
/// All the votes observed in the round.
pub votes: Vec>,
}
// Data about last completed rounds within a single voter set. Stores NUM_LAST_COMPLETED_ROUNDS and always
// contains data about at least one round (genesis).
#[derive(Debug, Clone, PartialEq)]
pub struct CompletedRounds {
rounds: VecDeque>,
set_id: u64,
voters: Vec,
}
// NOTE: the current strategy for persisting completed rounds is very naive
// (update everything) and we also rely on cloning to do atomic updates,
// therefore this value should be kept small for now.
const NUM_LAST_COMPLETED_ROUNDS: usize = 2;
impl Encode for CompletedRounds {
fn encode(&self) -> Vec {
let v = Vec::from_iter(&self.rounds);
(&v, &self.set_id, &self.voters).encode()
}
}
impl Decode for CompletedRounds {
fn decode(value: &mut I) -> Option {
<(Vec>, u64, Vec)>::decode(value)
.map(|(rounds, set_id, voters)| CompletedRounds {
rounds: rounds.into(),
set_id,
voters,
})
}
}
impl CompletedRounds {
/// Create a new completed rounds tracker with NUM_LAST_COMPLETED_ROUNDS capacity.
pub(crate) fn new(
genesis: CompletedRound,
set_id: u64,
voters: &AuthoritySet>,
)
-> CompletedRounds
{
let mut rounds = VecDeque::with_capacity(NUM_LAST_COMPLETED_ROUNDS);
rounds.push_back(genesis);
let voters = voters.current().1.iter().map(|(a, _)| a.clone()).collect();
CompletedRounds { rounds, set_id, voters }
}
/// Get the set-id and voter set of the completed rounds.
pub fn set_info(&self) -> (u64, &[AuthorityId]) {
(self.set_id, &self.voters[..])
}
/// Iterate over all completed rounds.
pub fn iter(&self) -> impl Iterator> {
self.rounds.iter()
}
/// Returns the last (latest) completed round.
pub fn last(&self) -> &CompletedRound {
self.rounds.back()
.expect("inner is never empty; always contains at least genesis; qed")
}
/// Push a new completed round, returns false if the given round is older
/// than the last completed round.
pub fn push(&mut self, completed_round: CompletedRound) -> bool {
if self.last().number >= completed_round.number {
return false;
}
if self.rounds.len() == NUM_LAST_COMPLETED_ROUNDS {
self.rounds.pop_front();
}
self.rounds.push_back(completed_round);
true
}
}
/// The state of the current voter set, whether it is currently active or not
/// and information related to the previously completed rounds. Current round
/// voting status is used when restarting the voter, i.e. it will re-use the
/// previous votes for a given round if appropriate (same round and same local
/// key).
#[derive(Debug, Decode, Encode, PartialEq)]
pub enum VoterSetState {
/// The voter is live, i.e. participating in rounds.
Live {
/// The previously completed rounds.
completed_rounds: CompletedRounds,
/// Vote status for the current round.
current_round: HasVoted,
},
/// The voter is paused, i.e. not casting or importing any votes.
Paused {
/// The previously completed rounds.
completed_rounds: CompletedRounds,
},
}
impl VoterSetState {
/// Returns the last completed rounds.
pub(crate) fn completed_rounds(&self) -> CompletedRounds {
match self {
VoterSetState::Live { completed_rounds, .. } =>
completed_rounds.clone(),
VoterSetState::Paused { completed_rounds } =>
completed_rounds.clone(),
}
}
/// Returns the last completed round.
pub(crate) fn last_completed_round(&self) -> CompletedRound {
match self {
VoterSetState::Live { completed_rounds, .. } =>
completed_rounds.last().clone(),
VoterSetState::Paused { completed_rounds } =>
completed_rounds.last().clone(),
}
}
}
/// Whether we've voted already during a prior run of the program.
#[derive(Debug, Decode, Encode, PartialEq)]
pub enum HasVoted {
/// Has not voted already in this round.
No,
/// Has voted in this round.
Yes(AuthorityId, Vote),
}
/// The votes cast by this voter already during a prior run of the program.
#[derive(Debug, Clone, Decode, Encode, PartialEq)]
pub enum Vote {
/// Has cast a proposal.
Propose(PrimaryPropose),
/// Has cast a prevote.
Prevote(Option>, Prevote),
/// Has cast a precommit (implies prevote.)
Precommit(Option>, Prevote, Precommit),
}
impl HasVoted {
/// Returns the proposal we should vote with (if any.)
pub fn propose(&self) -> Option<&PrimaryPropose> {
match self {
HasVoted::Yes(_, Vote::Propose(propose)) =>
Some(propose),
HasVoted::Yes(_, Vote::Prevote(propose, _)) | HasVoted::Yes(_, Vote::Precommit(propose, _, _)) =>
propose.as_ref(),
_ => None,
}
}
/// Returns the prevote we should vote with (if any.)
pub fn prevote(&self) -> Option<&Prevote> {
match self {
HasVoted::Yes(_, Vote::Prevote(_, prevote)) | HasVoted::Yes(_, Vote::Precommit(_, prevote, _)) =>
Some(prevote),
_ => None,
}
}
/// Returns the precommit we should vote with (if any.)
pub fn precommit(&self) -> Option<&Precommit> {
match self {
HasVoted::Yes(_, Vote::Precommit(_, _, precommit)) =>
Some(precommit),
_ => None,
}
}
/// Returns true if the voter can still propose, false otherwise.
pub fn can_propose(&self) -> bool {
self.propose().is_none()
}
/// Returns true if the voter can still prevote, false otherwise.
pub fn can_prevote(&self) -> bool {
self.prevote().is_none()
}
/// Returns true if the voter can still precommit, false otherwise.
pub fn can_precommit(&self) -> bool {
self.precommit().is_none()
}
}
/// A voter set state meant to be shared safely across multiple owners.
#[derive(Clone)]
pub struct SharedVoterSetState {
inner: Arc>>,
}
impl From> for SharedVoterSetState {
fn from(set_state: VoterSetState) -> Self {
SharedVoterSetState::new(set_state)
}
}
impl SharedVoterSetState {
/// Create a new shared voter set tracker with the given state.
pub(crate) fn new(state: VoterSetState) -> Self {
SharedVoterSetState { inner: Arc::new(RwLock::new(state)) }
}
/// Read the inner voter set state.
pub(crate) fn read(&self) -> parking_lot::RwLockReadGuard> {
self.inner.read()
}
/// Return vote status information for the current round.
pub(crate) fn has_voted(&self) -> HasVoted {
match &*self.inner.read() {
VoterSetState::Live { current_round: HasVoted::Yes(id, vote), .. } =>
HasVoted::Yes(id.clone(), vote.clone()),
_ => HasVoted::No,
}
}
// NOTE: not exposed outside of this module intentionally.
fn with(&self, f: F) -> R
where F: FnOnce(&mut VoterSetState) -> R
{
f(&mut *self.inner.write())
}
}
/// The environment we run GRANDPA in.
pub(crate) struct Environment, RA, SC> {
pub(crate) inner: Arc>,
pub(crate) select_chain: SC,
pub(crate) voters: Arc>,
pub(crate) config: Config,
pub(crate) authority_set: SharedAuthoritySet>,
pub(crate) consensus_changes: SharedConsensusChanges>,
pub(crate) network: crate::communication::NetworkBridge,
pub(crate) set_id: u64,
pub(crate) voter_set_state: SharedVoterSetState,
}
impl, RA, SC> Environment {
/// Updates the voter set state using the given closure. The write lock is
/// held during evaluation of the closure and the environment's voter set
/// state is set to its result if successful.
pub(crate) fn update_voter_set_state(&self, f: F) -> Result<(), Error> where
F: FnOnce(&VoterSetState) -> Result