aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordergoegge <n.goeggi@gmail.com>2024-02-22 11:27:49 +0000
committerglozow <gloriajzhao@gmail.com>2024-03-01 16:28:19 +0000
commit076c67c3aae424e58863dde3bc37cedecc496935 (patch)
tree6ea3f52793af4f150bffad6eb25124336d1d5e9c /src
parent97a1d0a45959a29464ae73087c7a0adcdebd5a61 (diff)
[refactor] Cleanup merkle root checks
Github-Pull: #29412 Rebased-From: e7669e1343aec4298fd30d539847963e6fa5619c
Diffstat (limited to 'src')
-rw-r--r--src/validation.cpp55
1 files changed, 41 insertions, 14 deletions
diff --git a/src/validation.cpp b/src/validation.cpp
index 234284c2f2..97f71db8b1 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3624,35 +3624,59 @@ static bool CheckBlockHeader(const CBlockHeader& block, BlockValidationState& st
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");
+ uint256 merkle_root = BlockMerkleRoot(block, &mutated);
+ if (block.hashMerkleRoot != merkle_root) {
+ return state.Invalid(
+ /*result=*/BlockValidationResult::BLOCK_MUTATED,
+ /*reject_reason=*/"bad-txnmrklroot",
+ /*debug_message=*/"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 (mutated) {
+ return state.Invalid(
+ /*result=*/BlockValidationResult::BLOCK_MUTATED,
+ /*reject_reason=*/"bad-txns-duplicate",
+ /*debug_message=*/"duplicate transaction");
+ }
return true;
}
+/** CheckWitnessMalleation performs checks for block malleation with regard to
+ * its witnesses.
+ *
+ * Note: If the witness commitment is expected (i.e. `expect_witness_commitment
+ * = true`), then the block is required to have at least one transaction and the
+ * first transaction needs to have at least one input. */
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);
+ assert(!block.vtx.empty() && !block.vtx[0]->vin.empty());
+ const auto& witness_stack{block.vtx[0]->vin[0].scriptWitness.stack};
+
+ if (witness_stack.size() != 1 || witness_stack[0].size() != 32) {
+ return state.Invalid(
+ /*result=*/BlockValidationResult::BLOCK_MUTATED,
+ /*reject_reason=*/"bad-witness-nonce-size",
+ /*debug_message=*/strprintf("%s : invalid witness reserved value size", __func__));
+ }
+
// 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__));
+ uint256 hash_witness = BlockWitnessMerkleRoot(block, /*mutated=*/nullptr);
+
+ CHash256().Write(hash_witness).Write(witness_stack[0]).Finalize(hash_witness);
+ if (memcmp(hash_witness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
+ return state.Invalid(
+ /*result=*/BlockValidationResult::BLOCK_MUTATED,
+ /*reject_reason=*/"bad-witness-merkle-match",
+ /*debug_message=*/strprintf("%s : witness merkle commitment mismatch", __func__));
}
return true;
@@ -3662,7 +3686,10 @@ static bool CheckWitnessMalleation(const CBlock& block, bool expect_witness_comm
// 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 state.Invalid(
+ /*result=*/BlockValidationResult::BLOCK_MUTATED,
+ /*reject_reason=*/"unexpected-witness",
+ /*debug_message=*/strprintf("%s : unexpected witness data found", __func__));
}
}