[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:
+13
-1
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user