From bf2dd5f419b6263657735661d69f681cbc2babec Mon Sep 17 00:00:00 2001
From: Pierre Krieger <pierre.krieger1708@gmail.com>
Date: Mon, 11 Feb 2019 11:39:14 +0100
Subject: [PATCH] Reduce the spam from network misbehaviours (#1750)

* Reduce the spam from network misbehaviours

* Add protocol id to misbehaviour
---
 .../src/custom_proto/behaviour.rs             | 16 ++++++++++---
 .../src/custom_proto/handler.rs               | 23 ++++++++++++++-----
 2 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/substrate/core/network-libp2p/src/custom_proto/behaviour.rs b/substrate/core/network-libp2p/src/custom_proto/behaviour.rs
index 66af5e048c5..92bc725afea 100644
--- a/substrate/core/network-libp2p/src/custom_proto/behaviour.rs
+++ b/substrate/core/network-libp2p/src/custom_proto/behaviour.rs
@@ -242,9 +242,14 @@ impl<TSubstream> CustomProtos<TSubstream> {
 	/// Disconnects the given peer if we are connected to it and disables it for a little while.
 	pub fn ban_peer(&mut self, peer_id: PeerId) {
 		// Peer is already banned
-		if self.banned_peers.iter().any(|(p, _)| p == &peer_id) {
-			return
+		if let Some(pos) = self.banned_peers.iter().position(|(p, _)| p == &peer_id) {
+			if self.banned_peers[pos].1 > Instant::now() {
+				return
+			} else {
+				self.banned_peers.remove(pos);
+			}
 		}
+
 		self.banned_peers.push((peer_id.clone(), Instant::now() + PEER_DISABLE_DURATION));
 		if self.enabled_peers.remove(&peer_id).is_some() {
 			self.events.push(NetworkBehaviourAction::SendEvent {
@@ -565,6 +570,11 @@ where
 					messages,
 				}));
 			}
+			CustomProtosHandlerOut::ProtocolError { protocol_id, error } => {
+				warn!(target: "sub-libp2p", "Network misbehaviour from {:?} with protocol \
+					{:?}: {:?}", source, protocol_id, error);
+				self.ban_peer(source);
+			}
 		}
 	}
 
@@ -589,7 +599,7 @@ where
 		}
 
 		// Clean up `banned_peers`
-		self.banned_peers.retain(|(_, end)| *end < Instant::now());
+		self.banned_peers.retain(|(_, end)| *end > Instant::now());
 		self.banned_peers.shrink_to_fit();
 
 		if !self.events.is_empty() {
diff --git a/substrate/core/network-libp2p/src/custom_proto/handler.rs b/substrate/core/network-libp2p/src/custom_proto/handler.rs
index 51ff2408ad8..b44407ff7f7 100644
--- a/substrate/core/network-libp2p/src/custom_proto/handler.rs
+++ b/substrate/core/network-libp2p/src/custom_proto/handler.rs
@@ -24,7 +24,7 @@ use libp2p::core::{
 	protocols_handler::ProtocolsHandlerUpgrErr,
 	upgrade::{InboundUpgrade, OutboundUpgrade}
 };
-use log::{trace, warn};
+use log::trace;
 use smallvec::SmallVec;
 use std::{fmt, io, time::Duration, time::Instant};
 use tokio_io::{AsyncRead, AsyncWrite};
@@ -50,7 +50,7 @@ pub struct CustomProtosHandler<TSubstream> {
 	substreams: SmallVec<[RegisteredProtocolSubstream<TSubstream>; 6]>,
 
 	/// Queue of events to send to the outside.
-	events_queue: SmallVec<[ProtocolsHandlerEvent<RegisteredProtocol, (), CustomProtosHandlerOut>; 16]>,
+	events_queue: SmallVec<[ProtocolsHandlerEvent<RegisteredProtocol, ProtocolId, CustomProtosHandlerOut>; 16]>,
 }
 
 /// State of the handler.
@@ -128,6 +128,14 @@ pub enum CustomProtosHandlerOut {
 		/// Copy of the messages that are within the buffer, for further diagnostic.
 		messages: Vec<Bytes>,
 	},
+
+	/// An error has happened on the protocol level with this node.
+	ProtocolError {
+		/// Protocol for which the error happened.
+		protocol_id: ProtocolId,
+		/// The error that happened.
+		error: ProtocolsHandlerUpgrErr<io::Error>,
+	},
 }
 
 impl<TSubstream> CustomProtosHandler<TSubstream>
@@ -191,7 +199,7 @@ where
 	type Error = Void;
 	type InboundProtocol = RegisteredProtocols;
 	type OutboundProtocol = RegisteredProtocol;
-	type OutboundOpenInfo = ();
+	type OutboundOpenInfo = ProtocolId;
 
 	#[inline]
 	fn listen_protocol(&self) -> Self::InboundProtocol {
@@ -258,7 +266,7 @@ where
 
 						self.events_queue.push(ProtocolsHandlerEvent::OutboundSubstreamRequest {
 							upgrade: protocol.clone(),
-							info: (),
+							info: protocol.id(),
 						});
 					}
 				}
@@ -286,8 +294,11 @@ where
 	fn inject_inbound_closed(&mut self) {}
 
 	#[inline]
-	fn inject_dial_upgrade_error(&mut self, _: Self::OutboundOpenInfo, err: ProtocolsHandlerUpgrErr<io::Error>) {
-		warn!(target: "sub-libp2p", "Error while opening custom protocol: {:?}", err);
+	fn inject_dial_upgrade_error(&mut self, protocol_id: Self::OutboundOpenInfo, error: ProtocolsHandlerUpgrErr<io::Error>) {
+		if let State::Normal = self.state {
+			let event = CustomProtosHandlerOut::ProtocolError { protocol_id, error };
+			self.events_queue.push(ProtocolsHandlerEvent::Custom(event));
+		}
 
 		// Right now if the remote doesn't support one of the custom protocols, we shut down the
 		// entire connection. This is a hack-ish solution to the problem where we connect to nodes
-- 
GitLab