perf: verify each block's RandomX solution once, not twice, during sync

RandomX PoW verification is ~84% of block-connect wall time during network IBD, and
CheckBlock was recomputing it TWICE per block: once in CheckBlockHeader and again in
hush_checkPOW (which has no CBlockIndex, so it cannot use the fRandomXVerified dedup
the parallel pre-verify pool relies on). Skip the redundant recompute inside
hush_checkPOW: CheckBlockHeader runs first in CheckBlock and rejects an invalid
solution before hush_checkPOW is reached, so the block is already verified once.
Equihash, PoW-target and notary checks in hush_checkPOW still run.

A scoped guard (ScopedRandomXSkip) SAVES and RESTORES the thread-local
fSkipRandomXValidation, so it neither clobbers the miner's own skip
(TestBlockValidity -> ConnectBlock re-entry, which would otherwise force the ~256MB
inline RandomX alloc the miner deliberately avoids) nor leaks the flag on an exception.

Measured on an isolated RandomX test chain: RandomX verifies per block 2.0 -> 1.03
(~40% faster network sync). The 2x behavior pre-exists in v1.0.2. Consensus-neutral:
RandomXPreVerify.ConsensusEquivalence gtest passes; each block is still verified
exactly once by CheckBlockHeader.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 01:26:30 +02:00
parent 762e25294f
commit 4e67e687d7
3 changed files with 20 additions and 2 deletions

View File

@@ -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);