This repository was archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
grandpa-rpc: allow proving finality of blocks from latest authority set #8585
Merged
Merged
Changes from 2 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
d3021d5
grandpa: use new latest stored justification in prove_finality
octol 0345162
grandpa: include end in range in FinalityProof::unknown_headers
octol 25ce3fc
grandpa: typo in comment
octol f028171
grandpa: remove ProvableJustification
octol 32b0182
Merge remote-tracking branch 'upstream/master' into jon/respond-with-…
octol 693254f
grandpa: revert unnecessary changes
andresilva 178095e
grandpa: extend AuthoritySetChangeId and cleanup get_set_id
andresilva 2da0df2
grandpa: move check_finality_proof to the test module
andresilva 890fe4c
grandpa: warn on missing authority set changes data
andresilva 1b81f27
grandpa: add missing use statement
octol 4e9b62d
grandpa: simplify finality_proof tests
octol 7221590
grandpa: additional tests for finality_proof
octol d0fa7ff
Merge remote-tracking branch 'upstream/master' into jon/respond-with-…
octol File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,8 @@ use sc_telemetry::{telemetry, TelemetryHandle, CONSENSUS_INFO}; | |
| use sp_finality_grandpa::{AuthorityId, AuthorityList}; | ||
| use sc_consensus::shared_data::{SharedData, SharedDataLocked}; | ||
|
|
||
| use crate::SetId; | ||
|
|
||
| use std::cmp::Ord; | ||
| use std::fmt::Debug; | ||
| use std::ops::Add; | ||
|
|
@@ -684,6 +686,17 @@ impl<H, N: Add<Output=N> + Clone> PendingChange<H, N> { | |
| #[derive(Debug, Encode, Decode, Clone, PartialEq)] | ||
| pub struct AuthoritySetChanges<N>(Vec<(u64, N)>); | ||
|
|
||
| /// The response when queuering for a the set id for a specific block. Either we get a set id | ||
| /// together with a block number for the last block in the set, or that the requested block is in the | ||
| /// latest set. | ||
| #[derive(Debug, PartialEq)] | ||
| pub enum AuthoritySetChangeId<N> { | ||
| /// The requested block is in the latest set. | ||
| Latest, | ||
| /// Tuple containing the set id and the last block number of that set. | ||
| Set(SetId, N), | ||
| } | ||
|
|
||
|
Comment on lines
+692
to
+702
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really like this type, seems overly complicated for what we're doing here. Perhaps we should just drop the assumption that some data might not be available. |
||
| impl<N> From<Vec<(u64, N)>> for AuthoritySetChanges<N> { | ||
| fn from(changes: Vec<(u64, N)>) -> AuthoritySetChanges<N> { | ||
| AuthoritySetChanges(changes) | ||
|
|
@@ -699,7 +712,11 @@ impl<N: Ord + Clone> AuthoritySetChanges<N> { | |
| self.0.push((set_id, block_number)); | ||
| } | ||
|
|
||
| pub(crate) fn get_set_id(&self, block_number: N) -> Option<(u64, N)> { | ||
| pub(crate) fn get_set_id(&self, block_number: N) -> Option<AuthoritySetChangeId<N>> { | ||
| if self.block_is_current_set(block_number.clone()).unwrap_or(false) { | ||
| return Some(AuthoritySetChangeId::Latest); | ||
| } | ||
|
|
||
| let idx = self.0 | ||
| .binary_search_by_key(&block_number, |(_, n)| n.clone()) | ||
| .unwrap_or_else(|b| b); | ||
|
|
@@ -718,12 +735,16 @@ impl<N: Ord + Clone> AuthoritySetChanges<N> { | |
| // that we are in the right set id. | ||
| return None; | ||
| } | ||
| Some((set_id, block_number)) | ||
| Some(AuthoritySetChangeId::Set(set_id, block_number)) | ||
| } else { | ||
| None | ||
| } | ||
| } | ||
|
|
||
| pub(crate) fn block_is_current_set(&self, block_number: N) -> Option<bool> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can just be moved above as it's not used elsewhere. |
||
| self.0.last().map(|last_auth_change| last_auth_change.1 < block_number) | ||
| } | ||
|
|
||
| /// Returns an iterator over all historical authority set changes starting at the given block | ||
| /// number (excluded). The iterator yields a tuple representing the set id and the block number | ||
| /// of the last block in that set. | ||
|
|
@@ -1660,11 +1681,11 @@ mod tests { | |
| authority_set_changes.append(1, 81); | ||
| authority_set_changes.append(2, 121); | ||
|
|
||
| assert_eq!(authority_set_changes.get_set_id(20), Some((0, 41))); | ||
| assert_eq!(authority_set_changes.get_set_id(40), Some((0, 41))); | ||
| assert_eq!(authority_set_changes.get_set_id(41), Some((0, 41))); | ||
| assert_eq!(authority_set_changes.get_set_id(42), Some((1, 81))); | ||
| assert_eq!(authority_set_changes.get_set_id(141), None); | ||
| assert_eq!(authority_set_changes.get_set_id(20), Some(AuthoritySetChangeId::Set(0, 41))); | ||
| assert_eq!(authority_set_changes.get_set_id(40), Some(AuthoritySetChangeId::Set(0, 41))); | ||
| assert_eq!(authority_set_changes.get_set_id(41), Some(AuthoritySetChangeId::Set(0, 41))); | ||
| assert_eq!(authority_set_changes.get_set_id(42), Some(AuthoritySetChangeId::Set(1, 81))); | ||
| assert_eq!(authority_set_changes.get_set_id(141), Some(AuthoritySetChangeId::Latest)); | ||
| } | ||
|
|
||
| #[test] | ||
|
|
@@ -1677,8 +1698,8 @@ mod tests { | |
| assert_eq!(authority_set_changes.get_set_id(20), None); | ||
| assert_eq!(authority_set_changes.get_set_id(40), None); | ||
| assert_eq!(authority_set_changes.get_set_id(41), None); | ||
| assert_eq!(authority_set_changes.get_set_id(42), Some((3, 81))); | ||
| assert_eq!(authority_set_changes.get_set_id(141), None); | ||
| assert_eq!(authority_set_changes.get_set_id(42), Some(AuthoritySetChangeId::Set(3, 81))); | ||
| assert_eq!(authority_set_changes.get_set_id(141), Some(AuthoritySetChangeId::Latest)); | ||
| } | ||
|
|
||
| #[test] | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,15 +28,19 @@ use fork_tree::ForkTree; | |
| use sc_client_api::backend::AuxStore; | ||
| use sp_blockchain::{Error as ClientError, Result as ClientResult}; | ||
| use sp_finality_grandpa::{AuthorityList, RoundNumber, SetId}; | ||
| use sp_runtime::traits::{Block as BlockT, NumberFor}; | ||
|
|
||
| use crate::authorities::{ | ||
| AuthoritySet, AuthoritySetChanges, DelayKind, PendingChange, SharedAuthoritySet, | ||
| }; | ||
| use crate::environment::{ | ||
| CompletedRound, CompletedRounds, CurrentRounds, HasVoted, SharedVoterSetState, VoterSetState, | ||
| use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; | ||
|
|
||
| use crate::{ | ||
| authorities::{ | ||
| AuthoritySet, AuthoritySetChanges, DelayKind, PendingChange, SharedAuthoritySet, | ||
| }, | ||
| environment::{ | ||
| CompletedRound, CompletedRounds, CurrentRounds, HasVoted, SharedVoterSetState, | ||
| VoterSetState, | ||
| }, | ||
| finality_proof::ProvableJustification, | ||
| NewAuthoritySet, | ||
| }; | ||
| use crate::{GrandpaJustification, NewAuthoritySet}; | ||
|
|
||
| const VERSION_KEY: &[u8] = b"grandpa_schema_version"; | ||
| const SET_STATE_KEY: &[u8] = b"grandpa_completed_round"; | ||
|
|
@@ -500,26 +504,29 @@ where | |
| /// We always keep around the justification for the best finalized block and overwrite it | ||
| /// as we finalize new blocks, this makes sure that we don't store useless justifications | ||
| /// but can always prove finality of the latest block. | ||
| pub(crate) fn update_best_justification<Block: BlockT, F, R>( | ||
| justification: &GrandpaJustification<Block>, | ||
| pub(crate) fn update_best_justification<Header, J, F, R>( | ||
| justification: &J, | ||
| write_aux: F, | ||
| ) -> R | ||
| where | ||
| Header: HeaderT, | ||
| J: ProvableJustification<Header>, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wanted to remove |
||
| F: FnOnce(&[(&'static [u8], &[u8])]) -> R, | ||
| { | ||
| let encoded_justification = justification.encode(); | ||
| write_aux(&[(BEST_JUSTIFICATION, &encoded_justification[..])]) | ||
| } | ||
|
|
||
| /// Fetch the justification for the latest block finalized by GRANDPA, if any. | ||
| pub fn best_justification<B, Block>( | ||
| pub fn best_justification<B, Header, J>( | ||
| backend: &B, | ||
| ) -> ClientResult<Option<GrandpaJustification<Block>>> | ||
| ) -> ClientResult<Option<J>> | ||
| where | ||
| B: AuxStore, | ||
| Block: BlockT, | ||
| Header: HeaderT, | ||
| J: ProvableJustification<Header>, | ||
| { | ||
| load_decode::<_, GrandpaJustification<Block>>(backend, BEST_JUSTIFICATION) | ||
| load_decode::<_, J>(backend, BEST_JUSTIFICATION) | ||
| } | ||
|
|
||
| /// Write voter set state. | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.