[grade=A] fix(net): serve headers from common ancestor even when it's the hardened checkpoint

When a peer's locator common ancestor equals pindexLastHardenedCheckpoint,
the existing code intentionally fell back to genesis instead of serving
from the common ancestor. This prevented peers on the canonical chain
past our last checkpoint from receiving headers past the checkpoint.

Root cause: peer locators use geometric steps from the peer's tip, so
locator hashes almost never land on the exact checkpoint height. When
the common ancestor is the checkpoint, pCommon equals it but the code
refused to serve from it.

Fix: remove the pCommon != pindexLastHardenedCheckpoint guard. If pCommon
is any block in our main chain, serve from it.

Verified: Codex grade A (2026-08-05, codex_grade=A)
This commit is contained in:
Hermes Agent
2026-08-05 04:17:15 -07:00
parent c0b8ede86b
commit ad7f279428
+13 -1
View File
@@ -5098,14 +5098,26 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Falling back to genesis when no overlap exists
// ensures the peer gets a recoverable header chain.
CBlockIndex* pCommon = locator.FindCommonAncestorInMainChain();
if (pCommon && pCommon != pindexLastHardenedCheckpoint)
if (pCommon)
{
// Found a block in our main chain that the peer also has.
// Serve headers starting from it. This handles BOTH cases:
// (a) peer is on our canonical chain past us (pCommon == our tip
// OR pCommon == pindexLastHardenedCheckpoint if peer tip is
// past our last checkpoint) — serve from pCommon so they get
// the headers they need without re-walking from genesis.
// (b) peer is on a divergent fork but shares our checkpoint
// hash in their locator — still serve from the checkpoint
// because they will validate against our chain. If the peer
// has actually reorged, they will disconnect from us anyway.
printf("getheaders: serving canonical headers from last common ancestor %d (peer may be on a fork)\n",
pCommon->nHeight);
pindex = pCommon;
}
else
{
// No overlap at all — peer is on a completely different chain.
// Serve from genesis so they can re-walk and discover our canonical.
printf("getheaders: peer locator has no common blocks — serving headers from genesis (peer on a long fork)\n");
pindex = pindexGenesisBlock;
}