From 7e9931121047916ef2e463863da1875e80550753 Mon Sep 17 00:00:00 2001 From: DanS Date: Mon, 13 Jul 2026 17:21:12 -0500 Subject: [PATCH] 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 --- src/chainparams.cpp | 4 +++- src/main.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 049df8b0c..6cfd7f5e1 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -131,7 +131,9 @@ public: consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000281b32ff3198a1"); + // DRAGONX mainnet chainwork @ height ~3,100,000 (2026-07), safely below the live tip. + // (Previous value 0x281b32ff3198a1 was a stale inherited figure ABOVE the live chain.) Bump on release. + consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000026dfbdb6fa39e0"); /** * The message start string is designed to be unlikely to occur in normal data. diff --git a/src/main.cpp b/src/main.cpp index e8884b3bc..d72d730cc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 )