mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-20 19:11:08 +03:00
prefer outbound peers when syncing (consistently) (#3521)
but use inbound peer for header and body sync if necessary sync state from inbound peer if no outbound peers to sync from
This commit is contained in:
parent
acba73bf40
commit
1baa59c44d
6 changed files with 69 additions and 44 deletions
|
@ -128,13 +128,6 @@ impl Peers {
|
||||||
self.iter().connected().by_addr(addr)
|
self.iter().connected().by_addr(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_peer_difficulty(&self) -> Difficulty {
|
|
||||||
self.iter()
|
|
||||||
.connected()
|
|
||||||
.max_difficulty()
|
|
||||||
.unwrap_or(Difficulty::zero())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_banned(&self, peer_addr: PeerAddr) -> bool {
|
pub fn is_banned(&self, peer_addr: PeerAddr) -> bool {
|
||||||
if let Ok(peer) = self.store.get_peer(peer_addr) {
|
if let Ok(peer) = self.store.get_peer(peer_addr) {
|
||||||
return peer.flags == State::Banned;
|
return peer.flags == State::Banned;
|
||||||
|
|
|
@ -26,6 +26,7 @@ use std::sync::{mpsc, Arc};
|
||||||
use std::{cmp, str, thread, time};
|
use std::{cmp, str, thread, time};
|
||||||
|
|
||||||
use crate::core::global;
|
use crate::core::global;
|
||||||
|
use crate::core::pow::Difficulty;
|
||||||
use crate::p2p;
|
use crate::p2p;
|
||||||
use crate::p2p::types::PeerAddr;
|
use crate::p2p::types::PeerAddr;
|
||||||
use crate::p2p::ChainAdapter;
|
use crate::p2p::ChainAdapter;
|
||||||
|
@ -172,15 +173,10 @@ fn monitor_peers(
|
||||||
total_count += 1;
|
total_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let peers_count = peers.iter().connected().count();
|
let peers_iter = || peers.iter().connected();
|
||||||
|
let peers_count = peers_iter().count();
|
||||||
let max_diff = peers.max_peer_difficulty();
|
let max_diff = peers_iter().max_difficulty().unwrap_or(Difficulty::zero());
|
||||||
let most_work_count = peers
|
let most_work_count = peers_iter().with_difficulty(|x| x >= max_diff).count();
|
||||||
.iter()
|
|
||||||
.outbound()
|
|
||||||
.with_difficulty(|x| x >= max_diff)
|
|
||||||
.connected()
|
|
||||||
.count();
|
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"monitor_peers: on {}:{}, {} connected ({} most_work). \
|
"monitor_peers: on {}:{}, {} connected ({} most_work). \
|
||||||
|
|
|
@ -93,14 +93,25 @@ impl BodySync {
|
||||||
let head = self.chain.head()?;
|
let head = self.chain.head()?;
|
||||||
|
|
||||||
// Find connected peers with strictly greater difficulty than us.
|
// Find connected peers with strictly greater difficulty than us.
|
||||||
let peers: Vec<_> = self
|
let peers_iter = || {
|
||||||
.peers
|
self.peers
|
||||||
.iter()
|
.iter()
|
||||||
.outbound()
|
.with_difficulty(|x| x > head.total_difficulty)
|
||||||
.with_difficulty(|x| x > head.total_difficulty)
|
.connected()
|
||||||
.connected()
|
};
|
||||||
.into_iter()
|
|
||||||
.collect();
|
// We prefer outbound peers with greater difficulty.
|
||||||
|
let mut peers: Vec<_> = peers_iter().outbound().into_iter().collect();
|
||||||
|
if peers.is_empty() {
|
||||||
|
debug!("no outbound peers with more work, considering inbound");
|
||||||
|
peers = peers_iter().inbound().into_iter().collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have no peers (outbound or inbound) then we are done for now.
|
||||||
|
if peers.is_empty() {
|
||||||
|
debug!("no peers (inbound or outbound) with more work");
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
// if we have 5 peers to sync from then ask for 50 blocks total (peer_count *
|
// if we have 5 peers to sync from then ask for 50 blocks total (peer_count *
|
||||||
// 10) max will be 80 if all 8 peers are advertising more work
|
// 10) max will be 80 if all 8 peers are advertising more work
|
||||||
|
|
|
@ -19,6 +19,7 @@ use std::sync::Arc;
|
||||||
use crate::chain::{self, SyncState, SyncStatus};
|
use crate::chain::{self, SyncState, SyncStatus};
|
||||||
use crate::common::types::Error;
|
use crate::common::types::Error;
|
||||||
use crate::core::core::hash::{Hash, Hashed};
|
use crate::core::core::hash::{Hash, Hashed};
|
||||||
|
use crate::core::pow::Difficulty;
|
||||||
use crate::p2p::{self, types::ReasonForBan, Capabilities, Peer};
|
use crate::p2p::{self, types::ReasonForBan, Capabilities, Peer};
|
||||||
|
|
||||||
pub struct HeaderSync {
|
pub struct HeaderSync {
|
||||||
|
@ -170,15 +171,23 @@ impl HeaderSync {
|
||||||
|
|
||||||
fn header_sync(&mut self) -> Option<Arc<Peer>> {
|
fn header_sync(&mut self) -> Option<Arc<Peer>> {
|
||||||
if let Ok(header_head) = self.chain.header_head() {
|
if let Ok(header_head) = self.chain.header_head() {
|
||||||
let max_diff = self.peers.max_peer_difficulty();
|
let peers_iter = || {
|
||||||
let peer = self
|
self.peers
|
||||||
.peers
|
.iter()
|
||||||
.iter()
|
.with_capabilities(Capabilities::HEADER_HIST)
|
||||||
.outbound()
|
.connected()
|
||||||
.with_capabilities(Capabilities::HEADER_HIST)
|
};
|
||||||
.with_difficulty(|x| x >= max_diff)
|
|
||||||
.connected()
|
// Filter peers further based on max difficulty.
|
||||||
.choose_random();
|
let max_diff = peers_iter().max_difficulty().unwrap_or(Difficulty::zero());
|
||||||
|
let peers_iter = || peers_iter().with_difficulty(|x| x >= max_diff);
|
||||||
|
|
||||||
|
// Choose a random "most work" peer, preferring outbound if at all possible.
|
||||||
|
let peer = peers_iter().outbound().choose_random().or_else(|| {
|
||||||
|
warn!("no suitable outbound peer for header sync, considering inbound");
|
||||||
|
peers_iter().inbound().choose_random()
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(peer) = peer {
|
if let Some(peer) = peer {
|
||||||
if peer.info.total_difficulty() > header_head.total_difficulty {
|
if peer.info.total_difficulty() > header_head.total_difficulty {
|
||||||
return self.request_headers(peer);
|
return self.request_headers(peer);
|
||||||
|
|
|
@ -19,6 +19,7 @@ use std::sync::Arc;
|
||||||
use crate::chain::{self, SyncState, SyncStatus};
|
use crate::chain::{self, SyncState, SyncStatus};
|
||||||
use crate::core::core::hash::Hashed;
|
use crate::core::core::hash::Hashed;
|
||||||
use crate::core::global;
|
use crate::core::global;
|
||||||
|
use crate::core::pow::Difficulty;
|
||||||
use crate::p2p::{self, Capabilities, Peer};
|
use crate::p2p::{self, Capabilities, Peer};
|
||||||
|
|
||||||
/// Fast sync has 3 "states":
|
/// Fast sync has 3 "states":
|
||||||
|
@ -158,15 +159,23 @@ impl StateSync {
|
||||||
let mut txhashset_height = header_head.height.saturating_sub(threshold);
|
let mut txhashset_height = header_head.height.saturating_sub(threshold);
|
||||||
txhashset_height = txhashset_height.saturating_sub(txhashset_height % archive_interval);
|
txhashset_height = txhashset_height.saturating_sub(txhashset_height % archive_interval);
|
||||||
|
|
||||||
let max_diff = self.peers.max_peer_difficulty();
|
let peers_iter = || {
|
||||||
let peer = self
|
self.peers
|
||||||
.peers
|
.iter()
|
||||||
.iter()
|
.with_capabilities(Capabilities::TXHASHSET_HIST)
|
||||||
.outbound()
|
.connected()
|
||||||
.with_capabilities(Capabilities::TXHASHSET_HIST)
|
};
|
||||||
.with_difficulty(|x| x >= max_diff)
|
|
||||||
.connected()
|
// Filter peers further based on max difficulty.
|
||||||
.choose_random();
|
let max_diff = peers_iter().max_difficulty().unwrap_or(Difficulty::zero());
|
||||||
|
let peers_iter = || peers_iter().with_difficulty(|x| x >= max_diff);
|
||||||
|
|
||||||
|
// Choose a random "most work" peer, preferring outbound if at all possible.
|
||||||
|
let peer = peers_iter().outbound().choose_random().or_else(|| {
|
||||||
|
warn!("no suitable outbound peer for state sync, considering inbound");
|
||||||
|
peers_iter().inbound().choose_random()
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(peer) = peer {
|
if let Some(peer) = peer {
|
||||||
// ask for txhashset at state_sync_threshold
|
// ask for txhashset at state_sync_threshold
|
||||||
let mut txhashset_head = self
|
let mut txhashset_head = self
|
||||||
|
|
|
@ -231,11 +231,18 @@ impl SyncRunner {
|
||||||
let mut is_syncing = self.sync_state.is_syncing();
|
let mut is_syncing = self.sync_state.is_syncing();
|
||||||
|
|
||||||
// Find a peer with greatest known difficulty.
|
// Find a peer with greatest known difficulty.
|
||||||
let max_diff = self.peers.max_peer_difficulty();
|
// Consider all peers, both inbound and outbound.
|
||||||
|
// We will prioritize syncing against outbound peers exclusively when possible.
|
||||||
|
// But we do support syncing against an inbound peer if greater work than any outbound peers.
|
||||||
|
let max_diff = self
|
||||||
|
.peers
|
||||||
|
.iter()
|
||||||
|
.connected()
|
||||||
|
.max_difficulty()
|
||||||
|
.unwrap_or(Difficulty::zero());
|
||||||
let peer = self
|
let peer = self
|
||||||
.peers
|
.peers
|
||||||
.iter()
|
.iter()
|
||||||
.outbound()
|
|
||||||
.with_difficulty(|x| x >= max_diff)
|
.with_difficulty(|x| x >= max_diff)
|
||||||
.connected()
|
.connected()
|
||||||
.choose_random();
|
.choose_random();
|
||||||
|
|
Loading…
Reference in a new issue