diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -214,7 +214,8 @@ GetSigOpCountWithoutP2SH(*pblock->vtx[0]); CValidationState state; - if (!TestBlockValidity(*config, state, *pblock, pindexPrev, false, false)) { + if (!TestBlockValidity(*config, state, *pblock, pindexPrev, + BlockValidationOptions(false, false))) { throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state))); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -516,7 +516,8 @@ return "inconclusive-not-best-prevblk"; } CValidationState state; - TestBlockValidity(config, state, block, pindexPrev, false, true); + TestBlockValidity(config, state, block, pindexPrev, + BlockValidationOptions(false, true)); return BIP22ValidationResult(config, state); } diff --git a/src/test/blockcheck_tests.cpp b/src/test/blockcheck_tests.cpp --- a/src/test/blockcheck_tests.cpp +++ b/src/test/blockcheck_tests.cpp @@ -17,7 +17,8 @@ static void RunCheckOnBlockImpl(const GlobalConfig &config, const CBlock &block, CValidationState &state, bool expected) { block.fChecked = false; - bool fValid = CheckBlock(config, block, state, false, false); + bool fValid = + CheckBlock(config, block, state, BlockValidationOptions(false, false)); BOOST_CHECK_EQUAL(fValid, expected); BOOST_CHECK_EQUAL(fValid, state.IsValid()); diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -246,6 +246,16 @@ // we can respect the target. static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 550 * 1024 * 1024; +struct BlockValidationOptions { + bool checkPoW; + bool checkMerkleRoot; + + // Do full validation by default + BlockValidationOptions() : checkPoW(true), checkMerkleRoot(true) {} + BlockValidationOptions(bool checkPoWIn, bool checkMerkleRootIn) + : checkPoW(checkPoWIn), checkMerkleRoot(checkMerkleRootIn) {} +}; + /** * Process an incoming block. This only returns after the best known valid * block is made active. Note that it does not, however, guarantee that the @@ -553,9 +563,9 @@ * Returns true if the provided block is valid (has valid header, * transactions are valid, block is a valid size, etc.) */ -bool CheckBlock(const Config &Config, const CBlock &block, - CValidationState &state, bool fCheckPOW = true, - bool fCheckMerkleRoot = true); +bool CheckBlock( + const Config &Config, const CBlock &block, CValidationState &state, + BlockValidationOptions validationOptions = BlockValidationOptions()); /** * Context dependent validity checks for non coinbase transactions. This @@ -582,9 +592,10 @@ * Check a block is completely valid from start to finish (only works on top of * our current best block, with cs_main held) */ -bool TestBlockValidity(const Config &config, CValidationState &state, - const CBlock &block, CBlockIndex *pindexPrev, - bool fCheckPOW = true, bool fCheckMerkleRoot = true); +bool TestBlockValidity( + const Config &config, CValidationState &state, const CBlock &block, + CBlockIndex *pindexPrev, + BlockValidationOptions validationOptions = BlockValidationOptions()); /** * When there are blocks in the active chain with missing data, rewind the diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1919,7 +1919,8 @@ int64_t nTimeStart = GetTimeMicros(); // Check it again in case a previous version let a bad block in - if (!CheckBlock(config, block, state, !fJustCheck, !fJustCheck)) { + if (!CheckBlock(config, block, state, + BlockValidationOptions(!fJustCheck, !fJustCheck))) { return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); } @@ -2390,7 +2391,8 @@ } /** - * Update chainActive and related internal data structures when adding a new block to the chain tip. + * Update chainActive and related internal data structures when adding a new + * block to the chain tip. */ static void UpdateTip(const Config &config, CBlockIndex *pindexNew) { const Consensus::Params &consensusParams = @@ -3306,10 +3308,17 @@ return true; } -static bool CheckBlockHeader(const Config &config, const CBlockHeader &block, - CValidationState &state, bool fCheckPOW = true) { +/** + * Return true if the provided block has a valid header. When + * blockValidationOptions is set to VALUE, CheckBlockHeader() will only + * return true with valid proof-of-work. + */ +static bool CheckBlockHeader( + const Config &config, const CBlockHeader &block, CValidationState &state, + BlockValidationOptions validationOptions = BlockValidationOptions()) { // Check proof of work matches claimed amount - if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, config)) { + if (validationOptions.checkPoW && + !CheckProofOfWork(block.GetHash(), block.nBits, config)) { return state.DoS(50, false, REJECT_INVALID, "high-hash", false, "proof of work failed"); } @@ -3318,8 +3327,8 @@ } bool CheckBlock(const Config &config, const CBlock &block, - CValidationState &state, bool fCheckPOW, - bool fCheckMerkleRoot) { + CValidationState &state, + BlockValidationOptions validationOptions) { // These are checks that are independent of context. if (block.fChecked) { return true; @@ -3327,12 +3336,13 @@ // Check that the header is valid (particularly PoW). This is mostly // redundant with the call in AcceptBlockHeader. - if (!CheckBlockHeader(config, block, state, fCheckPOW)) { + if (validationOptions.checkPoW && + !CheckBlockHeader(config, block, state, validationOptions)) { return false; } // Check the merkle root. - if (fCheckMerkleRoot) { + if (validationOptions.checkMerkleRoot) { bool mutated; uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated); if (block.hashMerkleRoot != hashMerkleRoot2) { @@ -3422,7 +3432,7 @@ } } - if (fCheckPOW && fCheckMerkleRoot) { + if (validationOptions.checkPoW && validationOptions.checkMerkleRoot) { block.fChecked = true; } @@ -3877,7 +3887,7 @@ bool TestBlockValidity(const Config &config, CValidationState &state, const CBlock &block, CBlockIndex *pindexPrev, - bool fCheckPOW, bool fCheckMerkleRoot) { + BlockValidationOptions validationOptions) { AssertLockHeld(cs_main); const CChainParams &chainparams = config.GetChainParams(); @@ -3900,7 +3910,7 @@ return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, FormatStateMessage(state)); } - if (!CheckBlock(config, block, state, fCheckPOW, fCheckMerkleRoot)) { + if (!CheckBlock(config, block, state, validationOptions)) { return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state)); }