aboutsummaryrefslogtreecommitdiff
path: root/src/rpc/mining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc/mining.cpp')
-rw-r--r--src/rpc/mining.cpp98
1 files changed, 46 insertions, 52 deletions
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 375352b18d..44605cbc89 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -3,7 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <config/bitcoin-config.h> // IWYU pragma: keep
+#include <bitcoin-build-config.h> // IWYU pragma: keep
#include <chain.h>
#include <chainparams.h>
@@ -45,9 +45,9 @@
#include <memory>
#include <stdint.h>
-using node::BlockAssembler;
-using node::CBlockTemplate;
+using interfaces::BlockTemplate;
using interfaces::Mining;
+using node::BlockAssembler;
using node::NodeContext;
using node::RegenerateCommitments;
using node::UpdateTime;
@@ -130,7 +130,7 @@ static RPCHelpMan getnetworkhashps()
};
}
-static bool GenerateBlock(ChainstateManager& chainman, Mining& miner, CBlock& block, uint64_t& max_tries, std::shared_ptr<const CBlock>& block_out, bool process_new_block)
+static bool GenerateBlock(ChainstateManager& chainman, Mining& miner, CBlock&& block, uint64_t& max_tries, std::shared_ptr<const CBlock>& block_out, bool process_new_block)
{
block_out.reset();
block.hashMerkleRoot = BlockMerkleRoot(block);
@@ -146,7 +146,7 @@ static bool GenerateBlock(ChainstateManager& chainman, Mining& miner, CBlock& bl
return true;
}
- block_out = std::make_shared<const CBlock>(block);
+ block_out = std::make_shared<const CBlock>(std::move(block));
if (!process_new_block) return true;
@@ -161,12 +161,11 @@ static UniValue generateBlocks(ChainstateManager& chainman, Mining& miner, const
{
UniValue blockHashes(UniValue::VARR);
while (nGenerate > 0 && !chainman.m_interrupt) {
- std::unique_ptr<CBlockTemplate> pblocktemplate(miner.createNewBlock(coinbase_script));
- if (!pblocktemplate.get())
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
+ std::unique_ptr<BlockTemplate> block_template(miner.createNewBlock(coinbase_script));
+ CHECK_NONFATAL(block_template);
std::shared_ptr<const CBlock> block_out;
- if (!GenerateBlock(chainman, miner, pblocktemplate->block, nMaxTries, block_out, /*process_new_block=*/true)) {
+ if (!GenerateBlock(chainman, miner, block_template->getBlock(), nMaxTries, block_out, /*process_new_block=*/true)) {
break;
}
@@ -371,11 +370,10 @@ static RPCHelpMan generateblock()
ChainstateManager& chainman = EnsureChainman(node);
{
- std::unique_ptr<CBlockTemplate> blocktemplate{miner.createNewBlock(coinbase_script, {.use_mempool = false})};
- if (!blocktemplate) {
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
- }
- block = blocktemplate->block;
+ std::unique_ptr<BlockTemplate> block_template{miner.createNewBlock(coinbase_script, {.use_mempool = false})};
+ CHECK_NONFATAL(block_template);
+
+ block = block_template->getBlock();
}
CHECK_NONFATAL(block.vtx.size() == 1);
@@ -394,7 +392,7 @@ static RPCHelpMan generateblock()
std::shared_ptr<const CBlock> block_out;
uint64_t max_tries{DEFAULT_MAX_TRIES};
- if (!GenerateBlock(chainman, miner, block, max_tries, block_out, process_new_block) || !block_out) {
+ if (!GenerateBlock(chainman, miner, std::move(block), max_tries, block_out, process_new_block) || !block_out) {
throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block.");
}
@@ -663,7 +661,7 @@ static RPCHelpMan getblocktemplate()
ChainstateManager& chainman = EnsureChainman(node);
Mining& miner = EnsureMining(node);
LOCK(cs_main);
- uint256 tip{CHECK_NONFATAL(miner.getTipHash()).value()};
+ uint256 tip{CHECK_NONFATAL(miner.getTip()).value().hash};
std::string strMode = "template";
UniValue lpval = NullUniValue;
@@ -740,7 +738,6 @@ static RPCHelpMan getblocktemplate()
{
// Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
uint256 hashWatchedChain;
- std::chrono::steady_clock::time_point checktxtime;
unsigned int nTransactionsUpdatedLastLP;
if (lpval.isStr())
@@ -761,24 +758,19 @@ static RPCHelpMan getblocktemplate()
// Release lock while waiting
LEAVE_CRITICAL_SECTION(cs_main);
{
- checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1);
-
- WAIT_LOCK(g_best_block_mutex, lock);
- while (g_best_block == hashWatchedChain && IsRPCRunning())
- {
- if (g_best_block_cv.wait_until(lock, checktxtime) == std::cv_status::timeout)
- {
- // Timeout: Check transactions for update
- // without holding the mempool lock to avoid deadlocks
- if (miner.getTransactionsUpdated() != nTransactionsUpdatedLastLP)
- break;
- checktxtime += std::chrono::seconds(10);
- }
+ MillisecondsDouble checktxtime{std::chrono::minutes(1)};
+ while (tip == hashWatchedChain && IsRPCRunning()) {
+ tip = miner.waitTipChanged(hashWatchedChain, checktxtime).hash;
+ // Timeout: Check transactions for update
+ // without holding the mempool lock to avoid deadlocks
+ if (miner.getTransactionsUpdated() != nTransactionsUpdatedLastLP)
+ break;
+ checktxtime = std::chrono::seconds(10);
}
}
ENTER_CRITICAL_SECTION(cs_main);
- tip = CHECK_NONFATAL(miner.getTipHash()).value();
+ tip = CHECK_NONFATAL(miner.getTip()).value().hash;
if (!IsRPCRunning())
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
@@ -800,7 +792,7 @@ static RPCHelpMan getblocktemplate()
// Update block
static CBlockIndex* pindexPrev;
static int64_t time_start;
- static std::unique_ptr<CBlockTemplate> pblocktemplate;
+ static std::unique_ptr<BlockTemplate> block_template;
if (!pindexPrev || pindexPrev->GetBlockHash() != tip ||
(miner.getTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - time_start > 5))
{
@@ -814,20 +806,19 @@ static RPCHelpMan getblocktemplate()
// Create new block
CScript scriptDummy = CScript() << OP_TRUE;
- pblocktemplate = miner.createNewBlock(scriptDummy);
- if (!pblocktemplate) {
- throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
- }
+ block_template = miner.createNewBlock(scriptDummy);
+ CHECK_NONFATAL(block_template);
+
// Need to update only after we know createNewBlock succeeded
pindexPrev = pindexPrevNew;
}
CHECK_NONFATAL(pindexPrev);
- CBlock* pblock = &pblocktemplate->block; // pointer for convenience
+ CBlock block{block_template->getBlock()};
// Update nTime
- UpdateTime(pblock, consensusParams, pindexPrev);
- pblock->nNonce = 0;
+ UpdateTime(&block, consensusParams, pindexPrev);
+ block.nNonce = 0;
// NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
const bool fPreSegWit = !DeploymentActiveAfter(pindexPrev, chainman, Consensus::DEPLOYMENT_SEGWIT);
@@ -836,8 +827,11 @@ static RPCHelpMan getblocktemplate()
UniValue transactions(UniValue::VARR);
std::map<uint256, int64_t> setTxIndex;
+ std::vector<CAmount> tx_fees{block_template->getTxFees()};
+ std::vector<CAmount> tx_sigops{block_template->getTxSigops()};
+
int i = 0;
- for (const auto& it : pblock->vtx) {
+ for (const auto& it : block.vtx) {
const CTransaction& tx = *it;
uint256 txHash = tx.GetHash();
setTxIndex[txHash] = i++;
@@ -860,8 +854,8 @@ static RPCHelpMan getblocktemplate()
entry.pushKV("depends", std::move(deps));
int index_in_template = i - 1;
- entry.pushKV("fee", pblocktemplate->vTxFees[index_in_template]);
- int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template];
+ entry.pushKV("fee", tx_fees.at(index_in_template));
+ int64_t nTxSigOps{tx_sigops.at(index_in_template)};
if (fPreSegWit) {
CHECK_NONFATAL(nTxSigOps % WITNESS_SCALE_FACTOR == 0);
nTxSigOps /= WITNESS_SCALE_FACTOR;
@@ -874,7 +868,7 @@ static RPCHelpMan getblocktemplate()
UniValue aux(UniValue::VOBJ);
- arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
+ arith_uint256 hashTarget = arith_uint256().SetCompact(block.nBits);
UniValue aMutable(UniValue::VARR);
aMutable.push_back("time");
@@ -904,7 +898,7 @@ static RPCHelpMan getblocktemplate()
break;
case ThresholdState::LOCKED_IN:
// Ensure bit is set in block version
- pblock->nVersion |= chainman.m_versionbitscache.Mask(consensusParams, pos);
+ block.nVersion |= chainman.m_versionbitscache.Mask(consensusParams, pos);
[[fallthrough]];
case ThresholdState::STARTED:
{
@@ -913,7 +907,7 @@ static RPCHelpMan getblocktemplate()
if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
if (!vbinfo.gbt_force) {
// If the client doesn't support this, don't indicate it in the [default] version
- pblock->nVersion &= ~chainman.m_versionbitscache.Mask(consensusParams, pos);
+ block.nVersion &= ~chainman.m_versionbitscache.Mask(consensusParams, pos);
}
}
break;
@@ -933,15 +927,15 @@ static RPCHelpMan getblocktemplate()
}
}
}
- result.pushKV("version", pblock->nVersion);
+ result.pushKV("version", block.nVersion);
result.pushKV("rules", std::move(aRules));
result.pushKV("vbavailable", std::move(vbavailable));
result.pushKV("vbrequired", int(0));
- result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex());
+ result.pushKV("previousblockhash", block.hashPrevBlock.GetHex());
result.pushKV("transactions", std::move(transactions));
result.pushKV("coinbaseaux", std::move(aux));
- result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue);
+ result.pushKV("coinbasevalue", (int64_t)block.vtx[0]->vout[0].nValue);
result.pushKV("longpollid", tip.GetHex() + ToString(nTransactionsUpdatedLast));
result.pushKV("target", hashTarget.GetHex());
result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
@@ -960,16 +954,16 @@ static RPCHelpMan getblocktemplate()
if (!fPreSegWit) {
result.pushKV("weightlimit", (int64_t)MAX_BLOCK_WEIGHT);
}
- result.pushKV("curtime", pblock->GetBlockTime());
- result.pushKV("bits", strprintf("%08x", pblock->nBits));
+ result.pushKV("curtime", block.GetBlockTime());
+ result.pushKV("bits", strprintf("%08x", block.nBits));
result.pushKV("height", (int64_t)(pindexPrev->nHeight+1));
if (consensusParams.signet_blocks) {
result.pushKV("signet_challenge", HexStr(consensusParams.signet_challenge));
}
- if (!pblocktemplate->vchCoinbaseCommitment.empty()) {
- result.pushKV("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment));
+ if (!block_template->getCoinbaseCommitment().empty()) {
+ result.pushKV("default_witness_commitment", HexStr(block_template->getCoinbaseCommitment()));
}
return result;