Skip to content

Commit 63d6ad7

Browse files
committed
Move BlockMerkleBranch back to merkle.{h,cpp}
The Mining interface uses this function in the next commit to calculate the coinbase merkle path. Stratum v2 uses this to send a compact work template. This partially undoes the change in 4defdfa, but is not a revert, because the implementation changed in the meantime. This commit also documents the function.
1 parent 65f6e70 commit 63d6ad7

File tree

3 files changed

+113
-104
lines changed

3 files changed

+113
-104
lines changed

src/consensus/merkle.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,106 @@ uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated)
8383
return ComputeMerkleRoot(std::move(leaves), mutated);
8484
}
8585

86+
/* This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */
87+
static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot, bool* pmutated, uint32_t branchpos, std::vector<uint256>* pbranch) {
88+
if (pbranch) pbranch->clear();
89+
if (leaves.size() == 0) {
90+
if (pmutated) *pmutated = false;
91+
if (proot) *proot = uint256();
92+
return;
93+
}
94+
bool mutated = false;
95+
// count is the number of leaves processed so far.
96+
uint32_t count = 0;
97+
// inner is an array of eagerly computed subtree hashes, indexed by tree
98+
// level (0 being the leaves).
99+
// For example, when count is 25 (11001 in binary), inner[4] is the hash of
100+
// the first 16 leaves, inner[3] of the next 8 leaves, and inner[0] equal to
101+
// the last leaf. The other inner entries are undefined.
102+
uint256 inner[32];
103+
// Which position in inner is a hash that depends on the matching leaf.
104+
int matchlevel = -1;
105+
// First process all leaves into 'inner' values.
106+
while (count < leaves.size()) {
107+
uint256 h = leaves[count];
108+
bool matchh = count == branchpos;
109+
count++;
110+
int level;
111+
// For each of the lower bits in count that are 0, do 1 step. Each
112+
// corresponds to an inner value that existed before processing the
113+
// current leaf, and each needs a hash to combine it.
114+
for (level = 0; !(count & ((uint32_t{1}) << level)); level++) {
115+
if (pbranch) {
116+
if (matchh) {
117+
pbranch->push_back(inner[level]);
118+
} else if (matchlevel == level) {
119+
pbranch->push_back(h);
120+
matchh = true;
121+
}
122+
}
123+
mutated |= (inner[level] == h);
124+
h = Hash(inner[level], h);
125+
}
126+
// Store the resulting hash at inner position level.
127+
inner[level] = h;
128+
if (matchh) {
129+
matchlevel = level;
130+
}
131+
}
132+
// Do a final 'sweep' over the rightmost branch of the tree to process
133+
// odd levels, and reduce everything to a single top value.
134+
// Level is the level (counted from the bottom) up to which we've sweeped.
135+
int level = 0;
136+
// As long as bit number level in count is zero, skip it. It means there
137+
// is nothing left at this level.
138+
while (!(count & ((uint32_t{1}) << level))) {
139+
level++;
140+
}
141+
uint256 h = inner[level];
142+
bool matchh = matchlevel == level;
143+
while (count != ((uint32_t{1}) << level)) {
144+
// If we reach this point, h is an inner value that is not the top.
145+
// We combine it with itself (Bitcoin's special rule for odd levels in
146+
// the tree) to produce a higher level one.
147+
if (pbranch && matchh) {
148+
pbranch->push_back(h);
149+
}
150+
h = Hash(h, h);
151+
// Increment count to the value it would have if two entries at this
152+
// level had existed.
153+
count += ((uint32_t{1}) << level);
154+
level++;
155+
// And propagate the result upwards accordingly.
156+
while (!(count & ((uint32_t{1}) << level))) {
157+
if (pbranch) {
158+
if (matchh) {
159+
pbranch->push_back(inner[level]);
160+
} else if (matchlevel == level) {
161+
pbranch->push_back(h);
162+
matchh = true;
163+
}
164+
}
165+
h = Hash(inner[level], h);
166+
level++;
167+
}
168+
}
169+
// Return result.
170+
if (pmutated) *pmutated = mutated;
171+
if (proot) *proot = h;
172+
}
173+
174+
static std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position) {
175+
std::vector<uint256> ret;
176+
MerkleComputation(leaves, nullptr, nullptr, position, &ret);
177+
return ret;
178+
}
179+
180+
std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position)
181+
{
182+
std::vector<uint256> leaves;
183+
leaves.resize(block.vtx.size());
184+
for (size_t s = 0; s < block.vtx.size(); s++) {
185+
leaves[s] = block.vtx[s]->GetHash();
186+
}
187+
return ComputeMerkleBranch(leaves, position);
188+
}

src/consensus/merkle.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,14 @@ uint256 BlockMerkleRoot(const CBlock& block, bool* mutated = nullptr);
2424
*/
2525
uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated = nullptr);
2626

27+
/**
28+
* Compute merkle path to the specified transaction
29+
*
30+
* @param[in] block the block
31+
* @param[in] position transaction for which to calculate the merkle path, defaults to coinbase
32+
*
33+
* @return merkle path ordered from the deepest
34+
*/
35+
std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position = 0);
36+
2737
#endif // BITCOIN_CONSENSUS_MERKLE_H

src/test/merkle_tests.cpp

Lines changed: 0 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -23,110 +23,6 @@ static uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vecto
2323
return hash;
2424
}
2525

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

0 commit comments

Comments
 (0)