Fix fresh sync failure at diff reset height 2838976
Fresh-syncing nodes rejected the on-chain min-diff block at the RANDOMX_VALIDATION activation height (2838976) because GetNextWorkRequired computed the expected nBits from the preceding normal-difficulty blocks, producing 469847994 instead of the on-chain 0x200f0f0f (HUSH_MINDIFF_NBITS). This caused all seed nodes to be banned with "Incorrect diffbits" and the node could never sync past that height. Two changes: 1. GetNextWorkRequired (pow.cpp): Return nProofOfWorkLimit at the exact RANDOMX_VALIDATION activation height, matching the on-chain diff reset. 2. ContextualCheckBlockHeader (main.cpp): Raise DragonX daaForkHeight to RANDOMX_VALIDATION + 62000, covering the window where nBits was never validated (diff reset at 2838976 through the attack at ~2879907). Tested by invalidating block 2838975 and reconsidering — node re-validated through the diff reset and attack window, syncing back to tip with zero bad-diffbits rejections. Bump version to 1.0.1.
This commit is contained in:
2
build.sh
2
build.sh
@@ -6,7 +6,7 @@
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
VERSION="1.0.0"
|
||||
VERSION="1.0.1"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
RELEASE_DIR="$SCRIPT_DIR/release"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 1)
|
||||
dnl Must be kept in sync with src/clientversion.h , ugh!
|
||||
define(_CLIENT_VERSION_MINOR, 0)
|
||||
define(_CLIENT_VERSION_REVISION, 0)
|
||||
define(_CLIENT_VERSION_REVISION, 1)
|
||||
define(_CLIENT_VERSION_BUILD, 50)
|
||||
define(_ZC_BUILD_VAL, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, m4_incr(_CLIENT_VERSION_BUILD), m4_eval(_CLIENT_VERSION_BUILD < 50), 1, m4_eval(_CLIENT_VERSION_BUILD - 24), m4_eval(_CLIENT_VERSION_BUILD == 50), 1, , m4_eval(_CLIENT_VERSION_BUILD - 50)))
|
||||
define(_CLIENT_VERSION_SUFFIX, m4_if(m4_eval(_CLIENT_VERSION_BUILD < 25), 1, _CLIENT_VERSION_REVISION-beta$1, m4_eval(_CLIENT_VERSION_BUILD < 50), 1, _CLIENT_VERSION_REVISION-rc$1, m4_eval(_CLIENT_VERSION_BUILD == 50), 1, _CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION-$1)))
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
// Must be kept in sync with configure.ac , ugh!
|
||||
#define CLIENT_VERSION_MAJOR 1
|
||||
#define CLIENT_VERSION_MINOR 0
|
||||
#define CLIENT_VERSION_REVISION 0
|
||||
#define CLIENT_VERSION_REVISION 1
|
||||
#define CLIENT_VERSION_BUILD 50
|
||||
|
||||
//! Set to true for release, false for prerelease or test build
|
||||
|
||||
@@ -5107,7 +5107,14 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
|
||||
|
||||
assert(pindexPrev);
|
||||
|
||||
int daaForkHeight = GetArg("-daaforkheight", 450000);
|
||||
// For HUSH3, nBits validation starts above the original DAA fork height (450000).
|
||||
// For DragonX, nBits was never validated before the standalone binary, so the
|
||||
// chain contains blocks with incorrect nBits during the vulnerable window
|
||||
// (diff reset at RANDOMX_VALIDATION height through the attack at ~2879907).
|
||||
// Set daaForkHeight past that window so fresh sync accepts historical blocks.
|
||||
bool isdragonx = strncmp(SMART_CHAIN_SYMBOL, "DRAGONX", 7) == 0;
|
||||
int defaultDaaForkHeight = isdragonx ? ASSETCHAINS_RANDOMX_VALIDATION + 62000 : 450000;
|
||||
int daaForkHeight = GetArg("-daaforkheight", defaultDaaForkHeight);
|
||||
int nHeight = pindexPrev->GetHeight()+1;
|
||||
bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false;
|
||||
// Check Proof-of-Work difficulty
|
||||
|
||||
10
src/pow.cpp
10
src/pow.cpp
@@ -315,6 +315,16 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
||||
if (pindexLast == NULL )
|
||||
return nProofOfWorkLimit;
|
||||
|
||||
// DragonX difficulty reset at the RANDOMX_VALIDATION activation height.
|
||||
// The chain transitioned to a new binary at this height and difficulty was
|
||||
// reset to minimum (powLimit). Without this, fresh-syncing nodes compute
|
||||
// a different nBits from GetNextWorkRequired (based on pre-reset blocks)
|
||||
// and reject the on-chain min-diff block, banning all seed nodes.
|
||||
if (ASSETCHAINS_RANDOMX_VALIDATION > 0 && pindexLast->GetHeight() + 1 == ASSETCHAINS_RANDOMX_VALIDATION) {
|
||||
LogPrintf("%s: difficulty reset to powLimit at height %d\n", __func__, ASSETCHAINS_RANDOMX_VALIDATION);
|
||||
return nProofOfWorkLimit;
|
||||
}
|
||||
|
||||
//{
|
||||
// Comparing to pindexLast->nHeight with >= because this function
|
||||
// returns the work required for the block after pindexLast.
|
||||
|
||||
Reference in New Issue
Block a user