@@ -168,6 +168,8 @@ struct CNodeState {
168
168
int nUnconnectingHeaders;
169
169
// ! Whether we've started headers synchronization with this peer.
170
170
bool fSyncStarted ;
171
+ // ! When to potentially disconnect peer for stalling headers download
172
+ int64_t nHeadersSyncTimeout;
171
173
// ! Since when we're stalling block download progress (in microseconds), or 0.
172
174
int64_t nStallingSince;
173
175
std::list<QueuedBlock> vBlocksInFlight;
@@ -207,6 +209,7 @@ struct CNodeState {
207
209
pindexBestHeaderSent = NULL ;
208
210
nUnconnectingHeaders = 0 ;
209
211
fSyncStarted = false ;
212
+ nHeadersSyncTimeout = 0 ;
210
213
nStallingSince = 0 ;
211
214
nDownloadingSince = 0 ;
212
215
nBlocksInFlight = 0 ;
@@ -481,7 +484,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<con
481
484
// Make sure pindexBestKnownBlock is up to date, we'll need it.
482
485
ProcessBlockAvailability (nodeid);
483
486
484
- if (state->pindexBestKnownBlock == NULL || state->pindexBestKnownBlock ->nChainWork < chainActive.Tip ()->nChainWork ) {
487
+ if (state->pindexBestKnownBlock == NULL || state->pindexBestKnownBlock ->nChainWork < chainActive.Tip ()->nChainWork || state-> pindexBestKnownBlock -> nChainWork < UintToArith256 (consensusParams. nMinimumChainWork ) ) {
485
488
// This peer has nothing interesting.
486
489
return ;
487
490
}
@@ -2881,6 +2884,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
2881
2884
// Only actively request headers from a single peer, unless we're close to today.
2882
2885
if ((nSyncStarted == 0 && fFetch ) || pindexBestHeader->GetBlockTime () > GetAdjustedTime () - 24 * 60 * 60 ) {
2883
2886
state.fSyncStarted = true ;
2887
+ state.nHeadersSyncTimeout = GetTimeMicros () + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * (GetAdjustedTime () - pindexBestHeader->GetBlockTime ())/(consensusParams.nPowTargetSpacing );
2884
2888
nSyncStarted++;
2885
2889
const CBlockIndex *pindexStart = pindexBestHeader;
2886
2890
/* If possible, start at the block preceding the currently
@@ -3204,6 +3208,39 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
3204
3208
return true ;
3205
3209
}
3206
3210
}
3211
+ // Check for headers sync timeouts
3212
+ if (state.fSyncStarted && state.nHeadersSyncTimeout < std::numeric_limits<int64_t >::max ()) {
3213
+ // Detect whether this is a stalling initial-headers-sync peer
3214
+ if (pindexBestHeader->GetBlockTime () <= GetAdjustedTime () - 24 *60 *60 ) {
3215
+ if (nNow > state.nHeadersSyncTimeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1 )) {
3216
+ // Disconnect a (non-whitelisted) peer if it is our only sync peer,
3217
+ // and we have others we could be using instead.
3218
+ // Note: If all our peers are inbound, then we won't
3219
+ // disconnect our sync peer for stalling; we have bigger
3220
+ // problems if we can't get any outbound peers.
3221
+ if (!pto->fWhitelisted ) {
3222
+ LogPrintf (" Timeout downloading headers from peer=%d, disconnecting\n " , pto->GetId ());
3223
+ pto->fDisconnect = true ;
3224
+ return true ;
3225
+ } else {
3226
+ LogPrintf (" Timeout downloading headers from whitelisted peer=%d, not disconnecting\n " , pto->GetId ());
3227
+ // Reset the headers sync state so that we have a
3228
+ // chance to try downloading from a different peer.
3229
+ // Note: this will also result in at least one more
3230
+ // getheaders message to be sent to
3231
+ // this peer (eventually).
3232
+ state.fSyncStarted = false ;
3233
+ nSyncStarted--;
3234
+ state.nHeadersSyncTimeout = 0 ;
3235
+ }
3236
+ }
3237
+ } else {
3238
+ // After we've caught up once, reset the timeout so we can't trigger
3239
+ // disconnect later.
3240
+ state.nHeadersSyncTimeout = std::numeric_limits<int64_t >::max ();
3241
+ }
3242
+ }
3243
+
3207
3244
3208
3245
//
3209
3246
// Message: getdata (blocks)
0 commit comments