grandpa: round catchup messages (#2801)

* grandpa: initial structure for catch up messages

* grandpa: answer catch up requests

* grandpa: inject catch up messages into global stream

* grandpa: keep track of pending catch up request

* grandpa: block catchup until all referenced blocks are imported

* grandpa: unify catch up and commit streams

* grandpa: simplify communication stream/sink types

* grandpa: note gossip validator on catch up message import

* grandpa: fix cost on catch up message validation

* grandpa: check signatures on catch up messages

* grandpa: clean up catch up request handling state

* grandpa: adjust costs on invalid catch up requests

* grandpa: release lock before pushing catch up message

* grandpa: validate catch up request against peer view

* grandpa: catch up docs

* grandpa: fix tests

* grandpa: until_imported: add tests for catch up messages

* grandpa: add tests for catch up message gossip validation

* grandpa: integrate HistoricalVotes changes

* grandpa: add test for neighbor packet triggering catch up

* grandpa: add test for full voter catch up

* grandpa: depend on finality-grandpa 0.8 from crates

* granda: use finality-grandpa test helpers

* grandpa: add PSM cost for answering catch up requests

* grandpa: code style fixes

Co-Authored-By: Robert Habermeier <rphmeier@gmail.com>

* grandpa: more trailing commas

* grandpa: lower cost of invalid catch up requests near set change

* grandpa: process catch up sending on import of neighbor message

* grandpa: add comments on HistoricalVotes

* grandpa: use finality-grandpa v0.8.1 from crates.io

* grandpa: fix test compilation
This commit is contained in:
André Silva
2019-07-04 20:40:16 +01:00
committed by GitHub
parent 90f214f000
commit d5bc7325b9
11 changed files with 1381 additions and 240 deletions
@@ -30,7 +30,7 @@ use client::{
};
use grandpa::{
BlockNumberOps, Equivocation, Error as GrandpaError, round::State as RoundState,
voter, voter_set::VoterSet, HistoricalVotes,
voter, voter_set::VoterSet,
};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{
@@ -50,9 +50,17 @@ use crate::authorities::{AuthoritySet, SharedAuthoritySet};
use crate::consensus_changes::SharedConsensusChanges;
use crate::justification::GrandpaJustification;
use crate::until_imported::UntilVoteTargetImported;
use fg_primitives::AuthorityId;
use fg_primitives::{AuthorityId, AuthoritySignature};
/// Data about a completed round.
type HistoricalVotes<Block> = grandpa::HistoricalVotes<
<Block as BlockT>::Hash,
NumberFor<Block>,
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<Block: BlockT> {
/// The round number.
@@ -177,6 +185,16 @@ impl<Block: BlockT> VoterSetState<Block> {
completed_rounds.clone(),
}
}
/// Returns the last completed round.
pub(crate) fn last_completed_round(&self) -> CompletedRound<Block> {
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.
@@ -636,7 +654,7 @@ where
round: u64,
state: RoundState<Block::Hash, NumberFor<Block>>,
base: (Block::Hash, NumberFor<Block>),
votes: &HistoricalVotes<Block::Hash, NumberFor<Block>, Self::Signature, Self::Id>,
historical_votes: &HistoricalVotes<Block>,
) -> Result<(), Self::Error> {
debug!(
target: "afg", "Voter {} completed round {} in set {}. Estimate = {:?}, Finalized in round = {:?}",
@@ -650,12 +668,15 @@ where
self.update_voter_set_state(|voter_set_state| {
let mut completed_rounds = voter_set_state.completed_rounds();
// TODO: Future integration will store the prevote and precommit index. See #2611.
let votes = historical_votes.seen().clone();
// NOTE: the Environment assumes that rounds are *always* completed in-order.
if !completed_rounds.push(CompletedRound {
number: round,
state: state.clone(),
base,
votes: votes.seen().to_owned(),
votes,
}) {
let msg = "Voter completed round that is older than the last completed round.";
return Err(Error::Safety(msg.to_string()));