beefy: initialize voter from genesis and fix initial sync (#11959)

* client/beefy: use backend instead of client where possible

* client/beefy: initialize voter from genesis

Now that we have justifications import, we can drop the "lean beefy"
behaviour and start building justifications chain from Genesis with
containing all past sessions' mandatory blocks justifications.

* client/beefy: walk finality tree_route to catch session changes

* client/beefy: fix block import

During initial block import blocks are not finalized, so trying to
validate and append justifications within block import fails (for
initial network sync imported blocks).

Changes:

- Move justification validation to _after_ `inner.block_import()`,
  so block is imported in backend and runtime api can be called to
  get the BEEFY authorities for said block.
- Move append-to-backend for imported BEEFY justification to voter,
  because it already has the required logic to BEEFY-finalize blocks
  only after GRANDPA finalized them.
- Mark voting rounds as concluded when finalizing through
  imported justifications as well as when finalizing through voting.

* client/beefy: valid justifications are one per block number

The only way we'd get _different_ _validated_ justifications for same
block number is if authorities are double voting, which will be handled
later.

* client/beefy: process incoming justifs during major sync

* client/beefy: correct voter initialization

BEEFY voter should resume voting from either:
  - last BEEFY finalized block,
  - session start,
whichever is closest to head.

* client/beefy: test voter initialization

* client/beefy: impl review suggestions

Signed-off-by: acatangiu <adrian@parity.io>
This commit is contained in:
Adrian Catangiu
2022-09-05 13:47:15 +03:00
committed by GitHub
parent 1fabf067d0
commit 84acfd5f50
4 changed files with 342 additions and 147 deletions
+18 -10
View File
@@ -147,13 +147,8 @@ where
trace!(target: "beefy", "🥩 Round #{} done: {}", round.1, done);
if done {
// remove this and older (now stale) rounds
let signatures = self.rounds.remove(round)?.votes;
self.rounds.retain(|&(_, number), _| number > round.1);
self.mandatory_done = self.mandatory_done || round.1 == self.session_start;
self.best_done = self.best_done.max(Some(round.1));
debug!(target: "beefy", "🥩 Concluded round #{}", round.1);
self.conclude(round.1);
Some(
self.validators()
.iter()
@@ -165,9 +160,12 @@ where
}
}
#[cfg(test)]
pub(crate) fn test_set_mandatory_done(&mut self, done: bool) {
self.mandatory_done = done;
pub(crate) fn conclude(&mut self, round_num: NumberFor<B>) {
// Remove this and older (now stale) rounds.
self.rounds.retain(|&(_, number), _| number > round_num);
self.mandatory_done = self.mandatory_done || round_num == self.session_start;
self.best_done = self.best_done.max(Some(round_num));
debug!(target: "beefy", "🥩 Concluded round #{}", round_num);
}
}
@@ -178,9 +176,19 @@ mod tests {
use beefy_primitives::{crypto::Public, ValidatorSet};
use super::{threshold, RoundTracker, Rounds};
use super::{threshold, Block as BlockT, Hash, RoundTracker, Rounds};
use crate::keystore::tests::Keyring;
impl<P, B> Rounds<P, B>
where
P: Ord + Hash + Clone,
B: BlockT,
{
pub(crate) fn test_set_mandatory_done(&mut self, done: bool) {
self.mandatory_done = done;
}
}
#[test]
fn round_tracker() {
let mut rt = RoundTracker::default();