kick stuck peer out of connected peers. (#1782)

* cherry-picking commit 7754adb8 from master for #1746
This commit is contained in:
Gary Yu 2018-10-18 10:04:05 +08:00 committed by GitHub
parent d65a9adb59
commit 53b10a083c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 31 additions and 1 deletions

View file

@ -66,6 +66,10 @@ pub const TESTNET2_INITIAL_DIFFICULTY: u64 = 1000;
/// a 30x Cuckoo adjustment factor /// a 30x Cuckoo adjustment factor
pub const TESTNET3_INITIAL_DIFFICULTY: u64 = 30000; pub const TESTNET3_INITIAL_DIFFICULTY: u64 = 30000;
/// If a peer's last updated difficulty is 2 hours ago and its difficulty's lower than ours,
/// we're sure this peer is a stuck node, and we will kick out such kind of stuck peers.
pub const STUCK_PEER_KICK_TIME: i64 = 2 * 3600 * 1000;
/// Testnet 4 initial block difficulty /// Testnet 4 initial block difficulty
/// 1_000 times natural scale factor for cuckatoo29 /// 1_000 times natural scale factor for cuckatoo29
pub const TESTNET4_INITIAL_DIFFICULTY: u64 = 1_000 * (2<<(29-24)) * 29; pub const TESTNET4_INITIAL_DIFFICULTY: u64 = 1_000 * (2<<(29-24)) * 29;

View file

@ -102,6 +102,7 @@ impl Handshake {
total_difficulty: shake.total_difficulty, total_difficulty: shake.total_difficulty,
height: 0, height: 0,
last_seen: Utc::now(), last_seen: Utc::now(),
stuck_detector: Utc::now(),
})), })),
direction: Direction::Outbound, direction: Direction::Outbound,
}; };
@ -161,6 +162,7 @@ impl Handshake {
total_difficulty: hand.total_difficulty, total_difficulty: hand.total_difficulty,
height: 0, height: 0,
last_seen: Utc::now(), last_seen: Utc::now(),
stuck_detector: Utc::now(),
})), })),
direction: Direction::Inbound, direction: Direction::Inbound,
}; };

View file

@ -18,9 +18,9 @@ use std::sync::{Arc, RwLock};
use chrono::prelude::{DateTime, Utc}; use chrono::prelude::{DateTime, Utc};
use conn; use conn;
use core::core;
use core::core::hash::{Hash, Hashed}; use core::core::hash::{Hash, Hashed};
use core::pow::Difficulty; use core::pow::Difficulty;
use core::{core, global};
use handshake::Handshake; use handshake::Handshake;
use msg::{self, BanReason, GetPeerAddrs, Locator, Ping, TxHashSetRequest}; use msg::{self, BanReason, GetPeerAddrs, Locator, Ping, TxHashSetRequest};
use protocol::Protocol; use protocol::Protocol;
@ -140,6 +140,18 @@ impl Peer {
State::Banned == *self.state.read().unwrap() State::Banned == *self.state.read().unwrap()
} }
/// Whether this peer is stuck on sync.
pub fn is_stuck(&self) -> (bool, Difficulty) {
let peer_live_info = self.info.live_info.read().unwrap();
let now = Utc::now().timestamp_millis();
// if last updated difficulty is 2 hours ago, we're sure this peer is a stuck node.
if now > peer_live_info.stuck_detector.timestamp_millis() + global::STUCK_PEER_KICK_TIME {
(true, peer_live_info.total_difficulty)
} else {
(false, peer_live_info.total_difficulty)
}
}
/// Set this peer status to banned /// Set this peer status to banned
pub fn set_banned(&self) { pub fn set_banned(&self) {
*self.state.write().unwrap() = State::Banned; *self.state.write().unwrap() = State::Banned;

View file

@ -424,6 +424,14 @@ impl Peers {
} else if !peer.is_connected() { } else if !peer.is_connected() {
debug!(LOGGER, "clean_peers {:?}, not connected", peer.info.addr); debug!(LOGGER, "clean_peers {:?}, not connected", peer.info.addr);
rm.push(peer.clone()); rm.push(peer.clone());
} else {
let (stuck, diff) = peer.is_stuck();
if stuck && diff < self.adapter.total_difficulty() {
debug!(LOGGER, "clean_peers {:?}, stuck peer", peer.info.addr);
peer.stop();
let _ = self.update_state(peer.info.addr, State::Defunct);
rm.push(peer.clone());
}
} }
} }

View file

@ -241,6 +241,7 @@ pub struct PeerLiveInfo {
pub total_difficulty: Difficulty, pub total_difficulty: Difficulty,
pub height: u64, pub height: u64,
pub last_seen: DateTime<Utc>, pub last_seen: DateTime<Utc>,
pub stuck_detector: DateTime<Utc>,
} }
/// General information about a connected peer that's useful to other modules. /// General information about a connected peer that's useful to other modules.
@ -274,6 +275,9 @@ impl PeerInfo {
/// Takes a write lock on the live_info. /// Takes a write lock on the live_info.
pub fn update(&self, height: u64, total_difficulty: Difficulty) { pub fn update(&self, height: u64, total_difficulty: Difficulty) {
let mut live_info = self.live_info.write().unwrap(); let mut live_info = self.live_info.write().unwrap();
if total_difficulty != live_info.total_difficulty {
live_info.stuck_detector = Utc::now();
}
live_info.height = height; live_info.height = height;
live_info.total_difficulty = total_difficulty; live_info.total_difficulty = total_difficulty;
live_info.last_seen = Utc::now() live_info.last_seen = Utc::now()