Fix nBits validation bypass and restore CheckProofOfWork rejection for HACs
Two critical vulnerabilities allowed an attacker to flood the DragonX chain
with minimum-difficulty blocks starting at height 2879907:
1. ContextualCheckBlockHeader only validated nBits for HUSH3 mainnet
(gated behind `if (ishush3)`), never for HAC/smart chains. An attacker
could submit blocks claiming any difficulty and the node accepted them.
Add nBits validation for all non-HUSH3 smart chains, gated above
daaForkHeight (default 450000) to maintain consensus with early chain
history that was mined by a different binary.
2. The rebrand commit (85c8d7f7d) commented out the `return false` block
in CheckProofOfWork that rejects blocks whose hash does not meet the
claimed target. This made PoW validation a no-op — any hash passed.
Restore the rejection block and add RANDOMX_VALIDATION height-gated
logic so blocks after the activation height are always validated even
during initial block loading.
Vulnerability #1 was inherited from the upstream hush3 codebase.
Vulnerability #2 was introduced by the DragonX rebrand.
This commit is contained in:
20
src/main.cpp
20
src/main.cpp
@@ -5140,6 +5140,26 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
|
||||
}
|
||||
}
|
||||
|
||||
// Check Proof-of-Work difficulty for smart chains (HACs)
|
||||
// Without this check, an attacker can submit blocks with arbitrary nBits
|
||||
// (e.g., powLimit / diff=1) and they will be accepted, allowing the chain
|
||||
// to be flooded with minimum-difficulty blocks.
|
||||
// Only enforce above daaForkHeight to avoid consensus mismatch with early
|
||||
// chain blocks that were mined by a different binary version.
|
||||
if (!ishush3 && SMART_CHAIN_SYMBOL[0] != 0 && nHeight > daaForkHeight) {
|
||||
unsigned int nNextWork = GetNextWorkRequired(pindexPrev, &block, consensusParams);
|
||||
if (fDebug) {
|
||||
LogPrintf("%s: HAC nbits height=%d expected=%lu actual=%lu\n",
|
||||
__func__, nHeight, (unsigned long)nNextWork, (unsigned long)block.nBits);
|
||||
}
|
||||
if (block.nBits != nNextWork) {
|
||||
return state.DoS(100,
|
||||
error("%s: Incorrect diffbits for %s at height %d: expected %lu got %lu",
|
||||
__func__, SMART_CHAIN_SYMBOL, nHeight, (unsigned long)nNextWork, (unsigned long)block.nBits),
|
||||
REJECT_INVALID, "bad-diffbits");
|
||||
}
|
||||
}
|
||||
|
||||
// Check timestamp against prev
|
||||
if (ASSETCHAINS_ADAPTIVEPOW <= 0 || nHeight < 30) {
|
||||
if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast() )
|
||||
|
||||
Reference in New Issue
Block a user