diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2014-09-16 00:30:05 +0200 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2014-09-24 19:17:02 +0200 |
commit | 584a358997e52a87e8c5402269c7fb3784ed2065 (patch) | |
tree | 72cb1589072c23bded2737f1fdf9b9fb0c3e0680 /src/main.cpp | |
parent | 7a04f3d708faab4af1f1a6aeddc5a6a4db3849a5 (diff) |
Do merkle root and txid duplicates check simultaneously
Move the txid duplicates check into BuildMerkleTree, where it can be done
much more efficiently (without needing to build a full txid set to detect
duplicates).
The previous version (using the std::set<uint256> to detect duplicates) was
also slightly too weak. A block mined with actual duplicate transactions
(which is invalid, due to the inputs of the duplicated transactions being
seen as double spends) would trigger the duplicates logic, resulting in the
block not being stored on disk, and rerequested. This change fixes that by
only triggering in the case of duplicated transactions that can actually
result in an identical merkle root.
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/src/main.cpp b/src/main.cpp index 15c3916a6f..d79644e638 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2289,13 +2289,12 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo if (!CheckTransaction(tx, state)) return error("CheckBlock() : CheckTransaction failed"); - // Check for duplicate txids. This is caught by ConnectInputs(), - // but catching it earlier avoids a potential DoS attack: - set<uint256> uniqueTx; - BOOST_FOREACH(const CTransaction &tx, block.vtx) { - uniqueTx.insert(tx.GetHash()); - } - if (uniqueTx.size() != block.vtx.size()) + // 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. + bool mutated; + uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated); + if (mutated) return state.DoS(100, error("CheckBlock() : duplicate transaction"), REJECT_INVALID, "bad-txns-duplicate", true); @@ -2309,7 +2308,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo REJECT_INVALID, "bad-blk-sigops", true); // Check merkle root - if (fCheckMerkleRoot && block.hashMerkleRoot != block.BuildMerkleTree()) + if (fCheckMerkleRoot && block.hashMerkleRoot != hashMerkleRoot2) return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"), REJECT_INVALID, "bad-txnmrklroot", true); |