mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 13:31:10 +00:00
Reputation changes requires reason (#4277)
This commit is contained in:
committed by
Gavin Wood
parent
5edc4350b4
commit
5ec0923285
@@ -940,7 +940,10 @@ where
|
||||
// a different chain, or a node that doesn't speak the same protocol(s). We
|
||||
// decrease the node's reputation, hence lowering the chances we try this node
|
||||
// again in the short term.
|
||||
self.peerset.report_peer(source.clone(), i32::min_value());
|
||||
self.peerset.report_peer(
|
||||
source.clone(),
|
||||
peerset::ReputationChange::new(i32::min_value(), "Protocol error")
|
||||
);
|
||||
self.disconnect_peer_inner(&source, Some(Duration::from_secs(5)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +199,7 @@ pub use libp2p::multiaddr;
|
||||
|
||||
pub use message::{generic as generic_message, RequestId, Status as StatusMessage};
|
||||
pub use on_demand_layer::{OnDemand, RemoteResponse};
|
||||
pub use peerset::ReputationChange;
|
||||
|
||||
// Used by the `construct_simple_protocol!` macro.
|
||||
#[doc(hidden)]
|
||||
|
||||
@@ -88,23 +88,38 @@ const MAX_CONSENSUS_MESSAGES: usize = 256;
|
||||
/// and disconnect to free connection slot.
|
||||
const LIGHT_MAXIMAL_BLOCKS_DIFFERENCE: u64 = 8192;
|
||||
|
||||
/// Reputation change when a peer is "clogged", meaning that it's not fast enough to process our
|
||||
/// messages.
|
||||
const CLOGGED_PEER_REPUTATION_CHANGE: i32 = -(1 << 12);
|
||||
/// Reputation change when a peer doesn't respond in time to our messages.
|
||||
const TIMEOUT_REPUTATION_CHANGE: i32 = -(1 << 10);
|
||||
/// Reputation change when a peer sends us a status message while we already received one.
|
||||
const UNEXPECTED_STATUS_REPUTATION_CHANGE: i32 = -(1 << 20);
|
||||
/// Reputation change when we are a light client and a peer is behind us.
|
||||
const PEER_BEHIND_US_LIGHT_REPUTATION_CHANGE: i32 = -(1 << 8);
|
||||
/// Reputation change when a peer sends us an extrinsic that we didn't know about.
|
||||
const GOOD_EXTRINSIC_REPUTATION_CHANGE: i32 = 1 << 7;
|
||||
/// Reputation change when a peer sends us a bad extrinsic.
|
||||
const BAD_EXTRINSIC_REPUTATION_CHANGE: i32 = -(1 << 12);
|
||||
/// We sent an RPC query to the given node, but it failed.
|
||||
const RPC_FAILED_REPUTATION_CHANGE: i32 = -(1 << 12);
|
||||
/// We received a message that failed to decode.
|
||||
const BAD_MESSAGE_REPUTATION_CHANGE: i32 = -(1 << 12);
|
||||
mod rep {
|
||||
use peerset::ReputationChange as Rep;
|
||||
/// Reputation change when a peer is "clogged", meaning that it's not fast enough to process our
|
||||
/// messages.
|
||||
pub const CLOGGED_PEER: Rep = Rep::new(-(1 << 12), "Clogged message queue");
|
||||
/// Reputation change when a peer doesn't respond in time to our messages.
|
||||
pub const TIMEOUT: Rep = Rep::new(-(1 << 10), "Request timeout");
|
||||
/// Reputation change when a peer sends us a status message while we already received one.
|
||||
pub const UNEXPECTED_STATUS: Rep = Rep::new(-(1 << 20), "Unexpected status message");
|
||||
/// Reputation change when we are a light client and a peer is behind us.
|
||||
pub const PEER_BEHIND_US_LIGHT: Rep = Rep::new(-(1 << 8), "Useless for a light peer");
|
||||
/// Reputation change when a peer sends us an extrinsic that we didn't know about.
|
||||
pub const GOOD_EXTRINSIC: Rep = Rep::new(1 << 7, "Good extrinsic");
|
||||
/// Reputation change when a peer sends us a bad extrinsic.
|
||||
pub const BAD_EXTRINSIC: Rep = Rep::new(-(1 << 12), "Bad extrinsic");
|
||||
/// We sent an RPC query to the given node, but it failed.
|
||||
pub const RPC_FAILED: Rep = Rep::new(-(1 << 12), "Remote call failed");
|
||||
/// We received a message that failed to decode.
|
||||
pub const BAD_MESSAGE: Rep = Rep::new(-(1 << 12), "Bad message");
|
||||
/// We received an unexpected response.
|
||||
pub const UNEXPECTED_RESPONSE: Rep = Rep::new_fatal("Unexpected response packet");
|
||||
/// We received an unexpected extrinsic packet.
|
||||
pub const UNEXPECTED_EXTRINSICS: Rep = Rep::new_fatal("Unexpected extrinsics packet");
|
||||
/// We received an unexpected light node request.
|
||||
pub const UNEXPECTED_REQUEST: Rep = Rep::new_fatal("Unexpected block request packet");
|
||||
/// Peer has different genesis.
|
||||
pub const GENESIS_MISMATCH: Rep = Rep::new_fatal("Genesis mismatch");
|
||||
/// Peer is on unsupported protocol version.
|
||||
pub const BAD_PROTOCOL: Rep = Rep::new_fatal("Unsupported protocol");
|
||||
/// Peer role does not match (e.g. light peer connecting to another light peer).
|
||||
pub const BAD_ROLE: Rep = Rep::new_fatal("Unsupported role");
|
||||
}
|
||||
|
||||
// Lock must always be taken in order declared here.
|
||||
pub struct Protocol<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> {
|
||||
@@ -183,7 +198,7 @@ struct LightDispatchIn<'a> {
|
||||
}
|
||||
|
||||
impl<'a, B: BlockT> LightDispatchNetwork<B> for LightDispatchIn<'a> {
|
||||
fn report_peer(&mut self, who: &PeerId, reputation: i32) {
|
||||
fn report_peer(&mut self, who: &PeerId, reputation: peerset::ReputationChange) {
|
||||
self.peerset.report_peer(who.clone(), reputation)
|
||||
}
|
||||
|
||||
@@ -303,7 +318,7 @@ impl<'a, B: BlockT> LightDispatchNetwork<B> for LightDispatchIn<'a> {
|
||||
pub trait Context<B: BlockT> {
|
||||
/// Adjusts the reputation of the peer. Use this to point out that a peer has been malign or
|
||||
/// irresponsible or appeared lazy.
|
||||
fn report_peer(&mut self, who: PeerId, reputation: i32);
|
||||
fn report_peer(&mut self, who: PeerId, reputation: peerset::ReputationChange);
|
||||
|
||||
/// Force disconnecting from a peer. Use this when a peer misbehaved.
|
||||
fn disconnect_peer(&mut self, who: PeerId);
|
||||
@@ -333,7 +348,7 @@ impl<'a, B: BlockT + 'a, H: 'a + ExHashT> ProtocolContext<'a, B, H> {
|
||||
}
|
||||
|
||||
impl<'a, B: BlockT + 'a, H: ExHashT + 'a> Context<B> for ProtocolContext<'a, B, H> {
|
||||
fn report_peer(&mut self, who: PeerId, reputation: i32) {
|
||||
fn report_peer(&mut self, who: PeerId, reputation: peerset::ReputationChange) {
|
||||
self.peerset_handle.report_peer(who, reputation)
|
||||
}
|
||||
|
||||
@@ -557,7 +572,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
return request.map(|(_, r)| r)
|
||||
}
|
||||
trace!(target: "sync", "Unexpected response packet from {} ({})", who, response.id);
|
||||
self.peerset_handle.report_peer(who.clone(), i32::min_value());
|
||||
self.peerset_handle.report_peer(who.clone(), rep::UNEXPECTED_RESPONSE);
|
||||
self.behaviour.disconnect_peer(&who);
|
||||
}
|
||||
None
|
||||
@@ -587,7 +602,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
Ok(message) => message,
|
||||
Err(err) => {
|
||||
debug!(target: "sync", "Couldn't decode packet sent by {}: {:?}: {}", who, data, err.what());
|
||||
self.peerset_handle.report_peer(who.clone(), BAD_MESSAGE_REPUTATION_CHANGE);
|
||||
self.peerset_handle.report_peer(who.clone(), rep::BAD_MESSAGE);
|
||||
return CustomMessageOutcome::None;
|
||||
}
|
||||
};
|
||||
@@ -755,7 +770,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
/// Called as a back-pressure mechanism if the networking detects that the peer cannot process
|
||||
/// our messaging rate fast enough.
|
||||
pub fn on_clogged_peer(&self, who: PeerId, _msg: Option<Message<B>>) {
|
||||
self.peerset_handle.report_peer(who.clone(), CLOGGED_PEER_REPUTATION_CHANGE);
|
||||
self.peerset_handle.report_peer(who.clone(), rep::CLOGGED_PEER);
|
||||
|
||||
// Print some diagnostics.
|
||||
if let Some(peer) = self.context_data.peers.get(&who) {
|
||||
@@ -784,7 +799,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
if !self.config.roles.is_full() {
|
||||
trace!(target: "sync", "Peer {} is trying to sync from the light node", peer);
|
||||
self.behaviour.disconnect_peer(&peer);
|
||||
self.peerset_handle.report_peer(peer, i32::min_value());
|
||||
self.peerset_handle.report_peer(peer, rep::UNEXPECTED_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -846,7 +861,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
}
|
||||
|
||||
/// Adjusts the reputation of a node.
|
||||
pub fn report_peer(&self, who: PeerId, reputation: i32) {
|
||||
pub fn report_peer(&self, who: PeerId, reputation: peerset::ReputationChange) {
|
||||
self.peerset_handle.report_peer(who, reputation)
|
||||
}
|
||||
|
||||
@@ -953,7 +968,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
);
|
||||
for p in aborting {
|
||||
self.behaviour.disconnect_peer(&p);
|
||||
self.peerset_handle.report_peer(p, TIMEOUT_REPUTATION_CHANGE);
|
||||
self.peerset_handle.report_peer(p, rep::TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -967,7 +982,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
if self.important_peers.contains(&who) { Level::Warn } else { Level::Debug },
|
||||
"Unexpected status packet from {}", who
|
||||
);
|
||||
self.peerset_handle.report_peer(who, UNEXPECTED_STATUS_REPUTATION_CHANGE);
|
||||
self.peerset_handle.report_peer(who, rep::UNEXPECTED_STATUS);
|
||||
return;
|
||||
}
|
||||
if status.genesis_hash != self.genesis_hash {
|
||||
@@ -977,7 +992,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
"Peer is on different chain (our genesis: {} theirs: {})",
|
||||
self.genesis_hash, status.genesis_hash
|
||||
);
|
||||
self.peerset_handle.report_peer(who.clone(), i32::min_value());
|
||||
self.peerset_handle.report_peer(who.clone(), rep::GENESIS_MISMATCH);
|
||||
self.behaviour.disconnect_peer(&who);
|
||||
return;
|
||||
}
|
||||
@@ -987,7 +1002,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
if self.important_peers.contains(&who) { Level::Warn } else { Level::Trace },
|
||||
"Peer {:?} using unsupported protocol version {}", who, status.version
|
||||
);
|
||||
self.peerset_handle.report_peer(who.clone(), i32::min_value());
|
||||
self.peerset_handle.report_peer(who.clone(), rep::BAD_PROTOCOL);
|
||||
self.behaviour.disconnect_peer(&who);
|
||||
return;
|
||||
}
|
||||
@@ -996,7 +1011,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
// we're not interested in light peers
|
||||
if status.roles.is_light() {
|
||||
debug!(target: "sync", "Peer {} is unable to serve light requests", who);
|
||||
self.peerset_handle.report_peer(who.clone(), i32::min_value());
|
||||
self.peerset_handle.report_peer(who.clone(), rep::BAD_ROLE);
|
||||
self.behaviour.disconnect_peer(&who);
|
||||
return;
|
||||
}
|
||||
@@ -1013,7 +1028,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
.saturated_into::<u64>();
|
||||
if blocks_difference > LIGHT_MAXIMAL_BLOCKS_DIFFERENCE {
|
||||
debug!(target: "sync", "Peer {} is far behind us and will unable to serve light requests", who);
|
||||
self.peerset_handle.report_peer(who.clone(), PEER_BEHIND_US_LIGHT_REPUTATION_CHANGE);
|
||||
self.peerset_handle.report_peer(who.clone(), rep::PEER_BEHIND_US_LIGHT);
|
||||
self.behaviour.disconnect_peer(&who);
|
||||
return;
|
||||
}
|
||||
@@ -1082,7 +1097,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
if !self.config.roles.is_full() {
|
||||
trace!(target: "sync", "Peer {} is trying to send extrinsic to the light node", who);
|
||||
self.behaviour.disconnect_peer(&who);
|
||||
self.peerset_handle.report_peer(who, i32::min_value());
|
||||
self.peerset_handle.report_peer(who, rep::UNEXPECTED_EXTRINSICS);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1100,8 +1115,8 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
self.transaction_pool.import(
|
||||
self.peerset_handle.clone().into(),
|
||||
who.clone(),
|
||||
GOOD_EXTRINSIC_REPUTATION_CHANGE,
|
||||
BAD_EXTRINSIC_REPUTATION_CHANGE,
|
||||
rep::GOOD_EXTRINSIC,
|
||||
rep::BAD_EXTRINSIC,
|
||||
t,
|
||||
);
|
||||
}
|
||||
@@ -1351,7 +1366,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
request.block,
|
||||
error
|
||||
);
|
||||
self.peerset_handle.report_peer(who.clone(), RPC_FAILED_REPUTATION_CHANGE);
|
||||
self.peerset_handle.report_peer(who.clone(), rep::RPC_FAILED);
|
||||
StorageProof::empty()
|
||||
}
|
||||
};
|
||||
@@ -1679,7 +1694,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
None
|
||||
},
|
||||
};
|
||||
self.send_message(
|
||||
self.send_message(
|
||||
&who,
|
||||
GenericMessage::FinalityProofResponse(message::FinalityProofResponse {
|
||||
id: 0,
|
||||
|
||||
@@ -61,15 +61,19 @@ use crate::config::Roles;
|
||||
const KNOWN_MESSAGES_CACHE_SIZE: usize = 4096;
|
||||
|
||||
const REBROADCAST_INTERVAL: time::Duration = time::Duration::from_secs(30);
|
||||
/// Reputation change when a peer sends us a gossip message that we didn't know about.
|
||||
const GOSSIP_SUCCESS_REPUTATION_CHANGE: i32 = 1 << 4;
|
||||
/// Reputation change when a peer sends us a gossip message that we already knew about.
|
||||
const DUPLICATE_GOSSIP_REPUTATION_CHANGE: i32 = -(1 << 2);
|
||||
/// Reputation change when a peer sends us a gossip message for an unknown engine, whatever that
|
||||
/// means.
|
||||
const UNKNOWN_GOSSIP_REPUTATION_CHANGE: i32 = -(1 << 6);
|
||||
/// Reputation change when a peer sends a message from a topic it isn't registered on.
|
||||
const UNREGISTERED_TOPIC_REPUTATION_CHANGE: i32 = -(1 << 10);
|
||||
|
||||
mod rep {
|
||||
use peerset::ReputationChange as Rep;
|
||||
/// Reputation change when a peer sends us a gossip message that we didn't know about.
|
||||
pub const GOSSIP_SUCCESS: Rep = Rep::new(1 << 4, "Successfull gossip");
|
||||
/// Reputation change when a peer sends us a gossip message that we already knew about.
|
||||
pub const DUPLICATE_GOSSIP: Rep = Rep::new(-(1 << 2), "Duplicate gossip");
|
||||
/// Reputation change when a peer sends us a gossip message for an unknown engine, whatever that
|
||||
/// means.
|
||||
pub const UNKNOWN_GOSSIP: Rep = Rep::new(-(1 << 6), "Unknown gossup message engine id");
|
||||
/// Reputation change when a peer sends a message from a topic it isn't registered on.
|
||||
pub const UNREGISTERED_TOPIC: Rep = Rep::new(-(1 << 10), "Unregistered gossip message topic");
|
||||
}
|
||||
|
||||
struct PeerConsensus<H> {
|
||||
known_messages: HashSet<H>,
|
||||
@@ -470,7 +474,7 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
|
||||
if self.known_messages.contains(&message_hash) {
|
||||
trace!(target:"gossip", "Ignored already known message from {}", who);
|
||||
protocol.report_peer(who.clone(), DUPLICATE_GOSSIP_REPUTATION_CHANGE);
|
||||
protocol.report_peer(who.clone(), rep::DUPLICATE_GOSSIP);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -489,14 +493,14 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
Some(ValidationResult::Discard) => None,
|
||||
None => {
|
||||
trace!(target:"gossip", "Unknown message engine id {:?} from {}", engine_id, who);
|
||||
protocol.report_peer(who.clone(), UNKNOWN_GOSSIP_REPUTATION_CHANGE);
|
||||
protocol.report_peer(who.clone(), rep::UNKNOWN_GOSSIP);
|
||||
protocol.disconnect_peer(who.clone());
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some((topic, keep)) = validation_result {
|
||||
protocol.report_peer(who.clone(), GOSSIP_SUCCESS_REPUTATION_CHANGE);
|
||||
protocol.report_peer(who.clone(), rep::GOSSIP_SUCCESS);
|
||||
if let Some(ref mut peer) = self.peers.get_mut(&who) {
|
||||
peer.known_messages.insert(message_hash);
|
||||
if let Entry::Occupied(mut entry) = self.live_message_sinks.entry((engine_id, topic)) {
|
||||
@@ -519,7 +523,7 @@ impl<B: BlockT> ConsensusGossip<B> {
|
||||
}
|
||||
} else {
|
||||
trace!(target:"gossip", "Ignored statement from unregistered peer {}", who);
|
||||
protocol.report_peer(who.clone(), UNREGISTERED_TOPIC_REPUTATION_CHANGE);
|
||||
protocol.report_peer(who.clone(), rep::UNREGISTERED_TOPIC);
|
||||
}
|
||||
} else {
|
||||
trace!(target:"gossip", "Handled valid one hop message from peer {}", who);
|
||||
|
||||
@@ -33,6 +33,7 @@ use crate::message::{self, BlockAttributes, Direction, FromBlock, RequestId};
|
||||
use libp2p::PeerId;
|
||||
use crate::config::Roles;
|
||||
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor};
|
||||
use peerset::ReputationChange;
|
||||
|
||||
/// Remote request timeout.
|
||||
const REQUEST_TIMEOUT: Duration = Duration::from_secs(15);
|
||||
@@ -44,7 +45,7 @@ const TIMEOUT_REPUTATION_CHANGE: i32 = -(1 << 8);
|
||||
/// Trait used by the `LightDispatch` service to communicate messages back to the network.
|
||||
pub trait LightDispatchNetwork<B: BlockT> {
|
||||
/// Adjusts the reputation of the given peer.
|
||||
fn report_peer(&mut self, who: &PeerId, reputation_change: i32);
|
||||
fn report_peer(&mut self, who: &PeerId, reputation_change: ReputationChange);
|
||||
|
||||
/// Disconnect from the given peer. Used in case of misbehaviour.
|
||||
fn disconnect_peer(&mut self, who: &PeerId);
|
||||
@@ -267,7 +268,7 @@ impl<B: BlockT> LightDispatch<B> where
|
||||
Some(request) => request,
|
||||
None => {
|
||||
info!("Invalid remote {} response from peer {}", rtype, peer);
|
||||
network.report_peer(&peer, i32::min_value());
|
||||
network.report_peer(&peer, ReputationChange::new_fatal("Invalid remote response"));
|
||||
network.disconnect_peer(&peer);
|
||||
self.remove_peer(peer);
|
||||
return;
|
||||
@@ -279,7 +280,7 @@ impl<B: BlockT> LightDispatch<B> where
|
||||
Accept::Ok => (retry_count, None),
|
||||
Accept::CheckFailed(error, retry_request_data) => {
|
||||
info!("Failed to check remote {} response from peer {}: {}", rtype, peer, error);
|
||||
network.report_peer(&peer, i32::min_value());
|
||||
network.report_peer(&peer, ReputationChange::new_fatal("Failed remote response check"));
|
||||
network.disconnect_peer(&peer);
|
||||
self.remove_peer(peer);
|
||||
|
||||
@@ -293,7 +294,7 @@ impl<B: BlockT> LightDispatch<B> where
|
||||
},
|
||||
Accept::Unexpected(retry_request_data) => {
|
||||
info!("Unexpected response to remote {} from peer", rtype);
|
||||
network.report_peer(&peer, i32::min_value());
|
||||
network.report_peer(&peer, ReputationChange::new_fatal("Unexpected remote response"));
|
||||
network.disconnect_peer(&peer);
|
||||
self.remove_peer(peer);
|
||||
|
||||
@@ -350,7 +351,7 @@ impl<B: BlockT> LightDispatch<B> where
|
||||
|
||||
let (bad_peer, request) = self.active_peers.pop_front().expect("front() is Some as checked above");
|
||||
self.pending_requests.push_front(request);
|
||||
network.report_peer(&bad_peer, TIMEOUT_REPUTATION_CHANGE);
|
||||
network.report_peer(&bad_peer, ReputationChange::new(TIMEOUT_REPUTATION_CHANGE, "Light request timeout"));
|
||||
network.disconnect_peer(&bad_peer);
|
||||
}
|
||||
|
||||
@@ -800,7 +801,7 @@ pub mod tests {
|
||||
}
|
||||
|
||||
impl<'a, B: BlockT> LightDispatchNetwork<B> for &'a mut DummyNetwork {
|
||||
fn report_peer(&mut self, _: &PeerId, _: i32) {}
|
||||
fn report_peer(&mut self, _: &PeerId, _: crate::ReputationChange) {}
|
||||
fn disconnect_peer(&mut self, who: &PeerId) {
|
||||
self.disconnected_peers.insert(who.clone());
|
||||
}
|
||||
|
||||
@@ -72,29 +72,34 @@ const MAJOR_SYNC_BLOCKS: u8 = 5;
|
||||
/// Number of recently announced blocks to track for each peer.
|
||||
const ANNOUNCE_HISTORY_SIZE: usize = 64;
|
||||
|
||||
/// Reputation change when a peer sent us a status message that led to a
|
||||
/// database read error.
|
||||
const BLOCKCHAIN_STATUS_READ_ERROR_REPUTATION_CHANGE: i32 = -(1 << 16);
|
||||
mod rep {
|
||||
use peerset::ReputationChange as Rep;
|
||||
/// Reputation change when a peer sent us a message that led to a
|
||||
/// database read error.
|
||||
pub const BLOCKCHAIN_READ_ERROR: Rep = Rep::new(-(1 << 16), "DB Error");
|
||||
|
||||
/// Reputation change when a peer failed to answer our legitimate ancestry
|
||||
/// block search.
|
||||
const ANCESTRY_BLOCK_ERROR_REPUTATION_CHANGE: i32 = -(1 << 9);
|
||||
/// Reputation change when a peer sent us a status message with a different
|
||||
/// genesis than us.
|
||||
pub const GENESIS_MISMATCH: Rep = Rep::new(i32::min_value(), "Genesis mismatch");
|
||||
|
||||
/// Reputation change when a peer sent us a status message with a different
|
||||
/// genesis than us.
|
||||
const GENESIS_MISMATCH_REPUTATION_CHANGE: i32 = i32::min_value() + 1;
|
||||
/// Reputation change for peers which send us a block with an incomplete header.
|
||||
pub const INCOMPLETE_HEADER: Rep = Rep::new(-(1 << 20), "Incomplete header");
|
||||
|
||||
/// Reputation change for peers which send us a block with an incomplete header.
|
||||
const INCOMPLETE_HEADER_REPUTATION_CHANGE: i32 = -(1 << 20);
|
||||
/// Reputation change for peers which send us a block which we fail to verify.
|
||||
pub const VERIFICATION_FAIL: Rep = Rep::new(-(1 << 20), "Block verification failed");
|
||||
|
||||
/// Reputation change for peers which send us a block which we fail to verify.
|
||||
const VERIFICATION_FAIL_REPUTATION_CHANGE: i32 = -(1 << 20);
|
||||
/// Reputation change for peers which send us a known bad block.
|
||||
pub const BAD_BLOCK: Rep = Rep::new(-(1 << 29), "Bad block");
|
||||
|
||||
/// Reputation change for peers which send us a bad block.
|
||||
const BAD_BLOCK_REPUTATION_CHANGE: i32 = -(1 << 29);
|
||||
/// Reputation change for peers which send us a block with bad justifications.
|
||||
pub const BAD_JUSTIFICATION: Rep = Rep::new(-(1 << 16), "Bad justification");
|
||||
|
||||
/// Reputation change for peers which send us a block with bad justifications.
|
||||
const BAD_JUSTIFICATION_REPUTATION_CHANGE: i32 = -(1 << 16);
|
||||
/// Reputation change for peers which send us a block with bad finality proof.
|
||||
pub const BAD_FINALITY_PROOF: Rep = Rep::new(-(1 << 16), "Bad finality proof");
|
||||
|
||||
/// Reputation change when a peer sent us invlid ancestry result.
|
||||
pub const UNKNOWN_ANCESTOR:Rep = Rep::new(-(1 << 16), "DB Error");
|
||||
}
|
||||
|
||||
/// The main data structure which contains all the state for a chains
|
||||
/// active syncing strategy.
|
||||
@@ -225,11 +230,11 @@ pub struct Status<B: BlockT> {
|
||||
|
||||
/// A peer did not behave as expected and should be reported.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct BadPeer(pub PeerId, pub i32);
|
||||
pub struct BadPeer(pub PeerId, pub peerset::ReputationChange);
|
||||
|
||||
impl fmt::Display for BadPeer {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "bad peer {}; reputation change: {}", self.0, self.1)
|
||||
write!(f, "Bad peer {}; Reputation change: {:?}", self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,16 +363,16 @@ impl<B: BlockT> ChainSync<B> {
|
||||
match self.block_status(&best_hash) {
|
||||
Err(e) => {
|
||||
debug!(target:"sync", "Error reading blockchain: {:?}", e);
|
||||
Err(BadPeer(who, BLOCKCHAIN_STATUS_READ_ERROR_REPUTATION_CHANGE))
|
||||
Err(BadPeer(who, rep::BLOCKCHAIN_READ_ERROR))
|
||||
}
|
||||
Ok(BlockStatus::KnownBad) => {
|
||||
info!("New peer with known bad best block {} ({}).", best_hash, best_number);
|
||||
Err(BadPeer(who, i32::min_value()))
|
||||
Err(BadPeer(who, rep::BAD_BLOCK))
|
||||
}
|
||||
Ok(BlockStatus::Unknown) => {
|
||||
if best_number.is_zero() {
|
||||
info!("New peer with unknown genesis hash {} ({}).", best_hash, best_number);
|
||||
return Err(BadPeer(who, i32::min_value()))
|
||||
return Err(BadPeer(who, rep::GENESIS_MISMATCH));
|
||||
}
|
||||
// If there are more than `MAJOR_SYNC_BLOCKS` in the import queue then we have
|
||||
// enough to do in the import queue that it's not worth kicking off
|
||||
@@ -688,11 +693,11 @@ impl<B: BlockT> ChainSync<B> {
|
||||
},
|
||||
(None, _) => {
|
||||
debug!(target: "sync", "Invalid response when searching for ancestor from {}", who);
|
||||
return Err(BadPeer(who, i32::min_value()))
|
||||
return Err(BadPeer(who, rep::UNKNOWN_ANCESTOR))
|
||||
},
|
||||
(_, Err(e)) => {
|
||||
info!("Error answering legitimate blockchain query: {:?}", e);
|
||||
return Err(BadPeer(who, ANCESTRY_BLOCK_ERROR_REPUTATION_CHANGE))
|
||||
return Err(BadPeer(who, rep::BLOCKCHAIN_READ_ERROR))
|
||||
}
|
||||
};
|
||||
if matching_hash.is_some() && peer.common_number < *num {
|
||||
@@ -700,7 +705,7 @@ impl<B: BlockT> ChainSync<B> {
|
||||
}
|
||||
if matching_hash.is_none() && num.is_zero() {
|
||||
trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who);
|
||||
return Err(BadPeer(who, GENESIS_MISMATCH_REPUTATION_CHANGE))
|
||||
return Err(BadPeer(who, rep::GENESIS_MISMATCH))
|
||||
}
|
||||
if let Some((next_state, next_num)) = handle_ancestor_search_state(state, *num, matching_hash.is_some()) {
|
||||
peer.state = PeerSyncState::AncestorSearch(next_num, next_state);
|
||||
@@ -790,9 +795,10 @@ impl<B: BlockT> ChainSync<B> {
|
||||
if let Some(block) = response.blocks.into_iter().next() {
|
||||
if hash != block.hash {
|
||||
info!(
|
||||
target: "sync",
|
||||
"Invalid block justification provided by {}: requested: {:?} got: {:?}", who, hash, block.hash
|
||||
);
|
||||
return Err(BadPeer(who, i32::min_value()))
|
||||
return Err(BadPeer(who, rep::BAD_JUSTIFICATION));
|
||||
}
|
||||
if let Some((peer, hash, number, j)) = self.extra_justifications.on_response(who, block.justification) {
|
||||
return Ok(OnBlockJustification::Import { peer, hash, number, justification: j })
|
||||
@@ -825,8 +831,13 @@ impl<B: BlockT> ChainSync<B> {
|
||||
|
||||
// We only request one finality proof at a time.
|
||||
if hash != resp.block {
|
||||
info!("Invalid block finality proof provided: requested: {:?} got: {:?}", hash, resp.block);
|
||||
return Err(BadPeer(who, i32::min_value()))
|
||||
info!(
|
||||
target: "sync",
|
||||
"Invalid block finality proof provided: requested: {:?} got: {:?}",
|
||||
hash,
|
||||
resp.block
|
||||
);
|
||||
return Err(BadPeer(who, rep::BAD_FINALITY_PROOF));
|
||||
}
|
||||
|
||||
if let Some((peer, hash, number, p)) = self.extra_finality_proofs.on_response(who, resp.proof) {
|
||||
@@ -887,7 +898,7 @@ impl<B: BlockT> ChainSync<B> {
|
||||
if aux.bad_justification {
|
||||
if let Some(peer) = who {
|
||||
info!("Sent block with bad justification to import");
|
||||
output.push(Err(BadPeer(peer, BAD_JUSTIFICATION_REPUTATION_CHANGE)));
|
||||
output.push(Err(BadPeer(peer, rep::BAD_JUSTIFICATION)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -903,21 +914,21 @@ impl<B: BlockT> ChainSync<B> {
|
||||
Err(BlockImportError::IncompleteHeader(who)) => {
|
||||
if let Some(peer) = who {
|
||||
info!("Peer sent block with incomplete header to import");
|
||||
output.push(Err(BadPeer(peer, INCOMPLETE_HEADER_REPUTATION_CHANGE)));
|
||||
output.push(Err(BadPeer(peer, rep::INCOMPLETE_HEADER)));
|
||||
output.extend(self.restart());
|
||||
}
|
||||
},
|
||||
Err(BlockImportError::VerificationFailed(who, e)) => {
|
||||
if let Some(peer) = who {
|
||||
info!("Verification failed from peer: {}", e);
|
||||
output.push(Err(BadPeer(peer, VERIFICATION_FAIL_REPUTATION_CHANGE)));
|
||||
output.push(Err(BadPeer(peer, rep::VERIFICATION_FAIL)));
|
||||
output.extend(self.restart());
|
||||
}
|
||||
},
|
||||
Err(BlockImportError::BadBlock(who)) => {
|
||||
if let Some(peer) = who {
|
||||
info!("Bad block");
|
||||
output.push(Err(BadPeer(peer, BAD_BLOCK_REPUTATION_CHANGE)));
|
||||
output.push(Err(BadPeer(peer, rep::BAD_BLOCK)));
|
||||
output.extend(self.restart());
|
||||
}
|
||||
},
|
||||
|
||||
@@ -42,7 +42,7 @@ use sp_runtime::{traits::{Block as BlockT, NumberFor}, ConsensusEngineId};
|
||||
|
||||
use crate::{behaviour::{Behaviour, BehaviourOut}, config::{parse_str_addr, parse_addr}};
|
||||
use crate::{NetworkState, NetworkStateNotConnectedPeer, NetworkStatePeer};
|
||||
use crate::{transport, config::NonReservedPeerMode};
|
||||
use crate::{transport, config::NonReservedPeerMode, ReputationChange};
|
||||
use crate::config::{Params, TransportConfig};
|
||||
use crate::error::Error;
|
||||
use crate::protocol::{self, Protocol, Context, CustomMessageOutcome, PeerInfo};
|
||||
@@ -71,8 +71,8 @@ pub trait TransactionPool<H: ExHashT, B: BlockT>: Send + Sync {
|
||||
&self,
|
||||
report_handle: ReportHandle,
|
||||
who: PeerId,
|
||||
reputation_change_good: i32,
|
||||
reputation_change_bad: i32,
|
||||
reputation_change_good: ReputationChange,
|
||||
reputation_change_bad: ReputationChange,
|
||||
transaction: B::Extrinsic,
|
||||
);
|
||||
/// Notify the pool about transactions broadcast.
|
||||
@@ -94,7 +94,7 @@ impl From<PeersetHandle> for ReportHandle {
|
||||
impl ReportHandle {
|
||||
/// Report a given peer as either beneficial (+) or costly (-) according to the
|
||||
/// given scalar.
|
||||
pub fn report_peer(&self, who: PeerId, cost_benefit: i32) {
|
||||
pub fn report_peer(&self, who: PeerId, cost_benefit: ReputationChange) {
|
||||
self.inner.report_peer(who, cost_benefit);
|
||||
}
|
||||
}
|
||||
@@ -449,7 +449,7 @@ impl<B: BlockT + 'static, S: NetworkSpecialization<B>, H: ExHashT> NetworkServic
|
||||
|
||||
/// Report a given peer as either beneficial (+) or costly (-) according to the
|
||||
/// given scalar.
|
||||
pub fn report_peer(&self, who: PeerId, cost_benefit: i32) {
|
||||
pub fn report_peer(&self, who: PeerId, cost_benefit: ReputationChange) {
|
||||
self.peerset.report_peer(who, cost_benefit);
|
||||
}
|
||||
|
||||
@@ -786,7 +786,7 @@ impl<'a, B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Link<B> for Network
|
||||
if !success {
|
||||
info!("Invalid justification provided by {} for #{}", who, hash);
|
||||
self.protocol.user_protocol_mut().disconnect_peer(&who);
|
||||
self.protocol.user_protocol_mut().report_peer(who, i32::min_value());
|
||||
self.protocol.user_protocol_mut().report_peer(who, ReputationChange::new_fatal("Invalid justification"));
|
||||
}
|
||||
}
|
||||
fn request_justification(&mut self, hash: &B::Hash, number: NumberFor<B>) {
|
||||
@@ -806,7 +806,7 @@ impl<'a, B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Link<B> for Network
|
||||
if !success {
|
||||
info!("Invalid finality proof provided by {} for #{}", who, request_block.0);
|
||||
self.protocol.user_protocol_mut().disconnect_peer(&who);
|
||||
self.protocol.user_protocol_mut().report_peer(who, i32::min_value());
|
||||
self.protocol.user_protocol_mut().report_peer(who, ReputationChange::new_fatal("Invalid finality proof"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,8 +401,8 @@ impl TransactionPool<Hash, Block> for EmptyTransactionPool {
|
||||
&self,
|
||||
_report_handle: ReportHandle,
|
||||
_who: PeerId,
|
||||
_rep_change_good: i32,
|
||||
_rep_change_bad: i32,
|
||||
_rep_change_good: crate::ReputationChange,
|
||||
_rep_change_bad: crate::ReputationChange,
|
||||
_transaction: Extrinsic
|
||||
) {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user