Limit gossip for non-authorities (#838)

* Limit gossip for non-authorities

* Random shuffle
This commit is contained in:
Arkadiy Paronyan
2018-09-29 14:08:22 +02:00
committed by Gav Wood
parent 79d538ee66
commit e1e6c19f64
5 changed files with 37 additions and 6 deletions
+1
View File
@@ -2991,6 +2991,7 @@ dependencies = [
"parity-codec 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-codec-derive 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sr-primitives 0.1.0",
"substrate-client 0.1.0",
+1
View File
@@ -15,6 +15,7 @@ bitflags = "1.0"
futures = "0.1.17"
linked-hash-map = "0.5"
rustc-hex = "1.0"
rand = "0.5"
substrate-primitives = { path = "../../core/primitives" }
substrate-client = { path = "../../core/client" }
sr-primitives = { path = "../../core/sr-primitives" }
+30 -3
View File
@@ -20,6 +20,7 @@
use std::collections::{HashMap, HashSet};
use futures::sync::mpsc;
use std::time::{Instant, Duration};
use rand::{self, Rng};
use network_libp2p::NodeIndex;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
use runtime_primitives::generic::BlockId;
@@ -32,6 +33,7 @@ const MESSAGE_LIFETIME: Duration = Duration::from_secs(600);
struct PeerConsensus<H> {
known_messages: HashSet<H>,
is_authority: bool,
}
/// Consensus messages.
@@ -75,9 +77,9 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
/// Handle new connected peer.
pub fn new_peer(&mut self, protocol: &mut Context<B>, who: NodeIndex, roles: Roles) {
if roles.intersects(Roles::AUTHORITY | Roles::FULL) {
if roles.intersects(Roles::AUTHORITY) {
trace!(target:"gossip", "Registering {:?} {}", roles, who);
// Send out all known messages.
// Send out all known messages to authorities.
// TODO: limit by size
let mut known_messages = HashSet::new();
for entry in self.messages.iter() {
@@ -91,14 +93,39 @@ impl<B: BlockT> ConsensusGossip<B> where B::Header: HeaderT<Number=u64> {
}
self.peers.insert(who, PeerConsensus {
known_messages,
is_authority: true,
});
}
else if roles.intersects(Roles::FULL) {
self.peers.insert(who, PeerConsensus {
known_messages: HashSet::new(),
is_authority: false,
});
}
}
fn propagate(&mut self, protocol: &mut Context<B>, message: message::Message<B>, hash: B::Hash) {
let mut non_authorities: Vec<_> = self.peers.iter()
.filter_map(|(id, ref peer)| if !peer.is_authority && !peer.known_messages.contains(&hash) { Some(*id) } else { None })
.collect();
rand::thread_rng().shuffle(&mut non_authorities);
let non_authorities: HashSet<_> = if non_authorities.is_empty() {
HashSet::new()
} else {
non_authorities[0..non_authorities.len().min(((non_authorities.len() as f64).sqrt() as usize).max(3))].iter().collect()
};
for (id, ref mut peer) in self.peers.iter_mut() {
if peer.known_messages.insert(hash.clone()) {
if peer.is_authority {
if peer.known_messages.insert(hash.clone()) {
trace!(target:"gossip", "Propagating to authority {}: {:?}", id, message);
protocol.send_message(*id, message.clone());
}
}
else if non_authorities.contains(&id) {
trace!(target:"gossip", "Propagating to {}: {:?}", id, message);
peer.known_messages.insert(hash.clone());
protocol.send_message(*id, message.clone());
}
}
+1
View File
@@ -31,6 +31,7 @@ extern crate substrate_network_libp2p as network_libp2p;
extern crate parity_codec as codec;
extern crate futures;
extern crate rustc_hex;
extern crate rand;
#[macro_use] extern crate log;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate error_chain;
+4 -3
View File
@@ -296,11 +296,11 @@ impl<B: BlockT> ChainSync<B> {
if !self.is_known_or_already_downloading(protocol, header.parent_hash()) {
trace!(target: "sync", "Ignoring unknown stale block announce from {}: {} {:?}", who, hash, header);
} else {
trace!(target: "sync", "Downloading new stale block announced from {}: {} {:?}", who, hash, header);
trace!(target: "sync", "Considering new stale block announced from {}: {} {:?}", who, hash, header);
self.download_stale(protocol, who, &hash);
}
} else {
trace!(target: "sync", "Downloading new block announced from {}: {} {:?}", who, hash, header);
trace!(target: "sync", "Considering new block announced from {}: {} {:?}", who, hash, header);
self.download_new(protocol, who);
}
} else {
@@ -371,6 +371,7 @@ impl<B: BlockT> ChainSync<B> {
let import_status = self.import_queue.status();
// when there are too many blocks in the queue => do not try to download new blocks
if import_status.importing_count > MAX_IMPORTING_BLOCKS {
trace!(target: "sync", "Too many blocks in the queue.");
return;
}
// we should not download already queued blocks
@@ -395,7 +396,7 @@ impl<B: BlockT> ChainSync<B> {
trace!(target: "sync", "Nothing to request");
}
},
_ => (),
_ => trace!(target: "sync", "Peer {} is busy", who),
}
}
}