mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 01:38:04 +00:00
Sync block justifications (#1410)
* core: sync protocol for justifications * core: basic test for justification sync * core: pass block number with justification * grandpa: request justifications when importing change blocks * core: pass finality notifications to chain sync * core: require justifications for pending change blocks on start * core: avoid requesting justifications from previous failed peers * core: timeout block justification requests * core: add some docs * core: fix unused variables warning * core: tick pending justifications fetch periodically * grandpa: add test for syncing justifications * core: early exit dispatch of pending justifications * core: style fix * core: grandpa: change logging level * core: sync: add missing docs * core: network: report peer on bad justification * core: replace mem::replace with Option::take * core: revert authority set changes on failed block finalization * core: grandpa: add docs to import_justification * core: warn on re-finalization of last finalized block * core: only notify sync with last finality notification * core: style fix * core: add docs for PendingJustifications * core: network: use BlockRequest messages for justification requests * core: reference issues in todo comments * core: grandpa: revert authority set changes on db * core: grandpa: remove inconsistent state warning
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
|
||||
//! Block import helpers.
|
||||
|
||||
use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Header as HeaderT, DigestItemFor};
|
||||
use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, DigestItemFor, Header as HeaderT, NumberFor};
|
||||
use runtime_primitives::Justification;
|
||||
use std::borrow::Cow;
|
||||
|
||||
@@ -33,6 +33,9 @@ pub enum ImportResult {
|
||||
KnownBad,
|
||||
/// Block parent is not in the chain.
|
||||
UnknownParent,
|
||||
/// Added to the import queue but must be justified
|
||||
/// (usually required to safely enact consensus changes).
|
||||
NeedsJustification,
|
||||
}
|
||||
|
||||
/// Block data origin.
|
||||
@@ -140,9 +143,22 @@ impl<Block: BlockT> ImportBlock<Block> {
|
||||
/// Block import trait.
|
||||
pub trait BlockImport<B: BlockT> {
|
||||
type Error: ::std::error::Error + Send + 'static;
|
||||
/// Import a Block alongside the new authorities valid form this block forward
|
||||
fn import_block(&self,
|
||||
|
||||
/// Called by the import queue when it is started.
|
||||
fn on_start(&self, _link: &::import_queue::Link<B>) { }
|
||||
|
||||
/// Import a Block alongside the new authorities valid from this block forward
|
||||
fn import_block(
|
||||
&self,
|
||||
block: ImportBlock<B>,
|
||||
new_authorities: Option<Vec<AuthorityIdFor<B>>>
|
||||
new_authorities: Option<Vec<AuthorityIdFor<B>>>,
|
||||
) -> Result<ImportResult, Self::Error>;
|
||||
|
||||
/// Import a Block justification and finalize the given block.
|
||||
fn import_justification(
|
||||
&self,
|
||||
hash: B::Hash,
|
||||
number: NumberFor<B>,
|
||||
justification: Justification,
|
||||
) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
@@ -92,6 +92,8 @@ pub trait ImportQueue<B: BlockT>: Send + Sync {
|
||||
fn is_importing(&self, hash: &B::Hash) -> bool;
|
||||
/// Import bunch of blocks.
|
||||
fn import_blocks(&self, origin: BlockOrigin, blocks: Vec<IncomingBlock<B>>);
|
||||
/// Import a block justification.
|
||||
fn import_justification(&self, hash: B::Hash, number: NumberFor<B>, justification: Justification) -> bool;
|
||||
}
|
||||
|
||||
/// Import queue status. It isn't completely accurate.
|
||||
@@ -161,6 +163,7 @@ impl<B: BlockT, V: 'static + Verifier<B>> ImportQueue<B> for BasicQueue<B, V> {
|
||||
let verifier = self.verifier.clone();
|
||||
let block_import = self.block_import.clone();
|
||||
*self.handle.lock() = Some(::std::thread::Builder::new().name("ImportQueue".into()).spawn(move || {
|
||||
block_import.on_start(&link);
|
||||
import_thread(block_import, link, qdata, verifier)
|
||||
})?);
|
||||
Ok(())
|
||||
@@ -218,6 +221,10 @@ impl<B: BlockT, V: 'static + Verifier<B>> ImportQueue<B> for BasicQueue<B, V> {
|
||||
queue.push_back((origin, blocks));
|
||||
self.data.signal.notify_one();
|
||||
}
|
||||
|
||||
fn import_justification(&self, hash: B::Hash, number: NumberFor<B>, justification: Justification) -> bool {
|
||||
self.block_import.import_justification(hash, number, justification).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BlockT, V: 'static + Verifier<B>> Drop for BasicQueue<B, V> {
|
||||
@@ -279,6 +286,8 @@ fn import_thread<B: BlockT, L: Link<B>, V: Verifier<B>>(
|
||||
pub trait Link<B: BlockT>: Send {
|
||||
/// Block imported.
|
||||
fn block_imported(&self, _hash: &B::Hash, _number: NumberFor<B>) { }
|
||||
/// Request a justification for the given block.
|
||||
fn request_justification(&self, _hash: &B::Hash, _number: NumberFor<B>) { }
|
||||
/// Maintain sync.
|
||||
fn maintain_sync(&self) { }
|
||||
/// Disconnect from peer.
|
||||
@@ -296,6 +305,8 @@ pub enum BlockImportResult<H: ::std::fmt::Debug + PartialEq, N: ::std::fmt::Debu
|
||||
ImportedKnown(H, N),
|
||||
/// Imported unknown block.
|
||||
ImportedUnknown(H, N),
|
||||
/// Imported unjustified block that requires one.
|
||||
ImportedUnjustified(H, N),
|
||||
}
|
||||
|
||||
/// Block import error.
|
||||
@@ -409,6 +420,10 @@ pub fn import_single_block<B: BlockT, V: Verifier<B>>(
|
||||
trace!(target: "sync", "Block queued {}: {:?}", number, hash);
|
||||
Ok(BlockImportResult::ImportedUnknown(hash, number))
|
||||
},
|
||||
Ok(ImportResult::NeedsJustification) => {
|
||||
trace!(target: "sync", "Block queued but requires justification {}: {:?}", number, hash);
|
||||
Ok(BlockImportResult::ImportedUnjustified(hash, number))
|
||||
},
|
||||
Ok(ImportResult::UnknownParent) => {
|
||||
debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent);
|
||||
Err(BlockImportError::UnknownParent)
|
||||
@@ -416,7 +431,7 @@ pub fn import_single_block<B: BlockT, V: Verifier<B>>(
|
||||
Ok(ImportResult::KnownBad) => {
|
||||
debug!(target: "sync", "Peer gave us a bad block {}: {:?}", number, hash);
|
||||
Err(BlockImportError::BadBlock(peer)) //TODO: use persistent ID
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
debug!(target: "sync", "Error importing block {}: {:?}: {:?}", number, hash, e);
|
||||
Err(BlockImportError::Error)
|
||||
@@ -439,6 +454,11 @@ pub fn process_import_result<B: BlockT>(
|
||||
link.block_imported(&hash, number);
|
||||
1
|
||||
},
|
||||
Ok(BlockImportResult::ImportedUnjustified(hash, number)) => {
|
||||
link.block_imported(&hash, number);
|
||||
link.request_justification(&hash, number);
|
||||
1
|
||||
},
|
||||
Err(BlockImportError::IncompleteHeader(who)) => {
|
||||
if let Some(peer) = who {
|
||||
link.useless_peer(peer, "Sent block with incomplete header to import");
|
||||
|
||||
Reference in New Issue
Block a user