mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 20:21:06 +00:00
Refactor out disable/disconnect peer to make API more declarative (#394)
* Refactor out disable/disconnect peer to make API more declarative * Minor fixes. * rename `disconnect_peer` to `drop_peer` in low-level
This commit is contained in:
@@ -49,7 +49,7 @@ use parking_lot::Mutex;
|
|||||||
use polkadot_consensus::{Statement, SignedStatement, GenericStatement};
|
use polkadot_consensus::{Statement, SignedStatement, GenericStatement};
|
||||||
use polkadot_primitives::{AccountId, Block, SessionKey, Hash, Header};
|
use polkadot_primitives::{AccountId, Block, SessionKey, Hash, Header};
|
||||||
use polkadot_primitives::parachain::{Id as ParaId, BlockData, Extrinsic, CandidateReceipt, Collation};
|
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::consensus_gossip::ConsensusGossip;
|
||||||
use substrate_network::{message, generic_message};
|
use substrate_network::{message, generic_message};
|
||||||
use substrate_network::specialization::Specialization;
|
use substrate_network::specialization::Specialization;
|
||||||
@@ -403,7 +403,7 @@ impl PolkadotProtocol {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if !info.claimed_validator {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,7 +438,7 @@ impl PolkadotProtocol {
|
|||||||
self.pending.push(req);
|
self.pending.push(req);
|
||||||
self.dispatch_pending_requests(ctx);
|
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 {
|
match info.validator_key {
|
||||||
None => ctx.disable_peer(
|
None => ctx.report_peer(
|
||||||
peer_id,
|
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) {
|
Some(key) => for (relay_parent, collation) in self.local_collations.note_validator_role(key, role) {
|
||||||
send_polkadot_message(
|
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 let Some((ref acc_id, ref para_id)) = local_status.collating_for {
|
||||||
if self.collator_peer_id(acc_id.clone()).is_some() {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,7 +571,7 @@ impl Specialization<Block> for PolkadotProtocol {
|
|||||||
Some(msg) => self.on_polkadot_message(ctx, peer_id, raw, msg),
|
Some(msg) => self.on_polkadot_message(ctx, peer_id, raw, msg),
|
||||||
None => {
|
None => {
|
||||||
trace!(target: "p_net", "Bad message from {}", peer_id);
|
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;
|
let collated_acc = collation.receipt.collator;
|
||||||
|
|
||||||
match self.peers.get(&from) {
|
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 {
|
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)) => {
|
Some((ref acc_id, ref para_id)) => {
|
||||||
let structurally_valid = para_id == &collation_para && acc_id == &collated_acc;
|
let structurally_valid = para_id == &collation_para && acc_id == &collated_acc;
|
||||||
if structurally_valid && collation.receipt.check_signature().is_ok() {
|
if structurally_valid && collation.receipt.check_signature().is_ok() {
|
||||||
self.collators.on_collation(acc_id.clone(), relay_parent, collation)
|
self.collators.on_collation(acc_id.clone(), relay_parent, collation)
|
||||||
} else {
|
} 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.
|
// disconnect a collator by account-id.
|
||||||
fn disconnect_bad_collator(&self, ctx: &mut Context<Block>, account_id: AccountId) {
|
fn disconnect_bad_collator(&self, ctx: &mut Context<Block>, account_id: AccountId) {
|
||||||
if let Some(peer_id) = self.collator_peer_id(account_id) {
|
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"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ use polkadot_primitives::{Block, Hash, SessionKey};
|
|||||||
use polkadot_primitives::parachain::{CandidateReceipt, HeadData, BlockData};
|
use polkadot_primitives::parachain::{CandidateReceipt, HeadData, BlockData};
|
||||||
use substrate_primitives::H512;
|
use substrate_primitives::H512;
|
||||||
use codec::Encode;
|
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 std::sync::Arc;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
@@ -41,12 +41,11 @@ impl Context<Block> for TestContext {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable_peer(&mut self, peer: PeerId, _reason: &str) {
|
fn report_peer(&mut self, peer: PeerId, reason: Severity) {
|
||||||
self.disabled.push(peer);
|
match reason {
|
||||||
}
|
Severity::Bad(_) => self.disabled.push(peer),
|
||||||
|
_ => self.disconnected.push(peer),
|
||||||
fn disconnect_peer(&mut self, peer: PeerId) {
|
}
|
||||||
self.disconnected.push(peer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peer_info(&self, _peer: PeerId) -> Option<PeerInfo<Block>> {
|
fn peer_info(&self, _peer: PeerId) -> Option<PeerInfo<Block>> {
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (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
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// 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.
|
//! Connection filter trait.
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (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
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// 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 bytes::{Bytes, BytesMut};
|
||||||
use ProtocolId;
|
use ProtocolId;
|
||||||
@@ -122,6 +122,7 @@ where C: AsyncRead + AsyncWrite + 'static, // TODO: 'static :-/
|
|||||||
type MultiaddrFuture = Maf;
|
type MultiaddrFuture = Maf;
|
||||||
type Future = future::FutureResult<(Self::Output, Self::MultiaddrFuture), IoError>;
|
type Future = future::FutureResult<(Self::Output, Self::MultiaddrFuture), IoError>;
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
fn upgrade(
|
fn upgrade(
|
||||||
self,
|
self,
|
||||||
socket: C,
|
socket: C,
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (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
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// 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 std::{io, net, fmt};
|
||||||
use libc::{ENFILE, EMFILE};
|
use libc::{ENFILE, EMFILE};
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (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
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// 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"]
|
#![recursion_limit="128"]
|
||||||
#![type_length_limit = "268435456"]
|
#![type_length_limit = "268435456"]
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (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
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// 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 bytes::Bytes;
|
||||||
use fnv::{FnvHashMap, FnvHashSet};
|
use fnv::{FnvHashMap, FnvHashSet};
|
||||||
@@ -126,6 +126,45 @@ struct PeerConnectionInfo {
|
|||||||
local_address: Option<Multiaddr>,
|
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 {
|
impl NetworkState {
|
||||||
pub fn new(config: &NetworkConfiguration) -> Result<NetworkState, Error> {
|
pub fn new(config: &NetworkConfiguration) -> Result<NetworkState, Error> {
|
||||||
// Private and public keys configuration.
|
// Private and public keys configuration.
|
||||||
@@ -581,24 +620,37 @@ impl NetworkState {
|
|||||||
} else {
|
} else {
|
||||||
// We are connected to this peer, but not with the current
|
// We are connected to this peer, but not with the current
|
||||||
// protocol.
|
// protocol.
|
||||||
debug!(target: "sub-libp2p", "Tried to send message to peer {} \
|
debug!(target: "sub-libp2p",
|
||||||
for which we aren't connected with the requested protocol",
|
"Tried to send message to peer {} for which we aren't connected with the requested protocol",
|
||||||
peer_id);
|
peer_id
|
||||||
|
);
|
||||||
return Err(ErrorKind::PeerNotFound.into())
|
return Err(ErrorKind::PeerNotFound.into())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!(target: "sub-libp2p", "Tried to send message to invalid \
|
debug!(target: "sub-libp2p", "Tried to send message to invalid peer ID {}", peer_id);
|
||||||
peer ID {}", peer_id);
|
|
||||||
return Err(ErrorKind::PeerNotFound.into())
|
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
|
/// Disconnects a peer, if a connection exists (ie. drops the Kademlia
|
||||||
/// controller, and the senders that were stored in the `UniqueConnec` of
|
/// controller, and the senders that were stored in the `UniqueConnec` of
|
||||||
/// `custom_proto`).
|
/// `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();
|
let mut connections = self.connections.write();
|
||||||
if let Some(peer_info) = connections.info_by_peer.remove(&peer_id) {
|
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 #{} {:?} ; \
|
trace!(target: "sub-libp2p", "Destroying peer #{} {:?} ; \
|
||||||
kademlia = {:?} ; num_protos = {:?}", peer_id, peer_info.id,
|
kademlia = {:?} ; num_protos = {:?}", peer_id, peer_info.id,
|
||||||
peer_info.kad_connec.is_alive(),
|
peer_info.kad_connec.is_alive(),
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (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
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// 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 bytes::Bytes;
|
||||||
use {Error, ErrorKind, NetworkConfiguration, NetworkProtocolHandler};
|
use {Error, ErrorKind, NetworkConfiguration, NetworkProtocolHandler};
|
||||||
use {NonReservedPeerMode, NetworkContext, PeerId, ProtocolId};
|
use {NonReservedPeerMode, NetworkContext, Severity, PeerId, ProtocolId};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use libp2p;
|
use libp2p;
|
||||||
use libp2p::multiaddr::{AddrComponent, Multiaddr};
|
use libp2p::multiaddr::{AddrComponent, Multiaddr};
|
||||||
@@ -299,8 +299,7 @@ struct NetworkContextImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkContext for NetworkContextImpl {
|
impl NetworkContext for NetworkContextImpl {
|
||||||
fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>)
|
fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec<u8>) {
|
||||||
-> Result<(), Error> {
|
|
||||||
self.send_protocol(self.protocol, peer, packet_id, data)
|
self.send_protocol(self.protocol, peer, packet_id, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +309,7 @@ impl NetworkContext for NetworkContextImpl {
|
|||||||
peer: PeerId,
|
peer: PeerId,
|
||||||
packet_id: PacketId,
|
packet_id: PacketId,
|
||||||
data: Vec<u8>
|
data: Vec<u8>
|
||||||
) -> Result<(), Error> {
|
) {
|
||||||
debug_assert!(self.inner.protocols.read().has_protocol(protocol),
|
debug_assert!(self.inner.protocols.read().has_protocol(protocol),
|
||||||
"invalid protocol id requested in the API of the libp2p networking");
|
"invalid protocol id requested in the API of the libp2p networking");
|
||||||
// TODO: could be "optimized" by building `message` only after checking the validity of
|
// 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());
|
let mut message = Bytes::with_capacity(1 + data.len());
|
||||||
message.extend_from_slice(&[packet_id]);
|
message.extend_from_slice(&[packet_id]);
|
||||||
message.extend_from_slice(&data);
|
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 {
|
if let Some(peer) = self.current_peer {
|
||||||
self.send_protocol(self.protocol, peer, packet_id, data)
|
self.send_protocol(self.protocol, peer, packet_id, data)
|
||||||
} else {
|
} else {
|
||||||
@@ -329,14 +330,19 @@ impl NetworkContext for NetworkContextImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable_peer(&self, peer: PeerId, reason: &str) {
|
fn report_peer(&self, peer: PeerId, reason: Severity) {
|
||||||
debug!(target: "sub-libp2p", "Request to disable peer {} for reason {}", peer, reason);
|
if let Some(info) = self.inner.network_state.peer_info(peer) {
|
||||||
self.inner.network_state.disable_peer(peer, reason);
|
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 {
|
||||||
fn disconnect_peer(&self, peer: PeerId) {
|
info!(target: "sub-libp2p", "Peer {} reported by client: {}", peer, reason);
|
||||||
debug!(target: "sub-libp2p", "Request to disconnect peer {}", peer);
|
}
|
||||||
self.inner.network_state.disconnect_peer(peer);
|
}
|
||||||
|
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 {
|
fn is_expired(&self) -> bool {
|
||||||
@@ -768,9 +774,12 @@ fn handle_custom_connection(
|
|||||||
|
|
||||||
impl Drop for ProtoDisconnectGuard {
|
impl Drop for ProtoDisconnectGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
debug!(target: "sub-libp2p", "Node {:?} with peer ID {} \
|
debug!(target: "sub-libp2p",
|
||||||
through protocol {:?} disconnected", self.node_id, self.peer_id,
|
"Node {:?} with peer ID {} through protocol {:?} disconnected",
|
||||||
self.protocol);
|
self.node_id,
|
||||||
|
self.peer_id,
|
||||||
|
self.protocol
|
||||||
|
);
|
||||||
self.handler.disconnected(&NetworkContextImpl {
|
self.handler.disconnected(&NetworkContextImpl {
|
||||||
inner: self.inner.clone(),
|
inner: self.inner.clone(),
|
||||||
protocol: self.protocol,
|
protocol: self.protocol,
|
||||||
@@ -779,7 +788,7 @@ fn handle_custom_connection(
|
|||||||
|
|
||||||
// When any custom protocol drops, we drop the peer entirely.
|
// When any custom protocol drops, we drop the peer entirely.
|
||||||
// TODO: is this correct?
|
// 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
|
let fut = pinger
|
||||||
.get_or_dial(&swarm_controller, &addr, transport.clone())
|
.get_or_dial(&swarm_controller, &addr, transport.clone())
|
||||||
.and_then(move |mut p| {
|
.and_then(move |mut p| {
|
||||||
trace!(target: "sub-libp2p",
|
trace!(target: "sub-libp2p", "Pinging peer #{} aka. {:?}", peer, peer_id);
|
||||||
"Pinging peer #{} aka. {:?}", peer, peer_id);
|
|
||||||
p.ping()
|
p.ping()
|
||||||
.map(|()| peer_id)
|
.map(|()| peer_id)
|
||||||
.map_err(|err| IoError::new(IoErrorKind::Other, err))
|
.map_err(|err| IoError::new(IoErrorKind::Other, err))
|
||||||
@@ -1282,16 +1290,14 @@ fn ping_all<T, St, C>(
|
|||||||
.then(move |val|
|
.then(move |val|
|
||||||
match val {
|
match val {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
trace!(target: "sub-libp2p",
|
trace!(target: "sub-libp2p", "Error while pinging #{:?} => {:?}", peer, err);
|
||||||
"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.
|
||||||
shared.network_state.disconnect_peer(peer);
|
|
||||||
// Return Ok, otherwise we would close the ping service
|
// Return Ok, otherwise we would close the ping service
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
Ok(peer_id) => {
|
Ok(peer_id) => {
|
||||||
let elapsed = ping_start_time.elapsed();
|
let elapsed = ping_start_time.elapsed();
|
||||||
trace!(target: "sub-libp2p", "Pong from #{:?} in {:?}",
|
trace!(target: "sub-libp2p", "Pong from #{:?} in {:?}", peer, elapsed);
|
||||||
peer, elapsed);
|
|
||||||
shared.network_state.report_ping_duration(peer, elapsed);
|
shared.network_state.report_ping_duration(peer, elapsed);
|
||||||
shared.kad_system.update_kbuckets(peer_id);
|
shared.kad_system.update_kbuckets(peer_id);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (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
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// 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 futures::{Async, future, Future, Poll, stream, Stream, sync::mpsc};
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (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
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// 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::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
|
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.
|
/// IO access point. This is passed to all IO handlers and provides an interface to the IO subsystem.
|
||||||
pub trait NetworkContext {
|
pub trait NetworkContext {
|
||||||
/// Send a packet over the network to another peer.
|
/// 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.
|
/// 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.
|
/// 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.
|
/// Report peer. Depending on the report, peer may be disconnected and possibly banned.
|
||||||
fn disable_peer(&self, peer: PeerId, reason: &str);
|
fn report_peer(&self, peer: PeerId, reason: Severity);
|
||||||
|
|
||||||
/// Disconnect peer. Reconnect can be attempted later.
|
|
||||||
fn disconnect_peer(&self, peer: PeerId);
|
|
||||||
|
|
||||||
/// Check if the session is still active.
|
/// Check if the session is still active.
|
||||||
fn is_expired(&self) -> bool;
|
fn is_expired(&self) -> bool;
|
||||||
@@ -250,24 +271,20 @@ pub trait NetworkContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> NetworkContext for &'a T where T: ?Sized + 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)
|
(**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)
|
(**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)
|
(**self).respond(packet_id, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable_peer(&self, peer: PeerId, reason: &str) {
|
fn report_peer(&self, peer: PeerId, reason: Severity) {
|
||||||
(**self).disable_peer(peer, reason)
|
(**self).report_peer(peer, reason)
|
||||||
}
|
|
||||||
|
|
||||||
fn disconnect_peer(&self, peer: PeerId) {
|
|
||||||
(**self).disconnect_peer(peer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_expired(&self) -> bool {
|
fn is_expired(&self) -> bool {
|
||||||
@@ -333,42 +350,42 @@ impl NonReservedPeerMode {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct IpFilter {
|
pub struct IpFilter {
|
||||||
pub predefined: AllowIP,
|
pub predefined: AllowIP,
|
||||||
pub custom_allow: Vec<IpNetwork>,
|
pub custom_allow: Vec<IpNetwork>,
|
||||||
pub custom_block: Vec<IpNetwork>,
|
pub custom_block: Vec<IpNetwork>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for IpFilter {
|
impl Default for IpFilter {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
IpFilter {
|
IpFilter {
|
||||||
predefined: AllowIP::All,
|
predefined: AllowIP::All,
|
||||||
custom_allow: vec![],
|
custom_allow: vec![],
|
||||||
custom_block: vec![],
|
custom_block: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IpFilter {
|
impl IpFilter {
|
||||||
/// Attempt to parse the peer mode from a string.
|
/// Attempt to parse the peer mode from a string.
|
||||||
pub fn parse(s: &str) -> Result<IpFilter, IpNetworkError> {
|
pub fn parse(s: &str) -> Result<IpFilter, IpNetworkError> {
|
||||||
let mut filter = IpFilter::default();
|
let mut filter = IpFilter::default();
|
||||||
for f in s.split_whitespace() {
|
for f in s.split_whitespace() {
|
||||||
match f {
|
match f {
|
||||||
"all" => filter.predefined = AllowIP::All,
|
"all" => filter.predefined = AllowIP::All,
|
||||||
"private" => filter.predefined = AllowIP::Private,
|
"private" => filter.predefined = AllowIP::Private,
|
||||||
"public" => filter.predefined = AllowIP::Public,
|
"public" => filter.predefined = AllowIP::Public,
|
||||||
"none" => filter.predefined = AllowIP::None,
|
"none" => filter.predefined = AllowIP::None,
|
||||||
custom => {
|
custom => {
|
||||||
if custom.starts_with("-") {
|
if custom.starts_with("-") {
|
||||||
filter.custom_block.push(IpNetwork::from_str(&custom.to_owned().split_off(1))?)
|
filter.custom_block.push(IpNetwork::from_str(&custom.to_owned().split_off(1))?)
|
||||||
} else {
|
} else {
|
||||||
filter.custom_allow.push(IpNetwork::from_str(custom)?)
|
filter.custom_allow.push(IpNetwork::from_str(custom)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(filter)
|
Ok(filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// IP fiter
|
/// IP fiter
|
||||||
@@ -380,6 +397,6 @@ pub enum AllowIP {
|
|||||||
Private,
|
Private,
|
||||||
/// Connect to public network only
|
/// Connect to public network only
|
||||||
Public,
|
Public,
|
||||||
/// Block all addresses
|
/// Block all addresses
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// (at your option) any later version.
|
// (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
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
// You should have received a copy of the GNU General Public License
|
// 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::{self, Transport, mplex, secio, yamux};
|
||||||
use libp2p::core::{MuxedTransport, either, upgrade};
|
use libp2p::core::{MuxedTransport, either, upgrade};
|
||||||
|
|||||||
@@ -73,9 +73,9 @@ impl NetworkProtocolHandler for TestProtocol {
|
|||||||
|
|
||||||
fn connected(&self, io: &NetworkContext, peer: &PeerId) {
|
fn connected(&self, io: &NetworkContext, peer: &PeerId) {
|
||||||
if self.drop_session {
|
if self.drop_session {
|
||||||
io.disconnect_peer(*peer)
|
io.report_peer(*peer, Severity::Bad("We are evil and just want to drop"))
|
||||||
} else {
|
} else {
|
||||||
io.respond(33, "hello".to_owned().into_bytes()).unwrap();
|
io.respond(33, "hello".to_owned().into_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||||||
use parking_lot::{Condvar, Mutex, RwLock};
|
use parking_lot::{Condvar, Mutex, RwLock};
|
||||||
|
|
||||||
use client::{BlockOrigin, BlockStatus, ImportResult};
|
use client::{BlockOrigin, BlockStatus, ImportResult};
|
||||||
use network_libp2p::PeerId;
|
use network_libp2p::{PeerId, Severity};
|
||||||
use runtime_primitives::generic::BlockId;
|
use runtime_primitives::generic::BlockId;
|
||||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero};
|
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero};
|
||||||
|
|
||||||
@@ -202,9 +202,9 @@ trait SyncLinkApi<B: BlockT> {
|
|||||||
/// Maintain sync.
|
/// Maintain sync.
|
||||||
fn maintain_sync(&mut self);
|
fn maintain_sync(&mut self);
|
||||||
/// Disconnect from peer.
|
/// 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.
|
/// 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.
|
/// Restart sync.
|
||||||
fn restart(&mut self);
|
fn restart(&mut self);
|
||||||
}
|
}
|
||||||
@@ -357,11 +357,15 @@ fn process_import_result<'a, B: BlockT>(
|
|||||||
1
|
1
|
||||||
},
|
},
|
||||||
Err(BlockImportError::Disconnect(peer_id)) => {
|
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
|
0
|
||||||
},
|
},
|
||||||
Err(BlockImportError::DisconnectAndRestart(peer_id)) => {
|
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
|
0
|
||||||
},
|
},
|
||||||
Err(BlockImportError::Restart) => {
|
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))
|
self.with_sync(|sync, protocol| sync.maintain_sync(protocol))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disconnect(&mut self, peer_id: PeerId) {
|
fn useless_peer(&mut self, peer_id: PeerId, reason: &str) {
|
||||||
self.with_sync(|_, protocol| protocol.disconnect_peer(peer_id))
|
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| {
|
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);
|
sync.restart(protocol);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -486,8 +490,8 @@ pub mod tests {
|
|||||||
fn chain(&self) -> &Client<Block> { &*self.chain }
|
fn chain(&self) -> &Client<Block> { &*self.chain }
|
||||||
fn block_imported(&mut self, _hash: &Hash, _number: NumberFor<Block>) { self.imported += 1; }
|
fn block_imported(&mut self, _hash: &Hash, _number: NumberFor<Block>) { self.imported += 1; }
|
||||||
fn maintain_sync(&mut self) { self.maintains += 1; }
|
fn maintain_sync(&mut self) { self.maintains += 1; }
|
||||||
fn disconnect(&mut self, _peer_id: PeerId) { self.disconnects += 1; }
|
fn useless_peer(&mut self, _: PeerId, _: &str) { self.disconnects += 1; }
|
||||||
fn disconnect_and_restart(&mut self, _peer_id: PeerId) { self.disconnects += 1; self.restarts += 1; }
|
fn note_useless_and_restart_sync(&mut self, _: PeerId, _: &str) { self.disconnects += 1; self.restarts += 1; }
|
||||||
fn restart(&mut self) { self.restarts += 1; }
|
fn restart(&mut self) { self.restarts += 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,17 +14,15 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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 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.
|
/// IO interface for the syncing handler.
|
||||||
/// Provides peer connection management and an interface to the blockchain client.
|
/// Provides peer connection management and an interface to the blockchain client.
|
||||||
pub trait SyncIo {
|
pub trait SyncIo {
|
||||||
/// Disable a peer
|
/// Report a peer for misbehaviour.
|
||||||
fn disable_peer(&mut self, peer_id: PeerId, reason: &str);
|
fn report_peer(&mut self, peer_id: PeerId, reason: Severity);
|
||||||
/// Disconnect peer
|
|
||||||
fn disconnect_peer(&mut self, peer_id: PeerId);
|
|
||||||
/// Send a packet to a peer.
|
/// 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
|
/// Returns peer identifier string
|
||||||
fn peer_info(&self, peer_id: PeerId) -> String {
|
fn peer_info(&self, peer_id: PeerId) -> String {
|
||||||
peer_id.to_string()
|
peer_id.to_string()
|
||||||
@@ -50,15 +48,11 @@ impl<'s> NetSyncIo<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> SyncIo for NetSyncIo<'s> {
|
impl<'s> SyncIo for NetSyncIo<'s> {
|
||||||
fn disable_peer(&mut self, peer_id: PeerId, reason: &str) {
|
fn report_peer(&mut self, peer_id: PeerId, reason: Severity) {
|
||||||
self.network.disable_peer(peer_id, reason);
|
self.network.report_peer(peer_id, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disconnect_peer(&mut self, peer_id: PeerId) {
|
fn send(&mut self, peer_id: PeerId, data: Vec<u8>) {
|
||||||
self.network.disconnect_peer(peer_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn send(&mut self, peer_id: PeerId, data: Vec<u8>) -> Result<(), NetworkError>{
|
|
||||||
self.network.send(peer_id, 0, data)
|
self.network.send(peer_id, 0, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ pub use service::{Service, FetchFuture, ConsensusService, BftMessageStream,
|
|||||||
TransactionPool, Params, ManageNetwork, SyncProvider};
|
TransactionPool, Params, ManageNetwork, SyncProvider};
|
||||||
pub use protocol::{ProtocolStatus, PeerInfo, Context};
|
pub use protocol::{ProtocolStatus, PeerInfo, Context};
|
||||||
pub use sync::{Status as SyncStatus, SyncState};
|
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 message::{generic as generic_message, RequestId, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal, Status as StatusMessage};
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use config::{Roles, ProtocolConfig};
|
pub use config::{Roles, ProtocolConfig};
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ use client;
|
|||||||
use client::light::fetcher::{Fetcher, FetchChecker, RemoteCallRequest};
|
use client::light::fetcher::{Fetcher, FetchChecker, RemoteCallRequest};
|
||||||
use io::SyncIo;
|
use io::SyncIo;
|
||||||
use message;
|
use message;
|
||||||
use network_libp2p::PeerId;
|
use network_libp2p::{Severity, PeerId};
|
||||||
use service;
|
use service;
|
||||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT};
|
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) {
|
let request = match core.remove(peer, request_id) {
|
||||||
Some(request) => request,
|
Some(request) => request,
|
||||||
None => {
|
None => {
|
||||||
trace!(target: "sync", "Invalid remote {} response from peer {}", rtype, peer);
|
io.report_peer(peer, Severity::Bad(&format!("Invalid remote {} response from peer", rtype)));
|
||||||
io.disconnect_peer(peer);
|
|
||||||
core.remove_peer(peer);
|
core.remove_peer(peer);
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
@@ -147,9 +146,7 @@ impl<B: BlockT, E> OnDemand<B, E> where
|
|||||||
let retry_request_data = match try_accept(request) {
|
let retry_request_data = match try_accept(request) {
|
||||||
Accept::Ok => None,
|
Accept::Ok => None,
|
||||||
Accept::CheckFailed(error, retry_request_data) => {
|
Accept::CheckFailed(error, retry_request_data) => {
|
||||||
trace!(target: "sync", "Failed to check remote {} response from peer {}: {}", rtype, peer, error);
|
io.report_peer(peer, Severity::Bad(&format!("Failed to check remote {} response from peer: {}", rtype, error)));
|
||||||
|
|
||||||
io.disconnect_peer(peer);
|
|
||||||
core.remove_peer(peer);
|
core.remove_peer(peer);
|
||||||
Some(retry_request_data)
|
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) {
|
fn maintain_peers(&self, io: &mut SyncIo) {
|
||||||
let mut core = self.core.lock();
|
let mut core = self.core.lock();
|
||||||
for bad_peer in core.maintain_peers() {
|
for bad_peer in core.maintain_peers() {
|
||||||
trace!(target: "sync", "Remote request timeout for peer {}", bad_peer);
|
io.report_peer(bad_peer, Severity::Timeout);
|
||||||
io.disconnect_peer(bad_peer);
|
|
||||||
}
|
}
|
||||||
core.dispatch();
|
core.dispatch();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ use std::time;
|
|||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash, HashFor, As};
|
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash, HashFor, As};
|
||||||
use runtime_primitives::generic::BlockId;
|
use runtime_primitives::generic::BlockId;
|
||||||
use network_libp2p::PeerId;
|
use network_libp2p::{PeerId, Severity};
|
||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
|
|
||||||
use message::{self, Message};
|
use message::{self, Message};
|
||||||
@@ -43,7 +43,6 @@ pub (crate) const CURRENT_VERSION: u32 = 1;
|
|||||||
/// Current packet count.
|
/// Current packet count.
|
||||||
pub (crate) const CURRENT_PACKET_COUNT: u8 = 1;
|
pub (crate) const CURRENT_PACKET_COUNT: u8 = 1;
|
||||||
|
|
||||||
|
|
||||||
// Maximum allowed entries in `BlockResponse`
|
// Maximum allowed entries in `BlockResponse`
|
||||||
const MAX_BLOCK_DATA_RESPONSE: u32 = 128;
|
const MAX_BLOCK_DATA_RESPONSE: u32 = 128;
|
||||||
|
|
||||||
@@ -110,11 +109,8 @@ pub trait Context<B: BlockT> {
|
|||||||
/// Get a reference to the client.
|
/// Get a reference to the client.
|
||||||
fn client(&self) -> &::chain::Client<B>;
|
fn client(&self) -> &::chain::Client<B>;
|
||||||
|
|
||||||
/// Disable a peer
|
/// Point out that a peer has been malign or irresponsible or appeared lazy.
|
||||||
fn disable_peer(&mut self, peer_id: PeerId, reason: &str);
|
fn report_peer(&mut self, peer_id: PeerId, reason: Severity);
|
||||||
|
|
||||||
/// Disconnect peer
|
|
||||||
fn disconnect_peer(&mut self, peer_id: PeerId);
|
|
||||||
|
|
||||||
/// Get peer info.
|
/// Get peer info.
|
||||||
fn peer_info(&self, peer: PeerId) -> Option<PeerInfo<B>>;
|
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)
|
send_message(&self.context_data.peers, self.io, peer_id, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_peer(&mut self, peer_id: PeerId, reason: &str) {
|
/// Point out that a peer has been malign or irresponsible or appeared lazy.
|
||||||
self.io.disable_peer(peer_id, reason);
|
pub fn report_peer(&mut self, peer_id: PeerId, reason: Severity) {
|
||||||
}
|
self.io.report_peer(peer_id, reason);
|
||||||
|
|
||||||
pub fn disconnect_peer(&mut self, peer_id: PeerId) {
|
|
||||||
self.io.disconnect_peer(peer_id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get peer info.
|
/// 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);
|
ProtocolContext::send_message(self, peer_id, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disable_peer(&mut self, peer_id: PeerId, reason: &str) {
|
fn report_peer(&mut self, peer_id: PeerId, reason: Severity) {
|
||||||
ProtocolContext::disable_peer(self, peer_id, reason);
|
ProtocolContext::report_peer(self, peer_id, reason);
|
||||||
}
|
|
||||||
|
|
||||||
fn disconnect_peer(&mut self, peer_id: PeerId) {
|
|
||||||
ProtocolContext::disconnect_peer(self, peer_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peer_info(&self, peer_id: PeerId) -> Option<PeerInfo<B>> {
|
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,
|
Some(m) => m,
|
||||||
None => {
|
None => {
|
||||||
trace!(target: "sync", "Invalid packet from {}", peer_id);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -260,12 +249,12 @@ impl<B: BlockT, S: Specialization<B>> Protocol<B, S> {
|
|||||||
match mem::replace(&mut peer.block_request, None) {
|
match mem::replace(&mut peer.block_request, None) {
|
||||||
Some(r) => r,
|
Some(r) => r,
|
||||||
None => {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
io.disable_peer(peer_id, "Unexpected packet received from peer");
|
io.report_peer(peer_id, Severity::Bad("Unexpected packet received from peer"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -385,7 +374,6 @@ impl<B: BlockT, S: Specialization<B>> Protocol<B, S> {
|
|||||||
.chain(handshaking_peers.iter()) {
|
.chain(handshaking_peers.iter()) {
|
||||||
if (tick - *timestamp).as_secs() > REQUEST_TIMEOUT_SEC {
|
if (tick - *timestamp).as_secs() > REQUEST_TIMEOUT_SEC {
|
||||||
trace!(target: "sync", "Timeout {}", peer_id);
|
trace!(target: "sync", "Timeout {}", peer_id);
|
||||||
io.disconnect_peer(*peer_id);
|
|
||||||
aborting.push(*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));
|
self.specialization.write().maintain_peers(&mut ProtocolContext::new(&self.context_data, io));
|
||||||
for p in aborting {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if status.genesis_hash != self.genesis_hash {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if status.version != CURRENT_VERSION {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,11 +613,7 @@ fn send_message<B: BlockT>(peers: &RwLock<HashMap<PeerId, Peer<B>>>, io: &mut Sy
|
|||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
let data = message.encode();
|
io.send(peer_id, message.encode());
|
||||||
if let Err(e) = io.send(peer_id, data) {
|
|
||||||
debug!(target:"sync", "Error sending message: {:?}", e);
|
|
||||||
io.disconnect_peer(peer_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hash a message.
|
/// Hash a message.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use protocol::Context;
|
use protocol::Context;
|
||||||
use network_libp2p::PeerId;
|
use network_libp2p::{Severity, PeerId};
|
||||||
use client::{BlockStatus, BlockOrigin, ClientInfo};
|
use client::{BlockStatus, BlockOrigin, ClientInfo};
|
||||||
use client::error::Error as ClientError;
|
use client::error::Error as ClientError;
|
||||||
use blocks::{self, BlockCollection};
|
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) {
|
match (block_status(&*protocol.client(), &*self.import_queue, info.best_hash), info.best_number) {
|
||||||
(Err(e), _) => {
|
(Err(e), _) => {
|
||||||
debug!(target:"sync", "Error reading blockchain: {:?}", 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), _) => {
|
(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) => {
|
(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), _) => {
|
(Ok(BlockStatus::Unknown), _) => {
|
||||||
let our_best = self.best_queued_number;
|
let our_best = self.best_queued_number;
|
||||||
@@ -211,19 +211,18 @@ impl<B: BlockT> ChainSync<B> {
|
|||||||
},
|
},
|
||||||
Ok(_) => { // genesis mismatch
|
Ok(_) => { // genesis mismatch
|
||||||
trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", peer_id);
|
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;
|
return;
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
debug!(target:"sync", "Error reading blockchain: {:?}", e);
|
protocol.report_peer(peer_id, Severity::Useless(&format!("Error answering legitimate blockchain query: {:?}", e)));
|
||||||
protocol.disconnect_peer(peer_id);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
trace!(target:"sync", "Invalid response when searching for ancestor from {}", peer_id);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ use io::SyncIo;
|
|||||||
use protocol::{Context, Protocol};
|
use protocol::{Context, Protocol};
|
||||||
use config::ProtocolConfig;
|
use config::ProtocolConfig;
|
||||||
use service::TransactionPool;
|
use service::TransactionPool;
|
||||||
use network_libp2p::{PeerId, SessionInfo, Error as NetworkError};
|
use network_libp2p::{PeerId, SessionInfo, Severity};
|
||||||
use keyring::Keyring;
|
use keyring::Keyring;
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
use import_queue::tests::SyncImportQueue;
|
use import_queue::tests::SyncImportQueue;
|
||||||
@@ -81,11 +81,7 @@ impl<'p> Drop for TestIo<'p> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'p> SyncIo for TestIo<'p> {
|
impl<'p> SyncIo for TestIo<'p> {
|
||||||
fn disable_peer(&mut self, peer_id: PeerId, _reason: &str) {
|
fn report_peer(&mut self, peer_id: PeerId, _reason: Severity) {
|
||||||
self.disconnect_peer(peer_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn disconnect_peer(&mut self, peer_id: PeerId) {
|
|
||||||
self.to_disconnect.insert(peer_id);
|
self.to_disconnect.insert(peer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,12 +89,11 @@ impl<'p> SyncIo for TestIo<'p> {
|
|||||||
false
|
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 {
|
self.packets.push(TestPacket {
|
||||||
data: data,
|
data: data,
|
||||||
recipient: peer_id,
|
recipient: peer_id,
|
||||||
});
|
});
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peer_info(&self, peer_id: PeerId) -> String {
|
fn peer_info(&self, peer_id: PeerId) -> String {
|
||||||
|
|||||||
Reference in New Issue
Block a user