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.7k
Light GRANDPA import handler #1669
Merged
Merged
Changes from 1 commit
Commits
Show all changes
58 commits
Select commit
Hold shift + click to select a range
9d58b46
GrandpaLightBlockImport
svyatonik 0b3443b
extract authorities in AuraVerifier
svyatonik 31b183d
Merge branch 'master' into light_grandpa_importer2
svyatonik da6c11e
post-merge fix
svyatonik 2d8a084
Merge branch 'master' into light_grandpa_importer2
svyatonik d42315b
restore authorities cache
svyatonik 4cbefb6
license
svyatonik 5344c61
new finality proof draft
svyatonik c3a8125
generalized PendingJustifications
svyatonik 2c4ae73
finality proof messages
svyatonik fbf49c6
fixed compilation
svyatonik ac72a40
pass verifier to import_finality_proof
svyatonik d4becc1
do not fetch remote proof from light import directly
svyatonik 41c4376
FinalityProofProvider
svyatonik 41a1dba
fixed authorities cache test
svyatonik 2c02eff
restored finality proof tests
svyatonik 527596d
finality_proof docs
svyatonik 7c4c71f
Merge branch 'master' into light_grandpa_importer2
svyatonik f94d5be
use DB backend in test client
svyatonik ac63880
justification_is_fetched_by_light_client_when_consensus_data_changes
svyatonik 410d02c
Merge branch 'master' into light_grandpa_importer2
svyatonik 8577c87
restore justification_is_fetched_by_light_client_when_consensus_data_…
svyatonik 8a3ba3d
some more tests
svyatonik b362518
added authorities-related TODO
svyatonik 4c69880
removed unneeded clear_finality_proof_requests field
svyatonik 0db08a0
truncated some long lines
svyatonik 1315130
more granular light import tests
svyatonik 9e5aabe
only provide finality proof if it is generated by the requested set
svyatonik a746448
Merge branch 'master' into light_grandpa_importer2
svyatonik f22ebf1
post-merge fix
svyatonik c6c128b
finality_proof_is_none_if_first_justification_is_generated_by_unknown…
svyatonik 188ab5a
make light+grandpa test rely on finality proofs (instead of simple ju…
svyatonik 6d3ba01
empty_finality_proof_is_returned_to_light_client_when_authority_set_i…
svyatonik b99f39d
missing trait method impl
svyatonik 5516ece
Merge branch 'master' into light_grandpa_importer2
svyatonik d6f01fa
fixed proof-of-finality docs
svyatonik 957139f
one more doc fix
svyatonik 262cdfa
fix docs
svyatonik 7e6e837
Merge branch 'master' into light_grandpa_importer2
svyatonik 271655d
Merge branch 'master' into light_grandpa_importer2
svyatonik 63cde59
initialize authorities cache (post-merge fix)
svyatonik b8c71b5
fixed cache initialization (post-merge fix)
svyatonik 63b5056
Merge branch 'master' into light_grandpa_importer2
svyatonik 100f4c8
post-fix merge: fix light + GRANDPA tests (bad way)
svyatonik 44d7714
proper fix of empty_finality_proof_is_returned_to_light_client_when_a…
svyatonik 70c8b39
fixed easy grumbles
svyatonik ff3ceeb
import finality proofs in BlockImportWorker thread
svyatonik e108f63
allow import of finality proofs for non-requested blocks
svyatonik e2b5458
limit number of fragments in finality proof
svyatonik 366cb2e
Merge branch 'master' into light_grandpa_importer2
svyatonik bf1706b
Merge branch 'master' into light_grandpa_importer2
svyatonik 0a5513f
Merge branch 'master' into light_grandpa_importer2
svyatonik 33d195c
GRANDPA post-merge fix
svyatonik d6cbbf3
BABE: pos-merge fix
svyatonik b7f2dbc
Merge branch 'master' into light_grandpa_importer2
svyatonik d42e730
Merge branch 'master' into light_grandpa_importer2
svyatonik fa0e328
Merge branch 'master' into light_grandpa_importer2
svyatonik 6c80a6e
Merge branch 'master' into light_grandpa_importer2
svyatonik 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
some more tests
- Loading branch information
commit 8a3ba3dfdb993f56d0898bdc3ce38d66b726204d
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,7 +20,7 @@ use parking_lot::RwLock; | |
|
|
||
| use client::{ | ||
| CallExecutor, Client, | ||
| backend::Backend, | ||
| backend::{AuxStore, Backend}, | ||
| blockchain::HeaderBackend, | ||
| error::Error as ClientError, error::ErrorKind as ClientErrorKind, | ||
| }; | ||
|
|
@@ -63,38 +63,11 @@ pub fn light_block_import<B, E, Block: BlockT<Hash=H256>, RA, PRA>( | |
| PRA: ProvideRuntimeApi, | ||
| PRA::Api: GrandpaApi<Block>, | ||
| { | ||
| use runtime_primitives::traits::Zero; | ||
| let authority_set = match Backend::get_aux(&**client.backend(), LIGHT_AUTHORITY_SET_KEY)? { | ||
| None => { | ||
| info!(target: "afg", "Loading GRANDPA authorities \ | ||
| from genesis on what appears to be first startup."); | ||
|
|
||
| // no authority set on disk: fetch authorities from genesis state | ||
| let genesis_authorities = api.runtime_api().grandpa_authorities(&BlockId::number(Zero::zero()))?; | ||
|
|
||
| let authority_set = LightAuthoritySet::genesis(genesis_authorities); | ||
| let encoded = authority_set.encode(); | ||
| Backend::insert_aux(&**client.backend(), &[(LIGHT_AUTHORITY_SET_KEY, &encoded[..])], &[])?; | ||
|
|
||
| authority_set | ||
| }, | ||
| Some(raw) => LightAuthoritySet::decode(&mut &raw[..]) | ||
| .ok_or_else(|| ::client::error::ErrorKind::Backend( | ||
| format!("GRANDPA authority set kept in invalid format") | ||
| ))? | ||
| .into(), | ||
| }; | ||
|
|
||
| let consensus_changes = load_decode(&**client.backend(), LIGHT_CONSENSUS_CHANGES_KEY)? | ||
| .unwrap_or_else(ConsensusChanges::<Block::Hash, NumberFor<Block>>::empty); | ||
|
|
||
| let import_data = load_aux_import_data(&**client.backend(), api)?; | ||
| Ok(GrandpaLightBlockImport { | ||
| client, | ||
| authority_set_provider, | ||
| data: Arc::new(RwLock::new(LightImportData { | ||
| authority_set, | ||
| consensus_changes, | ||
| })), | ||
| data: Arc::new(RwLock::new(import_data)), | ||
| }) | ||
| } | ||
|
|
||
|
|
@@ -436,6 +409,52 @@ fn do_finalize_block<B, E, Block: BlockT<Hash=H256>, RA>( | |
| Ok(ImportResult::imported()) | ||
| } | ||
|
|
||
| /// Load light impoty aux data from the store. | ||
| fn load_aux_import_data<B, Block: BlockT<Hash=H256>, PRA>( | ||
|
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. Maybe move to
Contributor
Author
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 thought that |
||
| aux_store: &B, | ||
| api: Arc<PRA>, | ||
| ) -> Result<LightImportData<Block>, ClientError> | ||
| where | ||
| B: AuxStore, | ||
| PRA: ProvideRuntimeApi, | ||
| PRA::Api: GrandpaApi<Block>, | ||
| { | ||
| use runtime_primitives::traits::Zero; | ||
| let authority_set = match load_decode(aux_store, LIGHT_AUTHORITY_SET_KEY)? { | ||
| Some(authority_set) => authority_set, | ||
| None => { | ||
| info!(target: "afg", "Loading GRANDPA authorities \ | ||
| from genesis on what appears to be first startup."); | ||
|
|
||
| // no authority set on disk: fetch authorities from genesis state | ||
| let genesis_authorities = api.runtime_api().grandpa_authorities(&BlockId::number(Zero::zero()))?; | ||
|
|
||
| let authority_set = LightAuthoritySet::genesis(genesis_authorities); | ||
| let encoded = authority_set.encode(); | ||
| aux_store.insert_aux(&[(LIGHT_AUTHORITY_SET_KEY, &encoded[..])], &[])?; | ||
|
|
||
| authority_set | ||
| }, | ||
| }; | ||
|
|
||
| let consensus_changes = match load_decode(aux_store, LIGHT_CONSENSUS_CHANGES_KEY)? { | ||
| Some(consensus_changes) => consensus_changes, | ||
| None => { | ||
| let consensus_changes = ConsensusChanges::<Block::Hash, NumberFor<Block>>::empty(); | ||
|
|
||
| let encoded = authority_set.encode(); | ||
| aux_store.insert_aux(&[(LIGHT_CONSENSUS_CHANGES_KEY, &encoded[..])], &[])?; | ||
|
|
||
| consensus_changes | ||
| }, | ||
| }; | ||
|
|
||
| Ok(LightImportData { | ||
| authority_set, | ||
| consensus_changes, | ||
| }) | ||
| } | ||
|
|
||
| /// Insert into aux store. If failed, return error && show inconsistency warning. | ||
| fn require_insert_aux<T: Encode, B, E, Block: BlockT<Hash=H256>, RA>( | ||
| client: &Client<B, E, Block, RA>, | ||
|
|
@@ -463,3 +482,55 @@ fn on_post_finalization_error(error: ClientError, value_type: &str) -> Consensus | |
| warn!(target: "finality", "Node is in a potentially inconsistent state."); | ||
| ConsensusError::from(ConsensusErrorKind::ClientImport(error.to_string())) | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
| use substrate_primitives::H256; | ||
| use test_client::client::in_mem::Blockchain as InMemoryAuxStore; | ||
| use test_client::runtime::Block; | ||
| use crate::tests::TestApi; | ||
|
|
||
| #[test] | ||
| fn aux_data_updated_on_start() { | ||
| let aux_store = InMemoryAuxStore::<Block>::new(); | ||
| let api = Arc::new(TestApi::new(vec![(Ed25519AuthorityId([1; 32]), 1)])); | ||
|
|
||
| // when aux store is empty initially | ||
| assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_none()); | ||
| assert!(aux_store.get_aux(LIGHT_CONSENSUS_CHANGES_KEY).unwrap().is_none()); | ||
|
|
||
| // it is updated on importer start | ||
| load_aux_import_data(&aux_store, api).unwrap(); | ||
| assert!(aux_store.get_aux(LIGHT_AUTHORITY_SET_KEY).unwrap().is_some()); | ||
| assert!(aux_store.get_aux(LIGHT_CONSENSUS_CHANGES_KEY).unwrap().is_some()); | ||
| } | ||
|
|
||
| #[test] | ||
| fn aux_data_loaded_on_restart() { | ||
| let aux_store = InMemoryAuxStore::<Block>::new(); | ||
| let api = Arc::new(TestApi::new(vec![(Ed25519AuthorityId([1; 32]), 1)])); | ||
|
|
||
| // when aux store is non-empty initially | ||
| let mut consensus_changes = ConsensusChanges::<H256, u64>::empty(); | ||
| consensus_changes.note_change((42, Default::default())); | ||
| aux_store.insert_aux( | ||
| &[ | ||
| ( | ||
| LIGHT_AUTHORITY_SET_KEY, | ||
| LightAuthoritySet::genesis(vec![(Ed25519AuthorityId([42; 32]), 2)]).encode().as_slice(), | ||
| ), | ||
| ( | ||
| LIGHT_CONSENSUS_CHANGES_KEY, | ||
| consensus_changes.encode().as_slice(), | ||
| ), | ||
| ], | ||
| &[], | ||
| ).unwrap(); | ||
|
|
||
| // importer uses it on start | ||
| let data = load_aux_import_data(&aux_store, api).unwrap(); | ||
| assert_eq!(data.authority_set.authorities(), vec![(Ed25519AuthorityId([42; 32]), 2)]); | ||
| assert_eq!(data.consensus_changes.pending_changes(), &[(42, Default::default())]); | ||
| } | ||
| } | ||
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
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.