mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 20:11:09 +00:00
GRANDPA: announce blocks we vote on to peers (#1593)
* announce blocks we vote on to peers (missing network impl) * Implemented 'announce' * Fixed test * improve announce docs and add logging * Track recently announced blocks
This commit is contained in:
committed by
André Silva
parent
0078927ac5
commit
d027123059
@@ -686,6 +686,34 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
self.transaction_pool.on_broadcasted(propagated_to);
|
||||
}
|
||||
|
||||
/// Make sure an important block is propagated to peers.
|
||||
///
|
||||
/// In chain-based consensus, we often need to make sure non-best forks are
|
||||
/// at least temporarily synced.
|
||||
pub fn announce_block(&self, io: &mut SyncIo, hash: B::Hash) {
|
||||
let header = match self.context_data.chain.header(&BlockId::Hash(hash)) {
|
||||
Ok(Some(header)) => header,
|
||||
Ok(None) => {
|
||||
warn!("Trying to announce unknown block: {}", hash);
|
||||
return;
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Error reading block header {}: {:?}", hash, e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let mut peers = self.context_data.peers.write();
|
||||
let hash = header.hash();
|
||||
for (who, ref mut peer) in peers.iter_mut() {
|
||||
if peer.known_blocks.insert(hash.clone()) {
|
||||
trace!(target: "sync", "Reannouncing block {:?} to {}", hash, who);
|
||||
self.send_message(io, *who, GenericMessage::BlockAnnounce(message::BlockAnnounce {
|
||||
header: header.clone()
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Send Status message
|
||||
fn send_status(&self, io: &mut SyncIo, who: NodeIndex) {
|
||||
if let Ok(info) = self.context_data.chain.info() {
|
||||
|
||||
@@ -200,6 +200,14 @@ impl<B: BlockT + 'static, S: NetworkSpecialization<B>, H: ExHashT> Service<B, S,
|
||||
self.handler.propagate_extrinsics(&mut NetSyncIo::new(&self.network, self.protocol_id));
|
||||
}
|
||||
|
||||
/// Make sure an important block is propagated to peers.
|
||||
///
|
||||
/// In chain-based consensus, we often need to make sure non-best forks are
|
||||
/// at least temporarily synced.
|
||||
pub fn announce_block(&self, hash: B::Hash) {
|
||||
self.handler.announce_block(&mut NetSyncIo::new(&self.network, self.protocol_id), hash);
|
||||
}
|
||||
|
||||
/// Send a consensus message through the gossip
|
||||
pub fn gossip_consensus_message(&self, topic: B::Hash, message: Vec<u8>, broadcast: bool) {
|
||||
self.handler.gossip_consensus_message(
|
||||
|
||||
@@ -38,12 +38,15 @@ const MAX_IMPORTING_BLOCKS: usize = 2048;
|
||||
const MAJOR_SYNC_BLOCKS: usize = 5;
|
||||
// Time to wait before trying to get a justification from the same peer.
|
||||
const JUSTIFICATION_RETRY_WAIT: Duration = Duration::from_secs(10);
|
||||
// Number of recently announced blocks to track for each peer.
|
||||
const ANNOUNCE_HISTORY_SIZE: usize = 64;
|
||||
|
||||
struct PeerSync<B: BlockT> {
|
||||
pub common_number: NumberFor<B>,
|
||||
pub best_hash: B::Hash,
|
||||
pub best_number: NumberFor<B>,
|
||||
pub state: PeerSyncState<B>,
|
||||
pub recently_announced: VecDeque<B::Hash>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
@@ -334,6 +337,7 @@ impl<B: BlockT> ChainSync<B> {
|
||||
best_hash: info.best_hash,
|
||||
best_number: info.best_number,
|
||||
state: PeerSyncState::Available,
|
||||
recently_announced: Default::default(),
|
||||
});
|
||||
}
|
||||
(Ok(BlockStatus::Unknown), _) => {
|
||||
@@ -346,6 +350,7 @@ impl<B: BlockT> ChainSync<B> {
|
||||
best_hash: info.best_hash,
|
||||
best_number: info.best_number,
|
||||
state: PeerSyncState::AncestorSearch(common_best),
|
||||
recently_announced: Default::default(),
|
||||
});
|
||||
Self::request_ancestry(protocol, who, common_best)
|
||||
} else {
|
||||
@@ -356,6 +361,7 @@ impl<B: BlockT> ChainSync<B> {
|
||||
best_hash: info.best_hash,
|
||||
best_number: info.best_number,
|
||||
state: PeerSyncState::Available,
|
||||
recently_announced: Default::default(),
|
||||
});
|
||||
self.download_new(protocol, who)
|
||||
}
|
||||
@@ -367,6 +373,7 @@ impl<B: BlockT> ChainSync<B> {
|
||||
best_hash: info.best_hash,
|
||||
best_number: info.best_number,
|
||||
state: PeerSyncState::Available,
|
||||
recently_announced: Default::default(),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -457,13 +464,16 @@ impl<B: BlockT> ChainSync<B> {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let best_seen = self.best_seen_block();
|
||||
let is_best = new_blocks.first().and_then(|b| b.header.as_ref()).map(|h| best_seen.as_ref().map_or(false, |n| h.number() >= n));
|
||||
let origin = if is_best.unwrap_or_default() { BlockOrigin::NetworkBroadcast } else { BlockOrigin::NetworkInitialSync };
|
||||
let is_recent = new_blocks
|
||||
.first()
|
||||
.map(|block| self.peers.iter().any(|(_, peer)| peer.recently_announced.contains(&block.hash)))
|
||||
.unwrap_or(false);
|
||||
let origin = if is_recent { BlockOrigin::NetworkBroadcast } else { BlockOrigin::NetworkInitialSync };
|
||||
|
||||
if let Some((hash, number)) = new_blocks.last()
|
||||
.and_then(|b| b.header.as_ref().map(|h| (b.hash.clone(), *h.number())))
|
||||
{
|
||||
trace!(target:"sync", "Accepted {} blocks ({:?}) with origin {:?}", new_blocks.len(), hash, origin);
|
||||
self.block_queued(&hash, number);
|
||||
}
|
||||
self.maintain_sync(protocol);
|
||||
@@ -586,6 +596,10 @@ impl<B: BlockT> ChainSync<B> {
|
||||
let known_parent = self.is_known(protocol, &header.parent_hash());
|
||||
let known = self.is_known(protocol, &hash);
|
||||
if let Some(ref mut peer) = self.peers.get_mut(&who) {
|
||||
while peer.recently_announced.len() >= ANNOUNCE_HISTORY_SIZE {
|
||||
peer.recently_announced.pop_front();
|
||||
}
|
||||
peer.recently_announced.push_back(hash.clone());
|
||||
if number > peer.best_number {
|
||||
// update their best block
|
||||
peer.best_number = number;
|
||||
|
||||
Reference in New Issue
Block a user