Bitcoin Core 31.99.0
P2P Digital Currency
merkle_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2015-present The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <consensus/merkle.h>
6#include <test/util/common.h>
7#include <test/util/random.h>
9
10#include <boost/test/unit_test.hpp>
11
13
14static uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& vMerkleBranch, uint32_t nIndex) {
15 uint256 hash = leaf;
16 for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) {
17 if (nIndex & 1) {
18 hash = Hash(*it, hash);
19 } else {
20 hash = Hash(hash, *it);
21 }
22 nIndex >>= 1;
23 }
24 return hash;
25}
26
27// Older version of the merkle root computation code, for comparison.
28static uint256 BlockBuildMerkleTree(const CBlock& block, bool* fMutated, std::vector<uint256>& vMerkleTree)
29{
30 vMerkleTree.clear();
31 vMerkleTree.reserve(block.vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
32 for (std::vector<CTransactionRef>::const_iterator it(block.vtx.begin()); it != block.vtx.end(); ++it)
33 vMerkleTree.push_back((*it)->GetHash().ToUint256());
34 int j = 0;
35 bool mutated = false;
36 for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
37 {
38 for (int i = 0; i < nSize; i += 2)
39 {
40 int i2 = std::min(i+1, nSize-1);
41 if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) {
42 // Two identical hashes at the end of the list at a particular level.
43 mutated = true;
44 }
45 vMerkleTree.push_back(Hash(vMerkleTree[j+i], vMerkleTree[j+i2]));
46 }
47 j += nSize;
48 }
49 if (fMutated) {
50 *fMutated = mutated;
51 }
52 return (vMerkleTree.empty() ? uint256() : vMerkleTree.back());
53}
54
55// Older version of the merkle branch computation code, for comparison.
56static std::vector<uint256> BlockGetMerkleBranch(const CBlock& block, const std::vector<uint256>& vMerkleTree, int nIndex)
57{
58 std::vector<uint256> vMerkleBranch;
59 int j = 0;
60 for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
61 {
62 int i = std::min(nIndex^1, nSize-1);
63 vMerkleBranch.push_back(vMerkleTree[j+i]);
64 nIndex >>= 1;
65 j += nSize;
66 }
67 return vMerkleBranch;
68}
69
70static inline int ctz(uint32_t i) {
71 if (i == 0) return 0;
72 int j = 0;
73 while (!(i & 1)) {
74 j++;
75 i >>= 1;
76 }
77 return j;
78}
79
81{
82 for (int i = 0; i < 32; i++) {
83 // Try 32 block sizes: all sizes from 0 to 16 inclusive, and then 15 random sizes.
84 int ntx = (i <= 16) ? i : 17 + (m_rng.randrange(4000));
85 // Try up to 3 mutations.
86 for (int mutate = 0; mutate <= 3; mutate++) {
87 int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; // The last how many transactions to duplicate first.
88 if (duplicate1 >= ntx) break; // Duplication of the entire tree results in a different root (it adds a level).
89 int ntx1 = ntx + duplicate1; // The resulting number of transactions after the first duplication.
90 int duplicate2 = mutate >= 2 ? 1 << ctz(ntx1) : 0; // Likewise for the second mutation.
91 if (duplicate2 >= ntx1) break;
92 int ntx2 = ntx1 + duplicate2;
93 int duplicate3 = mutate >= 3 ? 1 << ctz(ntx2) : 0; // And for the third mutation.
94 if (duplicate3 >= ntx2) break;
95 int ntx3 = ntx2 + duplicate3;
96 // Build a block with ntx different transactions.
97 CBlock block;
98 block.vtx.resize(ntx);
99 for (int j = 0; j < ntx; j++) {
101 mtx.nLockTime = j;
102 block.vtx[j] = MakeTransactionRef(std::move(mtx));
103 }
104 // Compute the root of the block before mutating it.
105 bool unmutatedMutated = false;
106 uint256 unmutatedRoot = BlockMerkleRoot(block, &unmutatedMutated);
107 BOOST_CHECK(unmutatedMutated == false);
108 // Optionally mutate by duplicating the last transactions, resulting in the same merkle root.
109 block.vtx.resize(ntx3);
110 for (int j = 0; j < duplicate1; j++) {
111 block.vtx[ntx + j] = block.vtx[ntx + j - duplicate1];
112 }
113 for (int j = 0; j < duplicate2; j++) {
114 block.vtx[ntx1 + j] = block.vtx[ntx1 + j - duplicate2];
115 }
116 for (int j = 0; j < duplicate3; j++) {
117 block.vtx[ntx2 + j] = block.vtx[ntx2 + j - duplicate3];
118 }
119 // Compute the merkle root and merkle tree using the old mechanism.
120 bool oldMutated = false;
121 std::vector<uint256> merkleTree;
122 uint256 oldRoot = BlockBuildMerkleTree(block, &oldMutated, merkleTree);
123 // Compute the merkle root using the new mechanism.
124 bool newMutated = false;
125 uint256 newRoot = BlockMerkleRoot(block, &newMutated);
126 BOOST_CHECK(oldRoot == newRoot);
127 BOOST_CHECK(newRoot == unmutatedRoot);
128 BOOST_CHECK((newRoot == uint256()) == (ntx == 0));
129 BOOST_CHECK(oldMutated == newMutated);
130 BOOST_CHECK(newMutated == !!mutate);
131 // If no mutation was done (once for every ntx value), try up to 16 branches.
132 if (mutate == 0) {
133 for (int loop = 0; loop < std::min(ntx, 16); loop++) {
134 // If ntx <= 16, try all branches. Otherwise, try 16 random ones.
135 int mtx = loop;
136 if (ntx > 16) {
137 mtx = m_rng.randrange(ntx);
138 }
139 std::vector<uint256> newBranch = TransactionMerklePath(block, mtx);
140 std::vector<uint256> oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx);
141 BOOST_CHECK(oldBranch == newBranch);
142 BOOST_CHECK(ComputeMerkleRootFromBranch(block.vtx[mtx]->GetHash().ToUint256(), newBranch, mtx) == oldRoot);
143 }
144 }
145 }
146 }
147}
148
149
150BOOST_AUTO_TEST_CASE(merkle_test_empty_block)
151{
152 bool mutated = false;
153 CBlock block;
154 uint256 root = BlockMerkleRoot(block, &mutated);
155
156 BOOST_CHECK_EQUAL(root.IsNull(), true);
157 BOOST_CHECK_EQUAL(mutated, false);
158
159 // Verify TransactionMerklePath handles empty block correctly
160 // This tests the early-return path in MerkleComputation
161 std::vector<uint256> merkle_path = TransactionMerklePath(block, 0);
162 BOOST_CHECK(merkle_path.empty());
163}
164
165BOOST_AUTO_TEST_CASE(merkle_test_oneTx_block)
166{
167 bool mutated = false;
168 CBlock block;
169
170 block.vtx.resize(1);
172 mtx.nLockTime = 0;
173 block.vtx[0] = MakeTransactionRef(std::move(mtx));
174 uint256 root = BlockMerkleRoot(block, &mutated);
175 BOOST_CHECK_EQUAL(root, block.vtx[0]->GetHash().ToUint256());
176 BOOST_CHECK_EQUAL(mutated, false);
177}
178
179BOOST_AUTO_TEST_CASE(merkle_test_OddTxWithRepeatedLastTx_block)
180{
181 bool mutated;
182 CBlock block, blockWithRepeatedLastTx;
183
184 block.vtx.resize(3);
185
186 for (std::size_t pos = 0; pos < block.vtx.size(); pos++) {
188 mtx.nLockTime = pos;
189 block.vtx[pos] = MakeTransactionRef(std::move(mtx));
190 }
191
192 blockWithRepeatedLastTx = block;
193 blockWithRepeatedLastTx.vtx.push_back(blockWithRepeatedLastTx.vtx.back());
194
195 uint256 rootofBlock = BlockMerkleRoot(block, &mutated);
196 BOOST_CHECK_EQUAL(mutated, false);
197
198 uint256 rootofBlockWithRepeatedLastTx = BlockMerkleRoot(blockWithRepeatedLastTx, &mutated);
199 BOOST_CHECK_EQUAL(rootofBlock, rootofBlockWithRepeatedLastTx);
200 BOOST_CHECK_EQUAL(mutated, true);
201}
202
203BOOST_AUTO_TEST_CASE(merkle_test_LeftSubtreeRightSubtree)
204{
205 CBlock block, leftSubtreeBlock, rightSubtreeBlock;
206
207 block.vtx.resize(4);
208 std::size_t pos;
209 for (pos = 0; pos < block.vtx.size(); pos++) {
211 mtx.nLockTime = pos;
212 block.vtx[pos] = MakeTransactionRef(std::move(mtx));
213 }
214
215 for (pos = 0; pos < block.vtx.size() / 2; pos++)
216 leftSubtreeBlock.vtx.push_back(block.vtx[pos]);
217
218 for (pos = block.vtx.size() / 2; pos < block.vtx.size(); pos++)
219 rightSubtreeBlock.vtx.push_back(block.vtx[pos]);
220
221 uint256 root = BlockMerkleRoot(block);
222 uint256 rootOfLeftSubtree = BlockMerkleRoot(leftSubtreeBlock);
223 uint256 rootOfRightSubtree = BlockMerkleRoot(rightSubtreeBlock);
224 std::vector<uint256> leftRight;
225 leftRight.push_back(rootOfLeftSubtree);
226 leftRight.push_back(rootOfRightSubtree);
227 uint256 rootOfLR = ComputeMerkleRoot(leftRight);
228
229 BOOST_CHECK_EQUAL(root, rootOfLR);
230}
231
232BOOST_AUTO_TEST_CASE(merkle_test_BlockWitness)
233{
234 CBlock block;
235
236 constexpr size_t vtx_count{3};
237 block.vtx.resize(vtx_count);
238 for (std::size_t pos = 0; pos < vtx_count; pos++) {
240 mtx.nLockTime = pos;
241 block.vtx[pos] = MakeTransactionRef(std::move(mtx));
242 }
243
244 uint256 blockWitness = BlockWitnessMerkleRoot(block);
245
246 std::vector<uint256> hashes;
247 hashes.resize(vtx_count); // Odd count exercises leaf duplication in ComputeMerkleRoot (which can append one extra hash).
248 hashes[0] = uint256::ZERO; // The witness hash of the coinbase is 0.
249 for (size_t pos{1}; pos < vtx_count; ++pos) {
250 hashes[pos] = block.vtx[pos]->GetWitnessHash().ToUint256();
251 }
252
253 uint256 merkleRootofHashes = ComputeMerkleRoot(hashes);
254 BOOST_CHECK_EQUAL(merkleRootofHashes, blockWitness);
255}
Definition: block.h:74
std::vector< CTransactionRef > vtx
Definition: block.h:77
constexpr bool IsNull() const
Definition: uint256.h:48
256-bit opaque blob.
Definition: uint256.h:195
static const uint256 ZERO
Definition: uint256.h:203
uint256 ComputeMerkleRoot(std::vector< uint256 > hashes, bool *mutated)
Definition: merkle.cpp:46
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
Definition: merkle.cpp:66
std::vector< uint256 > TransactionMerklePath(const CBlock &block, uint32_t position)
Compute merkle path to the specified transaction.
Definition: merkle.cpp:172
uint256 BlockWitnessMerkleRoot(const CBlock &block)
Definition: merkle.cpp:76
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition: hash.h:75
static uint256 BlockBuildMerkleTree(const CBlock &block, bool *fMutated, std::vector< uint256 > &vMerkleTree)
static int ctz(uint32_t i)
static uint256 ComputeMerkleRootFromBranch(const uint256 &leaf, const std::vector< uint256 > &vMerkleBranch, uint32_t nIndex)
static std::vector< uint256 > BlockGetMerkleBranch(const CBlock &block, const std::vector< uint256 > &vMerkleTree, int nIndex)
BOOST_AUTO_TEST_CASE(merkle_test)
Definition: common.h:29
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:17
#define BOOST_CHECK(expr)
Definition: object.cpp:16
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:404
A mutable version of CTransaction.
Definition: transaction.h:358
Testing setup that configures a complete environment.
Definition: setup_common.h:121