mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 07:01:05 +00:00
Run cargo fmt on the whole code base (#9394)
* Run cargo fmt on the whole code base * Second run * Add CI check * Fix compilation * More unnecessary braces * Handle weights * Use --all * Use correct attributes... * Fix UI tests * AHHHHHHHHH * 🤦 * Docs * Fix compilation * 🤷 * Please stop * 🤦 x 2 * More * make rustfmt.toml consistent with polkadot Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
@@ -16,13 +16,17 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Network, Validator};
|
||||
use crate::state_machine::{ConsensusGossip, TopicNotification, PERIODIC_MAINTENANCE_INTERVAL};
|
||||
use crate::{
|
||||
state_machine::{ConsensusGossip, TopicNotification, PERIODIC_MAINTENANCE_INTERVAL},
|
||||
Network, Validator,
|
||||
};
|
||||
|
||||
use sc_network::{Event, ReputationChange};
|
||||
|
||||
use futures::prelude::*;
|
||||
use futures::channel::mpsc::{channel, Sender, Receiver};
|
||||
use futures::{
|
||||
channel::mpsc::{channel, Receiver, Sender},
|
||||
prelude::*,
|
||||
};
|
||||
use libp2p::PeerId;
|
||||
use log::trace;
|
||||
use prometheus_endpoint::Registry;
|
||||
@@ -74,7 +78,10 @@ impl<B: BlockT> GossipEngine<B> {
|
||||
protocol: impl Into<Cow<'static, str>>,
|
||||
validator: Arc<dyn Validator<B>>,
|
||||
metrics_registry: Option<&Registry>,
|
||||
) -> Self where B: 'static {
|
||||
) -> Self
|
||||
where
|
||||
B: 'static,
|
||||
{
|
||||
let protocol = protocol.into();
|
||||
let network_event_stream = network.event_stream();
|
||||
|
||||
@@ -99,11 +106,7 @@ impl<B: BlockT> GossipEngine<B> {
|
||||
/// the message's topic. No validation is performed on the message, if the
|
||||
/// message is already expired it should be dropped on the next garbage
|
||||
/// collection.
|
||||
pub fn register_gossip_message(
|
||||
&mut self,
|
||||
topic: B::Hash,
|
||||
message: Vec<u8>,
|
||||
) {
|
||||
pub fn register_gossip_message(&mut self, topic: B::Hash, message: Vec<u8>) {
|
||||
self.state_machine.register_message(topic, message);
|
||||
}
|
||||
|
||||
@@ -113,9 +116,7 @@ impl<B: BlockT> GossipEngine<B> {
|
||||
}
|
||||
|
||||
/// Get data of valid, incoming messages for a topic (but might have expired meanwhile).
|
||||
pub fn messages_for(&mut self, topic: B::Hash)
|
||||
-> Receiver<TopicNotification>
|
||||
{
|
||||
pub fn messages_for(&mut self, topic: B::Hash) -> Receiver<TopicNotification> {
|
||||
let past_messages = self.state_machine.messages_for(topic).collect::<Vec<_>>();
|
||||
// The channel length is not critical for correctness. By the implementation of `channel`
|
||||
// each sender is guaranteed a single buffer slot, making it a non-rendezvous channel and
|
||||
@@ -124,7 +125,7 @@ impl<B: BlockT> GossipEngine<B> {
|
||||
// contains a single message.
|
||||
let (mut tx, rx) = channel(usize::max(past_messages.len(), 10));
|
||||
|
||||
for notification in past_messages{
|
||||
for notification in past_messages {
|
||||
tx.try_send(notification)
|
||||
.expect("receiver known to be live, and buffer size known to suffice; qed");
|
||||
}
|
||||
@@ -135,22 +136,12 @@ impl<B: BlockT> GossipEngine<B> {
|
||||
}
|
||||
|
||||
/// Send all messages with given topic to a peer.
|
||||
pub fn send_topic(
|
||||
&mut self,
|
||||
who: &PeerId,
|
||||
topic: B::Hash,
|
||||
force: bool
|
||||
) {
|
||||
pub fn send_topic(&mut self, who: &PeerId, topic: B::Hash, force: bool) {
|
||||
self.state_machine.send_topic(&mut *self.network, who, topic, force)
|
||||
}
|
||||
|
||||
/// Multicast a message to all peers.
|
||||
pub fn gossip_message(
|
||||
&mut self,
|
||||
topic: B::Hash,
|
||||
message: Vec<u8>,
|
||||
force: bool,
|
||||
) {
|
||||
pub fn gossip_message(&mut self, topic: B::Hash, message: Vec<u8>, force: bool) {
|
||||
self.state_machine.multicast(&mut *self.network, topic, message, force)
|
||||
}
|
||||
|
||||
@@ -184,30 +175,33 @@ impl<B: BlockT> Future for GossipEngine<B> {
|
||||
Poll::Ready(Some(event)) => match event {
|
||||
Event::SyncConnected { remote } => {
|
||||
this.network.add_set_reserved(remote, this.protocol.clone());
|
||||
}
|
||||
},
|
||||
Event::SyncDisconnected { remote } => {
|
||||
this.network.remove_set_reserved(remote, this.protocol.clone());
|
||||
}
|
||||
},
|
||||
Event::NotificationStreamOpened { remote, protocol, role, .. } => {
|
||||
if protocol != this.protocol {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
this.state_machine.new_peer(&mut *this.network, remote, role);
|
||||
}
|
||||
},
|
||||
Event::NotificationStreamClosed { remote, protocol } => {
|
||||
if protocol != this.protocol {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
this.state_machine.peer_disconnected(&mut *this.network, remote);
|
||||
},
|
||||
Event::NotificationsReceived { remote, messages } => {
|
||||
let messages = messages.into_iter().filter_map(|(engine, data)| {
|
||||
if engine == this.protocol {
|
||||
Some(data.to_vec())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect();
|
||||
let messages = messages
|
||||
.into_iter()
|
||||
.filter_map(|(engine, data)| {
|
||||
if engine == this.protocol {
|
||||
Some(data.to_vec())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let to_forward = this.state_machine.on_incoming(
|
||||
&mut *this.network,
|
||||
@@ -217,27 +211,25 @@ impl<B: BlockT> Future for GossipEngine<B> {
|
||||
|
||||
this.forwarding_state = ForwardingState::Busy(to_forward.into());
|
||||
},
|
||||
Event::Dht(_) => {}
|
||||
}
|
||||
Event::Dht(_) => {},
|
||||
},
|
||||
// The network event stream closed. Do the same for [`GossipValidator`].
|
||||
Poll::Ready(None) => return Poll::Ready(()),
|
||||
Poll::Pending => break,
|
||||
}
|
||||
}
|
||||
},
|
||||
ForwardingState::Busy(to_forward) => {
|
||||
let (topic, notification) = match to_forward.pop_front() {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
this.forwarding_state = ForwardingState::Idle;
|
||||
continue;
|
||||
}
|
||||
continue
|
||||
},
|
||||
};
|
||||
|
||||
let sinks = match this.message_sinks.get_mut(&topic) {
|
||||
Some(sinks) => sinks,
|
||||
None => {
|
||||
continue;
|
||||
},
|
||||
None => continue,
|
||||
};
|
||||
|
||||
// Make sure all sinks for the given topic are ready.
|
||||
@@ -249,8 +241,8 @@ impl<B: BlockT> Future for GossipEngine<B> {
|
||||
Poll::Pending => {
|
||||
// Push back onto queue for later.
|
||||
to_forward.push_front((topic, notification));
|
||||
break 'outer;
|
||||
}
|
||||
break 'outer
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +251,7 @@ impl<B: BlockT> Future for GossipEngine<B> {
|
||||
|
||||
if sinks.is_empty() {
|
||||
this.message_sinks.remove(&topic);
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
trace!(
|
||||
@@ -271,18 +263,16 @@ impl<B: BlockT> Future for GossipEngine<B> {
|
||||
for sink in sinks {
|
||||
match sink.start_send(notification.clone()) {
|
||||
Ok(()) => {},
|
||||
Err(e) if e.is_full() => unreachable!(
|
||||
"Previously ensured that all sinks are ready; qed.",
|
||||
),
|
||||
Err(e) if e.is_full() =>
|
||||
unreachable!("Previously ensured that all sinks are ready; qed.",),
|
||||
// Receiver got dropped. Will be removed in next iteration (See (1)).
|
||||
Err(_) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while let Poll::Ready(()) = this.periodic_maintenance_interval.poll_unpin(cx) {
|
||||
this.periodic_maintenance_interval.reset(PERIODIC_MAINTENANCE_INTERVAL);
|
||||
this.state_machine.tick(&mut *this.network);
|
||||
@@ -299,17 +289,23 @@ impl<B: BlockT> Future for GossipEngine<B> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use async_std::task::spawn;
|
||||
use super::*;
|
||||
use crate::{ValidationResult, ValidatorContext};
|
||||
use futures::{channel::mpsc::{unbounded, UnboundedSender}, executor::{block_on, block_on_stream}, future::poll_fn};
|
||||
use async_std::task::spawn;
|
||||
use futures::{
|
||||
channel::mpsc::{unbounded, UnboundedSender},
|
||||
executor::{block_on, block_on_stream},
|
||||
future::poll_fn,
|
||||
};
|
||||
use quickcheck::{Arbitrary, Gen, QuickCheck};
|
||||
use sc_network::ObservedRole;
|
||||
use sp_runtime::{testing::H256, traits::{Block as BlockT}};
|
||||
use std::borrow::Cow;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use sp_runtime::{testing::H256, traits::Block as BlockT};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
convert::TryInto,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use substrate_test_runtime_client::runtime::Block;
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct TestNetwork {
|
||||
@@ -329,18 +325,15 @@ mod tests {
|
||||
Box::pin(rx)
|
||||
}
|
||||
|
||||
fn report_peer(&self, _: PeerId, _: ReputationChange) {
|
||||
}
|
||||
fn report_peer(&self, _: PeerId, _: ReputationChange) {}
|
||||
|
||||
fn disconnect_peer(&self, _: PeerId, _: Cow<'static, str>) {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn add_set_reserved(&self, _: PeerId, _: Cow<'static, str>) {
|
||||
}
|
||||
fn add_set_reserved(&self, _: PeerId, _: Cow<'static, str>) {}
|
||||
|
||||
fn remove_set_reserved(&self, _: PeerId, _: Cow<'static, str>) {
|
||||
}
|
||||
fn remove_set_reserved(&self, _: PeerId, _: Cow<'static, str>) {}
|
||||
|
||||
fn write_notification(&self, _: PeerId, _: Cow<'static, str>, _: Vec<u8>) {
|
||||
unimplemented!();
|
||||
@@ -405,32 +398,32 @@ mod tests {
|
||||
None,
|
||||
);
|
||||
|
||||
let mut event_sender = network.inner.lock()
|
||||
.unwrap()
|
||||
.event_senders
|
||||
.pop()
|
||||
.unwrap();
|
||||
let mut event_sender = network.inner.lock().unwrap().event_senders.pop().unwrap();
|
||||
|
||||
// Register the remote peer.
|
||||
event_sender.start_send(
|
||||
Event::NotificationStreamOpened {
|
||||
event_sender
|
||||
.start_send(Event::NotificationStreamOpened {
|
||||
remote: remote_peer.clone(),
|
||||
protocol: protocol.clone(),
|
||||
negotiated_fallback: None,
|
||||
role: ObservedRole::Authority,
|
||||
}
|
||||
).expect("Event stream is unbounded; qed.");
|
||||
})
|
||||
.expect("Event stream is unbounded; qed.");
|
||||
|
||||
let messages = vec![vec![1], vec![2]];
|
||||
let events = messages.iter().cloned().map(|m| {
|
||||
Event::NotificationsReceived {
|
||||
let events = messages
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|m| Event::NotificationsReceived {
|
||||
remote: remote_peer.clone(),
|
||||
messages: vec![(protocol.clone(), m.into())]
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
messages: vec![(protocol.clone(), m.into())],
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Send first event before subscribing.
|
||||
event_sender.start_send(events[0].clone()).expect("Event stream is unbounded; qed.");
|
||||
event_sender
|
||||
.start_send(events[0].clone())
|
||||
.expect("Event stream is unbounded; qed.");
|
||||
|
||||
let mut subscribers = vec![];
|
||||
for _ in 0..2 {
|
||||
@@ -438,13 +431,14 @@ mod tests {
|
||||
}
|
||||
|
||||
// Send second event after subscribing.
|
||||
event_sender.start_send(events[1].clone()).expect("Event stream is unbounded; qed.");
|
||||
event_sender
|
||||
.start_send(events[1].clone())
|
||||
.expect("Event stream is unbounded; qed.");
|
||||
|
||||
spawn(gossip_engine);
|
||||
|
||||
let mut subscribers = subscribers.into_iter()
|
||||
.map(|s| block_on_stream(s))
|
||||
.collect::<Vec<_>>();
|
||||
let mut subscribers =
|
||||
subscribers.into_iter().map(|s| block_on_stream(s)).collect::<Vec<_>>();
|
||||
|
||||
// Expect each subscriber to receive both events.
|
||||
for message in messages {
|
||||
@@ -463,7 +457,7 @@ mod tests {
|
||||
#[test]
|
||||
fn forwarding_to_different_size_and_topic_channels() {
|
||||
#[derive(Clone, Debug)]
|
||||
struct ChannelLengthAndTopic{
|
||||
struct ChannelLengthAndTopic {
|
||||
length: usize,
|
||||
topic: H256,
|
||||
}
|
||||
@@ -486,7 +480,7 @@ mod tests {
|
||||
topic: H256,
|
||||
}
|
||||
|
||||
impl Arbitrary for Message{
|
||||
impl Arbitrary for Message {
|
||||
fn arbitrary(g: &mut Gen) -> Self {
|
||||
let possible_topics = (0..10).collect::<Vec<u64>>();
|
||||
Self {
|
||||
@@ -517,13 +511,16 @@ mod tests {
|
||||
let remote_peer = PeerId::random();
|
||||
let network = TestNetwork::default();
|
||||
|
||||
let num_channels_per_topic = channels.iter()
|
||||
.fold(HashMap::new(), |mut acc, ChannelLengthAndTopic { topic, .. }| {
|
||||
let num_channels_per_topic = channels.iter().fold(
|
||||
HashMap::new(),
|
||||
|mut acc, ChannelLengthAndTopic { topic, .. }| {
|
||||
acc.entry(topic).and_modify(|e| *e += 1).or_insert(1);
|
||||
acc
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
let expected_msgs_per_topic_all_chan = notifications.iter()
|
||||
let expected_msgs_per_topic_all_chan = notifications
|
||||
.iter()
|
||||
.fold(HashMap::new(), |mut acc, messages| {
|
||||
for message in messages {
|
||||
acc.entry(message.topic).and_modify(|e| *e += 1).or_insert(1);
|
||||
@@ -545,12 +542,12 @@ mod tests {
|
||||
);
|
||||
|
||||
// Create channels.
|
||||
let (txs, mut rxs) = channels.iter()
|
||||
.map(|ChannelLengthAndTopic { length, topic }| {
|
||||
(topic.clone(), channel(*length))
|
||||
})
|
||||
let (txs, mut rxs) = channels
|
||||
.iter()
|
||||
.map(|ChannelLengthAndTopic { length, topic }| (topic.clone(), channel(*length)))
|
||||
.fold((vec![], vec![]), |mut acc, (topic, (tx, rx))| {
|
||||
acc.0.push((topic, tx)); acc.1.push((topic, rx));
|
||||
acc.0.push((topic, tx));
|
||||
acc.1.push((topic, rx));
|
||||
acc
|
||||
});
|
||||
|
||||
@@ -560,30 +557,27 @@ mod tests {
|
||||
Some(entry) => entry.push(tx),
|
||||
None => {
|
||||
gossip_engine.message_sinks.insert(topic, vec![tx]);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let mut event_sender = network.inner.lock()
|
||||
.unwrap()
|
||||
.event_senders
|
||||
.pop()
|
||||
.unwrap();
|
||||
let mut event_sender = network.inner.lock().unwrap().event_senders.pop().unwrap();
|
||||
|
||||
// Register the remote peer.
|
||||
event_sender.start_send(
|
||||
Event::NotificationStreamOpened {
|
||||
event_sender
|
||||
.start_send(Event::NotificationStreamOpened {
|
||||
remote: remote_peer.clone(),
|
||||
protocol: protocol.clone(),
|
||||
negotiated_fallback: None,
|
||||
role: ObservedRole::Authority,
|
||||
}
|
||||
).expect("Event stream is unbounded; qed.");
|
||||
})
|
||||
.expect("Event stream is unbounded; qed.");
|
||||
|
||||
// Send messages into the network event stream.
|
||||
for (i_notification, messages) in notifications.iter().enumerate() {
|
||||
let messages = messages.into_iter().enumerate()
|
||||
let messages = messages
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i_message, Message { topic })| {
|
||||
// Embed the topic in the first 256 bytes of the message to be extracted by
|
||||
// the [`TestValidator`] later on.
|
||||
@@ -595,12 +589,15 @@ mod tests {
|
||||
message.push(i_message.try_into().unwrap());
|
||||
|
||||
(protocol.clone(), message.into())
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
|
||||
event_sender.start_send(Event::NotificationsReceived {
|
||||
remote: remote_peer.clone(),
|
||||
messages,
|
||||
}).expect("Event stream is unbounded; qed.");
|
||||
event_sender
|
||||
.start_send(Event::NotificationsReceived {
|
||||
remote: remote_peer.clone(),
|
||||
messages,
|
||||
})
|
||||
.expect("Event stream is unbounded; qed.");
|
||||
}
|
||||
|
||||
let mut received_msgs_per_topic_all_chan = HashMap::<H256, _>::new();
|
||||
@@ -621,19 +618,19 @@ mod tests {
|
||||
match rx.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(_)) => {
|
||||
progress = true;
|
||||
received_msgs_per_topic_all_chan.entry(*topic)
|
||||
received_msgs_per_topic_all_chan
|
||||
.entry(*topic)
|
||||
.and_modify(|e| *e += 1)
|
||||
.or_insert(1);
|
||||
},
|
||||
Poll::Ready(None) => unreachable!(
|
||||
"Sender side of channel is never dropped",
|
||||
),
|
||||
Poll::Ready(None) =>
|
||||
unreachable!("Sender side of channel is never dropped",),
|
||||
Poll::Pending => {},
|
||||
}
|
||||
}
|
||||
|
||||
if !progress {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
Poll::Ready(())
|
||||
@@ -655,10 +652,10 @@ mod tests {
|
||||
}
|
||||
|
||||
// Past regressions.
|
||||
prop(vec![], vec![vec![Message{ topic: H256::default()}]]);
|
||||
prop(vec![], vec![vec![Message { topic: H256::default() }]]);
|
||||
prop(
|
||||
vec![ChannelLengthAndTopic {length: 71, topic: H256::default()}],
|
||||
vec![vec![Message{ topic: H256::default()}]],
|
||||
vec![ChannelLengthAndTopic { length: 71, topic: H256::default() }],
|
||||
vec![vec![Message { topic: H256::default() }]],
|
||||
);
|
||||
|
||||
QuickCheck::new().quickcheck(prop as fn(_, _))
|
||||
|
||||
@@ -61,13 +61,15 @@
|
||||
//! These status packets will typically contain light pieces of information
|
||||
//! used to inform peers of a current view of protocol state.
|
||||
|
||||
pub use self::bridge::GossipEngine;
|
||||
pub use self::state_machine::TopicNotification;
|
||||
pub use self::validator::{DiscardAll, MessageIntent, Validator, ValidatorContext, ValidationResult};
|
||||
pub use self::{
|
||||
bridge::GossipEngine,
|
||||
state_machine::TopicNotification,
|
||||
validator::{DiscardAll, MessageIntent, ValidationResult, Validator, ValidatorContext},
|
||||
};
|
||||
|
||||
use futures::prelude::*;
|
||||
use sc_network::{multiaddr, Event, ExHashT, NetworkService, PeerId, ReputationChange};
|
||||
use sp_runtime::{traits::Block as BlockT};
|
||||
use sp_runtime::traits::Block as BlockT;
|
||||
use std::{borrow::Cow, iter, pin::Pin, sync::Arc};
|
||||
|
||||
mod bridge;
|
||||
@@ -111,18 +113,23 @@ impl<B: BlockT, H: ExHashT> Network<B> for Arc<NetworkService<B, H>> {
|
||||
}
|
||||
|
||||
fn add_set_reserved(&self, who: PeerId, protocol: Cow<'static, str>) {
|
||||
let addr = iter::once(multiaddr::Protocol::P2p(who.into()))
|
||||
.collect::<multiaddr::Multiaddr>();
|
||||
let result = NetworkService::add_peers_to_reserved_set(self, protocol, iter::once(addr).collect());
|
||||
let addr =
|
||||
iter::once(multiaddr::Protocol::P2p(who.into())).collect::<multiaddr::Multiaddr>();
|
||||
let result =
|
||||
NetworkService::add_peers_to_reserved_set(self, protocol, iter::once(addr).collect());
|
||||
if let Err(err) = result {
|
||||
log::error!(target: "gossip", "add_set_reserved failed: {}", err);
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_set_reserved(&self, who: PeerId, protocol: Cow<'static, str>) {
|
||||
let addr = iter::once(multiaddr::Protocol::P2p(who.into()))
|
||||
.collect::<multiaddr::Multiaddr>();
|
||||
let result = NetworkService::remove_peers_from_reserved_set(self, protocol, iter::once(addr).collect());
|
||||
let addr =
|
||||
iter::once(multiaddr::Protocol::P2p(who.into())).collect::<multiaddr::Multiaddr>();
|
||||
let result = NetworkService::remove_peers_from_reserved_set(
|
||||
self,
|
||||
protocol,
|
||||
iter::once(addr).collect(),
|
||||
);
|
||||
if let Err(err) = result {
|
||||
log::error!(target: "gossip", "remove_set_reserved failed: {}", err);
|
||||
}
|
||||
|
||||
@@ -16,18 +16,20 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Network, MessageIntent, Validator, ValidatorContext, ValidationResult};
|
||||
use crate::{MessageIntent, Network, ValidationResult, Validator, ValidatorContext};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use std::iter;
|
||||
use std::time;
|
||||
use lru::LruCache;
|
||||
use libp2p::PeerId;
|
||||
use lru::LruCache;
|
||||
use prometheus_endpoint::{register, Counter, PrometheusError, Registry, U64};
|
||||
use sp_runtime::traits::{Block as BlockT, Hash, HashFor};
|
||||
use sc_network::ObservedRole;
|
||||
use sp_runtime::traits::{Block as BlockT, Hash, HashFor};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::{HashMap, HashSet},
|
||||
iter,
|
||||
sync::Arc,
|
||||
time,
|
||||
};
|
||||
use wasm_timer::Instant;
|
||||
|
||||
// FIXME: Add additional spam/DoS attack protection: https://github.com/paritytech/substrate/issues/1115
|
||||
@@ -87,17 +89,13 @@ impl<'g, 'p, B: BlockT> ValidatorContext<B> for NetworkContext<'g, 'p, B> {
|
||||
|
||||
/// Broadcast a message to all peers that have not received it previously.
|
||||
fn broadcast_message(&mut self, topic: B::Hash, message: Vec<u8>, force: bool) {
|
||||
self.gossip.multicast(
|
||||
self.network,
|
||||
topic,
|
||||
message,
|
||||
force,
|
||||
);
|
||||
self.gossip.multicast(self.network, topic, message, force);
|
||||
}
|
||||
|
||||
/// Send addressed message to a peer.
|
||||
fn send_message(&mut self, who: &PeerId, message: Vec<u8>) {
|
||||
self.network.write_notification(who.clone(), self.gossip.protocol.clone(), message);
|
||||
self.network
|
||||
.write_notification(who.clone(), self.gossip.protocol.clone(), message);
|
||||
}
|
||||
|
||||
/// Send all messages with given topic to a peer.
|
||||
@@ -114,8 +112,9 @@ fn propagate<'a, B: BlockT, I>(
|
||||
peers: &mut HashMap<PeerId, PeerConsensus<B::Hash>>,
|
||||
validator: &Arc<dyn Validator<B>>,
|
||||
)
|
||||
// (msg_hash, topic, message)
|
||||
where I: Clone + IntoIterator<Item=(&'a B::Hash, &'a B::Hash, &'a Vec<u8>)>,
|
||||
// (msg_hash, topic, message)
|
||||
where
|
||||
I: Clone + IntoIterator<Item = (&'a B::Hash, &'a B::Hash, &'a Vec<u8>)>,
|
||||
{
|
||||
let mut message_allowed = validator.message_allowed();
|
||||
|
||||
@@ -124,7 +123,7 @@ fn propagate<'a, B: BlockT, I>(
|
||||
let intent = match intent {
|
||||
MessageIntent::Broadcast { .. } =>
|
||||
if peer.known_messages.contains(&message_hash) {
|
||||
continue;
|
||||
continue
|
||||
} else {
|
||||
MessageIntent::Broadcast
|
||||
},
|
||||
@@ -140,7 +139,7 @@ fn propagate<'a, B: BlockT, I>(
|
||||
};
|
||||
|
||||
if !message_allowed(id, intent, &topic, &message) {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
peer.known_messages.insert(message_hash.clone());
|
||||
@@ -180,7 +179,7 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
Some(Err(e)) => {
|
||||
tracing::debug!(target: "gossip", "Failed to register metrics: {:?}", e);
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
@@ -204,9 +203,7 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
?role,
|
||||
"Registering peer",
|
||||
);
|
||||
self.peers.insert(who.clone(), PeerConsensus {
|
||||
known_messages: HashSet::new(),
|
||||
});
|
||||
self.peers.insert(who.clone(), PeerConsensus { known_messages: HashSet::new() });
|
||||
|
||||
let validator = self.validator.clone();
|
||||
let mut context = NetworkContext { gossip: self, network };
|
||||
@@ -221,12 +218,7 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
sender: Option<PeerId>,
|
||||
) {
|
||||
if self.known_messages.put(message_hash.clone(), ()).is_none() {
|
||||
self.messages.push(MessageEntry {
|
||||
message_hash,
|
||||
topic,
|
||||
message,
|
||||
sender,
|
||||
});
|
||||
self.messages.push(MessageEntry { message_hash, topic, message, sender });
|
||||
|
||||
if let Some(ref metrics) = self.metrics {
|
||||
metrics.registered_messages.inc();
|
||||
@@ -239,11 +231,7 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
/// the message's topic. No validation is performed on the message, if the
|
||||
/// message is already expired it should be dropped on the next garbage
|
||||
/// collection.
|
||||
pub fn register_message(
|
||||
&mut self,
|
||||
topic: B::Hash,
|
||||
message: Vec<u8>,
|
||||
) {
|
||||
pub fn register_message(&mut self, topic: B::Hash, message: Vec<u8>) {
|
||||
let message_hash = HashFor::<B>::hash(&message[..]);
|
||||
self.register_message_hashed(message_hash, topic, message, None);
|
||||
}
|
||||
@@ -267,7 +255,9 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
|
||||
/// Rebroadcast all messages to all peers.
|
||||
fn rebroadcast(&mut self, network: &mut dyn Network<B>) {
|
||||
let messages = self.messages.iter()
|
||||
let messages = self
|
||||
.messages
|
||||
.iter()
|
||||
.map(|entry| (&entry.message_hash, &entry.topic, &entry.message));
|
||||
propagate(
|
||||
network,
|
||||
@@ -275,20 +265,28 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
messages,
|
||||
MessageIntent::PeriodicRebroadcast,
|
||||
&mut self.peers,
|
||||
&self.validator
|
||||
&self.validator,
|
||||
);
|
||||
}
|
||||
|
||||
/// Broadcast all messages with given topic.
|
||||
pub fn broadcast_topic(&mut self, network: &mut dyn Network<B>, topic: B::Hash, force: bool) {
|
||||
let messages = self.messages.iter()
|
||||
.filter_map(|entry|
|
||||
if entry.topic == topic {
|
||||
Some((&entry.message_hash, &entry.topic, &entry.message))
|
||||
} else { None }
|
||||
);
|
||||
let messages = self.messages.iter().filter_map(|entry| {
|
||||
if entry.topic == topic {
|
||||
Some((&entry.message_hash, &entry.topic, &entry.message))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
let intent = if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast };
|
||||
propagate(network, self.protocol.clone(), messages, intent, &mut self.peers, &self.validator);
|
||||
propagate(
|
||||
network,
|
||||
self.protocol.clone(),
|
||||
messages,
|
||||
intent,
|
||||
&mut self.peers,
|
||||
&self.validator,
|
||||
);
|
||||
}
|
||||
|
||||
/// Prune old or no longer relevant consensus messages. Provide a predicate
|
||||
@@ -298,8 +296,7 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
let before = self.messages.len();
|
||||
|
||||
let mut message_expired = self.validator.message_expired();
|
||||
self.messages
|
||||
.retain(|entry| !message_expired(entry.topic, &entry.message));
|
||||
self.messages.retain(|entry| !message_expired(entry.topic, &entry.message));
|
||||
|
||||
let expired_messages = before - self.messages.len();
|
||||
|
||||
@@ -323,10 +320,13 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
|
||||
/// Get valid messages received in the past for a topic (might have expired meanwhile).
|
||||
pub fn messages_for(&mut self, topic: B::Hash) -> impl Iterator<Item = TopicNotification> + '_ {
|
||||
self.messages.iter().filter(move |e| e.topic == topic).map(|entry| TopicNotification {
|
||||
message: entry.message.clone(),
|
||||
sender: entry.sender.clone(),
|
||||
})
|
||||
self.messages
|
||||
.iter()
|
||||
.filter(move |e| e.topic == topic)
|
||||
.map(|entry| TopicNotification {
|
||||
message: entry.message.clone(),
|
||||
sender: entry.sender.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Register incoming messages and return the ones that are new and valid (according to a gossip
|
||||
@@ -360,7 +360,7 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
"Ignored already known message",
|
||||
);
|
||||
network.report_peer(who.clone(), rep::DUPLICATE_GOSSIP);
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
// validate the message
|
||||
@@ -380,7 +380,7 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
protocol = %self.protocol,
|
||||
"Discard message from peer",
|
||||
);
|
||||
continue;
|
||||
continue
|
||||
},
|
||||
};
|
||||
|
||||
@@ -393,24 +393,19 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
protocol = %self.protocol,
|
||||
"Got message from unregistered peer",
|
||||
);
|
||||
continue;
|
||||
}
|
||||
continue
|
||||
},
|
||||
};
|
||||
|
||||
network.report_peer(who.clone(), rep::GOSSIP_SUCCESS);
|
||||
peer.known_messages.insert(message_hash);
|
||||
to_forward.push((topic, TopicNotification {
|
||||
message: message.clone(),
|
||||
sender: Some(who.clone())
|
||||
}));
|
||||
to_forward.push((
|
||||
topic,
|
||||
TopicNotification { message: message.clone(), sender: Some(who.clone()) },
|
||||
));
|
||||
|
||||
if keep {
|
||||
self.register_message_hashed(
|
||||
message_hash,
|
||||
topic,
|
||||
message,
|
||||
Some(who.clone()),
|
||||
);
|
||||
self.register_message_hashed(message_hash, topic, message, Some(who.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,24 +418,21 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
network: &mut dyn Network<B>,
|
||||
who: &PeerId,
|
||||
topic: B::Hash,
|
||||
force: bool
|
||||
force: bool,
|
||||
) {
|
||||
let mut message_allowed = self.validator.message_allowed();
|
||||
|
||||
if let Some(ref mut peer) = self.peers.get_mut(who) {
|
||||
for entry in self.messages.iter().filter(|m| m.topic == topic) {
|
||||
let intent = if force {
|
||||
MessageIntent::ForcedBroadcast
|
||||
} else {
|
||||
MessageIntent::Broadcast
|
||||
};
|
||||
let intent =
|
||||
if force { MessageIntent::ForcedBroadcast } else { MessageIntent::Broadcast };
|
||||
|
||||
if !force && peer.known_messages.contains(&entry.message_hash) {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
if !message_allowed(who, intent, &entry.topic, &entry.message) {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
peer.known_messages.insert(entry.message_hash.clone());
|
||||
@@ -452,7 +444,11 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
?entry.message,
|
||||
"Sending topic message",
|
||||
);
|
||||
network.write_notification(who.clone(), self.protocol.clone(), entry.message.clone());
|
||||
network.write_notification(
|
||||
who.clone(),
|
||||
self.protocol.clone(),
|
||||
entry.message.clone(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,18 +470,13 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
iter::once((&message_hash, &topic, &message)),
|
||||
intent,
|
||||
&mut self.peers,
|
||||
&self.validator
|
||||
&self.validator,
|
||||
);
|
||||
}
|
||||
|
||||
/// Send addressed message to a peer. The message is not kept or multicast
|
||||
/// later on.
|
||||
pub fn send_message(
|
||||
&mut self,
|
||||
network: &mut dyn Network<B>,
|
||||
who: &PeerId,
|
||||
message: Vec<u8>,
|
||||
) {
|
||||
pub fn send_message(&mut self, network: &mut dyn Network<B>, who: &PeerId, message: Vec<u8>) {
|
||||
let peer = match self.peers.get_mut(who) {
|
||||
None => return,
|
||||
Some(peer) => peer,
|
||||
@@ -534,11 +525,15 @@ impl Metrics {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use futures::prelude::*;
|
||||
use sc_network::{Event, ReputationChange};
|
||||
use sp_runtime::testing::{H256, Block as RawBlock, ExtrinsicWrapper};
|
||||
use std::{borrow::Cow, pin::Pin, sync::{Arc, Mutex}};
|
||||
use super::*;
|
||||
use sp_runtime::testing::{Block as RawBlock, ExtrinsicWrapper, H256};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
pin::Pin,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
type Block = RawBlock<ExtrinsicWrapper<u64>>;
|
||||
|
||||
@@ -552,7 +547,7 @@ mod tests {
|
||||
sender: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct AllowAll;
|
||||
@@ -568,7 +563,7 @@ mod tests {
|
||||
}
|
||||
|
||||
struct DiscardAll;
|
||||
impl Validator<Block> for DiscardAll{
|
||||
impl Validator<Block> for DiscardAll {
|
||||
fn validate(
|
||||
&self,
|
||||
_context: &mut dyn ValidatorContext<Block>,
|
||||
@@ -602,11 +597,9 @@ mod tests {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn add_set_reserved(&self, _: PeerId, _: Cow<'static, str>) {
|
||||
}
|
||||
fn add_set_reserved(&self, _: PeerId, _: Cow<'static, str>) {}
|
||||
|
||||
fn remove_set_reserved(&self, _: PeerId, _: Cow<'static, str>) {
|
||||
}
|
||||
fn remove_set_reserved(&self, _: PeerId, _: Cow<'static, str>) {}
|
||||
|
||||
fn write_notification(&self, _: PeerId, _: Cow<'static, str>, _: Vec<u8>) {
|
||||
unimplemented!();
|
||||
@@ -677,7 +670,7 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
consensus.messages_for(topic).next(),
|
||||
Some(TopicNotification { message: message, sender: None }),
|
||||
Some(TopicNotification { message, sender: None }),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -712,15 +705,12 @@ mod tests {
|
||||
#[test]
|
||||
fn on_incoming_ignores_discarded_messages() {
|
||||
let to_forward = ConsensusGossip::<Block>::new(Arc::new(DiscardAll), "/foo".into(), None)
|
||||
.on_incoming(
|
||||
&mut NoOpNetwork::default(),
|
||||
PeerId::random(),
|
||||
vec![vec![1, 2, 3]],
|
||||
);
|
||||
.on_incoming(&mut NoOpNetwork::default(), PeerId::random(), vec![vec![1, 2, 3]]);
|
||||
|
||||
assert!(
|
||||
to_forward.is_empty(),
|
||||
"Expected `on_incoming` to ignore discarded message but got {:?}", to_forward,
|
||||
"Expected `on_incoming` to ignore discarded message but got {:?}",
|
||||
to_forward,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,15 +26,14 @@ pub trait Validator<B: BlockT>: Send + Sync {
|
||||
}
|
||||
|
||||
/// New connection is dropped.
|
||||
fn peer_disconnected(&self, _context: &mut dyn ValidatorContext<B>, _who: &PeerId) {
|
||||
}
|
||||
fn peer_disconnected(&self, _context: &mut dyn ValidatorContext<B>, _who: &PeerId) {}
|
||||
|
||||
/// Validate consensus message.
|
||||
fn validate(
|
||||
&self,
|
||||
context: &mut dyn ValidatorContext<B>,
|
||||
sender: &PeerId,
|
||||
data: &[u8]
|
||||
data: &[u8],
|
||||
) -> ValidationResult<B::Hash>;
|
||||
|
||||
/// Produce a closure for validating messages on a given topic.
|
||||
@@ -43,7 +42,9 @@ pub trait Validator<B: BlockT>: Send + Sync {
|
||||
}
|
||||
|
||||
/// Produce a closure for filtering egress messages.
|
||||
fn message_allowed<'a>(&'a self) -> Box<dyn FnMut(&PeerId, MessageIntent, &B::Hash, &[u8]) -> bool + 'a> {
|
||||
fn message_allowed<'a>(
|
||||
&'a self,
|
||||
) -> Box<dyn FnMut(&PeerId, MessageIntent, &B::Hash, &[u8]) -> bool + 'a> {
|
||||
Box::new(move |_who, _intent, _topic, _data| true)
|
||||
}
|
||||
}
|
||||
@@ -99,7 +100,9 @@ impl<B: BlockT> Validator<B> for DiscardAll {
|
||||
Box::new(move |_topic, _data| true)
|
||||
}
|
||||
|
||||
fn message_allowed<'a>(&'a self) -> Box<dyn FnMut(&PeerId, MessageIntent, &B::Hash, &[u8]) -> bool + 'a> {
|
||||
fn message_allowed<'a>(
|
||||
&'a self,
|
||||
) -> Box<dyn FnMut(&PeerId, MessageIntent, &B::Hash, &[u8]) -> bool + 'a> {
|
||||
Box::new(move |_who, _intent, _topic, _data| false)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user