Validate RandomX proof of work when reading blocks

This commit is contained in:
Capri 2026-09-15 22:06:59 +00:00
commit e9e4cad8e8
Signed by: VextaProject
SSH key fingerprint: SHA256:739BZv8LvIDY2tR7lXLy/IQ6MaGTQtYcG9GNvCjmpVM
3 changed files with 35 additions and 11 deletions

View file

@ -379,10 +379,17 @@ bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::P
return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString());
}
// Check the header
// Check context-free proof of work. RandomX requires the previous block
// index to resolve its deterministic seed and is therefore checked by
// the CBlockIndex overload below.
if (block.GetHash() == consensusParams.hashGenesisBlock ||
block.GetAlgo() == ALGO_SHA256D) {
if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) {
return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString());
}
} else if (block.GetAlgo() != ALGO_RANDOMX) {
return error("ReadBlockFromDisk: Unknown proof-of-work algorithm at %s", pos.ToString());
}
// Signet only: check block solution
if (consensusParams.signet_blocks && !CheckSignetBlockSolution(block, consensusParams)) {
@ -403,6 +410,22 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s",
pindex->ToString(), block_pos.ToString());
}
if (block.GetHash() != consensusParams.hashGenesisBlock &&
block.GetAlgo() == ALGO_RANDOMX) {
if (pindex->pprev == nullptr) {
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): RandomX block has no previous block index for %s at %s",
pindex->ToString(), block_pos.ToString());
}
BlockValidationState state;
if (!CheckContextualRandomXProofOfWork(
block, state, consensusParams, pindex->pprev, true)) {
return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): RandomX proof of work failed for %s at %s: %s",
pindex->ToString(), block_pos.ToString(), state.ToString());
}
}
return true;
}

View file

@ -1747,13 +1747,6 @@ static int64_t nTimeCallbacks = 0;
static int64_t nTimeTotal = 0;
static int64_t nBlocksTotal = 0;
static bool CheckContextualRandomXProofOfWork(
const CBlockHeader& block,
BlockValidationState& state,
const Consensus::Params& consensusParams,
const CBlockIndex* pindexPrev,
bool fCheckPOW);
/** Apply the effects of this block (with given index) on the UTXO set represented by coins.
* Validity checks that depend on the UTXO set are also done; ConnectBlock()
* can fail if those validity checks fail (among other reasons). */
@ -3157,7 +3150,7 @@ static bool CheckRandomXProofOfWork(
return true;
}
static bool CheckContextualRandomXProofOfWork(
bool CheckContextualRandomXProofOfWork(
const CBlockHeader& block,
BlockValidationState& state,
const Consensus::Params& consensusParams,

View file

@ -346,6 +346,14 @@ void InitScriptExecutionCache();
/** Context-independent validity checks */
bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
/** Context-dependent RandomX proof-of-work validation. */
bool CheckContextualRandomXProofOfWork(
const CBlockHeader& block,
BlockValidationState& state,
const Consensus::Params& consensusParams,
const CBlockIndex* pindexPrev,
bool fCheckPOW = true);
/** Check a block is completely valid from start to finish (only works on top of our current best block) */
bool TestBlockValidity(BlockValidationState& state,
const CChainParams& chainparams,