diff --git a/src/main.cpp b/src/main.cpp index 4fd905a04..05d2a45db 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5100,6 +5100,14 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex, int32_t hush_checkPOW(int32_t slowflag,CBlock *pblock,int32_t height); +// RAII: save+restore the thread-local RandomX-skip flag around the verify-once dedup in CheckBlock, +// so it can never clobber the miner's own fSkipRandomXValidation (TestBlockValidity -> ConnectBlock +// re-entry) nor leak TRUE on an exception thrown out of hush_checkPOW. +struct ScopedRandomXSkip { + bool prev; + ScopedRandomXSkip() : prev(GetSkipRandomXValidation()) { SetSkipRandomXValidation(true); } + ~ScopedRandomXSkip() { SetSkipRandomXValidation(prev); } +}; bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, libzcash::ProofVerifier& verifier, bool fCheckPOW, bool fCheckMerkleRoot) @@ -5130,8 +5138,16 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C fprintf(stderr," failed hash ht.%d\n",height); return state.DoS(50, error("CheckBlock: proof of work failed"),REJECT_INVALID, "high-hash"); } - if ( ASSETCHAINS_STAKED == 0 && hush_checkPOW(1,(CBlock *)&block,height) < 0 ) // checks Equihash - return state.DoS(100, error("CheckBlock: failed slow_checkPOW"),REJECT_INVALID, "failed-slow_checkPOW"); + if ( ASSETCHAINS_STAKED == 0 ) { + // verify-once: CheckBlockHeader above already verified this block RandomX solution; skip the + // redundant recompute inside hush_checkPOW (the un-deduped 2nd verify, ~half the RandomX cost + // that dominates IBD). The scoped guard saves/restores the skip flag (never hardcodes false) + // so the miner's own skip is preserved and nothing leaks on throw. Equihash + PoW-target in + // hush_checkPOW still run. + ScopedRandomXSkip _rxskip; + if ( hush_checkPOW(1,(CBlock *)&block,height) < 0 ) + return state.DoS(100, error("CheckBlock: failed slow_checkPOW"),REJECT_INVALID, "failed-slow_checkPOW"); + } } // Check the merkle root. diff --git a/src/pow.cpp b/src/pow.cpp index 398c84751..1daf60e61 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -715,6 +715,7 @@ static int64_t nTimeRandomX = 0; // cumulative RandomX validation time (us), r thread_local bool fSkipRandomXValidation = false; void SetSkipRandomXValidation(bool skip) { fSkipRandomXValidation = skip; } +bool GetSkipRandomXValidation() { return fSkipRandomXValidation; } CBlockIndex *hush_chainactive(int32_t height); diff --git a/src/pow.h b/src/pow.h index b25a53dd6..a7fe1156d 100644 --- a/src/pow.h +++ b/src/pow.h @@ -97,6 +97,7 @@ void RandomXValidatorShutdown(); /** Set thread-local flag to skip RandomX validation (used by miner during TestBlockValidity) */ void SetSkipRandomXValidation(bool skip); +bool GetSkipRandomXValidation(); /** Return the RandomX key rotation interval in blocks */ int GetRandomXInterval();