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.cpp80
1 files changed, 46 insertions, 34 deletions
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 0f6853ef37..2b93c18965 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -16,6 +16,7 @@
#include <core_io.h>
#include <deploymentinfo.h>
#include <deploymentstatus.h>
+#include <interfaces/mining.h>
#include <key_io.h>
#include <net.h>
#include <node/context.h>
@@ -45,6 +46,7 @@
using node::BlockAssembler;
using node::CBlockTemplate;
+using interfaces::Mining;
using node::NodeContext;
using node::RegenerateCommitments;
using node::UpdateTime;
@@ -127,7 +129,7 @@ static RPCHelpMan getnetworkhashps()
};
}
-static bool GenerateBlock(ChainstateManager& chainman, 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);
@@ -147,23 +149,23 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t&
if (!process_new_block) return true;
- if (!chainman.ProcessNewBlock(block_out, /*force_processing=*/true, /*min_pow_checked=*/true, nullptr)) {
+ if (!miner.processNewBlock(block_out, nullptr)) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
}
return true;
}
-static UniValue generateBlocks(ChainstateManager& chainman, const CTxMemPool& mempool, const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
+static UniValue generateBlocks(ChainstateManager& chainman, Mining& miner, const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
{
UniValue blockHashes(UniValue::VARR);
while (nGenerate > 0 && !chainman.m_interrupt) {
- std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler{chainman.ActiveChainstate(), &mempool}.CreateNewBlock(coinbase_script));
+ std::unique_ptr<CBlockTemplate> pblocktemplate(miner.createNewBlock(coinbase_script));
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
std::shared_ptr<const CBlock> block_out;
- if (!GenerateBlock(chainman, pblocktemplate->block, nMaxTries, block_out, /*process_new_block=*/true)) {
+ if (!GenerateBlock(chainman, miner, pblocktemplate->block, nMaxTries, block_out, /*process_new_block=*/true)) {
break;
}
@@ -239,10 +241,10 @@ static RPCHelpMan generatetodescriptor()
}
NodeContext& node = EnsureAnyNodeContext(request.context);
- const CTxMemPool& mempool = EnsureMemPool(node);
+ Mining& miner = EnsureMining(node);
ChainstateManager& chainman = EnsureChainman(node);
- return generateBlocks(chainman, mempool, coinbase_script, num_blocks, max_tries);
+ return generateBlocks(chainman, miner, coinbase_script, num_blocks, max_tries);
},
};
}
@@ -285,12 +287,12 @@ static RPCHelpMan generatetoaddress()
}
NodeContext& node = EnsureAnyNodeContext(request.context);
- const CTxMemPool& mempool = EnsureMemPool(node);
+ Mining& miner = EnsureMining(node);
ChainstateManager& chainman = EnsureChainman(node);
CScript coinbase_script = GetScriptForDestination(destination);
- return generateBlocks(chainman, mempool, coinbase_script, num_blocks, max_tries);
+ return generateBlocks(chainman, miner, coinbase_script, num_blocks, max_tries);
},
};
}
@@ -337,6 +339,7 @@ static RPCHelpMan generateblock()
}
NodeContext& node = EnsureAnyNodeContext(request.context);
+ Mining& miner = EnsureMining(node);
const CTxMemPool& mempool = EnsureMemPool(node);
std::vector<CTransactionRef> txs;
@@ -370,7 +373,7 @@ static RPCHelpMan generateblock()
{
LOCK(cs_main);
- std::unique_ptr<CBlockTemplate> blocktemplate(BlockAssembler{chainman.ActiveChainstate(), nullptr}.CreateNewBlock(coinbase_script));
+ std::unique_ptr<CBlockTemplate> blocktemplate{miner.createNewBlock(coinbase_script, /*use_mempool=*/false)};
if (!blocktemplate) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
}
@@ -387,15 +390,15 @@ static RPCHelpMan generateblock()
LOCK(cs_main);
BlockValidationState state;
- if (!TestBlockValidity(state, chainman.GetParams(), chainman.ActiveChainstate(), block, chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), false, false)) {
- throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.ToString()));
+ if (!miner.testBlockValidity(state, block, /*check_merkle_root=*/false)) {
+ throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("testBlockValidity failed: %s", state.ToString()));
}
}
std::shared_ptr<const CBlock> block_out;
uint64_t max_tries{DEFAULT_MAX_TRIES};
- if (!GenerateBlock(chainman, block, max_tries, block_out, process_new_block) || !block_out) {
+ if (!GenerateBlock(chainman, miner, block, max_tries, block_out, process_new_block) || !block_out) {
throw JSONRPCError(RPC_MISC_ERROR, "Failed to make block.");
}
@@ -662,13 +665,15 @@ static RPCHelpMan getblocktemplate()
{
NodeContext& node = EnsureAnyNodeContext(request.context);
ChainstateManager& chainman = EnsureChainman(node);
+ Mining& miner = EnsureMining(node);
LOCK(cs_main);
+ std::optional<uint256> maybe_tip{miner.getTipHash()};
+ CHECK_NONFATAL(maybe_tip);
+ uint256 tip{maybe_tip.value()};
std::string strMode = "template";
UniValue lpval = NullUniValue;
std::set<std::string> setClientRules;
- Chainstate& active_chainstate = chainman.ActiveChainstate();
- CChain& active_chain = active_chainstate.m_chain;
if (!request.params[0].isNull())
{
const UniValue& oparam = request.params[0].get_obj();
@@ -703,12 +708,12 @@ static RPCHelpMan getblocktemplate()
return "duplicate-inconclusive";
}
- CBlockIndex* const pindexPrev = active_chain.Tip();
- // TestBlockValidity only supports blocks built on the current Tip
- if (block.hashPrevBlock != pindexPrev->GetBlockHash())
+ // testBlockValidity only supports blocks built on the current Tip
+ if (block.hashPrevBlock != tip) {
return "inconclusive-not-best-prevblk";
+ }
BlockValidationState state;
- TestBlockValidity(state, chainman.GetParams(), active_chainstate, block, pindexPrev, false, true);
+ miner.testBlockValidity(state, block);
return BIP22ValidationResult(state);
}
@@ -724,19 +729,18 @@ static RPCHelpMan getblocktemplate()
if (strMode != "template")
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
- if (!chainman.GetParams().IsTestChain()) {
+ if (!miner.isTestChain()) {
const CConnman& connman = EnsureConnman(node);
if (connman.GetNodeCount(ConnectionDirection::Both) == 0) {
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
}
- if (chainman.IsInitialBlockDownload()) {
+ if (miner.isInitialBlockDownload()) {
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME " is in initial sync and waiting for blocks...");
}
}
static unsigned int nTransactionsUpdatedLast;
- const CTxMemPool& mempool = EnsureMemPool(node);
if (!lpval.isNull())
{
@@ -756,7 +760,7 @@ static RPCHelpMan getblocktemplate()
else
{
// NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
- hashWatchedChain = active_chain.Tip()->GetBlockHash();
+ hashWatchedChain = tip;
nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
}
@@ -772,7 +776,7 @@ static RPCHelpMan getblocktemplate()
{
// Timeout: Check transactions for update
// without holding the mempool lock to avoid deadlocks
- if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
+ if (miner.getTransactionsUpdated() != nTransactionsUpdatedLastLP)
break;
checktxtime += std::chrono::seconds(10);
}
@@ -780,6 +784,10 @@ static RPCHelpMan getblocktemplate()
}
ENTER_CRITICAL_SECTION(cs_main);
+ std::optional<uint256> maybe_tip{miner.getTipHash()};
+ CHECK_NONFATAL(maybe_tip);
+ tip = maybe_tip.value();
+
if (!IsRPCRunning())
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
// TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
@@ -801,24 +809,25 @@ static RPCHelpMan getblocktemplate()
static CBlockIndex* pindexPrev;
static int64_t time_start;
static std::unique_ptr<CBlockTemplate> pblocktemplate;
- if (pindexPrev != active_chain.Tip() ||
- (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - time_start > 5))
+ if (!pindexPrev || pindexPrev->GetBlockHash() != tip ||
+ (miner.getTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - time_start > 5))
{
// Clear pindexPrev so future calls make a new block, despite any failures from here on
pindexPrev = nullptr;
- // Store the pindexBest used before CreateNewBlock, to avoid races
- nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
- CBlockIndex* pindexPrevNew = active_chain.Tip();
+ // Store the pindexBest used before createNewBlock, to avoid races
+ nTransactionsUpdatedLast = miner.getTransactionsUpdated();
+ CBlockIndex* pindexPrevNew = chainman.m_blockman.LookupBlockIndex(tip);
time_start = GetTime();
// Create new block
CScript scriptDummy = CScript() << OP_TRUE;
- pblocktemplate = BlockAssembler{active_chainstate, &mempool}.CreateNewBlock(scriptDummy);
- if (!pblocktemplate)
+ pblocktemplate = miner.createNewBlock(scriptDummy);
+ if (!pblocktemplate) {
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
+ }
- // Need to update only after we know CreateNewBlock succeeded
+ // Need to update only after we know createNewBlock succeeded
pindexPrev = pindexPrevNew;
}
CHECK_NONFATAL(pindexPrev);
@@ -941,7 +950,7 @@ static RPCHelpMan getblocktemplate()
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("longpollid", active_chain.Tip()->GetBlockHash().GetHex() + ToString(nTransactionsUpdatedLast));
+ result.pushKV("longpollid", tip.GetHex() + ToString(nTransactionsUpdatedLast));
result.pushKV("target", hashTarget.GetHex());
result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1);
result.pushKV("mutable", std::move(aMutable));
@@ -1047,10 +1056,13 @@ static RPCHelpMan submitblock()
}
}
+ NodeContext& node = EnsureAnyNodeContext(request.context);
+ Mining& miner = EnsureMining(node);
+
bool new_block;
auto sc = std::make_shared<submitblock_StateCatcher>(block.GetHash());
CHECK_NONFATAL(chainman.m_options.signals)->RegisterSharedValidationInterface(sc);
- bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block);
+ bool accepted = miner.processNewBlock(blockptr, /*new_block=*/&new_block);
CHECK_NONFATAL(chainman.m_options.signals)->UnregisterSharedValidationInterface(sc);
if (!new_block && accepted) {
return "duplicate";