net: Enforce minimum block download window multiplier

The timeout window for block downloads scales proportionally to the target
spacing for the chain, as set in chainparams.cpp. This causes issues on regtest
because the spacing is set to 1 second, allowing insufficient time for very
large blocks to sync when requested in batch, preventing success of the pruning
qa test.

We fix this by introducing a minimum multiplier (in seconds) that will be used
instead of the target block spacing whenever the latter is lower. With a value
of 10 seconds, pruning tests pass.
This commit is contained in:
Dakoda Greaves 2021-10-19 14:50:30 -07:00
parent 12202c61bb
commit 1ec3f19fc0
No known key found for this signature in database
GPG Key ID: E9E1D8252D569306
2 changed files with 11 additions and 1 deletions

View File

@ -3250,7 +3250,12 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
if (state.vBlocksInFlight.size() > 0) {
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
if (nNow > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
int64_t nCalculatedDlWindow = std::max(consensusParams.nPowTargetSpacing, MIN_BLOCK_DOWNLOAD_MULTIPLIER) *
(BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads);
if (nNow > state.nDownloadingSince + nCalculatedDlWindow) {
LogPrint("net", "Timeout downloading block: window=%d; inFlight=%d; validHeaders=%d; otherDlPeers=%d;",
nCalculatedDlWindow, state.vBlocksInFlight.size(),
state.nBlocksInFlightValidHeaders, nOtherPeersWithValidatedDownloads);
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->id);
pto->fDisconnect = true;
return true;

View File

@ -21,6 +21,11 @@ static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN = 100;
* 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
/** Sets a hard minimum to the multiplier used for block download
* timeouts, only triggers on regtest, where nPowTargetTimespan
* is set to 1 second.
*/
static constexpr int64_t MIN_BLOCK_DOWNLOAD_MULTIPLIER = 10; // 10 seconds
/** Register with a network node to receive its signals */
void RegisterNodeSignals(CNodeSignals& nodeSignals);
/** Unregister a network node */