fix(net): enforce nMinimumChainWork in IBD (eclipse / low-work fake-chain protection)

nMinimumChainWork was defined in chainparams but never checked, and IsInitialBlockDownload
decided "synced" from tip timestamp/height alone -- so an eclipsed or bootstrapping node
could be fed a cheap low-work fake chain with recent timestamps and trust it. Reset the
stale mainnet floor (0x281b32ff3198a1 was ABOVE the live chain, would have bricked mainnet)
to the real chainwork at height ~3,100,000, and hold a node in IBD until its tip reaches the
floor. Gated to the DRAGONX symbol so ephemeral assetchains from the same binary are not
trapped in IBD; the check can only keep a node in IBD, never force it out (no false-sync risk).
Complements the header-flood fix (b9fdc7981): that stops invalid-PoW headers off the real tip;
this stops valid-but-cheap fake chains from a fake genesis.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 17:21:12 -05:00
parent 14e3fb6708
commit 7e99311210
2 changed files with 14 additions and 1 deletions

View File

@@ -2456,6 +2456,17 @@ bool IsInitialBlockDownload()
//fprintf(stderr,"nullptr in IsInitialDownload\n");
return true;
}
// SECURITY: enforce the known-good minimum chain work (defined in chainparams but previously
// never checked). Keeps an eclipsed/bootstrapping node from trusting a cheap low-work fake
// chain -- a recent tip timestamp alone (below) is not sufficient. Gated to the DRAGONX symbol
// so ephemeral assetchains (fresh, low work) run from the same binary are not trapped in IBD.
if (strncmp(SMART_CHAIN_SYMBOL, "DRAGONX", 7) == 0 &&
ptr->chainPower.chainWork < UintToArith256(chainParams.GetConsensus().nMinimumChainWork))
{
return true;
}
state = ((chainActive.Height() < ptr->GetHeight() - 24*60) ||
ptr->GetBlockTime() < (GetTime() - nMaxTipAge));
if ( HUSH_INSYNC != 0 )