mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-23 07:15:29 +01:00
[refactor] Cleanup merkle root checks
This commit is contained in:
parent
95bddb930a
commit
e7669e1343
1 changed files with 41 additions and 14 deletions
|
@ -3642,35 +3642,59 @@ static bool CheckBlockHeader(const CBlockHeader& block, BlockValidationState& st
|
||||||
static bool CheckMerkleRoot(const CBlock& block, BlockValidationState& state)
|
static bool CheckMerkleRoot(const CBlock& block, BlockValidationState& state)
|
||||||
{
|
{
|
||||||
bool mutated;
|
bool mutated;
|
||||||
uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated);
|
uint256 merkle_root = BlockMerkleRoot(block, &mutated);
|
||||||
if (block.hashMerkleRoot != hashMerkleRoot2)
|
if (block.hashMerkleRoot != merkle_root) {
|
||||||
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txnmrklroot", "hashMerkleRoot mismatch");
|
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
|
// Check for merkle tree malleability (CVE-2012-2459): repeating sequences
|
||||||
// of transactions in a block without affecting the merkle root of a block,
|
// of transactions in a block without affecting the merkle root of a block,
|
||||||
// while still invalidating it.
|
// while still invalidating it.
|
||||||
if (mutated)
|
if (mutated) {
|
||||||
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txns-duplicate", "duplicate transaction");
|
return state.Invalid(
|
||||||
|
/*result=*/BlockValidationResult::BLOCK_MUTATED,
|
||||||
|
/*reject_reason=*/"bad-txns-duplicate",
|
||||||
|
/*debug_message=*/"duplicate transaction");
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
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)
|
static bool CheckWitnessMalleation(const CBlock& block, bool expect_witness_commitment, BlockValidationState& state)
|
||||||
{
|
{
|
||||||
if (expect_witness_commitment) {
|
if (expect_witness_commitment) {
|
||||||
int commitpos = GetWitnessCommitmentIndex(block);
|
int commitpos = GetWitnessCommitmentIndex(block);
|
||||||
if (commitpos != NO_WITNESS_COMMITMENT) {
|
if (commitpos != NO_WITNESS_COMMITMENT) {
|
||||||
bool malleated = false;
|
assert(!block.vtx.empty() && !block.vtx[0]->vin.empty());
|
||||||
uint256 hashWitness = BlockWitnessMerkleRoot(block, &malleated);
|
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
|
// The malleation check is ignored; as the transaction tree itself
|
||||||
// already does not permit it, it is impossible to trigger in the
|
// already does not permit it, it is impossible to trigger in the
|
||||||
// witness tree.
|
// witness tree.
|
||||||
if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
|
uint256 hash_witness = BlockWitnessMerkleRoot(block, /*mutated=*/nullptr);
|
||||||
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-nonce-size", strprintf("%s : invalid witness reserved value size", __func__));
|
|
||||||
}
|
CHash256().Write(hash_witness).Write(witness_stack[0]).Finalize(hash_witness);
|
||||||
CHash256().Write(hashWitness).Write(block.vtx[0]->vin[0].scriptWitness.stack[0]).Finalize(hashWitness);
|
if (memcmp(hash_witness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
|
||||||
if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
|
return state.Invalid(
|
||||||
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__));
|
/*result=*/BlockValidationResult::BLOCK_MUTATED,
|
||||||
|
/*reject_reason=*/"bad-witness-merkle-match",
|
||||||
|
/*debug_message=*/strprintf("%s : witness merkle commitment mismatch", __func__));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -3680,7 +3704,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
|
// 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) {
|
for (const auto& tx : block.vtx) {
|
||||||
if (tx->HasWitness()) {
|
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__));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue