Bitcoin Core
31.1.0
P2P Digital Currency
Toggle main menu visibility
Loading...
Searching...
No Matches
src
test
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
>
8
#include <
test/util/setup_common.h
>
9
10
#include <boost/test/unit_test.hpp>
11
12
BOOST_FIXTURE_TEST_SUITE
(merkle_tests,
TestingSetup
)
13
14
static
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.
28
static
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.
56
static
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
70
static
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
80
BOOST_AUTO_TEST_CASE
(merkle_test)
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++) {
100
CMutableTransaction
mtx;
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
150
BOOST_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
165
BOOST_AUTO_TEST_CASE
(merkle_test_oneTx_block)
166
{
167
bool
mutated =
false
;
168
CBlock
block;
169
170
block.
vtx
.resize(1);
171
CMutableTransaction
mtx;
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
179
BOOST_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++) {
187
CMutableTransaction
mtx;
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
203
BOOST_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++) {
210
CMutableTransaction
mtx;
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
232
BOOST_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++) {
239
CMutableTransaction
mtx;
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
}
256
BOOST_AUTO_TEST_SUITE_END
()
CBlock
Definition
block.h:74
CBlock::vtx
std::vector< CTransactionRef > vtx
Definition
block.h:77
base_blob::IsNull
constexpr bool IsNull() const
Definition
uint256.h:48
uint256
256-bit opaque blob.
Definition
uint256.h:195
uint256::ZERO
static const uint256 ZERO
Definition
uint256.h:203
ComputeMerkleRoot
uint256 ComputeMerkleRoot(std::vector< uint256 > hashes, bool *mutated)
Definition
merkle.cpp:46
BlockMerkleRoot
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
Definition
merkle.cpp:66
TransactionMerklePath
std::vector< uint256 > TransactionMerklePath(const CBlock &block, uint32_t position)
Compute merkle path to the specified transaction.
Definition
merkle.cpp:172
BlockWitnessMerkleRoot
uint256 BlockWitnessMerkleRoot(const CBlock &block)
Definition
merkle.cpp:76
BOOST_FIXTURE_TEST_SUITE
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END
BOOST_AUTO_TEST_SUITE_END()
Hash
uint256 Hash(const T &in1)
Compute the 256-bit hash of an object.
Definition
hash.h:75
merkle.h
BlockBuildMerkleTree
static uint256 BlockBuildMerkleTree(const CBlock &block, bool *fMutated, std::vector< uint256 > &vMerkleTree)
Definition
merkle_tests.cpp:28
ctz
static int ctz(uint32_t i)
Definition
merkle_tests.cpp:70
ComputeMerkleRootFromBranch
static uint256 ComputeMerkleRootFromBranch(const uint256 &leaf, const std::vector< uint256 > &vMerkleBranch, uint32_t nIndex)
Definition
merkle_tests.cpp:14
BlockGetMerkleBranch
static std::vector< uint256 > BlockGetMerkleBranch(const CBlock &block, const std::vector< uint256 > &vMerkleTree, int nIndex)
Definition
merkle_tests.cpp:56
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(merkle_test)
Definition
merkle_tests.cpp:80
std
Definition
common.h:29
BOOST_CHECK_EQUAL
#define BOOST_CHECK_EQUAL(v1, v2)
Definition
object.cpp:17
BOOST_CHECK
#define BOOST_CHECK(expr)
Definition
object.cpp:16
MakeTransactionRef
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition
transaction.h:404
setup_common.h
CMutableTransaction
A mutable version of CTransaction.
Definition
transaction.h:358
CMutableTransaction::nLockTime
uint32_t nLockTime
Definition
transaction.h:362
TestingSetup
Testing setup that configures a complete environment.
Definition
setup_common.h:121
common.h
random.h
Generated on
for Bitcoin Core by
1.17.0