From 8c845c51a9a629a8b056299b65b6258ecaa5482a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Tue, 7 Dec 2021 21:31:28 +0000 Subject: [PATCH] grandpa: allow authority set hard forks to be forced (#10444) * grandpa: allow authority set hard forks to be forced * grandpa: fix authority set hard forks in warp proof provider * grandpa: make AuthoritySetHardFork public * grandpa: extend comment --- client/finality-grandpa/src/lib.rs | 41 ++++++++++++++++++----- client/finality-grandpa/src/warp_proof.rs | 11 +++--- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/client/finality-grandpa/src/lib.rs b/client/finality-grandpa/src/lib.rs index e7618929fd089..b300066469472 100644 --- a/client/finality-grandpa/src/lib.rs +++ b/client/finality-grandpa/src/lib.rs @@ -541,6 +541,24 @@ where ) } +/// A descriptor for an authority set hard fork. These are authority set changes +/// that are not signalled by the runtime and instead are defined off-chain +/// (hence the hard fork). +pub struct AuthoritySetHardFork { + /// The new authority set id. + pub set_id: SetId, + /// The block hash and number at which the hard fork should be applied. + pub block: (Block::Hash, NumberFor), + /// The authorities in the new set. + pub authorities: AuthorityList, + /// The latest block number that was finalized before this authority set + /// hard fork. When defined, the authority set change will be forced, i.e. + /// the node won't wait for the block above to be finalized before enacting + /// the change, and the given finalized number will be used as a base for + /// voting. + pub last_finalized: Option>, +} + /// Make block importer and link half necessary to tie the background voter to /// it. A vector of authority set hard forks can be passed, any authority set /// change signaled at the given block (either already signalled or in a further @@ -550,7 +568,7 @@ pub fn block_import_with_authority_set_hard_forks client: Arc, genesis_authorities_provider: &dyn GenesisAuthoritySetProvider, select_chain: SC, - authority_set_hard_forks: Vec<(SetId, (Block::Hash, NumberFor), AuthorityList)>, + authority_set_hard_forks: Vec>, telemetry: Option, ) -> Result<(GrandpaBlockImport, LinkHalf), ClientError> where @@ -580,19 +598,24 @@ where let (justification_sender, justification_stream) = GrandpaJustificationStream::channel(); - // create pending change objects with 0 delay and enacted on finality - // (i.e. standard changes) for each authority set hard fork. + // create pending change objects with 0 delay for each authority set hard fork. let authority_set_hard_forks = authority_set_hard_forks .into_iter() - .map(|(set_id, (hash, number), authorities)| { + .map(|fork| { + let delay_kind = if let Some(last_finalized) = fork.last_finalized { + authorities::DelayKind::Best { median_last_finalized: last_finalized } + } else { + authorities::DelayKind::Finalized + }; + ( - set_id, + fork.set_id, authorities::PendingChange { - next_authorities: authorities, + next_authorities: fork.authorities, delay: Zero::zero(), - canon_hash: hash, - canon_height: number, - delay_kind: authorities::DelayKind::Finalized, + canon_hash: fork.block.0, + canon_height: fork.block.1, + delay_kind, }, ) }) diff --git a/client/finality-grandpa/src/warp_proof.rs b/client/finality-grandpa/src/warp_proof.rs index 3c1fa4892f8a3..39d570d22bd7d 100644 --- a/client/finality-grandpa/src/warp_proof.rs +++ b/client/finality-grandpa/src/warp_proof.rs @@ -19,8 +19,8 @@ use sp_runtime::codec::{self, Decode, Encode}; use crate::{ - best_justification, find_scheduled_change, AuthoritySetChanges, BlockNumberOps, - GrandpaJustification, SharedAuthoritySet, + best_justification, find_scheduled_change, AuthoritySetChanges, AuthoritySetHardFork, + BlockNumberOps, GrandpaJustification, SharedAuthoritySet, }; use sc_client_api::Backend as ClientBackend; use sc_network::warp_request_handler::{EncodedProof, VerificationResult, WarpSyncProvider}; @@ -255,12 +255,15 @@ where pub fn new( backend: Arc, authority_set: SharedAuthoritySet>, - hard_forks: Vec<(SetId, (Block::Hash, NumberFor), AuthorityList)>, + hard_forks: Vec>, ) -> Self { NetworkProvider { backend, authority_set, - hard_forks: hard_forks.into_iter().map(|(s, hn, list)| (hn, (s, list))).collect(), + hard_forks: hard_forks + .into_iter() + .map(|fork| (fork.block, (fork.set_id, fork.authorities))) + .collect(), } } }