diff --git a/substrate/polkadot/network/src/lib.rs b/substrate/polkadot/network/src/lib.rs index cb3d97bdbbff878be43e502e4bc2b338d41da2d2..016a884fe9af63797ea040af8928b942ee92e9d7 100644 --- a/substrate/polkadot/network/src/lib.rs +++ b/substrate/polkadot/network/src/lib.rs @@ -49,7 +49,7 @@ use parking_lot::Mutex; use polkadot_consensus::{Statement, SignedStatement, GenericStatement}; use polkadot_primitives::{AccountId, Block, SessionKey, Hash, Header}; use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt, Collation}; -use substrate_network::{PeerId, RequestId, Context}; +use substrate_network::{PeerId, RequestId, Context, Severity}; use substrate_network::consensus_gossip::ConsensusGossip; use substrate_network::{message, generic_message}; use substrate_network::specialization::Specialization; @@ -403,7 +403,7 @@ impl PolkadotProtocol { }; if !info.claimed_validator { - ctx.disable_peer(peer_id, "Session key broadcasted without setting authority role"); + ctx.report_peer(peer_id, Severity::Bad("Session key broadcasted without setting authority role")); return; } @@ -438,7 +438,7 @@ impl PolkadotProtocol { self.pending.push(req); self.dispatch_pending_requests(ctx); } - None => ctx.disable_peer(peer_id, "Unexpected block data response"), + None => ctx.report_peer(peer_id, Severity::Bad("Unexpected block data response")), } } @@ -453,9 +453,9 @@ impl PolkadotProtocol { }; match info.validator_key { - None => ctx.disable_peer( + None => ctx.report_peer( peer_id, - "Sent collator role without registering first as validator", + Severity::Bad("Sent collator role without registering first as validator"), ), Some(key) => for (relay_parent, collation) in self.local_collations.note_validator_role(key, role) { send_polkadot_message( @@ -483,7 +483,7 @@ impl Specialization<Block> for PolkadotProtocol { if let Some((ref acc_id, ref para_id)) = local_status.collating_for { if self.collator_peer_id(acc_id.clone()).is_some() { - ctx.disconnect_peer(peer_id); + ctx.report_peer(peer_id, Severity::Useless("Unknown Polkadot-specific reason")); return } @@ -571,7 +571,7 @@ impl Specialization<Block> for PolkadotProtocol { Some(msg) => self.on_polkadot_message(ctx, peer_id, raw, msg), None => { trace!(target: "p_net", "Bad message from {}", peer_id); - ctx.disable_peer(peer_id, "Invalid polkadot protocol message format"); + ctx.report_peer(peer_id, Severity::Bad("Invalid polkadot protocol message format")); } } } @@ -616,15 +616,15 @@ impl PolkadotProtocol { let collated_acc = collation.receipt.collator; match self.peers.get(&from) { - None => ctx.disconnect_peer(from), + None => ctx.report_peer(from, Severity::Useless("Unknown Polkadot specific reason")), Some(peer_info) => match peer_info.collating_for { - None => ctx.disable_peer(from, "Sent collation without registering collator intent"), + None => ctx.report_peer(from, Severity::Bad("Sent collation without registering collator intent")), Some((ref acc_id, ref para_id)) => { let structurally_valid = para_id == &collation_para && acc_id == &collated_acc; if structurally_valid && collation.receipt.check_signature().is_ok() { self.collators.on_collation(acc_id.clone(), relay_parent, collation) } else { - ctx.disable_peer(from, "Sent malformed collation") + ctx.report_peer(from, Severity::Bad("Sent malformed collation")) }; } }, @@ -654,7 +654,7 @@ impl PolkadotProtocol { // disconnect a collator by account-id. fn disconnect_bad_collator(&self, ctx: &mut Context<Block>, account_id: AccountId) { if let Some(peer_id) = self.collator_peer_id(account_id) { - ctx.disable_peer(peer_id, "Consensus layer determined the given collator misbehaved") + ctx.report_peer(peer_id, Severity::Bad("Consensus layer determined the given collator misbehaved")) } } } diff --git a/substrate/polkadot/network/src/tests.rs b/substrate/polkadot/network/src/tests.rs index 021ea739b1b7f5c5bbf20f7705d1634677067903..6d7fde3fe51236960a4b2e47ea30789d65cccdea 100644 --- a/substrate/polkadot/network/src/tests.rs +++ b/substrate/polkadot/network/src/tests.rs @@ -24,7 +24,7 @@ use polkadot_primitives::{Block, Hash, SessionKey}; use polkadot_primitives::parachain::{CandidateReceipt, HeadData, BlockData}; use substrate_primitives::H512; use codec::Encode; -use substrate_network::{PeerId, PeerInfo, ClientHandle, Context, Roles, message::Message as SubstrateMessage, specialization::Specialization, generic_message::Message as GenericMessage}; +use substrate_network::{Severity, PeerId, PeerInfo, ClientHandle, Context, Roles, message::Message as SubstrateMessage, specialization::Specialization, generic_message::Message as GenericMessage}; use std::sync::Arc; use futures::Future; @@ -41,12 +41,11 @@ impl Context<Block> for TestContext { unimplemented!() } - fn disable_peer(&mut self, peer: PeerId, _reason: &str) { - self.disabled.push(peer); - } - - fn disconnect_peer(&mut self, peer: PeerId) { - self.disconnected.push(peer); + fn report_peer(&mut self, peer: PeerId, reason: Severity) { + match reason { + Severity::Bad(_) => self.disabled.push(peer), + _ => self.disconnected.push(peer), + } } fn peer_info(&self, _peer: PeerId) -> Option<PeerInfo<Block>> { diff --git a/substrate/substrate/network-libp2p/src/connection_filter.rs b/substrate/substrate/network-libp2p/src/connection_filter.rs index e146aee4c7c6aed553674c3c5ae96c51ba7e0302..46d9d86b58d33da1a22a1ad07f66224e8ddab6b5 100644 --- a/substrate/substrate/network-libp2p/src/connection_filter.rs +++ b/substrate/substrate/network-libp2p/src/connection_filter.rs @@ -1,18 +1,18 @@ // Copyright 2015-2018 Parity Technologies (UK) Ltd. -// This file is part of Parity. +// This file is part of Substrate. -// Parity is free software: you can redistribute it and/or modify +// Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Parity is distributed in the hope that it will be useful, +// Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License -// along with Parity. If not, see <http://www.gnu.org/licenses/>. +// along with Substrate. If not, see <http://www.gnu.org/licenses/>. //! Connection filter trait. diff --git a/substrate/substrate/network-libp2p/src/custom_proto.rs b/substrate/substrate/network-libp2p/src/custom_proto.rs index 685aeae95cde20bdb626e37912e84446714177ac..77d2fdec3e1f38206cd973b4b16b8386cf43af26 100644 --- a/substrate/substrate/network-libp2p/src/custom_proto.rs +++ b/substrate/substrate/network-libp2p/src/custom_proto.rs @@ -1,18 +1,18 @@ // Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Polkadot is distributed in the hope that it will be useful, +// Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.? +// along with Substrate. If not, see <http://www.gnu.org/licenses/>.? use bytes::{Bytes, BytesMut}; use ProtocolId; @@ -122,6 +122,7 @@ where C: AsyncRead + AsyncWrite + 'static, // TODO: 'static :-/ type MultiaddrFuture = Maf; type Future = future::FutureResult<(Self::Output, Self::MultiaddrFuture), IoError>; + #[allow(deprecated)] fn upgrade( self, socket: C, diff --git a/substrate/substrate/network-libp2p/src/error.rs b/substrate/substrate/network-libp2p/src/error.rs index b60ca6f70697a8deea33c252066d12a459b8c754..d095858b12203cad635d3c83076764792ef1fd2b 100644 --- a/substrate/substrate/network-libp2p/src/error.rs +++ b/substrate/substrate/network-libp2p/src/error.rs @@ -1,18 +1,18 @@ // Copyright 2015-2018 Parity Technologies (UK) Ltd. -// This file is part of Parity. +// This file is part of Substrate. -// Parity is free software: you can redistribute it and/or modify +// Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Parity is distributed in the hope that it will be useful, +// Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License -// along with Parity. If not, see <http://www.gnu.org/licenses/>. +// along with Substrate. If not, see <http://www.gnu.org/licenses/>. use std::{io, net, fmt}; use libc::{ENFILE, EMFILE}; diff --git a/substrate/substrate/network-libp2p/src/lib.rs b/substrate/substrate/network-libp2p/src/lib.rs index b428ca6ceb408f1323ceac95ac1fe1f5282502ed..5e4b7f309382728a089357a89ebb88bbf7ebeb57 100644 --- a/substrate/substrate/network-libp2p/src/lib.rs +++ b/substrate/substrate/network-libp2p/src/lib.rs @@ -1,18 +1,18 @@ // Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Polkadot is distributed in the hope that it will be useful, +// Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.? +// along with Substrate. If not, see <http://www.gnu.org/licenses/>.? #![recursion_limit="128"] #![type_length_limit = "268435456"] diff --git a/substrate/substrate/network-libp2p/src/network_state.rs b/substrate/substrate/network-libp2p/src/network_state.rs index 00b97eecf9a8200db12c4ea151f15a46ade05c9f..789482554d12d22a61755ac4a199f5305c3ad181 100644 --- a/substrate/substrate/network-libp2p/src/network_state.rs +++ b/substrate/substrate/network-libp2p/src/network_state.rs @@ -1,18 +1,18 @@ // Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Polkadot is distributed in the hope that it will be useful, +// Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.? +// along with Substrate. If not, see <http://www.gnu.org/licenses/>.? use bytes::Bytes; use fnv::{FnvHashMap, FnvHashSet}; @@ -126,6 +126,45 @@ struct PeerConnectionInfo { local_address: Option<Multiaddr>, } +/// Simplified, POD version of PeerConnectionInfo. +#[derive(Debug, Clone)] +pub struct PeerInfo { + /// Id of the peer. + pub id: PeerstorePeerId, + + /// True if this connection was initiated by us. + /// Note that it is theoretically possible that we dial the remote at the + /// same time they dial us, in which case the protocols may be dispatched + /// between both connections, and in which case the value here will be racy. + pub originated: bool, + + /// Latest known ping duration. + pub ping: Option<Duration>, + + /// The client version of the remote, or `None` if not known. + pub client_version: Option<String>, + + /// The multiaddress of the remote, or `None` if not known. + pub remote_address: Option<Multiaddr>, + + /// The local multiaddress used to communicate with the remote, or `None` + /// if not known. + pub local_address: Option<Multiaddr>, +} + +impl<'a> From<&'a PeerConnectionInfo> for PeerInfo { + fn from(i: &'a PeerConnectionInfo) -> PeerInfo { + PeerInfo { + id: i.id.clone(), + originated: i.originated, + ping: i.ping.lock().clone(), + client_version: i.client_version.clone(), + remote_address: i.remote_address.clone(), + local_address: i.local_address.clone(), + } + } +} + impl NetworkState { pub fn new(config: &NetworkConfiguration) -> Result<NetworkState, Error> { // Private and public keys configuration. @@ -581,24 +620,37 @@ impl NetworkState { } else { // We are connected to this peer, but not with the current // protocol. - debug!(target: "sub-libp2p", "Tried to send message to peer {} \ - for which we aren't connected with the requested protocol", - peer_id); + debug!(target: "sub-libp2p", + "Tried to send message to peer {} for which we aren't connected with the requested protocol", + peer_id + ); return Err(ErrorKind::PeerNotFound.into()) } } else { - debug!(target: "sub-libp2p", "Tried to send message to invalid \ - peer ID {}", peer_id); + debug!(target: "sub-libp2p", "Tried to send message to invalid peer ID {}", peer_id); return Err(ErrorKind::PeerNotFound.into()) } } + /// Get the info on a peer, if there's an active connection. + pub fn peer_info(&self, who: PeerId) -> Option<PeerInfo> { + self.connections.read().info_by_peer.get(&who).map(Into::into) + } + /// Disconnects a peer, if a connection exists (ie. drops the Kademlia /// controller, and the senders that were stored in the `UniqueConnec` of /// `custom_proto`). - pub fn disconnect_peer(&self, peer_id: PeerId) { + pub fn drop_peer(&self, peer_id: PeerId, reason: Option<&str>) { let mut connections = self.connections.write(); if let Some(peer_info) = connections.info_by_peer.remove(&peer_id) { + if let Some(reason) = reason { + if let (&Some(ref client_version), &Some(ref remote_address)) = (&peer_info.client_version, &peer_info.remote_address) { + debug!(target: "sub-libp2p", "Disconnected peer {} (version: {}, address: {}). {}", peer_id, client_version, remote_address, reason); + } else { + debug!(target: "sub-libp2p", "Disconnected peer {}. {}", peer_id, reason); + } + } + trace!(target: "sub-libp2p", "Destroying peer #{} {:?} ; \ kademlia = {:?} ; num_protos = {:?}", peer_id, peer_info.id, peer_info.kad_connec.is_alive(), diff --git a/substrate/substrate/network-libp2p/src/service.rs b/substrate/substrate/network-libp2p/src/service.rs index 23958cca5aaef31f2eedb1142a7bb90c4edc448f..bc1dcc5d035022dc55169f00bc2ac72a1142baab 100644 --- a/substrate/substrate/network-libp2p/src/service.rs +++ b/substrate/substrate/network-libp2p/src/service.rs @@ -1,22 +1,22 @@ // Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Polkadot is distributed in the hope that it will be useful, +// Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.? +// along with Substrate. If not, see <http://www.gnu.org/licenses/>.? use bytes::Bytes; use {Error, ErrorKind, NetworkConfiguration, NetworkProtocolHandler}; -use {NonReservedPeerMode, NetworkContext, PeerId, ProtocolId}; +use {NonReservedPeerMode, NetworkContext, Severity, PeerId, ProtocolId}; use parking_lot::{Mutex, RwLock}; use libp2p; use libp2p::multiaddr::{AddrComponent, Multiaddr}; @@ -299,8 +299,7 @@ struct NetworkContextImpl { } impl NetworkContext for NetworkContextImpl { - fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>) - -> Result<(), Error> { + fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>) { self.send_protocol(self.protocol, peer, packet_id, data) } @@ -310,7 +309,7 @@ impl NetworkContext for NetworkContextImpl { peer: PeerId, packet_id: PacketId, data: Vec<u8> - ) -> Result<(), Error> { + ) { debug_assert!(self.inner.protocols.read().has_protocol(protocol), "invalid protocol id requested in the API of the libp2p networking"); // TODO: could be "optimized" by building `message` only after checking the validity of @@ -318,10 +317,12 @@ impl NetworkContext for NetworkContextImpl { let mut message = Bytes::with_capacity(1 + data.len()); message.extend_from_slice(&[packet_id]); message.extend_from_slice(&data); - self.inner.network_state.send(protocol, peer, message) + if self.inner.network_state.send(protocol, peer, message).is_err() { + self.inner.network_state.drop_peer(peer, Some("Sending to peer failed")); + } } - fn respond(&self, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> { + fn respond(&self, packet_id: PacketId, data: Vec<u8>) { if let Some(peer) = self.current_peer { self.send_protocol(self.protocol, peer, packet_id, data) } else { @@ -329,14 +330,19 @@ impl NetworkContext for NetworkContextImpl { } } - fn disable_peer(&self, peer: PeerId, reason: &str) { - debug!(target: "sub-libp2p", "Request to disable peer {} for reason {}", peer, reason); - self.inner.network_state.disable_peer(peer, reason); - } - - fn disconnect_peer(&self, peer: PeerId) { - debug!(target: "sub-libp2p", "Request to disconnect peer {}", peer); - self.inner.network_state.disconnect_peer(peer); + fn report_peer(&self, peer: PeerId, reason: Severity) { + if let Some(info) = self.inner.network_state.peer_info(peer) { + if let (Some(client_version), Some(remote_address)) = (info.client_version, info.remote_address) { + info!(target: "sub-libp2p", "Peer {} ({} {}) reported by client: {}", peer, remote_address, client_version, reason); + } else { + info!(target: "sub-libp2p", "Peer {} reported by client: {}", peer, reason); + } + } + match reason { + Severity::Bad(reason) => self.inner.network_state.disable_peer(peer, reason), + Severity::Useless(reason) => self.inner.network_state.drop_peer(peer, Some(reason)), + Severity::Timeout => self.inner.network_state.drop_peer(peer, Some("Timeout waiting for response")), + } } fn is_expired(&self) -> bool { @@ -768,9 +774,12 @@ fn handle_custom_connection( impl Drop for ProtoDisconnectGuard { fn drop(&mut self) { - debug!(target: "sub-libp2p", "Node {:?} with peer ID {} \ - through protocol {:?} disconnected", self.node_id, self.peer_id, - self.protocol); + debug!(target: "sub-libp2p", + "Node {:?} with peer ID {} through protocol {:?} disconnected", + self.node_id, + self.peer_id, + self.protocol + ); self.handler.disconnected(&NetworkContextImpl { inner: self.inner.clone(), protocol: self.protocol, @@ -779,7 +788,7 @@ fn handle_custom_connection( // When any custom protocol drops, we drop the peer entirely. // TODO: is this correct? - self.inner.network_state.disconnect_peer(self.peer_id); + self.inner.network_state.drop_peer(self.peer_id, Some("Remote end disconnected")); } } @@ -1271,8 +1280,7 @@ fn ping_all<T, St, C>( let fut = pinger .get_or_dial(&swarm_controller, &addr, transport.clone()) .and_then(move |mut p| { - trace!(target: "sub-libp2p", - "Pinging peer #{} aka. {:?}", peer, peer_id); + trace!(target: "sub-libp2p", "Pinging peer #{} aka. {:?}", peer, peer_id); p.ping() .map(|()| peer_id) .map_err(|err| IoError::new(IoErrorKind::Other, err)) @@ -1282,16 +1290,14 @@ fn ping_all<T, St, C>( .then(move |val| match val { Err(err) => { - trace!(target: "sub-libp2p", - "Error while pinging #{:?} => {:?}", peer, err); - shared.network_state.disconnect_peer(peer); + trace!(target: "sub-libp2p", "Error while pinging #{:?} => {:?}", peer, err); + shared.network_state.drop_peer(peer, None); // None so that we don't print messages on such low-level issues. // Return Ok, otherwise we would close the ping service Ok(()) }, Ok(peer_id) => { let elapsed = ping_start_time.elapsed(); - trace!(target: "sub-libp2p", "Pong from #{:?} in {:?}", - peer, elapsed); + trace!(target: "sub-libp2p", "Pong from #{:?} in {:?}", peer, elapsed); shared.network_state.report_ping_duration(peer, elapsed); shared.kad_system.update_kbuckets(peer_id); Ok(()) diff --git a/substrate/substrate/network-libp2p/src/timeouts.rs b/substrate/substrate/network-libp2p/src/timeouts.rs index 12e16f34d8f5eb386cd2623c1d34b74772040839..eb3fecb2a0f36a77e658b15f432224a970942133 100644 --- a/substrate/substrate/network-libp2p/src/timeouts.rs +++ b/substrate/substrate/network-libp2p/src/timeouts.rs @@ -1,18 +1,18 @@ // Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Polkadot is distributed in the hope that it will be useful, +// Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.? +// along with Substrate. If not, see <http://www.gnu.org/licenses/>.? use futures::{Async, future, Future, Poll, stream, Stream, sync::mpsc}; use std::io::Error as IoError; diff --git a/substrate/substrate/network-libp2p/src/traits.rs b/substrate/substrate/network-libp2p/src/traits.rs index a20065328d97c00a41e2d18d9c40e47ed938850c..fac9f1915a9505d5e6c21ab14381b5239f2091ca 100644 --- a/substrate/substrate/network-libp2p/src/traits.rs +++ b/substrate/substrate/network-libp2p/src/traits.rs @@ -1,19 +1,20 @@ // Copyright 2015-2018 Parity Technologies (UK) Ltd. -// This file is part of Parity. +// This file is part of Substrate. -// Parity is free software: you can redistribute it and/or modify +// Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Parity is distributed in the hope that it will be useful, +// Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License -// along with Parity. If not, see <http://www.gnu.org/licenses/>. +// along with Substrate. If not, see <http://www.gnu.org/licenses/>. +use std::fmt; use std::cmp::Ordering; use std::collections::HashMap; use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; @@ -213,22 +214,42 @@ impl NetworkConfiguration { } } +/// The severity of misbehaviour of a peer that is reported. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Severity<'a> { + /// Peer is timing out. Could be bad connectivity of overload of work on either of our sides. + Timeout, + /// Peer has been notably useless. E.g. unable to answer a request that we might reasonably consider + /// it could answer. + Useless(&'a str), + /// Peer has behaved in an invalid manner. This doesn't necessarily need to be Byzantine, but peer + /// must have taken concrete action in order to behave in such a way which is wantanly invalid. + Bad(&'a str), +} + +impl<'a> fmt::Display for Severity<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + Severity::Timeout => write!(fmt, "Timeout"), + Severity::Useless(r) => write!(fmt, "Useless ({})", r), + Severity::Bad(r) => write!(fmt, "Bad ({})", r), + } + } +} + /// IO access point. This is passed to all IO handlers and provides an interface to the IO subsystem. pub trait NetworkContext { /// Send a packet over the network to another peer. - fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error>; + fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>); /// Send a packet over the network to another peer using specified protocol. - fn send_protocol(&self, protocol: ProtocolId, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error>; + fn send_protocol(&self, protocol: ProtocolId, peer: PeerId, packet_id: PacketId, data: Vec<u8>); /// Respond to a current network message. Panics if no there is no packet in the context. If the session is expired returns nothing. - fn respond(&self, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error>; + fn respond(&self, packet_id: PacketId, data: Vec<u8>); - /// Disconnect a peer and prevent it from connecting again. - fn disable_peer(&self, peer: PeerId, reason: &str); - - /// Disconnect peer. Reconnect can be attempted later. - fn disconnect_peer(&self, peer: PeerId); + /// Report peer. Depending on the report, peer may be disconnected and possibly banned. + fn report_peer(&self, peer: PeerId, reason: Severity); /// Check if the session is still active. fn is_expired(&self) -> bool; @@ -250,24 +271,20 @@ pub trait NetworkContext { } impl<'a, T> NetworkContext for &'a T where T: ?Sized + NetworkContext { - fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> { + fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>) { (**self).send(peer, packet_id, data) } - fn send_protocol(&self, protocol: ProtocolId, peer: PeerId, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> { + fn send_protocol(&self, protocol: ProtocolId, peer: PeerId, packet_id: PacketId, data: Vec<u8>) { (**self).send_protocol(protocol, peer, packet_id, data) } - fn respond(&self, packet_id: PacketId, data: Vec<u8>) -> Result<(), Error> { + fn respond(&self, packet_id: PacketId, data: Vec<u8>) { (**self).respond(packet_id, data) } - fn disable_peer(&self, peer: PeerId, reason: &str) { - (**self).disable_peer(peer, reason) - } - - fn disconnect_peer(&self, peer: PeerId) { - (**self).disconnect_peer(peer) + fn report_peer(&self, peer: PeerId, reason: Severity) { + (**self).report_peer(peer, reason) } fn is_expired(&self) -> bool { @@ -333,42 +350,42 @@ impl NonReservedPeerMode { #[derive(Clone, Debug, PartialEq, Eq)] pub struct IpFilter { - pub predefined: AllowIP, - pub custom_allow: Vec<IpNetwork>, - pub custom_block: Vec<IpNetwork>, + pub predefined: AllowIP, + pub custom_allow: Vec<IpNetwork>, + pub custom_block: Vec<IpNetwork>, } impl Default for IpFilter { - fn default() -> Self { - IpFilter { - predefined: AllowIP::All, - custom_allow: vec![], - custom_block: vec![], - } - } + fn default() -> Self { + IpFilter { + predefined: AllowIP::All, + custom_allow: vec![], + custom_block: vec![], + } + } } impl IpFilter { - /// Attempt to parse the peer mode from a string. - pub fn parse(s: &str) -> Result<IpFilter, IpNetworkError> { - let mut filter = IpFilter::default(); - for f in s.split_whitespace() { - match f { - "all" => filter.predefined = AllowIP::All, - "private" => filter.predefined = AllowIP::Private, - "public" => filter.predefined = AllowIP::Public, - "none" => filter.predefined = AllowIP::None, - custom => { - if custom.starts_with("-") { - filter.custom_block.push(IpNetwork::from_str(&custom.to_owned().split_off(1))?) - } else { - filter.custom_allow.push(IpNetwork::from_str(custom)?) - } - } - } - } - Ok(filter) - } + /// Attempt to parse the peer mode from a string. + pub fn parse(s: &str) -> Result<IpFilter, IpNetworkError> { + let mut filter = IpFilter::default(); + for f in s.split_whitespace() { + match f { + "all" => filter.predefined = AllowIP::All, + "private" => filter.predefined = AllowIP::Private, + "public" => filter.predefined = AllowIP::Public, + "none" => filter.predefined = AllowIP::None, + custom => { + if custom.starts_with("-") { + filter.custom_block.push(IpNetwork::from_str(&custom.to_owned().split_off(1))?) + } else { + filter.custom_allow.push(IpNetwork::from_str(custom)?) + } + } + } + } + Ok(filter) + } } /// IP fiter @@ -380,6 +397,6 @@ pub enum AllowIP { Private, /// Connect to public network only Public, - /// Block all addresses - None, + /// Block all addresses + None, } diff --git a/substrate/substrate/network-libp2p/src/transport.rs b/substrate/substrate/network-libp2p/src/transport.rs index 82b7a9a5fc406144fc641cdd6bfa6a123bf86e59..bbcce3de4fdf5b196d00e5913690586052a1e4d9 100644 --- a/substrate/substrate/network-libp2p/src/transport.rs +++ b/substrate/substrate/network-libp2p/src/transport.rs @@ -1,18 +1,18 @@ // Copyright 2018 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. +// This file is part of Substrate. -// Polkadot is free software: you can redistribute it and/or modify +// Substrate is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// Polkadot is distributed in the hope that it will be useful, +// Substrate is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.? +// along with Substrate. If not, see <http://www.gnu.org/licenses/>.? use libp2p::{self, Transport, mplex, secio, yamux}; use libp2p::core::{MuxedTransport, either, upgrade}; diff --git a/substrate/substrate/network-libp2p/tests/tests.rs b/substrate/substrate/network-libp2p/tests/tests.rs index 1cd9456127dd60eff40bf721aa5525689568a415..c7c98d877535afbc3139f0ae29ff7210d3d5d463 100644 --- a/substrate/substrate/network-libp2p/tests/tests.rs +++ b/substrate/substrate/network-libp2p/tests/tests.rs @@ -73,9 +73,9 @@ impl NetworkProtocolHandler for TestProtocol { fn connected(&self, io: &NetworkContext, peer: &PeerId) { if self.drop_session { - io.disconnect_peer(*peer) + io.report_peer(*peer, Severity::Bad("We are evil and just want to drop")) } else { - io.respond(33, "hello".to_owned().into_bytes()).unwrap(); + io.respond(33, "hello".to_owned().into_bytes()); } } diff --git a/substrate/substrate/network/src/import_queue.rs b/substrate/substrate/network/src/import_queue.rs index 308a68fffd3b067a710b54e86c9972566afa83d2..585bbae5c1a70f0b1c2ee13803e6db1b83a8e917 100644 --- a/substrate/substrate/network/src/import_queue.rs +++ b/substrate/substrate/network/src/import_queue.rs @@ -22,7 +22,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use parking_lot::{Condvar, Mutex, RwLock}; use client::{BlockOrigin, BlockStatus, ImportResult}; -use network_libp2p::PeerId; +use network_libp2p::{PeerId, Severity}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero}; @@ -202,9 +202,9 @@ trait SyncLinkApi<B: BlockT> { /// Maintain sync. fn maintain_sync(&mut self); /// Disconnect from peer. - fn disconnect(&mut self, peer_id: PeerId); + fn useless_peer(&mut self, peer_id: PeerId, reason: &str); /// Disconnect from peer and restart sync. - fn disconnect_and_restart(&mut self, peer_id: PeerId); + fn note_useless_and_restart_sync(&mut self, peer_id: PeerId, reason: &str); /// Restart sync. fn restart(&mut self); } @@ -357,11 +357,15 @@ fn process_import_result<'a, B: BlockT>( 1 }, Err(BlockImportError::Disconnect(peer_id)) => { - link.disconnect(peer_id); + // TODO: FIXME: @arkpar BlockImport shouldn't be trying to manage the peer set. + // This should contain an actual reason. + link.useless_peer(peer_id, "Import result was stated Disconnect"); 0 }, Err(BlockImportError::DisconnectAndRestart(peer_id)) => { - link.disconnect_and_restart(peer_id); + // TODO: FIXME: @arkpar BlockImport shouldn't be trying to manage the peer set. + // This should contain an actual reason. + link.note_useless_and_restart_sync(peer_id, "Import result was stated DisconnectAndRestart"); 0 }, Err(BlockImportError::Restart) => { @@ -404,13 +408,13 @@ impl<'a, B: 'static + BlockT, E: ExecuteInContext<B>> SyncLinkApi<B> for SyncLin self.with_sync(|sync, protocol| sync.maintain_sync(protocol)) } - fn disconnect(&mut self, peer_id: PeerId) { - self.with_sync(|_, protocol| protocol.disconnect_peer(peer_id)) + fn useless_peer(&mut self, peer_id: PeerId, reason: &str) { + self.with_sync(|_, protocol| protocol.report_peer(peer_id, Severity::Useless(reason))) } - fn disconnect_and_restart(&mut self, peer_id: PeerId) { + fn note_useless_and_restart_sync(&mut self, peer_id: PeerId, reason: &str) { self.with_sync(|sync, protocol| { - protocol.disconnect_peer(peer_id); + protocol.report_peer(peer_id, Severity::Useless(reason)); // is this actually malign or just useless? sync.restart(protocol); }) } @@ -486,8 +490,8 @@ pub mod tests { fn chain(&self) -> &Client<Block> { &*self.chain } fn block_imported(&mut self, _hash: &Hash, _number: NumberFor<Block>) { self.imported += 1; } fn maintain_sync(&mut self) { self.maintains += 1; } - fn disconnect(&mut self, _peer_id: PeerId) { self.disconnects += 1; } - fn disconnect_and_restart(&mut self, _peer_id: PeerId) { self.disconnects += 1; self.restarts += 1; } + fn useless_peer(&mut self, _: PeerId, _: &str) { self.disconnects += 1; } + fn note_useless_and_restart_sync(&mut self, _: PeerId, _: &str) { self.disconnects += 1; self.restarts += 1; } fn restart(&mut self) { self.restarts += 1; } } diff --git a/substrate/substrate/network/src/io.rs b/substrate/substrate/network/src/io.rs index 757a539fd0ad1cbc1f95025c43267481cc35ed4a..d38827bee62ab8e71d1a15fac9f6848728e3449f 100644 --- a/substrate/substrate/network/src/io.rs +++ b/substrate/substrate/network/src/io.rs @@ -14,17 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see <http://www.gnu.org/licenses/>.? -use network_libp2p::{NetworkContext, PeerId, Error as NetworkError, SessionInfo}; +use network_libp2p::{NetworkContext, Severity, PeerId, SessionInfo}; /// IO interface for the syncing handler. /// Provides peer connection management and an interface to the blockchain client. pub trait SyncIo { - /// Disable a peer - fn disable_peer(&mut self, peer_id: PeerId, reason: &str); - /// Disconnect peer - fn disconnect_peer(&mut self, peer_id: PeerId); + /// Report a peer for misbehaviour. + fn report_peer(&mut self, peer_id: PeerId, reason: Severity); /// Send a packet to a peer. - fn send(&mut self, peer_id: PeerId, data: Vec<u8>) -> Result<(), NetworkError>; + fn send(&mut self, peer_id: PeerId, data: Vec<u8>); /// Returns peer identifier string fn peer_info(&self, peer_id: PeerId) -> String { peer_id.to_string() @@ -50,15 +48,11 @@ impl<'s> NetSyncIo<'s> { } impl<'s> SyncIo for NetSyncIo<'s> { - fn disable_peer(&mut self, peer_id: PeerId, reason: &str) { - self.network.disable_peer(peer_id, reason); + fn report_peer(&mut self, peer_id: PeerId, reason: Severity) { + self.network.report_peer(peer_id, reason); } - fn disconnect_peer(&mut self, peer_id: PeerId) { - self.network.disconnect_peer(peer_id); - } - - fn send(&mut self, peer_id: PeerId, data: Vec<u8>) -> Result<(), NetworkError>{ + fn send(&mut self, peer_id: PeerId, data: Vec<u8>) { self.network.send(peer_id, 0, data) } diff --git a/substrate/substrate/network/src/lib.rs b/substrate/substrate/network/src/lib.rs index 2bb025a83511383f65e11c03b0d9280531ef4273..8ea6ca3db94e16b46fac86141e3909ca9334de19 100644 --- a/substrate/substrate/network/src/lib.rs +++ b/substrate/substrate/network/src/lib.rs @@ -59,7 +59,7 @@ pub use service::{Service, FetchFuture, ConsensusService, BftMessageStream, TransactionPool, Params, ManageNetwork, SyncProvider}; pub use protocol::{ProtocolStatus, PeerInfo, Context}; pub use sync::{Status as SyncStatus, SyncState}; -pub use network_libp2p::{NonReservedPeerMode, NetworkConfiguration, PeerId, ProtocolId, ConnectionFilter, ConnectionDirection}; +pub use network_libp2p::{NonReservedPeerMode, NetworkConfiguration, PeerId, ProtocolId, ConnectionFilter, ConnectionDirection, Severity}; pub use message::{generic as generic_message, RequestId, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal, Status as StatusMessage}; pub use error::Error; pub use config::{Roles, ProtocolConfig}; diff --git a/substrate/substrate/network/src/on_demand.rs b/substrate/substrate/network/src/on_demand.rs index 054b8356254c2f11f00bf56042f6a2c88f9881ca..9689a3f39d90fd841faadb6f9c104adf2c4823ab 100644 --- a/substrate/substrate/network/src/on_demand.rs +++ b/substrate/substrate/network/src/on_demand.rs @@ -28,7 +28,7 @@ use client; use client::light::fetcher::{Fetcher, FetchChecker, RemoteCallRequest}; use io::SyncIo; use message; -use network_libp2p::PeerId; +use network_libp2p::{Severity, PeerId}; use service; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT}; @@ -137,8 +137,7 @@ impl<B: BlockT, E> OnDemand<B, E> where let request = match core.remove(peer, request_id) { Some(request) => request, None => { - trace!(target: "sync", "Invalid remote {} response from peer {}", rtype, peer); - io.disconnect_peer(peer); + io.report_peer(peer, Severity::Bad(&format!("Invalid remote {} response from peer", rtype))); core.remove_peer(peer); return; }, @@ -147,9 +146,7 @@ impl<B: BlockT, E> OnDemand<B, E> where let retry_request_data = match try_accept(request) { Accept::Ok => None, Accept::CheckFailed(error, retry_request_data) => { - trace!(target: "sync", "Failed to check remote {} response from peer {}: {}", rtype, peer, error); - - io.disconnect_peer(peer); + io.report_peer(peer, Severity::Bad(&format!("Failed to check remote {} response from peer: {}", rtype, error))); core.remove_peer(peer); Some(retry_request_data) }, @@ -187,8 +184,7 @@ impl<B, E> OnDemandService<B> for OnDemand<B, E> where fn maintain_peers(&self, io: &mut SyncIo) { let mut core = self.core.lock(); for bad_peer in core.maintain_peers() { - trace!(target: "sync", "Remote request timeout for peer {}", bad_peer); - io.disconnect_peer(bad_peer); + io.report_peer(bad_peer, Severity::Timeout); } core.dispatch(); } diff --git a/substrate/substrate/network/src/protocol.rs b/substrate/substrate/network/src/protocol.rs index 6bc20af5b86a08ffc85703e3eed301eae4640f0a..f09ca9c37e4509c7da9cc691aa0c2030bec52fc0 100644 --- a/substrate/substrate/network/src/protocol.rs +++ b/substrate/substrate/network/src/protocol.rs @@ -21,7 +21,7 @@ use std::time; use parking_lot::RwLock; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash, HashFor, As}; use runtime_primitives::generic::BlockId; -use network_libp2p::PeerId; +use network_libp2p::{PeerId, Severity}; use codec::{Encode, Decode}; use message::{self, Message}; @@ -43,7 +43,6 @@ pub (crate) const CURRENT_VERSION: u32 = 1; /// Current packet count. pub (crate) const CURRENT_PACKET_COUNT: u8 = 1; - // Maximum allowed entries in `BlockResponse` const MAX_BLOCK_DATA_RESPONSE: u32 = 128; @@ -110,11 +109,8 @@ pub trait Context<B: BlockT> { /// Get a reference to the client. fn client(&self) -> &::chain::Client<B>; - /// Disable a peer - fn disable_peer(&mut self, peer_id: PeerId, reason: &str); - - /// Disconnect peer - fn disconnect_peer(&mut self, peer_id: PeerId); + /// Point out that a peer has been malign or irresponsible or appeared lazy. + fn report_peer(&mut self, peer_id: PeerId, reason: Severity); /// Get peer info. fn peer_info(&self, peer: PeerId) -> Option<PeerInfo<B>>; @@ -142,12 +138,9 @@ impl<'a, B: BlockT + 'a> ProtocolContext<'a, B> { send_message(&self.context_data.peers, self.io, peer_id, message) } - pub fn disable_peer(&mut self, peer_id: PeerId, reason: &str) { - self.io.disable_peer(peer_id, reason); - } - - pub fn disconnect_peer(&mut self, peer_id: PeerId) { - self.io.disconnect_peer(peer_id) + /// Point out that a peer has been malign or irresponsible or appeared lazy. + pub fn report_peer(&mut self, peer_id: PeerId, reason: Severity) { + self.io.report_peer(peer_id, reason); } /// Get peer info. @@ -168,12 +161,8 @@ impl<'a, B: BlockT + 'a> Context<B> for ProtocolContext<'a, B> { ProtocolContext::send_message(self, peer_id, message); } - fn disable_peer(&mut self, peer_id: PeerId, reason: &str) { - ProtocolContext::disable_peer(self, peer_id, reason); - } - - fn disconnect_peer(&mut self, peer_id: PeerId) { - ProtocolContext::disconnect_peer(self, peer_id); + fn report_peer(&mut self, peer_id: PeerId, reason: Severity) { + ProtocolContext::report_peer(self, peer_id, reason); } fn peer_info(&self, peer_id: PeerId) -> Option<PeerInfo<B>> { @@ -244,7 +233,7 @@ impl<B: BlockT, S: Specialization<B>> Protocol<B, S> { Some(m) => m, None => { trace!(target: "sync", "Invalid packet from {}", peer_id); - io.disable_peer(peer_id, "Peer sent us a packet with invalid format"); + io.report_peer(peer_id, Severity::Bad("Peer sent us a packet with invalid format")); return; } }; @@ -260,12 +249,12 @@ impl<B: BlockT, S: Specialization<B>> Protocol<B, S> { match mem::replace(&mut peer.block_request, None) { Some(r) => r, None => { - io.disable_peer(peer_id, "Unexpected response packet received from peer"); + io.report_peer(peer_id, Severity::Bad("Unexpected response packet received from peer")); return; } } } else { - io.disable_peer(peer_id, "Unexpected packet received from peer"); + io.report_peer(peer_id, Severity::Bad("Unexpected packet received from peer")); return; } }; @@ -385,7 +374,6 @@ impl<B: BlockT, S: Specialization<B>> Protocol<B, S> { .chain(handshaking_peers.iter()) { if (tick - *timestamp).as_secs() > REQUEST_TIMEOUT_SEC { trace!(target: "sync", "Timeout {}", peer_id); - io.disconnect_peer(*peer_id); aborting.push(*peer_id); } } @@ -393,7 +381,7 @@ impl<B: BlockT, S: Specialization<B>> Protocol<B, S> { self.specialization.write().maintain_peers(&mut ProtocolContext::new(&self.context_data, io)); for p in aborting { - io.disconnect_peer(p); + io.report_peer(p, Severity::Timeout); } } @@ -424,11 +412,11 @@ impl<B: BlockT, S: Specialization<B>> Protocol<B, S> { return; } if status.genesis_hash != self.genesis_hash { - io.disable_peer(peer_id, &format!("Peer is on different chain (our genesis: {} theirs: {})", self.genesis_hash, status.genesis_hash)); + io.report_peer(peer_id, Severity::Bad(&format!("Peer is on different chain (our genesis: {} theirs: {})", self.genesis_hash, status.genesis_hash))); return; } if status.version != CURRENT_VERSION { - io.disable_peer(peer_id, &format!("Peer using unsupported protocol version {}", status.version)); + io.report_peer(peer_id, Severity::Bad(&format!("Peer using unsupported protocol version {}", status.version))); return; } @@ -625,11 +613,7 @@ fn send_message<B: BlockT>(peers: &RwLock<HashMap<PeerId, Peer<B>>>, io: &mut Sy }, _ => (), } - let data = message.encode(); - if let Err(e) = io.send(peer_id, data) { - debug!(target:"sync", "Error sending message: {:?}", e); - io.disconnect_peer(peer_id); - } + io.send(peer_id, message.encode()); } /// Hash a message. diff --git a/substrate/substrate/network/src/sync.rs b/substrate/substrate/network/src/sync.rs index 900cf864e564af50cb1d99476659e36c3b440e2c..6096cd294a24f93f176b5c95ecd5c0dd2bc8cc3d 100644 --- a/substrate/substrate/network/src/sync.rs +++ b/substrate/substrate/network/src/sync.rs @@ -17,7 +17,7 @@ use std::collections::HashMap; use std::sync::Arc; use protocol::Context; -use network_libp2p::PeerId; +use network_libp2p::{Severity, PeerId}; use client::{BlockStatus, BlockOrigin, ClientInfo}; use client::error::Error as ClientError; use blocks::{self, BlockCollection}; @@ -124,13 +124,13 @@ impl<B: BlockT> ChainSync<B> { match (block_status(&*protocol.client(), &*self.import_queue, info.best_hash), info.best_number) { (Err(e), _) => { debug!(target:"sync", "Error reading blockchain: {:?}", e); - protocol.disconnect_peer(peer_id); + protocol.report_peer(peer_id, Severity::Useless(&format!("Error legimimately reading blockchain status: {:?}", e))); }, (Ok(BlockStatus::KnownBad), _) => { - protocol.disable_peer(peer_id, &format!("New peer with known bad best block {} ({}).", info.best_hash, info.best_number)); + protocol.report_peer(peer_id, Severity::Bad(&format!("New peer with known bad best block {} ({}).", info.best_hash, info.best_number))); }, (Ok(BlockStatus::Unknown), b) if b == As::sa(0) => { - protocol.disable_peer(peer_id, &format!("New peer with unknown genesis hash {} ({}).", info.best_hash, info.best_number)); + protocol.report_peer(peer_id, Severity::Bad(&format!("New peer with unknown genesis hash {} ({}).", info.best_hash, info.best_number))); }, (Ok(BlockStatus::Unknown), _) => { let our_best = self.best_queued_number; @@ -211,19 +211,18 @@ impl<B: BlockT> ChainSync<B> { }, Ok(_) => { // genesis mismatch trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", peer_id); - protocol.disable_peer(peer_id, "Ancestry search: genesis mismatch for peer"); + protocol.report_peer(peer_id, Severity::Bad("Ancestry search: genesis mismatch for peer")); return; }, Err(e) => { - debug!(target:"sync", "Error reading blockchain: {:?}", e); - protocol.disconnect_peer(peer_id); + protocol.report_peer(peer_id, Severity::Useless(&format!("Error answering legitimate blockchain query: {:?}", e))); return; } } }, None => { trace!(target:"sync", "Invalid response when searching for ancestor from {}", peer_id); - protocol.disconnect_peer(peer_id); + protocol.report_peer(peer_id, Severity::Bad("Invalid response when searching for ancestor")); return; } } diff --git a/substrate/substrate/network/src/test/mod.rs b/substrate/substrate/network/src/test/mod.rs index 40a4ad61d10b479f7eae72213a1f5aadfd07244d..1011d970dcb397489d238ecd68dea14a81c45424 100644 --- a/substrate/substrate/network/src/test/mod.rs +++ b/substrate/substrate/network/src/test/mod.rs @@ -28,7 +28,7 @@ use io::SyncIo; use protocol::{Context, Protocol}; use config::ProtocolConfig; use service::TransactionPool; -use network_libp2p::{PeerId, SessionInfo, Error as NetworkError}; +use network_libp2p::{PeerId, SessionInfo, Severity}; use keyring::Keyring; use codec::Encode; use import_queue::tests::SyncImportQueue; @@ -81,11 +81,7 @@ impl<'p> Drop for TestIo<'p> { } impl<'p> SyncIo for TestIo<'p> { - fn disable_peer(&mut self, peer_id: PeerId, _reason: &str) { - self.disconnect_peer(peer_id); - } - - fn disconnect_peer(&mut self, peer_id: PeerId) { + fn report_peer(&mut self, peer_id: PeerId, _reason: Severity) { self.to_disconnect.insert(peer_id); } @@ -93,12 +89,11 @@ impl<'p> SyncIo for TestIo<'p> { false } - fn send(&mut self, peer_id: PeerId, data: Vec<u8>) -> Result<(), NetworkError> { + fn send(&mut self, peer_id: PeerId, data: Vec<u8>) { self.packets.push(TestPacket { data: data, recipient: peer_id, }); - Ok(()) } fn peer_info(&self, peer_id: PeerId) -> String {