Skip to content

Commit 0c2c3bb

Browse files
committed
Merge bitcoin/bitcoin#30955: Mining interface: getCoinbaseMerklePath() and submitSolution()
525e9dc Add submitSolution to BlockTemplate interface (Sjors Provoost) 47b4875 Add getCoinbaseMerklePath() to Mining interface (Sjors Provoost) 63d6ad7 Move BlockMerkleBranch back to merkle.{h,cpp} (Sjors Provoost) Pull request description: The new `BlockTemplate` interface introduced in #30440 allows for a more efficient way for a miner to submit the block solution. Instead of having the send the full block, it only needs to provide the nonce, timestamp, version fields and coinbase transaction. This PR introduces `submitSolution()` for that. It's currently unused. #29432 and Sjors/bitcoin#48 use it to process the Stratum v2 message [SubmitSolution](https://github.com/stratum-mining/sv2-spec/blob/main/07-Template-Distribution-Protocol.md#77-submitsolution-client---server). The method should be sufficiently generic to work with alternative mining protocols (none exist that I'm aware off). This PR also introduces `getCoinbaseMerklePath()`, which is needed in Stratum v2 to construct the `merkle_path` field of the `NewTemplate` message (see [spec](https://github.com/stratum-mining/sv2-spec/blob/main/07-Template-Distribution-Protocol.md#72-newtemplate-server---client)). The coinbase merkle path is also used in Stratum "v1", see e.g. https://bitcoin.stackexchange.com/questions/109820/questions-on-merkle-root-hashing-for-stratum-pools This last function uses `BlockMerkleBranch` which was moved to the test code in #13191. The reason back then for moving it was that it was no longer used. This PR moves it back. This PR does not change behaviour since both methods are unused. ACKs for top commit: achow101: ACK 525e9dc itornaza: Code review ACK 525e9dc tdb3: Code review and light test ACK 525e9dc ryanofsky: Code review ACK 525e9dc. Left minor suggestions but none are important, and looks like this could be merged as-is Tree-SHA512: 2a6a8f5d409ff4926643193cb67702240c7c687615414371e53383d2c13c485807f65e21e8ed98515b5456eca3d9fca13cec04675814a4081467d88b849c5653
2 parents 9909a34 + 525e9dc commit 0c2c3bb

File tree

6 files changed

+162
-106
lines changed

6 files changed

+162
-106
lines changed

src/consensus/merkle.cpp

+103
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

+10
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/interfaces/mining.h

+14
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,20 @@ class BlockTemplate
4242
virtual CTransactionRef getCoinbaseTx() = 0;
4343
virtual std::vector<unsigned char> getCoinbaseCommitment() = 0;
4444
virtual int getWitnessCommitmentIndex() = 0;
45+
46+
/**
47+
* Compute merkle path to the coinbase transaction
48+
*
49+
* @return merkle path ordered from the deepest
50+
*/
51+
virtual std::vector<uint256> getCoinbaseMerklePath() = 0;
52+
53+
/**
54+
* Construct and broadcast the block.
55+
*
56+
* @returns if the block was processed, independent of block validity
57+
*/
58+
virtual bool submitSolution(uint32_t version, uint32_t timestamp, uint32_t nonce, CMutableTransaction coinbase) = 0;
4559
};
4660

4761
//! Interface giving clients (RPC, Stratum v2 Template Provider in the future)

src/ipc/capnp/mining.capnp

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
3131
getCoinbaseTx @4 (context: Proxy.Context) -> (result: Data);
3232
getCoinbaseCommitment @5 (context: Proxy.Context) -> (result: Data);
3333
getWitnessCommitmentIndex @6 (context: Proxy.Context) -> (result: Int32);
34+
getCoinbaseMerklePath @7 (context: Proxy.Context) -> (result: List(Data));
35+
submitSolution@8 (context: Proxy.Context, version: UInt32, timestamp: UInt32, nonce: UInt32, coinbase :Data) -> (result: Bool);
3436
}
3537

3638
struct BlockCreateOptions $Proxy.wrap("node::BlockCreateOptions") {

src/node/interfaces.cpp

+33-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <chain.h>
99
#include <chainparams.h>
1010
#include <common/args.h>
11+
#include <consensus/merkle.h>
1112
#include <consensus/validation.h>
1213
#include <deploymentstatus.h>
1314
#include <external_signer.h>
@@ -872,7 +873,7 @@ class ChainImpl : public Chain
872873
class BlockTemplateImpl : public BlockTemplate
873874
{
874875
public:
875-
explicit BlockTemplateImpl(std::unique_ptr<CBlockTemplate> block_template) : m_block_template(std::move(block_template))
876+
explicit BlockTemplateImpl(std::unique_ptr<CBlockTemplate> block_template, NodeContext& node) : m_block_template(std::move(block_template)), m_node(node)
876877
{
877878
assert(m_block_template);
878879
}
@@ -912,7 +913,37 @@ class BlockTemplateImpl : public BlockTemplate
912913
return GetWitnessCommitmentIndex(m_block_template->block);
913914
}
914915

916+
std::vector<uint256> getCoinbaseMerklePath() override
917+
{
918+
return BlockMerkleBranch(m_block_template->block);
919+
}
920+
921+
bool submitSolution(uint32_t version, uint32_t timestamp, uint32_t nonce, CMutableTransaction coinbase) override
922+
{
923+
CBlock block{m_block_template->block};
924+
925+
auto cb = MakeTransactionRef(std::move(coinbase));
926+
927+
if (block.vtx.size() == 0) {
928+
block.vtx.push_back(cb);
929+
} else {
930+
block.vtx[0] = cb;
931+
}
932+
933+
block.nVersion = version;
934+
block.nTime = timestamp;
935+
block.nNonce = nonce;
936+
937+
block.hashMerkleRoot = BlockMerkleRoot(block);
938+
939+
auto block_ptr = std::make_shared<const CBlock>(block);
940+
return chainman().ProcessNewBlock(block_ptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/nullptr);
941+
}
942+
915943
const std::unique_ptr<CBlockTemplate> m_block_template;
944+
945+
ChainstateManager& chainman() { return *Assert(m_node.chainman); }
946+
NodeContext& m_node;
916947
};
917948

918949
class MinerImpl : public Mining
@@ -979,7 +1010,7 @@ class MinerImpl : public Mining
9791010
{
9801011
BlockAssembler::Options assemble_options{options};
9811012
ApplyArgsManOptions(*Assert(m_node.args), assemble_options);
982-
return std::make_unique<BlockTemplateImpl>(BlockAssembler{chainman().ActiveChainstate(), context()->mempool.get(), assemble_options}.CreateNewBlock(script_pub_key));
1013+
return std::make_unique<BlockTemplateImpl>(BlockAssembler{chainman().ActiveChainstate(), context()->mempool.get(), assemble_options}.CreateNewBlock(script_pub_key), m_node);
9831014
}
9841015

9851016
NodeContext* context() override { return &m_node; }

src/test/merkle_tests.cpp

-104
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)