diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2017-06-06 12:14:21 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2017-06-06 12:23:56 +0200 |
commit | 67700b39241dd75a9848dfef28c65e15e30289e9 (patch) | |
tree | fe7bf410242703e41f58ef448be4e99161bd5d8d | |
parent | 16f6c98fa8ee3f5bf02db470d698b1c4c50fc431 (diff) | |
parent | 76f74811c44b5119d5c19364b0594d423248ac0e (diff) |
Merge #10345: [P2P] Timeout for headers sync
76f7481 Add timeout for headers sync (Suhas Daftuar)
e265200 Delay parallel block download until chain has sufficient work (Suhas Daftuar)
Tree-SHA512: e7f5468b7defe67d4d2d5c976bc129dba2b32b2ea52d3ff33b9cbff5c3b5b799be867653f1bcd354340d707d76dcadf2da4588abf6d6ec4a06672cdc5e1101eb
-rw-r--r-- | src/net_processing.cpp | 39 | ||||
-rw-r--r-- | src/net_processing.h | 4 |
2 files changed, 42 insertions, 1 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 971db3427c..4ca02c281d 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -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 { pindexBestHeaderSent = NULL; nUnconnectingHeaders = 0; fSyncStarted = false; + nHeadersSyncTimeout = 0; nStallingSince = 0; nDownloadingSince = 0; nBlocksInFlight = 0; @@ -481,7 +484,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<con // Make sure pindexBestKnownBlock is up to date, we'll need it. ProcessBlockAvailability(nodeid); - if (state->pindexBestKnownBlock == NULL || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork) { + if (state->pindexBestKnownBlock == NULL || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < UintToArith256(consensusParams.nMinimumChainWork)) { // This peer has nothing interesting. return; } @@ -2881,6 +2884,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 @@ -3204,6 +3208,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) diff --git a/src/net_processing.h b/src/net_processing.h index f460595bc1..db6d81e6b6 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -17,6 +17,10 @@ static const int64_t ORPHAN_TX_EXPIRE_TIME = 20 * 60; static const int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60; /** Default number of orphan+recently-replaced txn to keep around for block reconstruction */ static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN = 100; +/** Headers download timeout expressed in microseconds + * Timeout = base + per_header * (expected number of headers) */ +static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes +static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER = 1000; // 1ms/header /** Register with a network node to receive its signals */ void RegisterNodeSignals(CNodeSignals& nodeSignals); |