|
6 | 6 | #include <consensus/validation.h> // NO_WITNESS_COMMITMENT |
7 | 7 | #include <script/script.h> |
8 | 8 |
|
9 | | -node::Sv2NewTemplateMsg::Sv2NewTemplateMsg(const CBlockHeader& header, const CTransactionRef coinbase_tx, std::vector<uint256> coinbase_merkle_path, uint64_t template_id, bool future_template) |
| 9 | +node::Sv2NewTemplateMsg::Sv2NewTemplateMsg(const CBlockHeader& header, const node::CoinbaseTemplate coinbase, std::vector<uint256> coinbase_merkle_path, uint64_t template_id, bool future_template) |
10 | 10 | : m_template_id{template_id}, m_future_template{future_template} |
11 | 11 | { |
12 | 12 | m_version = header.nVersion; |
13 | 13 |
|
14 | | - m_coinbase_tx_version = coinbase_tx->CURRENT_VERSION; |
15 | | - m_coinbase_prefix = coinbase_tx->vin[0].scriptSig; |
16 | | - m_coinbase_tx_input_sequence = coinbase_tx->vin[0].nSequence; |
| 14 | + m_coinbase_tx_version = coinbase.version; |
| 15 | + m_coinbase_prefix = coinbase.script_sig_prefix; |
| 16 | + m_coinbase_tx_input_sequence = coinbase.input_sequence; |
17 | 17 |
|
18 | 18 | // The coinbase nValue already contains the nFee + the Block Subsidy when built using CreateBlock(). |
19 | | - m_coinbase_tx_value_remaining = static_cast<uint64_t>(coinbase_tx->vout[0].nValue); |
| 19 | + m_coinbase_tx_value_remaining = static_cast<uint64_t>(coinbase.value_remaining); |
20 | 20 |
|
21 | 21 | // Extract only OP_RETURN coinbase outputs (witness commitment, merge mining, etc.) |
22 | 22 | // Bitcoin Core adds a dummy output with the full reward that we must exclude, |
23 | 23 | // otherwise the pool would create an invalid block trying to spend that amount again. |
24 | 24 | m_coinbase_tx_outputs.clear(); |
25 | | - for (const auto& output : coinbase_tx->vout) { |
26 | | - if (!output.scriptPubKey.empty() && output.scriptPubKey[0] == OP_RETURN) { |
27 | | - m_coinbase_tx_outputs.push_back(output); |
28 | | - } |
| 25 | + for (const auto& output : coinbase.outputs) { |
| 26 | + m_coinbase_tx_outputs.push_back(output); |
29 | 27 | } |
30 | | - m_coinbase_tx_outputs_count = m_coinbase_tx_outputs.size(); |
| 28 | + m_coinbase_tx_outputs_count = coinbase.outputs.size(); |
31 | 29 |
|
32 | | - m_coinbase_tx_locktime = coinbase_tx->nLockTime; |
| 30 | + m_coinbase_tx_locktime = coinbase.lock_time; |
33 | 31 |
|
34 | 32 | for (const auto& hash : coinbase_merkle_path) { |
35 | 33 | m_merkle_path.push_back(hash); |
36 | 34 | } |
37 | 35 |
|
38 | 36 | } |
39 | 37 |
|
| 38 | +node::CoinbaseTemplate ExtractCoinbaseTemplate(const CTransactionRef coinbase_tx) |
| 39 | +{ |
| 40 | + node::CoinbaseTemplate coinbase; |
| 41 | + |
| 42 | + coinbase.version = coinbase_tx->CURRENT_VERSION; |
| 43 | + coinbase.script_sig_prefix = coinbase_tx->vin[0].scriptSig; |
| 44 | + // The CoinbaseTemplate interface guarantees a size limit. Raising it (e.g. |
| 45 | + // if a future softfork needs to commit more than BIP34) is a |
| 46 | + // breaking change for clients. |
| 47 | + Assume(coinbase.script_sig_prefix.size() <= 8); |
| 48 | + |
| 49 | + if (coinbase_tx->HasWitness()) { |
| 50 | + const auto& witness_stack{coinbase_tx->vin[0].scriptWitness.stack}; |
| 51 | + // Consensus requires the coinbase witness stack to have exactly one |
| 52 | + // element of 32 bytes. |
| 53 | + Assert(witness_stack.size() == 1 || witness_stack[0].size() == 32); |
| 54 | + coinbase.witness = uint256(witness_stack[0]); |
| 55 | + } |
| 56 | + |
| 57 | + coinbase.input_sequence = coinbase_tx->vin[0].nSequence; |
| 58 | + |
| 59 | + // The first dummy coinbase output produced by CreateBlock() has an nValue |
| 60 | + // set to nFee + the Block Subsidy |
| 61 | + coinbase.value_remaining = coinbase_tx->vout[0].nValue; |
| 62 | + |
| 63 | + // Extract only OP_RETURN coinbase outputs (witness commitment, merge |
| 64 | + // mining, etc). BlockAssembler::CreateNewBlock adds a dummy output with |
| 65 | + // the full reward that we must exclude. |
| 66 | + for (const auto& output : coinbase_tx->vout) { |
| 67 | + if (!output.scriptPubKey.empty() && output.scriptPubKey[0] == OP_RETURN) { |
| 68 | + coinbase.outputs.push_back(output); |
| 69 | + } |
| 70 | + } |
| 71 | + |
| 72 | + coinbase.lock_time = coinbase_tx->nLockTime; |
| 73 | + |
| 74 | + return coinbase; |
| 75 | +} |
| 76 | + |
| 77 | +node::Sv2NewTemplateMsg::Sv2NewTemplateMsg(const CBlockHeader& header, const CTransactionRef coinbase_tx, std::vector<uint256> coinbase_merkle_path, uint64_t template_id, bool future_template) : |
| 78 | + node::Sv2NewTemplateMsg(header, ExtractCoinbaseTemplate(coinbase_tx), coinbase_merkle_path, template_id, future_template) {}; |
| 79 | + |
40 | 80 | node::Sv2SetNewPrevHashMsg::Sv2SetNewPrevHashMsg(const CBlockHeader& header, uint64_t template_id) : m_template_id{template_id} |
41 | 81 | { |
42 | 82 | m_prev_hash = header.hashPrevBlock; |
|
0 commit comments