@ -168,6 +168,8 @@ struct CNodeState {
@@ -168,6 +168,8 @@ struct CNodeState {
int nUnconnectingHeaders ;
//! Whether we've started headers synchronization with this peer.
bool fSyncStarted ;
//! When to potentially disconnect peer for stalling headers download
int64_t nHeadersSyncTimeout ;
//! Since when we're stalling block download progress (in microseconds), or 0.
int64_t nStallingSince ;
std : : list < QueuedBlock > vBlocksInFlight ;
@ -207,6 +209,7 @@ struct CNodeState {
@@ -207,6 +209,7 @@ struct CNodeState {
pindexBestHeaderSent = NULL ;
nUnconnectingHeaders = 0 ;
fSyncStarted = false ;
nHeadersSyncTimeout = 0 ;
nStallingSince = 0 ;
nDownloadingSince = 0 ;
nBlocksInFlight = 0 ;
@ -2883,6 +2886,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
@@ -2883,6 +2886,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
// Only actively request headers from a single peer, unless we're close to today.
if ( ( nSyncStarted = = 0 & & fFetch ) | | pindexBestHeader - > GetBlockTime ( ) > GetAdjustedTime ( ) - 24 * 60 * 60 ) {
state . fSyncStarted = true ;
state . nHeadersSyncTimeout = GetTimeMicros ( ) + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * ( GetAdjustedTime ( ) - pindexBestHeader - > GetBlockTime ( ) ) / ( consensusParams . nPowTargetSpacing ) ;
nSyncStarted + + ;
const CBlockIndex * pindexStart = pindexBestHeader ;
/* If possible, start at the block preceding the currently
@ -3206,6 +3210,39 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
@@ -3206,6 +3210,39 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
return true ;
}
}
// Check for headers sync timeouts
if ( state . fSyncStarted & & state . nHeadersSyncTimeout < std : : numeric_limits < int64_t > : : max ( ) ) {
// Detect whether this is a stalling initial-headers-sync peer
if ( pindexBestHeader - > GetBlockTime ( ) < = GetAdjustedTime ( ) - 24 * 60 * 60 ) {
if ( nNow > state . nHeadersSyncTimeout & & nSyncStarted = = 1 & & ( nPreferredDownload - state . fPreferredDownload > = 1 ) ) {
// Disconnect a (non-whitelisted) peer if it is our only sync peer,
// and we have others we could be using instead.
// Note: If all our peers are inbound, then we won't
// disconnect our sync peer for stalling; we have bigger
// problems if we can't get any outbound peers.
if ( ! pto - > fWhitelisted ) {
LogPrintf ( " Timeout downloading headers from peer=%d, disconnecting \n " , pto - > GetId ( ) ) ;
pto - > fDisconnect = true ;
return true ;
} else {
LogPrintf ( " Timeout downloading headers from whitelisted peer=%d, not disconnecting \n " , pto - > GetId ( ) ) ;
// Reset the headers sync state so that we have a
// chance to try downloading from a different peer.
// Note: this will also result in at least one more
// getheaders message to be sent to
// this peer (eventually).
state . fSyncStarted = false ;
nSyncStarted - - ;
state . nHeadersSyncTimeout = 0 ;
}
}
} else {
// After we've caught up once, reset the timeout so we can't trigger
// disconnect later.
state . nHeadersSyncTimeout = std : : numeric_limits < int64_t > : : max ( ) ;
}
}
//
// Message: getdata (blocks)