penalize for unknown headers

This commit is contained in:
Svyatoslav Nikolsky 2019-03-21 10:06:03 +03:00
parent b69ef3eada
commit 746dcf503a
3 changed files with 42 additions and 11 deletions

View File

@ -280,7 +280,20 @@ impl<T> ClientCore for SynchronizationClientCore<T> where T: TaskExecutor {
// => all headers are also unknown to us
let header0 = headers[0].clone();
if self.chain.block_state(&header0.raw.previous_header_hash) == BlockState::Unknown {
warn!(target: "sync", "Previous header of the first header from peer#{} `headers` message is unknown. First: {}. Previous: {}", peer_index, header0.hash.to_reversed_str(), header0.raw.previous_header_hash.to_reversed_str());
warn!(
target: "sync",
"Previous header of the first header from peer#{} `headers` message is unknown. First: {}. Previous: {}",
peer_index,
header0.hash.to_reversed_str(),
header0.raw.previous_header_hash.to_reversed_str(),
);
// there could be competing chains that are running the network with the same magic (like Zcash vs ZelCash)
// => providing unknown headers. Penalize node so that it'll disconnect
if self.peers_tasks.penalize(peer_index) {
self.peers.misbehaving(peer_index, "Too many failures.");
}
return;
}

View File

@ -316,7 +316,7 @@ mod tests {
use std::collections::HashSet;
use primitives::hash::H256;
use synchronization_peers::PeersImpl;
use synchronization_peers_tasks::PeersTasks;
use synchronization_peers_tasks::{PeersTasks, TrustLevel};
use super::{ManagePeersConfig, ManageUnknownBlocksConfig, ManageOrphanTransactionsConfig, manage_synchronization_peers_blocks,
manage_unknown_orphaned_blocks, manage_orphaned_transactions};
use utils::{OrphanBlocksPool, OrphanTransactionsPool};
@ -335,10 +335,12 @@ mod tests {
fn manage_bad_peers() {
use std::thread::sleep;
use std::time::Duration;
let config = ManagePeersConfig { new_block_failure_interval_ms: 0, ..Default::default() };
let config = ManagePeersConfig { trusted_block_failure_interval_ms: 0, ..Default::default() };
let mut peers = PeersTasks::default();
peers.on_blocks_requested(1, &vec![H256::from(0)]);
peers.on_blocks_requested(2, &vec![H256::from(1)]);
peers.get_peer_stats_mut(1).unwrap().set_trust(TrustLevel::Trusted);
peers.get_peer_stats_mut(2).unwrap().set_trust(TrustLevel::Trusted);
sleep(Duration::from_millis(1));
let managed_tasks = manage_synchronization_peers_blocks(&config, Arc::new(PeersImpl::default()), &mut peers).0;

View File

@ -154,6 +154,12 @@ impl PeersTasks {
self.stats.get(&peer_index)
}
/// Get mutable reference to peer statistics
#[cfg(test)]
pub fn get_peer_stats_mut(&mut self, peer_index: PeerIndex) -> Option<&mut PeerStats> {
self.stats.get_mut(&peer_index)
}
/// Mark peer as useful.
pub fn useful_peer(&mut self, peer_index: PeerIndex) {
// if peer is unknown => insert to idle queue
@ -304,12 +310,7 @@ impl PeersTasks {
/// We have failed to get block from peer during given period
pub fn on_peer_block_failure(&mut self, peer_index: PeerIndex) -> bool {
self.stats.get_mut(&peer_index)
.map(|s| {
s.failures += 1;
s.failures > MAX_PEER_FAILURES
})
.unwrap_or_default()
self.penalize(peer_index)
}
/// We have failed to get headers from peer during given period
@ -318,10 +319,20 @@ impl PeersTasks {
self.headers_requests.remove(&peer_index);
self.idle_for_headers.insert(peer_index);
self.penalize(peer_index)
}
/// Penalize peer. Returns true if the peer score is too low to keep connection.
pub fn penalize(&mut self, peer_index: PeerIndex) -> bool {
self.stats.get_mut(&peer_index)
.map(|s| {
s.failures += 1;
s.failures > MAX_PEER_FAILURES
if s.trust == TrustLevel::Trusted {
s.failures += 1;
s.failures > MAX_PEER_FAILURES
} else {
s.failures = MAX_PEER_FAILURES;
true
}
})
.unwrap_or_default()
}
@ -374,6 +385,11 @@ impl PeerStats {
pub fn trust(&self) -> TrustLevel {
self.trust
}
#[cfg(test)]
pub fn set_trust(&mut self, trust: TrustLevel) {
self.trust = trust;
}
}
impl fmt::Debug for Information {