mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 20:27:58 +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:
@@ -30,7 +30,7 @@ use client::block_builder::BlockBuilder;
|
||||
use primitives::Ed25519AuthorityId;
|
||||
use runtime_primitives::Justification;
|
||||
use runtime_primitives::generic::BlockId;
|
||||
use runtime_primitives::traits::{Block as BlockT, Zero, Header, Digest, DigestItem, AuthorityIdFor};
|
||||
use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Digest, DigestItem, Header, NumberFor, Zero};
|
||||
use io::SyncIo;
|
||||
use protocol::{Context, Protocol, ProtocolContext};
|
||||
use config::ProtocolConfig;
|
||||
@@ -190,6 +190,15 @@ impl<B: 'static + BlockT, V: 'static + Verifier<B>> ImportQueue<B> for SyncImpor
|
||||
fn import_blocks(&self, origin: BlockOrigin, blocks: Vec<IncomingBlock<B>>) {
|
||||
self.link.call(origin, blocks);
|
||||
}
|
||||
|
||||
fn import_justification(
|
||||
&self,
|
||||
hash: B::Hash,
|
||||
number: NumberFor<B>,
|
||||
justification: Justification,
|
||||
) -> bool {
|
||||
self.block_import.import_justification(hash, number, justification).is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
struct DummyContextExecutor(Arc<Protocol<Block, DummySpecialization, Hash>>, Arc<RwLock<VecDeque<TestPacket>>>);
|
||||
@@ -366,6 +375,13 @@ impl<V: 'static + Verifier<Block>, D> Peer<V, D> {
|
||||
self.sync.on_block_imported(&mut TestIo::new(&self.queue, None), info.chain.best_hash, &header);
|
||||
}
|
||||
|
||||
/// Send block finalization notifications.
|
||||
pub fn send_finality_notifications(&self) {
|
||||
let info = self.client.info().expect("In-mem client does not fail");
|
||||
let header = self.client.header(&BlockId::Hash(info.chain.finalized_hash)).unwrap().unwrap();
|
||||
self.sync.on_block_finalized(&mut TestIo::new(&self.queue, None), info.chain.finalized_hash, &header);
|
||||
}
|
||||
|
||||
/// Restart sync for a peer.
|
||||
fn restart_sync(&self) {
|
||||
self.sync.abort();
|
||||
@@ -380,6 +396,14 @@ impl<V: 'static + Verifier<Block>, D> Peer<V, D> {
|
||||
self.sync.gossip_consensus_message(&mut TestIo::new(&self.queue, None), topic, data, broadcast);
|
||||
}
|
||||
|
||||
/// Request a justification for the given block.
|
||||
#[cfg(test)]
|
||||
fn request_justification(&self, hash: &::primitives::H256, number: NumberFor<Block>) {
|
||||
self.executor.execute_in_context(|context| {
|
||||
self.sync.sync().write().request_justification(hash, number, context);
|
||||
})
|
||||
}
|
||||
|
||||
/// Add blocks to the peer -- edit the block before adding
|
||||
pub fn generate_blocks<F>(&self, count: usize, origin: BlockOrigin, mut edit_block: F)
|
||||
where F: FnMut(BlockBuilder<Block, (), PeersClient>) -> Block
|
||||
@@ -601,6 +625,15 @@ pub trait TestNetFactory: Sized {
|
||||
})
|
||||
}
|
||||
|
||||
/// Send block finalization notifications for all peers.
|
||||
fn send_finality_notifications(&mut self) {
|
||||
self.mut_peers(|peers| {
|
||||
for peer in peers {
|
||||
peer.send_finality_notifications();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Restart sync for a peer.
|
||||
fn restart_peer(&mut self, i: usize) {
|
||||
self.peers()[i].restart_sync();
|
||||
|
||||
@@ -65,6 +65,27 @@ fn sync_no_common_longer_chain_fails() {
|
||||
assert!(!net.peer(0).client.backend().blockchain().canon_equals_to(net.peer(1).client.backend().blockchain()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_justifications() {
|
||||
::env_logger::init().ok();
|
||||
let mut net = TestNet::new(3);
|
||||
net.peer(0).push_blocks(20, false);
|
||||
net.sync();
|
||||
|
||||
// there's currently no justification for block #10
|
||||
assert_eq!(net.peer(0).client().justification(&BlockId::Number(10)).unwrap(), None);
|
||||
// we finalize block #10 for peer 0 with a justification
|
||||
net.peer(0).client().finalize_block(BlockId::Number(10), Some(Vec::new()), true).unwrap();
|
||||
|
||||
let header = net.peer(1).client().header(&BlockId::Number(10)).unwrap().unwrap();
|
||||
net.peer(1).request_justification(&header.hash().into(), 10);
|
||||
|
||||
net.sync();
|
||||
|
||||
assert_eq!(net.peer(0).client().justification(&BlockId::Number(10)).unwrap(), Some(Vec::new()));
|
||||
assert_eq!(net.peer(1).client().justification(&BlockId::Number(10)).unwrap(), Some(Vec::new()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_after_fork_works() {
|
||||
::env_logger::init().ok();
|
||||
|
||||
Reference in New Issue
Block a user