Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

grandpa: allow authority set hard forks to be forced #10444

Merged
merged 4 commits into from
Dec 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 32 additions & 9 deletions client/finality-grandpa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Block: BlockT> {
/// 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<Block>),
/// 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<NumberFor<Block>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry again me :P

Does this mean that block above should be last_finalized + 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't necessarily need to be + 1, but it needs to be a block that is higher than last_finalized yes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm completely confused now.

Let's say we set last_finalized to 1 and block is 3. So, the set will be enacted at 3, but it will already be active at 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that scenario the change gets enacted when block #3 is imported, and the GRANDPA voter will act as if block #1 is finalized, i.e. this is the base it will start voting on.

(I think you are forgetting that GRANDPA needs to distinguish between best imported and best finalized, and best finalized is always lower or equal to best imported)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that scenario the change gets enacted when block #3 is imported, and the GRANDPA voter will act as if block #1 is finalized, i.e. this is the base it will start voting on.

With the new set?

}

/// 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
Expand All @@ -550,7 +568,7 @@ pub fn block_import_with_authority_set_hard_forks<BE, Block: BlockT, Client, SC>
client: Arc<Client>,
genesis_authorities_provider: &dyn GenesisAuthoritySetProvider<Block>,
select_chain: SC,
authority_set_hard_forks: Vec<(SetId, (Block::Hash, NumberFor<Block>), AuthorityList)>,
authority_set_hard_forks: Vec<AuthoritySetHardFork<Block>>,
telemetry: Option<TelemetryHandle>,
) -> Result<(GrandpaBlockImport<BE, Block, Client, SC>, LinkHalf<Block, Client, SC>), ClientError>
where
Expand Down Expand Up @@ -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,
},
)
})
Expand Down
11 changes: 7 additions & 4 deletions client/finality-grandpa/src/warp_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -255,12 +255,15 @@ where
pub fn new(
backend: Arc<Backend>,
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
hard_forks: Vec<(SetId, (Block::Hash, NumberFor<Block>), AuthorityList)>,
hard_forks: Vec<AuthoritySetHardFork<Block>>,
) -> 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(),
}
}
}
Expand Down