@@ -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 ;
@@ -2883,6 +2886,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
2883
2886
// Only actively request headers from a single peer, unless we're close to today.
2884
2887
if ((nSyncStarted == 0 && fFetch ) || pindexBestHeader->GetBlockTime () > GetAdjustedTime () - 24 * 60 * 60 ) {
2885
2888
state.fSyncStarted = true ;
2889
+ state.nHeadersSyncTimeout = GetTimeMicros () + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * (GetAdjustedTime () - pindexBestHeader->GetBlockTime ())/(consensusParams.nPowTargetSpacing );
2886
2890
nSyncStarted++;
2887
2891
const CBlockIndex *pindexStart = pindexBestHeader;
2888
2892
/* 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
3210
return true ;
3207
3211
}
3208
3212
}
3213
+ // Check for headers sync timeouts
3214
+ if (state.fSyncStarted && state.nHeadersSyncTimeout < std::numeric_limits<int64_t >::max ()) {
3215
+ // Detect whether this is a stalling initial-headers-sync peer
3216
+ if (pindexBestHeader->GetBlockTime () <= GetAdjustedTime () - 24 *60 *60 ) {
3217
+ if (nNow > state.nHeadersSyncTimeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1 )) {
3218
+ // Disconnect a (non-whitelisted) peer if it is our only sync peer,
3219
+ // and we have others we could be using instead.
3220
+ // Note: If all our peers are inbound, then we won't
3221
+ // disconnect our sync peer for stalling; we have bigger
3222
+ // problems if we can't get any outbound peers.
3223
+ if (!pto->fWhitelisted ) {
3224
+ LogPrintf (" Timeout downloading headers from peer=%d, disconnecting\n " , pto->GetId ());
3225
+ pto->fDisconnect = true ;
3226
+ return true ;
3227
+ } else {
3228
+ LogPrintf (" Timeout downloading headers from whitelisted peer=%d, not disconnecting\n " , pto->GetId ());
3229
+ // Reset the headers sync state so that we have a
3230
+ // chance to try downloading from a different peer.
3231
+ // Note: this will also result in at least one more
3232
+ // getheaders message to be sent to
3233
+ // this peer (eventually).
3234
+ state.fSyncStarted = false ;
3235
+ nSyncStarted--;
3236
+ state.nHeadersSyncTimeout = 0 ;
3237
+ }
3238
+ }
3239
+ } else {
3240
+ // After we've caught up once, reset the timeout so we can't trigger
3241
+ // disconnect later.
3242
+ state.nHeadersSyncTimeout = std::numeric_limits<int64_t >::max ();
3243
+ }
3244
+ }
3245
+
3209
3246
3210
3247
//
3211
3248
// Message: getdata (blocks)
0 commit comments