From 012598880cf69a6a4d4d495c78e40ab4abb4eb39 Mon Sep 17 00:00:00 2001
From: Pieter Wuille <pieter.wuille@gmail.com>
Date: Sat, 22 Nov 2014 15:44:43 +0100
Subject: [PATCH] Implement test for merkle tree malleability in
 CPartialMerkleTree

This is a check that is mentioned in BIP 37, but never implemented in the
reference code. As Bitcoin Core so far never decodes partial merkle trees,
this is not a problem. But perhaps others use the code as a reference.
---
 src/merkleblock.cpp    | 10 ++++++++--
 src/test/pmt_tests.cpp | 11 +++++++++++
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index 8618e355d..0500cfde8 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -93,10 +93,16 @@ uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, uns
     } else {
         // otherwise, descend into the subtrees to extract matched txids and hashes
         uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch), right;
-        if (pos*2+1 < CalcTreeWidth(height-1))
+        if (pos*2+1 < CalcTreeWidth(height-1)) {
             right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch);
-        else
+            if (right == left) {
+                // If the left and right branch should never be identical as the transaction
+                // hashes covered by them must be unique.
+                fBad = true;
+            }
+        } else {
             right = left;
+        }
         // and combine them before returning
         return Hash(BEGIN(left), END(left), BEGIN(right), END(right));
     }
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index 3b535a84f..eea5b0af4 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -10,6 +10,7 @@
 
 #include <vector>
 
+#include <boost/assign/list_of.hpp>
 #include <boost/test/unit_test.hpp>
 
 using namespace std;
@@ -104,4 +105,14 @@ BOOST_AUTO_TEST_CASE(pmt_test1)
     }
 }
 
+BOOST_AUTO_TEST_CASE(pmt_malleability)
+{
+    std::vector<uint256> vTxid = boost::assign::list_of(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(9)(10);
+    std::vector<bool> vMatch = boost::assign::list_of(false)(false)(false)(false)(false)(false)(false)(false)(false)(true)(true)(false);
+
+    CPartialMerkleTree tree(vTxid, vMatch);
+    std::vector<uint256> vTxid2;
+    BOOST_CHECK(tree.ExtractMatches(vTxid) == 0);
+}
+
 BOOST_AUTO_TEST_SUITE_END()