Skip to content

Commit e8475e7

Browse files
committed
Fix stuck IBD when discarding unwanted headers from peers.
When receiving unwanted headers from a peer, first check whether we have recent "best known block" state for that peer. If not, accept one batch of headers to refresh it. Otherwise, we can become stuck in a state where we need blocks, but we don't know which peers have those blocks available. This especially happens during startup, when we don't have this information for any peers until we start processing header messages.
1 parent 8cad8cd commit e8475e7

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

src/net_processing.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,18 +2018,26 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
20182018
uint64_t headers_ahead = pindexBestHeader->nHeight - m_chainman.ActiveHeight();
20192019
bool too_far_ahead = fTrimHeaders && (headers_ahead >= nHeaderDownloadBuffer);
20202020
if (too_far_ahead) {
2021-
LogPrint(BCLog::NET, "Discarding received headers and pausing header sync from peer=%d, because we are too far ahead of block sync (%d > %d, %d new headers received)\n", pfrom.GetId(), pindexBestHeader->nHeight, m_chainman.ActiveHeight(), nCount);
20222021
LOCK(cs_main);
20232022
CNodeState *nodestate = State(pfrom.GetId());
2024-
if (nodestate->fSyncStarted) {
2025-
// Cancel sync from this node, so we don't penalize it later.
2026-
// This will cause us to automatically start syncing from a different node (or restart syncing from the same node) later,
2027-
// if we still need to sync headers.
2028-
nSyncStarted--;
2029-
nodestate->fSyncStarted = false;
2030-
nodestate->m_headers_sync_timeout = 0us;
2023+
if ((nodestate->pindexBestKnownBlock == nullptr) ||
2024+
(nodestate->pindexBestKnownBlock->nHeight < m_chainman.ActiveHeight())) {
2025+
// Our notion of what blocks a peer has available is based on its pindexBestKnownBlock,
2026+
// which is based on headers recieved from it. If we don't have one, or it's too old,
2027+
// then we can never get blocks from this peer until we accept headers from it first.
2028+
LogPrint(BCLog::NET, "NOT discarding headers from peer=%d, to update its block availability. (current best header %d, active chain height %d)\n", pfrom.GetId(), pindexBestHeader->nHeight, m_chainman.ActiveHeight());
2029+
} else {
2030+
LogPrint(BCLog::NET, "Discarding received headers and pausing header sync from peer=%d, because we are too far ahead of block sync. (%d > %d)\n", pfrom.GetId(), pindexBestHeader->nHeight, m_chainman.ActiveHeight());
2031+
if (nodestate->fSyncStarted) {
2032+
// Cancel sync from this node, so we don't penalize it later.
2033+
// This will cause us to automatically start syncing from a different node (or restart syncing from the same node) later,
2034+
// if we still need to sync headers.
2035+
nSyncStarted--;
2036+
nodestate->fSyncStarted = false;
2037+
nodestate->m_headers_sync_timeout = 0us;
2038+
}
2039+
return;
20312040
}
2032-
return;
20332041
}
20342042
}
20352043

0 commit comments

Comments
 (0)