aboutsummaryrefslogtreecommitdiff
path: root/src/validation.cpp
diff options
context:
space:
mode:
authordergoegge <n.goeggi@gmail.com>2024-01-19 11:49:48 +0000
committerdergoegge <n.goeggi@gmail.com>2024-02-27 14:17:32 +0000
commit95bddb930aa72edd40fdff52cf447202995b0dce (patch)
tree5c773d02c9a8697c87fab3f9a89edcef48c3bac0 /src/validation.cpp
parent0471aee5077fef81a0e2e032f3c16bdc948a70f2 (diff)
downloadbitcoin-95bddb930aa72edd40fdff52cf447202995b0dce.tar.xz
[validation] Isolate merkle root checks
Diffstat (limited to 'src/validation.cpp')
-rw-r--r--src/validation.cpp90
1 files changed, 52 insertions, 38 deletions
diff --git a/src/validation.cpp b/src/validation.cpp
index caa4ff3115..98383cd133 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3639,6 +3639,54 @@ static bool CheckBlockHeader(const CBlockHeader& block, BlockValidationState& st
return true;
}
+static bool CheckMerkleRoot(const CBlock& block, BlockValidationState& state)
+{
+ bool mutated;
+ uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated);
+ if (block.hashMerkleRoot != hashMerkleRoot2)
+ return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txnmrklroot", "hashMerkleRoot mismatch");
+
+ // Check for merkle tree malleability (CVE-2012-2459): repeating sequences
+ // of transactions in a block without affecting the merkle root of a block,
+ // while still invalidating it.
+ if (mutated)
+ return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txns-duplicate", "duplicate transaction");
+
+ return true;
+}
+
+static bool CheckWitnessMalleation(const CBlock& block, bool expect_witness_commitment, BlockValidationState& state)
+{
+ if (expect_witness_commitment) {
+ int commitpos = GetWitnessCommitmentIndex(block);
+ if (commitpos != NO_WITNESS_COMMITMENT) {
+ bool malleated = false;
+ uint256 hashWitness = BlockWitnessMerkleRoot(block, &malleated);
+ // The malleation check is ignored; as the transaction tree itself
+ // already does not permit it, it is impossible to trigger in the
+ // witness tree.
+ if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
+ return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-nonce-size", strprintf("%s : invalid witness reserved value size", __func__));
+ }
+ CHash256().Write(hashWitness).Write(block.vtx[0]->vin[0].scriptWitness.stack[0]).Finalize(hashWitness);
+ if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
+ return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__));
+ }
+
+ return true;
+ }
+ }
+
+ // No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam
+ for (const auto& tx : block.vtx) {
+ if (tx->HasWitness()) {
+ return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "unexpected-witness", strprintf("%s : unexpected witness data found", __func__));
+ }
+ }
+
+ return true;
+}
+
bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW, bool fCheckMerkleRoot)
{
// These are checks that are independent of context.
@@ -3657,17 +3705,8 @@ bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensu
}
// Check the merkle root.
- if (fCheckMerkleRoot) {
- bool mutated;
- uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated);
- if (block.hashMerkleRoot != hashMerkleRoot2)
- return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txnmrklroot", "hashMerkleRoot mismatch");
-
- // Check for merkle tree malleability (CVE-2012-2459): repeating sequences
- // of transactions in a block without affecting the merkle root of a block,
- // while still invalidating it.
- if (mutated)
- return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txns-duplicate", "duplicate transaction");
+ if (fCheckMerkleRoot && !CheckMerkleRoot(block, state)) {
+ return false;
}
// All potential-corruption validation must be done before we do any
@@ -3866,33 +3905,8 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
// * There must be at least one output whose scriptPubKey is a single 36-byte push, the first 4 bytes of which are
// {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness reserved value). In case there are
// multiple, the last one is used.
- bool fHaveWitness = false;
- if (DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT)) {
- int commitpos = GetWitnessCommitmentIndex(block);
- if (commitpos != NO_WITNESS_COMMITMENT) {
- bool malleated = false;
- uint256 hashWitness = BlockWitnessMerkleRoot(block, &malleated);
- // The malleation check is ignored; as the transaction tree itself
- // already does not permit it, it is impossible to trigger in the
- // witness tree.
- if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
- return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-nonce-size", strprintf("%s : invalid witness reserved value size", __func__));
- }
- CHash256().Write(hashWitness).Write(block.vtx[0]->vin[0].scriptWitness.stack[0]).Finalize(hashWitness);
- if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
- return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__));
- }
- fHaveWitness = true;
- }
- }
-
- // No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam
- if (!fHaveWitness) {
- for (const auto& tx : block.vtx) {
- if (tx->HasWitness()) {
- return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "unexpected-witness", strprintf("%s : unexpected witness data found", __func__));
- }
- }
+ if (!CheckWitnessMalleation(block, DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT), state)) {
+ return false;
}
// After the coinbase witness reserved value and commitment are verified,