Skip to content

Commit 95bddb9

Browse files
committed
[validation] Isolate merkle root checks
1 parent 0471aee commit 95bddb9

File tree

1 file changed

+52
-38
lines changed

1 file changed

+52
-38
lines changed

src/validation.cpp

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3639,6 +3639,54 @@ static bool CheckBlockHeader(const CBlockHeader& block, BlockValidationState& st
36393639
return true;
36403640
}
36413641

3642+
static bool CheckMerkleRoot(const CBlock& block, BlockValidationState& state)
3643+
{
3644+
bool mutated;
3645+
uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated);
3646+
if (block.hashMerkleRoot != hashMerkleRoot2)
3647+
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txnmrklroot", "hashMerkleRoot mismatch");
3648+
3649+
// Check for merkle tree malleability (CVE-2012-2459): repeating sequences
3650+
// of transactions in a block without affecting the merkle root of a block,
3651+
// while still invalidating it.
3652+
if (mutated)
3653+
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txns-duplicate", "duplicate transaction");
3654+
3655+
return true;
3656+
}
3657+
3658+
static bool CheckWitnessMalleation(const CBlock& block, bool expect_witness_commitment, BlockValidationState& state)
3659+
{
3660+
if (expect_witness_commitment) {
3661+
int commitpos = GetWitnessCommitmentIndex(block);
3662+
if (commitpos != NO_WITNESS_COMMITMENT) {
3663+
bool malleated = false;
3664+
uint256 hashWitness = BlockWitnessMerkleRoot(block, &malleated);
3665+
// The malleation check is ignored; as the transaction tree itself
3666+
// already does not permit it, it is impossible to trigger in the
3667+
// witness tree.
3668+
if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
3669+
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-nonce-size", strprintf("%s : invalid witness reserved value size", __func__));
3670+
}
3671+
CHash256().Write(hashWitness).Write(block.vtx[0]->vin[0].scriptWitness.stack[0]).Finalize(hashWitness);
3672+
if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
3673+
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__));
3674+
}
3675+
3676+
return true;
3677+
}
3678+
}
3679+
3680+
// No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam
3681+
for (const auto& tx : block.vtx) {
3682+
if (tx->HasWitness()) {
3683+
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "unexpected-witness", strprintf("%s : unexpected witness data found", __func__));
3684+
}
3685+
}
3686+
3687+
return true;
3688+
}
3689+
36423690
bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW, bool fCheckMerkleRoot)
36433691
{
36443692
// These are checks that are independent of context.
@@ -3657,17 +3705,8 @@ bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensu
36573705
}
36583706

36593707
// Check the merkle root.
3660-
if (fCheckMerkleRoot) {
3661-
bool mutated;
3662-
uint256 hashMerkleRoot2 = BlockMerkleRoot(block, &mutated);
3663-
if (block.hashMerkleRoot != hashMerkleRoot2)
3664-
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txnmrklroot", "hashMerkleRoot mismatch");
3665-
3666-
// Check for merkle tree malleability (CVE-2012-2459): repeating sequences
3667-
// of transactions in a block without affecting the merkle root of a block,
3668-
// while still invalidating it.
3669-
if (mutated)
3670-
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-txns-duplicate", "duplicate transaction");
3708+
if (fCheckMerkleRoot && !CheckMerkleRoot(block, state)) {
3709+
return false;
36713710
}
36723711

36733712
// All potential-corruption validation must be done before we do any
@@ -3866,33 +3905,8 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
38663905
// * There must be at least one output whose scriptPubKey is a single 36-byte push, the first 4 bytes of which are
38673906
// {0xaa, 0x21, 0xa9, 0xed}, and the following 32 bytes are SHA256^2(witness root, witness reserved value). In case there are
38683907
// multiple, the last one is used.
3869-
bool fHaveWitness = false;
3870-
if (DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT)) {
3871-
int commitpos = GetWitnessCommitmentIndex(block);
3872-
if (commitpos != NO_WITNESS_COMMITMENT) {
3873-
bool malleated = false;
3874-
uint256 hashWitness = BlockWitnessMerkleRoot(block, &malleated);
3875-
// The malleation check is ignored; as the transaction tree itself
3876-
// already does not permit it, it is impossible to trigger in the
3877-
// witness tree.
3878-
if (block.vtx[0]->vin[0].scriptWitness.stack.size() != 1 || block.vtx[0]->vin[0].scriptWitness.stack[0].size() != 32) {
3879-
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-nonce-size", strprintf("%s : invalid witness reserved value size", __func__));
3880-
}
3881-
CHash256().Write(hashWitness).Write(block.vtx[0]->vin[0].scriptWitness.stack[0]).Finalize(hashWitness);
3882-
if (memcmp(hashWitness.begin(), &block.vtx[0]->vout[commitpos].scriptPubKey[6], 32)) {
3883-
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "bad-witness-merkle-match", strprintf("%s : witness merkle commitment mismatch", __func__));
3884-
}
3885-
fHaveWitness = true;
3886-
}
3887-
}
3888-
3889-
// No witness data is allowed in blocks that don't commit to witness data, as this would otherwise leave room for spam
3890-
if (!fHaveWitness) {
3891-
for (const auto& tx : block.vtx) {
3892-
if (tx->HasWitness()) {
3893-
return state.Invalid(BlockValidationResult::BLOCK_MUTATED, "unexpected-witness", strprintf("%s : unexpected witness data found", __func__));
3894-
}
3895-
}
3908+
if (!CheckWitnessMalleation(block, DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT), state)) {
3909+
return false;
38963910
}
38973911

38983912
// After the coinbase witness reserved value and commitment are verified,

0 commit comments

Comments
 (0)