Skip to content

Commit 4defdfa

Browse files
committed
[MOVEONLY] Move unused Merkle branch code to tests
1 parent 4437d6e commit 4defdfa

File tree

3 files changed

+118
-124
lines changed

3 files changed

+118
-124
lines changed

src/consensus/merkle.cpp

Lines changed: 0 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -42,93 +42,6 @@
4242
root.
4343
*/
4444

45-
/* This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */
46-
static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot, bool* pmutated, uint32_t branchpos, std::vector<uint256>* pbranch) {
47-
if (pbranch) pbranch->clear();
48-
if (leaves.size() == 0) {
49-
if (pmutated) *pmutated = false;
50-
if (proot) *proot = uint256();
51-
return;
52-
}
53-
bool mutated = false;
54-
// count is the number of leaves processed so far.
55-
uint32_t count = 0;
56-
// inner is an array of eagerly computed subtree hashes, indexed by tree
57-
// level (0 being the leaves).
58-
// For example, when count is 25 (11001 in binary), inner[4] is the hash of
59-
// the first 16 leaves, inner[3] of the next 8 leaves, and inner[0] equal to
60-
// the last leaf. The other inner entries are undefined.
61-
uint256 inner[32];
62-
// Which position in inner is a hash that depends on the matching leaf.
63-
int matchlevel = -1;
64-
// First process all leaves into 'inner' values.
65-
while (count < leaves.size()) {
66-
uint256 h = leaves[count];
67-
bool matchh = count == branchpos;
68-
count++;
69-
int level;
70-
// For each of the lower bits in count that are 0, do 1 step. Each
71-
// corresponds to an inner value that existed before processing the
72-
// current leaf, and each needs a hash to combine it.
73-
for (level = 0; !(count & (((uint32_t)1) << level)); level++) {
74-
if (pbranch) {
75-
if (matchh) {
76-
pbranch->push_back(inner[level]);
77-
} else if (matchlevel == level) {
78-
pbranch->push_back(h);
79-
matchh = true;
80-
}
81-
}
82-
mutated |= (inner[level] == h);
83-
CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
84-
}
85-
// Store the resulting hash at inner position level.
86-
inner[level] = h;
87-
if (matchh) {
88-
matchlevel = level;
89-
}
90-
}
91-
// Do a final 'sweep' over the rightmost branch of the tree to process
92-
// odd levels, and reduce everything to a single top value.
93-
// Level is the level (counted from the bottom) up to which we've sweeped.
94-
int level = 0;
95-
// As long as bit number level in count is zero, skip it. It means there
96-
// is nothing left at this level.
97-
while (!(count & (((uint32_t)1) << level))) {
98-
level++;
99-
}
100-
uint256 h = inner[level];
101-
bool matchh = matchlevel == level;
102-
while (count != (((uint32_t)1) << level)) {
103-
// If we reach this point, h is an inner value that is not the top.
104-
// We combine it with itself (Bitcoin's special rule for odd levels in
105-
// the tree) to produce a higher level one.
106-
if (pbranch && matchh) {
107-
pbranch->push_back(h);
108-
}
109-
CHash256().Write(h.begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
110-
// Increment count to the value it would have if two entries at this
111-
// level had existed.
112-
count += (((uint32_t)1) << level);
113-
level++;
114-
// And propagate the result upwards accordingly.
115-
while (!(count & (((uint32_t)1) << level))) {
116-
if (pbranch) {
117-
if (matchh) {
118-
pbranch->push_back(inner[level]);
119-
} else if (matchlevel == level) {
120-
pbranch->push_back(h);
121-
matchh = true;
122-
}
123-
}
124-
CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
125-
level++;
126-
}
127-
}
128-
// Return result.
129-
if (pmutated) *pmutated = mutated;
130-
if (proot) *proot = h;
131-
}
13245

13346
uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated) {
13447
bool mutation = false;
@@ -149,24 +62,6 @@ uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated) {
14962
return hashes[0];
15063
}
15164

152-
std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position) {
153-
std::vector<uint256> ret;
154-
MerkleComputation(leaves, nullptr, nullptr, position, &ret);
155-
return ret;
156-
}
157-
158-
uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& vMerkleBranch, uint32_t nIndex) {
159-
uint256 hash = leaf;
160-
for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) {
161-
if (nIndex & 1) {
162-
hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
163-
} else {
164-
hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
165-
}
166-
nIndex >>= 1;
167-
}
168-
return hash;
169-
}
17065

17166
uint256 BlockMerkleRoot(const CBlock& block, bool* mutated)
17267
{
@@ -189,12 +84,3 @@ uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated)
18984
return ComputeMerkleRoot(std::move(leaves), mutated);
19085
}
19186

192-
std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position)
193-
{
194-
std::vector<uint256> leaves;
195-
leaves.resize(block.vtx.size());
196-
for (size_t s = 0; s < block.vtx.size(); s++) {
197-
leaves[s] = block.vtx[s]->GetHash();
198-
}
199-
return ComputeMerkleBranch(leaves, position);
200-
}

src/consensus/merkle.h

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
#include <primitives/block.h>
1313
#include <uint256.h>
1414

15-
uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated);
16-
std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position);
17-
uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& branch, uint32_t position);
15+
uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated = nullptr);
1816

1917
/*
2018
* Compute the Merkle root of the transactions in a block.
@@ -28,11 +26,4 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated = nullptr);
2826
*/
2927
uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated = nullptr);
3028

31-
/*
32-
* Compute the Merkle branch for the tree of transactions in a block, for a
33-
* given position.
34-
* This can be verified using ComputeMerkleRootFromBranch.
35-
*/
36-
std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position);
37-
3829
#endif // BITCOIN_CONSENSUS_MERKLE_H

src/test/merkle_tests.cpp

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,123 @@
99

1010
BOOST_FIXTURE_TEST_SUITE(merkle_tests, TestingSetup)
1111

12+
static uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& vMerkleBranch, uint32_t nIndex) {
13+
uint256 hash = leaf;
14+
for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) {
15+
if (nIndex & 1) {
16+
hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
17+
} else {
18+
hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
19+
}
20+
nIndex >>= 1;
21+
}
22+
return hash;
23+
}
24+
25+
/* This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */
26+
static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot, bool* pmutated, uint32_t branchpos, std::vector<uint256>* pbranch) {
27+
if (pbranch) pbranch->clear();
28+
if (leaves.size() == 0) {
29+
if (pmutated) *pmutated = false;
30+
if (proot) *proot = uint256();
31+
return;
32+
}
33+
bool mutated = false;
34+
// count is the number of leaves processed so far.
35+
uint32_t count = 0;
36+
// inner is an array of eagerly computed subtree hashes, indexed by tree
37+
// level (0 being the leaves).
38+
// For example, when count is 25 (11001 in binary), inner[4] is the hash of
39+
// the first 16 leaves, inner[3] of the next 8 leaves, and inner[0] equal to
40+
// the last leaf. The other inner entries are undefined.
41+
uint256 inner[32];
42+
// Which position in inner is a hash that depends on the matching leaf.
43+
int matchlevel = -1;
44+
// First process all leaves into 'inner' values.
45+
while (count < leaves.size()) {
46+
uint256 h = leaves[count];
47+
bool matchh = count == branchpos;
48+
count++;
49+
int level;
50+
// For each of the lower bits in count that are 0, do 1 step. Each
51+
// corresponds to an inner value that existed before processing the
52+
// current leaf, and each needs a hash to combine it.
53+
for (level = 0; !(count & (((uint32_t)1) << level)); level++) {
54+
if (pbranch) {
55+
if (matchh) {
56+
pbranch->push_back(inner[level]);
57+
} else if (matchlevel == level) {
58+
pbranch->push_back(h);
59+
matchh = true;
60+
}
61+
}
62+
mutated |= (inner[level] == h);
63+
CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
64+
}
65+
// Store the resulting hash at inner position level.
66+
inner[level] = h;
67+
if (matchh) {
68+
matchlevel = level;
69+
}
70+
}
71+
// Do a final 'sweep' over the rightmost branch of the tree to process
72+
// odd levels, and reduce everything to a single top value.
73+
// Level is the level (counted from the bottom) up to which we've sweeped.
74+
int level = 0;
75+
// As long as bit number level in count is zero, skip it. It means there
76+
// is nothing left at this level.
77+
while (!(count & (((uint32_t)1) << level))) {
78+
level++;
79+
}
80+
uint256 h = inner[level];
81+
bool matchh = matchlevel == level;
82+
while (count != (((uint32_t)1) << level)) {
83+
// If we reach this point, h is an inner value that is not the top.
84+
// We combine it with itself (Bitcoin's special rule for odd levels in
85+
// the tree) to produce a higher level one.
86+
if (pbranch && matchh) {
87+
pbranch->push_back(h);
88+
}
89+
CHash256().Write(h.begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
90+
// Increment count to the value it would have if two entries at this
91+
// level had existed.
92+
count += (((uint32_t)1) << level);
93+
level++;
94+
// And propagate the result upwards accordingly.
95+
while (!(count & (((uint32_t)1) << level))) {
96+
if (pbranch) {
97+
if (matchh) {
98+
pbranch->push_back(inner[level]);
99+
} else if (matchlevel == level) {
100+
pbranch->push_back(h);
101+
matchh = true;
102+
}
103+
}
104+
CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
105+
level++;
106+
}
107+
}
108+
// Return result.
109+
if (pmutated) *pmutated = mutated;
110+
if (proot) *proot = h;
111+
}
112+
113+
static std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position) {
114+
std::vector<uint256> ret;
115+
MerkleComputation(leaves, nullptr, nullptr, position, &ret);
116+
return ret;
117+
}
118+
119+
static std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position)
120+
{
121+
std::vector<uint256> leaves;
122+
leaves.resize(block.vtx.size());
123+
for (size_t s = 0; s < block.vtx.size(); s++) {
124+
leaves[s] = block.vtx[s]->GetHash();
125+
}
126+
return ComputeMerkleBranch(leaves, position);
127+
}
128+
12129
// Older version of the merkle root computation code, for comparison.
13130
static uint256 BlockBuildMerkleTree(const CBlock& block, bool* fMutated, std::vector<uint256>& vMerkleTree)
14131
{

0 commit comments

Comments
 (0)