mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-04 12:09:26 +01:00
mining: add new getCoinbaseTx() returning a struct
Introduce a new method intended to replace getCoinbaseRawTx(), which provides a struct with everything clients need to construct a coinbase. This is safer than providing a raw dummy coinbase that clients then have to manipulate. The CoinbaseTx data is populated during the dummy transaction generation and stored in struct CBlockTemplate. Expand the interface_ipc.py functional test to document its usage and ensure equivalence.
This commit is contained in:
@@ -158,18 +158,51 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock()
|
||||
|
||||
// Create coinbase transaction.
|
||||
CMutableTransaction coinbaseTx;
|
||||
|
||||
// Construct coinbase transaction struct in parallel
|
||||
CoinbaseTx& coinbase_tx{pblocktemplate->m_coinbase_tx};
|
||||
coinbase_tx.version = coinbaseTx.version;
|
||||
|
||||
coinbaseTx.vin.resize(1);
|
||||
coinbaseTx.vin[0].prevout.SetNull();
|
||||
coinbaseTx.vin[0].nSequence = CTxIn::MAX_SEQUENCE_NONFINAL; // Make sure timelock is enforced.
|
||||
coinbase_tx.sequence = coinbaseTx.vin[0].nSequence;
|
||||
|
||||
// Add an output that spends the full coinbase reward.
|
||||
coinbaseTx.vout.resize(1);
|
||||
coinbaseTx.vout[0].scriptPubKey = m_options.coinbase_output_script;
|
||||
coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus());
|
||||
// Block subsidy + fees
|
||||
const CAmount block_reward{nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus())};
|
||||
coinbaseTx.vout[0].nValue = block_reward;
|
||||
coinbase_tx.block_reward_remaining = block_reward;
|
||||
|
||||
// Start the coinbase scriptSig with the block height as required by BIP34.
|
||||
// The trailing OP_0 (historically an extranonce) is optional padding and
|
||||
// could be removed without a consensus change. Mining clients are expected
|
||||
// to append extra data to this prefix, so increasing its length would reduce
|
||||
// the space they can use and may break existing clients.
|
||||
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
|
||||
coinbase_tx.script_sig_prefix = coinbaseTx.vin[0].scriptSig;
|
||||
Assert(nHeight > 0);
|
||||
coinbaseTx.nLockTime = static_cast<uint32_t>(nHeight - 1);
|
||||
coinbase_tx.lock_time = coinbaseTx.nLockTime;
|
||||
|
||||
pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));
|
||||
pblocktemplate->vchCoinbaseCommitment = m_chainstate.m_chainman.GenerateCoinbaseCommitment(*pblock, pindexPrev);
|
||||
|
||||
const CTransactionRef& final_coinbase{pblock->vtx[0]};
|
||||
if (final_coinbase->HasWitness()) {
|
||||
const auto& witness_stack{final_coinbase->vin[0].scriptWitness.stack};
|
||||
// Consensus requires the coinbase witness stack to have exactly one
|
||||
// element of 32 bytes.
|
||||
Assert(witness_stack.size() == 1 && witness_stack[0].size() == 32);
|
||||
coinbase_tx.witness = uint256(witness_stack[0]);
|
||||
}
|
||||
if (const int witness_index = GetWitnessCommitmentIndex(*pblock); witness_index != NO_WITNESS_COMMITMENT) {
|
||||
Assert(witness_index >= 0 && static_cast<size_t>(witness_index) < final_coinbase->vout.size());
|
||||
coinbase_tx.required_outputs.push_back(final_coinbase->vout[witness_index]);
|
||||
}
|
||||
|
||||
LogInfo("CreateNewBlock(): block weight: %u txs: %u fees: %ld sigops %d\n", GetBlockWeight(*pblock), nBlockTx, nFees, nBlockSigOpsCost);
|
||||
|
||||
// Fill in header
|
||||
@@ -440,4 +473,5 @@ std::optional<BlockRef> WaitTipChanged(ChainstateManager& chainman, KernelNotifi
|
||||
// avoid deadlocks.
|
||||
return GetTip(chainman);
|
||||
}
|
||||
|
||||
} // namespace node
|
||||
|
||||
Reference in New Issue
Block a user