Add reputation system to network crate (#2454)

This commit is contained in:
Pierre Krieger
2019-05-04 13:51:06 +02:00
committed by Gavin Wood
parent 18ec2d14d0
commit 8ca343ca8c
10 changed files with 166 additions and 168 deletions
+28 -20
View File
@@ -17,10 +17,10 @@
use std::cmp::max;
use std::collections::{HashMap, VecDeque};
use std::time::{Duration, Instant};
use log::{debug, trace, warn};
use log::{debug, trace, info, warn};
use crate::protocol::Context;
use fork_tree::ForkTree;
use network_libp2p::{Severity, PeerId};
use network_libp2p::PeerId;
use client::{BlockStatus, ClientInfo};
use consensus::BlockOrigin;
use consensus::import_queue::{ImportQueue, IncomingBlock};
@@ -47,6 +47,12 @@ const JUSTIFICATION_RETRY_WAIT: Duration = Duration::from_secs(10);
const ANNOUNCE_HISTORY_SIZE: usize = 64;
// Max number of blocks to download for unknown forks.
const MAX_UNKNOWN_FORK_DOWNLOAD_LEN: u32 = 32;
/// 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);
/// 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.
const GENESIS_MISMATCH_REPUTATION_CHANGE: i32 = i32::min_value() + 1;
#[derive(Debug)]
struct PeerSync<B: BlockT> {
@@ -470,16 +476,18 @@ impl<B: BlockT> ChainSync<B> {
match (status, info.best_number) {
(Err(e), _) => {
debug!(target:"sync", "Error reading blockchain: {:?}", e);
let reason = format!("Error legimimately reading blockchain status: {:?}", e);
protocol.report_peer(who, Severity::Useless(reason));
protocol.report_peer(who.clone(), BLOCKCHAIN_STATUS_READ_ERROR_REPUTATION_CHANGE);
protocol.disconnect_peer(who);
},
(Ok(BlockStatus::KnownBad), _) => {
let reason = format!("New peer with known bad best block {} ({}).", info.best_hash, info.best_number);
protocol.report_peer(who, Severity::Bad(reason));
info!("New peer with known bad best block {} ({}).", info.best_hash, info.best_number);
protocol.report_peer(who.clone(), i32::min_value());
protocol.disconnect_peer(who);
},
(Ok(BlockStatus::Unknown), b) if b == As::sa(0) => {
let reason = format!("New peer with unknown genesis hash {} ({}).", info.best_hash, info.best_number);
protocol.report_peer(who, Severity::Bad(reason));
info!("New peer with unknown genesis hash {} ({}).", info.best_hash, info.best_number);
protocol.report_peer(who.clone(), i32::min_value());
protocol.disconnect_peer(who);
},
(Ok(BlockStatus::Unknown), _) if self.queue_blocks.len() > MAJOR_SYNC_BLOCKS => {
// when actively syncing the common point moves too fast.
@@ -638,13 +646,15 @@ impl<B: BlockT> ChainSync<B> {
maybe_our_block_hash.map_or(false, |x| x == block.hash)
},
(None, _) => {
trace!(target:"sync", "Invalid response when searching for ancestor from {}", who);
protocol.report_peer(who, Severity::Bad("Invalid response when searching for ancestor".to_string()));
debug!(target: "sync", "Invalid response when searching for ancestor from {}", who);
protocol.report_peer(who.clone(), i32::min_value());
protocol.disconnect_peer(who);
return;
},
(_, Err(e)) => {
let reason = format!("Error answering legitimate blockchain query: {:?}", e);
protocol.report_peer(who, Severity::Useless(reason));
info!("Error answering legitimate blockchain query: {:?}", e);
protocol.report_peer(who.clone(), ANCESTRY_BLOCK_ERROR_REPUTATION_CHANGE);
protocol.disconnect_peer(who);
return;
},
};
@@ -653,7 +663,8 @@ impl<B: BlockT> ChainSync<B> {
}
if !block_hash_match && num == As::sa(0) {
trace!(target:"sync", "Ancestry search: genesis mismatch for peer {}", who);
protocol.report_peer(who, Severity::Bad("Ancestry search: genesis mismatch for peer".to_string()));
protocol.report_peer(who.clone(), GENESIS_MISMATCH_REPUTATION_CHANGE);
protocol.disconnect_peer(who);
return;
}
if let Some((next_state, next_block_num)) = Self::handle_ancestor_search_state(state, num, block_hash_match) {
@@ -710,13 +721,10 @@ impl<B: BlockT> ChainSync<B> {
match response.blocks.into_iter().next() {
Some(response) => {
if hash != response.hash {
let msg = format!(
"Invalid block justification provided: requested: {:?} got: {:?}",
hash,
response.hash,
);
protocol.report_peer(who, Severity::Bad(msg));
info!("Invalid block justification provided by {}: requested: {:?} got: {:?}",
who, hash, response.hash);
protocol.report_peer(who.clone(), i32::min_value());
protocol.disconnect_peer(who);
return;
}