I don't really like duplicating every single line of CreateNewBlock. After #17781 there is no reason that we can't just pass an empty mempool to the miner and get an empty block out.
See here:
diff --git a/src/miner.cpp b/src/miner.cpp
index 61d27d17c1..b769121d97 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -39,6 +39,17 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
return nNewTime - nOldTime;
}
+void ReGenerateCommitments(CBlock& block)
+{
+ CMutableTransaction tx{*block.vtx.at(0)};
+ tx.vout.erase(tx.vout.begin() + GetWitnessCommitmentIndex(block));
+ block.vtx.at(0) = MakeTransactionRef(tx);
+
+ GenerateCoinbaseCommitment(block, WITH_LOCK(cs_main, return LookupBlockIndex(block.hashPrevBlock)), Params().GetConsensus());
+
+ block.hashMerkleRoot = BlockMerkleRoot(block);
+}
+
BlockAssembler::Options::Options() {
blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
diff --git a/src/miner.h b/src/miner.h
index cc8fc31a9f..fee02b591d 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -203,4 +203,7 @@ private:
void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
+/** Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed */
+void ReGenerateCommitments(CBlock& block);
+
#endif // BITCOIN_MINER_H
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 007d9253a1..58aaccd1c3 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -104,6 +104,11 @@ static bool GenerateBlock(CBlock& block, uint64_t& max_tries, unsigned int& extr
{
block_hash.SetNull();
+ {
+ LOCK(cs_main);
+ IncrementExtraNonce(&block, ::ChainActive().Tip(), extra_nonce);
+ }
+
CChainParams chainparams(Params());
while (max_tries > 0 && block.nNonce < std::numeric_limits<uint32_t>::max() && !CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus()) && !ShutdownRequested()) {
@@ -143,11 +148,6 @@ static UniValue generateBlocks(const CTxMemPool& mempool, const CScript& coinbas
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
CBlock *pblock = &pblocktemplate->block;
- {
- LOCK(cs_main);
- IncrementExtraNonce(pblock, ::ChainActive().Tip(), nExtraNonce);
- }
-
uint256 block_hash;
if (!GenerateBlock(*pblock, nMaxTries, nExtraNonce, block_hash)) {
break;
@@ -329,51 +329,29 @@ static UniValue generateblock(const JSONRPCRequest& request)
}
}
- CChainParams chainparams(Params());
+ const CChainParams& chainparams = Params();
+ unsigned int extra_nonce{0};
CBlock block;
-
- CBlockIndex* previous_index;
{
LOCK(cs_main);
- previous_index = ::ChainActive().Tip();
- }
- CHECK_NONFATAL(previous_index != nullptr);
-
- const int height = previous_index->nHeight + 1;
- // Create coinbase transaction.
- CMutableTransaction coinbase_tx;
- coinbase_tx.vin.resize(1);
- coinbase_tx.vin[0].prevout.SetNull();
- coinbase_tx.vout.resize(1);
- coinbase_tx.vout[0].scriptPubKey = coinbase_script;
- coinbase_tx.vout[0].nValue = GetBlockSubsidy(height, chainparams.GetConsensus());
- coinbase_tx.vin[0].scriptSig = CScript() << height << OP_0;
- block.vtx.push_back(MakeTransactionRef(std::move(coinbase_tx)));
+ CTxMemPool empty_pool;
+ std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler(empty_pool, chainparams).CreateNewBlock(coinbase_script));
+ if (!blocktemplate) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
+ }
+ block = blocktemplate->block;
+ CHECK_NONFATAL(block.vtx.size() == 1);
+ }
// Add transactions
block.vtx.insert(block.vtx.end(), txs.begin(), txs.end());
+ ReGenerateCommitments(block);
- block.nVersion = ComputeBlockVersion(previous_index, chainparams.GetConsensus());
- if (chainparams.MineBlocksOnDemand())
- block.nVersion = gArgs.GetArg("-blockversion", block.nVersion);
-
- // Fill in header
- block.hashPrevBlock = previous_index->GetBlockHash();
- block.nTime = GetAdjustedTime();
- UpdateTime(&block, chainparams.GetConsensus(), previous_index);
- block.nBits = GetNextWorkRequired(previous_index, &block, chainparams.GetConsensus());
- block.nNonce = 0;
-
- GenerateCoinbaseCommitment(block, previous_index, chainparams.GetConsensus());
-
- unsigned int extra_nonce{0};
{
LOCK(cs_main);
- IncrementExtraNonce(&block, ::ChainActive().Tip(), extra_nonce);
-
BlockValidationState state;
- if (!TestBlockValidity(state, chainparams, block, previous_index, false, false)) {
+ if (!TestBlockValidity(state, chainparams, block, LookupBlockIndex(block.hashPrevBlock), false, false)) {
throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.ToString()));
}
}