Convert block/header sync timeouts to std::chrono types
This commit is contained in:
1 parent
4d98b401fb
commit
c733ac4d8a
1 file changed
+30
-27
+30
-27
@@ -43,10 +43,10 @@ static constexpr int64_t ORPHAN_TX_EXPIRE_INTERVAL = 5 * 60;
|
|||||||
static constexpr std::chrono::seconds RELAY_TX_CACHE_TIME = std::chrono::minutes{15};
|
static constexpr std::chrono::seconds RELAY_TX_CACHE_TIME = std::chrono::minutes{15};
|
||||||
/** How long a transaction has to be in the mempool before it can unconditionally be relayed (even when not in mapRelay). */
|
/** How long a transaction has to be in the mempool before it can unconditionally be relayed (even when not in mapRelay). */
|
||||||
static constexpr std::chrono::seconds UNCONDITIONAL_RELAY_DELAY = std::chrono::minutes{2};
|
static constexpr std::chrono::seconds UNCONDITIONAL_RELAY_DELAY = std::chrono::minutes{2};
|
||||||
/** Headers download timeout expressed in microseconds
|
/** Headers download timeout.
|
||||||
* Timeout = base + per_header * (expected number of headers) */
|
* Timeout = base + per_header * (expected number of headers) */
|
||||||
static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes
|
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE = 15min;
|
||||||
static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER = 1000; // 1ms/header
|
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER = 1ms;
|
||||||
/** Protect at least this many outbound peers from disconnection due to slow/
|
/** Protect at least this many outbound peers from disconnection due to slow/
|
||||||
* behind headers chain.
|
* behind headers chain.
|
||||||
*/
|
*/
|
||||||
@@ -93,8 +93,8 @@ static constexpr std::chrono::microseconds GETDATA_TX_INTERVAL{std::chrono::seco
|
|||||||
static const unsigned int MAX_GETDATA_SZ = 1000;
|
static const unsigned int MAX_GETDATA_SZ = 1000;
|
||||||
/** Number of blocks that can be requested at any given time from a single peer. */
|
/** Number of blocks that can be requested at any given time from a single peer. */
|
||||||
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
|
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
|
||||||
/** Timeout in seconds during which a peer must stall block download progress before being disconnected. */
|
/** Time during which a peer must stall block download progress before being disconnected. */
|
||||||
static const unsigned int BLOCK_STALLING_TIMEOUT = 2;
|
static constexpr auto BLOCK_STALLING_TIMEOUT = 2s;
|
||||||
/** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends
|
/** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends
|
||||||
* less than this number, we reached its tip. Changing this value is a protocol upgrade. */
|
* less than this number, we reached its tip. Changing this value is a protocol upgrade. */
|
||||||
static const unsigned int MAX_HEADERS_RESULTS = 2000;
|
static const unsigned int MAX_HEADERS_RESULTS = 2000;
|
||||||
@@ -108,10 +108,10 @@ static const int MAX_BLOCKTXN_DEPTH = 10;
|
|||||||
* degree of disordering of blocks on disk (which make reindexing and pruning harder). We'll probably
|
* degree of disordering of blocks on disk (which make reindexing and pruning harder). We'll probably
|
||||||
* want to make this a per-peer adaptive value at some point. */
|
* want to make this a per-peer adaptive value at some point. */
|
||||||
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
|
static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
|
||||||
/** Block download timeout base, expressed in millionths of the block interval (i.e. 10 min) */
|
/** Block download timeout base, expressed in multiples of the block interval (i.e. 10 min) */
|
||||||
static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000;
|
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE = 1;
|
||||||
/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
|
/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
|
||||||
static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000;
|
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 0.5;
|
||||||
/** Maximum number of headers to announce when relaying blocks with headers message.*/
|
/** Maximum number of headers to announce when relaying blocks with headers message.*/
|
||||||
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
|
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
|
||||||
/** Maximum number of unconnecting headers announcements before DoS score */
|
/** Maximum number of unconnecting headers announcements before DoS score */
|
||||||
@@ -533,12 +533,12 @@ struct CNodeState {
|
|||||||
//! Whether we've started headers synchronization with this peer.
|
//! Whether we've started headers synchronization with this peer.
|
||||||
bool fSyncStarted;
|
bool fSyncStarted;
|
||||||
//! When to potentially disconnect peer for stalling headers download
|
//! When to potentially disconnect peer for stalling headers download
|
||||||
int64_t nHeadersSyncTimeout;
|
std::chrono::microseconds m_headers_sync_timeout{0us};
|
||||||
//! Since when we're stalling block download progress (in microseconds), or 0.
|
//! Since when we're stalling block download progress (in microseconds), or 0.
|
||||||
int64_t nStallingSince;
|
std::chrono::microseconds m_stalling_since{0us};
|
||||||
std::list<QueuedBlock> vBlocksInFlight;
|
std::list<QueuedBlock> vBlocksInFlight;
|
||||||
//! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty.
|
//! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty.
|
||||||
int64_t nDownloadingSince;
|
std::chrono::microseconds m_downloading_since{0us};
|
||||||
int nBlocksInFlight;
|
int nBlocksInFlight;
|
||||||
int nBlocksInFlightValidHeaders;
|
int nBlocksInFlightValidHeaders;
|
||||||
//! Whether we consider this a preferred download peer.
|
//! Whether we consider this a preferred download peer.
|
||||||
@@ -621,9 +621,6 @@ struct CNodeState {
|
|||||||
pindexBestHeaderSent = nullptr;
|
pindexBestHeaderSent = nullptr;
|
||||||
nUnconnectingHeaders = 0;
|
nUnconnectingHeaders = 0;
|
||||||
fSyncStarted = false;
|
fSyncStarted = false;
|
||||||
nHeadersSyncTimeout = 0;
|
|
||||||
nStallingSince = 0;
|
|
||||||
nDownloadingSince = 0;
|
|
||||||
nBlocksInFlight = 0;
|
nBlocksInFlight = 0;
|
||||||
nBlocksInFlightValidHeaders = 0;
|
nBlocksInFlightValidHeaders = 0;
|
||||||
fPreferredDownload = false;
|
fPreferredDownload = false;
|
||||||
@@ -672,11 +669,11 @@ bool PeerManagerImpl::MarkBlockAsReceived(const uint256& hash)
|
|||||||
}
|
}
|
||||||
if (state->vBlocksInFlight.begin() == itInFlight->second.second) {
|
if (state->vBlocksInFlight.begin() == itInFlight->second.second) {
|
||||||
// First block on the queue was received, update the start download time for the next one
|
// First block on the queue was received, update the start download time for the next one
|
||||||
state->nDownloadingSince = std::max(state->nDownloadingSince, count_microseconds(GetTime<std::chrono::microseconds>()));
|
state->m_downloading_since = std::max(state->m_downloading_since, GetTime<std::chrono::microseconds>());
|
||||||
}
|
}
|
||||||
state->vBlocksInFlight.erase(itInFlight->second.second);
|
state->vBlocksInFlight.erase(itInFlight->second.second);
|
||||||
state->nBlocksInFlight--;
|
state->nBlocksInFlight--;
|
||||||
state->nStallingSince = 0;
|
state->m_stalling_since = 0us;
|
||||||
mapBlocksInFlight.erase(itInFlight);
|
mapBlocksInFlight.erase(itInFlight);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -706,7 +703,7 @@ bool PeerManagerImpl::MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, co
|
|||||||
state->nBlocksInFlightValidHeaders += it->fValidatedHeaders;
|
state->nBlocksInFlightValidHeaders += it->fValidatedHeaders;
|
||||||
if (state->nBlocksInFlight == 1) {
|
if (state->nBlocksInFlight == 1) {
|
||||||
// We're starting a block download (batch) from this peer.
|
// We're starting a block download (batch) from this peer.
|
||||||
state->nDownloadingSince = GetTime<std::chrono::microseconds>().count();
|
state->m_downloading_since = GetTime<std::chrono::microseconds>();
|
||||||
}
|
}
|
||||||
if (state->nBlocksInFlightValidHeaders == 1 && pindex != nullptr) {
|
if (state->nBlocksInFlightValidHeaders == 1 && pindex != nullptr) {
|
||||||
nPeersWithValidatedDownloads++;
|
nPeersWithValidatedDownloads++;
|
||||||
@@ -4485,7 +4482,13 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
// Only actively request headers from a single peer, unless we're close to today.
|
// Only actively request headers from a single peer, unless we're close to today.
|
||||||
if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) {
|
if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) {
|
||||||
state.fSyncStarted = true;
|
state.fSyncStarted = true;
|
||||||
state.nHeadersSyncTimeout = count_microseconds(current_time) + HEADERS_DOWNLOAD_TIMEOUT_BASE + HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER * (GetAdjustedTime() - pindexBestHeader->GetBlockTime())/(consensusParams.nPowTargetSpacing);
|
state.m_headers_sync_timeout = current_time + HEADERS_DOWNLOAD_TIMEOUT_BASE +
|
||||||
|
(
|
||||||
|
// Convert HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER to microseconds before scaling
|
||||||
|
// to maintain precision
|
||||||
|
std::chrono::microseconds{HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER} *
|
||||||
|
(GetAdjustedTime() - pindexBestHeader->GetBlockTime()) / consensusParams.nPowTargetSpacing
|
||||||
|
);
|
||||||
nSyncStarted++;
|
nSyncStarted++;
|
||||||
const CBlockIndex *pindexStart = pindexBestHeader;
|
const CBlockIndex *pindexStart = pindexBestHeader;
|
||||||
/* If possible, start at the block preceding the currently
|
/* If possible, start at the block preceding the currently
|
||||||
@@ -4795,7 +4798,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
|
|
||||||
// Detect whether we're stalling
|
// Detect whether we're stalling
|
||||||
current_time = GetTime<std::chrono::microseconds>();
|
current_time = GetTime<std::chrono::microseconds>();
|
||||||
if (state.nStallingSince && state.nStallingSince < count_microseconds(current_time) - 1000000 * BLOCK_STALLING_TIMEOUT) {
|
if (state.m_stalling_since.count() && state.m_stalling_since < current_time - BLOCK_STALLING_TIMEOUT) {
|
||||||
// Stalling only triggers when the block download window cannot move. During normal steady state,
|
// Stalling only triggers when the block download window cannot move. During normal steady state,
|
||||||
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
|
// the download window should be much larger than the to-be-downloaded set of blocks, so disconnection
|
||||||
// should only happen during initial block download.
|
// should only happen during initial block download.
|
||||||
@@ -4803,7 +4806,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
pto->fDisconnect = true;
|
pto->fDisconnect = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// In case there is a block that has been in flight from this peer for 2 + 0.5 * N times the block interval
|
// In case there is a block that has been in flight from this peer for block_interval * (1 + 0.5 * N)
|
||||||
// (with N the number of peers from which we're downloading validated blocks), disconnect due to timeout.
|
// (with N the number of peers from which we're downloading validated blocks), disconnect due to timeout.
|
||||||
// We compensate for other peers to prevent killing off peers due to our own downstream link
|
// We compensate for other peers to prevent killing off peers due to our own downstream link
|
||||||
// being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes
|
// being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes
|
||||||
@@ -4811,17 +4814,17 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
if (state.vBlocksInFlight.size() > 0) {
|
if (state.vBlocksInFlight.size() > 0) {
|
||||||
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
|
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
|
||||||
int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
|
int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
|
||||||
if (count_microseconds(current_time) > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
|
if (current_time > state.m_downloading_since + std::chrono::seconds{consensusParams.nPowTargetSpacing} * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
|
||||||
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->GetId());
|
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->GetId());
|
||||||
pto->fDisconnect = true;
|
pto->fDisconnect = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for headers sync timeouts
|
// Check for headers sync timeouts
|
||||||
if (state.fSyncStarted && state.nHeadersSyncTimeout < std::numeric_limits<int64_t>::max()) {
|
if (state.fSyncStarted && state.m_headers_sync_timeout < std::chrono::microseconds::max()) {
|
||||||
// Detect whether this is a stalling initial-headers-sync peer
|
// Detect whether this is a stalling initial-headers-sync peer
|
||||||
if (pindexBestHeader->GetBlockTime() <= GetAdjustedTime() - 24 * 60 * 60) {
|
if (pindexBestHeader->GetBlockTime() <= GetAdjustedTime() - 24 * 60 * 60) {
|
||||||
if (count_microseconds(current_time) > state.nHeadersSyncTimeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1)) {
|
if (current_time > state.m_headers_sync_timeout && nSyncStarted == 1 && (nPreferredDownload - state.fPreferredDownload >= 1)) {
|
||||||
// Disconnect a peer (without the noban permission) if it is our only sync peer,
|
// Disconnect a peer (without the noban permission) if it is our only sync peer,
|
||||||
// and we have others we could be using instead.
|
// and we have others we could be using instead.
|
||||||
// Note: If all our peers are inbound, then we won't
|
// Note: If all our peers are inbound, then we won't
|
||||||
@@ -4840,13 +4843,13 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
// this peer (eventually).
|
// this peer (eventually).
|
||||||
state.fSyncStarted = false;
|
state.fSyncStarted = false;
|
||||||
nSyncStarted--;
|
nSyncStarted--;
|
||||||
state.nHeadersSyncTimeout = 0;
|
state.m_headers_sync_timeout = 0us;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// After we've caught up once, reset the timeout so we can't trigger
|
// After we've caught up once, reset the timeout so we can't trigger
|
||||||
// disconnect later.
|
// disconnect later.
|
||||||
state.nHeadersSyncTimeout = std::numeric_limits<int64_t>::max();
|
state.m_headers_sync_timeout = std::chrono::microseconds::max();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4870,8 +4873,8 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
|
|||||||
pindex->nHeight, pto->GetId());
|
pindex->nHeight, pto->GetId());
|
||||||
}
|
}
|
||||||
if (state.nBlocksInFlight == 0 && staller != -1) {
|
if (state.nBlocksInFlight == 0 && staller != -1) {
|
||||||
if (State(staller)->nStallingSince == 0) {
|
if (State(staller)->m_stalling_since == 0us) {
|
||||||
State(staller)->nStallingSince = count_microseconds(current_time);
|
State(staller)->m_stalling_since = current_time;
|
||||||
LogPrint(BCLog::NET, "Stall started peer=%d\n", staller);
|
LogPrint(BCLog::NET, "Stall started peer=%d\n", staller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user