Light GRANDPA import handler (#1669)

* GrandpaLightBlockImport

* extract authorities in AuraVerifier

* post-merge fix

* restore authorities cache

* license

* new finality proof draft

* generalized PendingJustifications

* finality proof messages

* fixed compilation

* pass verifier to import_finality_proof

* do not fetch remote proof from light import directly

* FinalityProofProvider

* fixed authorities cache test

* restored finality proof tests

* finality_proof docs

* use DB backend in test client

* justification_is_fetched_by_light_client_when_consensus_data_changes

* restore justification_is_fetched_by_light_client_when_consensus_data_changes

* some more tests

* added authorities-related TODO

* removed unneeded clear_finality_proof_requests field

* truncated some long lines

* more granular light import tests

* only provide finality proof if it is generated by the requested set

* post-merge fix

* finality_proof_is_none_if_first_justification_is_generated_by_unknown_set

* make light+grandpa test rely on finality proofs (instead of simple justifications)

* empty_finality_proof_is_returned_to_light_client_when_authority_set_is_different

* missing trait method impl

* fixed proof-of-finality docs

* one more doc fix

* fix docs

* initialize authorities cache (post-merge fix)

* fixed cache initialization (post-merge fix)

* post-fix merge: fix light + GRANDPA tests (bad way)

* proper fix of empty_finality_proof_is_returned_to_light_client_when_authority_set_is_different

* fixed easy grumbles

* import finality proofs in BlockImportWorker thread

* allow import of finality proofs for non-requested blocks

* limit number of fragments in finality proof

* GRANDPA post-merge fix

* BABE: pos-merge fix
This commit is contained in:
Svyatoslav Nikolsky
2019-05-13 12:36:52 +03:00
committed by Gavin Wood
parent 258f0835e4
commit 22586113ea
36 changed files with 3320 additions and 803 deletions
+86 -25
View File
@@ -33,7 +33,10 @@ use consensus_common::{self, Authorities, BlockImport, Environment, Proposer,
ForkChoiceStrategy, ImportBlock, BlockOrigin, Error as ConsensusError,
SelectChain, well_known_cache_keys
};
use consensus_common::import_queue::{Verifier, BasicQueue, SharedBlockImport, SharedJustificationImport};
use consensus_common::import_queue::{
Verifier, BasicQueue, SharedBlockImport, SharedJustificationImport, SharedFinalityProofImport,
SharedFinalityProofRequestBuilder,
};
use client::{
block_builder::api::BlockBuilder as BlockBuilderApi,
blockchain::ProvideCache,
@@ -44,7 +47,7 @@ use client::{
use aura_primitives::AURA_ENGINE_ID;
use runtime_primitives::{generic, generic::BlockId, Justification};
use runtime_primitives::traits::{
Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor,
Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi, AuthorityIdFor, Zero,
};
use primitives::Pair;
use inherents::{InherentDataProviders, InherentData, RuntimeString};
@@ -653,6 +656,10 @@ impl<B: Block, C, E, P> Verifier<B> for AuraVerifier<C, E, P> where
extra_verification.into_future().wait()?;
let new_authorities = pre_header.digest()
.log(DigestItem::as_authorities_change)
.map(|digest| digest.to_vec());
let import_block = ImportBlock {
origin,
header: pre_header,
@@ -664,8 +671,7 @@ impl<B: Block, C, E, P> Verifier<B> for AuraVerifier<C, E, P> where
fork_choice: ForkChoiceStrategy::LongestChain,
};
// FIXME #1019 extract authorities
Ok((import_block, None))
Ok((import_block, new_authorities))
}
CheckedHeader::Deferred(a, b) => {
debug!(target: "aura", "Checking {:?} failed; {:?}, {:?}.", hash, a, b);
@@ -690,6 +696,38 @@ impl<B, C, E, P> Authorities<B> for AuraVerifier<C, E, P> where
}
}
fn initialize_authorities_cache<B, C>(client: &C) -> Result<(), ConsensusError> where
B: Block,
C: ProvideRuntimeApi + ProvideCache<B>,
C::Api: AuthoritiesApi<B>,
{
// no cache => no initialization
let cache = match client.cache() {
Some(cache) => cache,
None => return Ok(()),
};
// check if we already have initialized the cache
let genesis_id = BlockId::Number(Zero::zero());
let genesis_authorities: Option<Vec<AuthorityIdFor<B>>> = cache
.get_at(&well_known_cache_keys::AUTHORITIES, &genesis_id)
.and_then(|v| Decode::decode(&mut &v[..]));
if genesis_authorities.is_some() {
return Ok(());
}
let map_err = |error| consensus_common::Error::from(consensus_common::ErrorKind::ClientImport(
format!(
"Error initializing authorities cache: {}",
error,
)));
let genesis_authorities = authorities(client, &genesis_id)?;
cache.initialize(&well_known_cache_keys::AUTHORITIES, genesis_authorities.encode())
.map_err(map_err)?;
Ok(())
}
#[allow(deprecated)]
fn authorities<B, C>(client: &C, at: &BlockId<B>) -> Result<Vec<AuthorityIdFor<B>>, ConsensusError> where
B: Block,
@@ -731,6 +769,8 @@ pub fn import_queue<B, C, E, P>(
slot_duration: SlotDuration,
block_import: SharedBlockImport<B>,
justification_import: Option<SharedJustificationImport<B>>,
finality_proof_import: Option<SharedFinalityProofImport<B>>,
finality_proof_request_builder: Option<SharedFinalityProofRequestBuilder<B>>,
client: Arc<C>,
extra: E,
inherent_data_providers: InherentDataProviders,
@@ -745,6 +785,7 @@ pub fn import_queue<B, C, E, P>(
P::Signature: Encode + Decode,
{
register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?;
initialize_authorities_cache(&*client)?;
let verifier = Arc::new(
AuraVerifier {
@@ -755,7 +796,13 @@ pub fn import_queue<B, C, E, P>(
allow_old_seals: false,
}
);
Ok(BasicQueue::new(verifier, block_import, justification_import))
Ok(BasicQueue::new(
verifier,
block_import,
justification_import,
finality_proof_import,
finality_proof_request_builder,
))
}
/// Start an import queue for the Aura consensus algorithm with backwards compatibility.
@@ -767,6 +814,8 @@ pub fn import_queue_accept_old_seals<B, C, E, P>(
slot_duration: SlotDuration,
block_import: SharedBlockImport<B>,
justification_import: Option<SharedJustificationImport<B>>,
finality_proof_import: Option<SharedFinalityProofImport<B>>,
finality_proof_request_builder: Option<SharedFinalityProofRequestBuilder<B>>,
client: Arc<C>,
extra: E,
inherent_data_providers: InherentDataProviders,
@@ -781,6 +830,7 @@ pub fn import_queue_accept_old_seals<B, C, E, P>(
P::Signature: Encode + Decode,
{
register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?;
initialize_authorities_cache(&*client)?;
let verifier = Arc::new(
AuraVerifier {
@@ -791,7 +841,13 @@ pub fn import_queue_accept_old_seals<B, C, E, P>(
allow_old_seals: true,
}
);
Ok(BasicQueue::new(verifier, block_import, justification_import))
Ok(BasicQueue::new(
verifier,
block_import,
justification_import,
finality_proof_import,
finality_proof_request_builder,
))
}
#[cfg(test)]
@@ -799,7 +855,7 @@ mod tests {
use super::*;
use consensus_common::NoNetwork as DummyOracle;
use network::test::*;
use network::test::{Block as TestBlock, PeersClient};
use network::test::{Block as TestBlock, PeersClient, PeersFullClient};
use runtime_primitives::traits::Block as BlockT;
use network::config::ProtocolConfig;
use parking_lot::Mutex;
@@ -846,7 +902,7 @@ mod tests {
impl TestNetFactory for AuraTestNet {
type Specialization = DummySpecialization;
type Verifier = AuraVerifier<PeersClient, NothingExtra, sr25519::Pair>;
type Verifier = AuraVerifier<PeersFullClient, NothingExtra, sr25519::Pair>;
type PeerData = ();
/// Create new test network with peers and given config.
@@ -857,25 +913,30 @@ mod tests {
}
}
fn make_verifier(&self, client: Arc<PeersClient>, _cfg: &ProtocolConfig)
fn make_verifier(&self, client: PeersClient, _cfg: &ProtocolConfig)
-> Arc<Self::Verifier>
{
let slot_duration = SlotDuration::get_or_compute(&*client)
.expect("slot duration available");
let inherent_data_providers = InherentDataProviders::new();
register_aura_inherent_data_provider(
&inherent_data_providers,
slot_duration.get()
).expect("Registers aura inherent data provider");
match client {
PeersClient::Full(client) => {
let slot_duration = SlotDuration::get_or_compute(&*client)
.expect("slot duration available");
let inherent_data_providers = InherentDataProviders::new();
register_aura_inherent_data_provider(
&inherent_data_providers,
slot_duration.get()
).expect("Registers aura inherent data provider");
assert_eq!(slot_duration.get(), SLOT_DURATION);
Arc::new(AuraVerifier {
client,
extra: NothingExtra,
inherent_data_providers,
phantom: Default::default(),
allow_old_seals: false,
})
assert_eq!(slot_duration.get(), SLOT_DURATION);
Arc::new(AuraVerifier {
client,
extra: NothingExtra,
inherent_data_providers,
phantom: Default::default(),
allow_old_seals: false,
})
},
PeersClient::Light(_) => unreachable!("No (yet) tests for light client + Aura"),
}
}
fn peer(&self, i: usize) -> &Peer<Self::PeerData, DummySpecialization> {
@@ -917,7 +978,7 @@ mod tests {
let mut runtime = current_thread::Runtime::new().unwrap();
for (peer_id, key) in peers {
let client = net.lock().peer(*peer_id).client().clone();
let client = net.lock().peer(*peer_id).client().as_full().expect("full clients are created").clone();
let select_chain = LongestChain::new(
client.backend().clone(),
client.import_lock().clone(),