Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/mining.cpp
Show First 20 Lines • Show All 797 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
ChainstateManager &chainman = EnsureChainman(node); | ChainstateManager &chainman = EnsureChainman(node); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CChainParams &chainparams = config.GetChainParams(); | const CChainParams &chainparams = config.GetChainParams(); | ||||
std::string strMode = "template"; | std::string strMode = "template"; | ||||
UniValue lpval = NullUniValue; | UniValue lpval = NullUniValue; | ||||
std::set<std::string> setClientRules; | std::set<std::string> setClientRules; | ||||
CChainState &active_chainstate = chainman.ActiveChainstate(); | |||||
CChain &active_chain = active_chainstate.m_chain; | |||||
if (!request.params[0].isNull()) { | if (!request.params[0].isNull()) { | ||||
const UniValue &oparam = request.params[0].get_obj(); | const UniValue &oparam = request.params[0].get_obj(); | ||||
const UniValue &modeval = find_value(oparam, "mode"); | const UniValue &modeval = find_value(oparam, "mode"); | ||||
if (modeval.isStr()) { | if (modeval.isStr()) { | ||||
strMode = modeval.get_str(); | strMode = modeval.get_str(); | ||||
} else if (modeval.isNull()) { | } else if (modeval.isNull()) { | ||||
/* Do nothing */ | /* Do nothing */ | ||||
} else { | } else { | ||||
Show All 23 Lines | return RPCHelpMan{ | ||||
return "duplicate"; | return "duplicate"; | ||||
} | } | ||||
if (pindex->nStatus.isInvalid()) { | if (pindex->nStatus.isInvalid()) { | ||||
return "duplicate-invalid"; | return "duplicate-invalid"; | ||||
} | } | ||||
return "duplicate-inconclusive"; | return "duplicate-inconclusive"; | ||||
} | } | ||||
CBlockIndex *const pindexPrev = chainman.ActiveTip(); | CBlockIndex *const pindexPrev = active_chain.Tip(); | ||||
// TestBlockValidity only supports blocks built on the | // TestBlockValidity only supports blocks built on the | ||||
// current Tip | // current Tip | ||||
if (block.hashPrevBlock != pindexPrev->GetBlockHash()) { | if (block.hashPrevBlock != pindexPrev->GetBlockHash()) { | ||||
return "inconclusive-not-best-prevblk"; | return "inconclusive-not-best-prevblk"; | ||||
} | } | ||||
BlockValidationState state; | BlockValidationState state; | ||||
TestBlockValidity(state, chainparams, | TestBlockValidity(state, chainparams, active_chainstate, | ||||
chainman.ActiveChainstate(), block, | block, pindexPrev, | ||||
pindexPrev, | |||||
BlockValidationOptions(config) | BlockValidationOptions(config) | ||||
.withCheckPoW(false) | .withCheckPoW(false) | ||||
.withCheckMerkleRoot(true)); | .withCheckMerkleRoot(true)); | ||||
return BIP22ValidationResult(config, state); | return BIP22ValidationResult(config, state); | ||||
} | } | ||||
} | } | ||||
if (strMode != "template") { | if (strMode != "template") { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode"); | ||||
} | } | ||||
if (!node.connman) { | if (!node.connman) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_CLIENT_P2P_DISABLED, | RPC_CLIENT_P2P_DISABLED, | ||||
"Error: Peer-to-peer functionality missing or disabled"); | "Error: Peer-to-peer functionality missing or disabled"); | ||||
} | } | ||||
if (node.connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) { | if (node.connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) { | ||||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, | throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, | ||||
"Bitcoin is not connected!"); | "Bitcoin is not connected!"); | ||||
} | } | ||||
if (chainman.ActiveChainstate().IsInitialBlockDownload()) { | if (active_chainstate.IsInitialBlockDownload()) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME | RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME | ||||
" is in initial sync and waiting for blocks..."); | " is in initial sync and waiting for blocks..."); | ||||
} | } | ||||
static unsigned int nTransactionsUpdatedLast; | static unsigned int nTransactionsUpdatedLast; | ||||
const CTxMemPool &mempool = EnsureMemPool(node); | const CTxMemPool &mempool = EnsureMemPool(node); | ||||
Show All 9 Lines | return RPCHelpMan{ | ||||
std::string lpstr = lpval.get_str(); | std::string lpstr = lpval.get_str(); | ||||
hashWatchedChain = | hashWatchedChain = | ||||
ParseHashV(lpstr.substr(0, 64), "longpollid"); | ParseHashV(lpstr.substr(0, 64), "longpollid"); | ||||
nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64)); | nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64)); | ||||
} else { | } else { | ||||
// NOTE: Spec does not specify behaviour for non-string | // NOTE: Spec does not specify behaviour for non-string | ||||
// longpollid, but this makes testing easier | // longpollid, but this makes testing easier | ||||
hashWatchedChain = chainman.ActiveTip()->GetBlockHash(); | hashWatchedChain = active_chain.Tip()->GetBlockHash(); | ||||
nTransactionsUpdatedLastLP = nTransactionsUpdatedLast; | nTransactionsUpdatedLastLP = nTransactionsUpdatedLast; | ||||
} | } | ||||
// Release lock while waiting | // Release lock while waiting | ||||
LEAVE_CRITICAL_SECTION(cs_main); | LEAVE_CRITICAL_SECTION(cs_main); | ||||
{ | { | ||||
checktxtime = std::chrono::steady_clock::now() + | checktxtime = std::chrono::steady_clock::now() + | ||||
std::chrono::minutes(1); | std::chrono::minutes(1); | ||||
Show All 22 Lines | return RPCHelpMan{ | ||||
// TODO: Maybe recheck connections/IBD and (if something wrong) | // TODO: Maybe recheck connections/IBD and (if something wrong) | ||||
// send an expires-immediately template to stop miners? | // send an expires-immediately template to stop miners? | ||||
} | } | ||||
// Update block | // Update block | ||||
static CBlockIndex *pindexPrev; | static CBlockIndex *pindexPrev; | ||||
static int64_t nStart; | static int64_t nStart; | ||||
static std::unique_ptr<CBlockTemplate> pblocktemplate; | static std::unique_ptr<CBlockTemplate> pblocktemplate; | ||||
if (pindexPrev != chainman.ActiveTip() || | if (pindexPrev != active_chain.Tip() || | ||||
(mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && | (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && | ||||
GetTime() - nStart > 5)) { | GetTime() - nStart > 5)) { | ||||
// Clear pindexPrev so future calls make a new block, despite | // Clear pindexPrev so future calls make a new block, despite | ||||
// any failures from here on | // any failures from here on | ||||
pindexPrev = nullptr; | pindexPrev = nullptr; | ||||
// Store the pindexBest used before CreateNewBlock, to avoid | // Store the pindexBest used before CreateNewBlock, to avoid | ||||
// races | // races | ||||
nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); | nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); | ||||
CBlockIndex *pindexPrevNew = chainman.ActiveTip(); | CBlockIndex *pindexPrevNew = active_chain.Tip(); | ||||
nStart = GetTime(); | nStart = GetTime(); | ||||
// Create new block | // Create new block | ||||
CScript scriptDummy = CScript() << OP_TRUE; | CScript scriptDummy = CScript() << OP_TRUE; | ||||
pblocktemplate = | pblocktemplate = | ||||
BlockAssembler(config, chainman.ActiveChainstate(), mempool) | BlockAssembler(config, active_chainstate, mempool) | ||||
.CreateNewBlock(scriptDummy); | .CreateNewBlock(scriptDummy); | ||||
if (!pblocktemplate) { | if (!pblocktemplate) { | ||||
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); | 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; | pindexPrev = pindexPrevNew; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
result.pushKV("version", pblock->nVersion); | result.pushKV("version", pblock->nVersion); | ||||
result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex()); | result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex()); | ||||
result.pushKV("transactions", transactions); | result.pushKV("transactions", transactions); | ||||
result.pushKV("coinbaseaux", aux); | result.pushKV("coinbaseaux", aux); | ||||
result.pushKV("coinbasetxn", coinbasetxn); | result.pushKV("coinbasetxn", coinbasetxn); | ||||
result.pushKV("coinbasevalue", int64_t(coinbasevalue / SATOSHI)); | result.pushKV("coinbasevalue", int64_t(coinbasevalue / SATOSHI)); | ||||
result.pushKV("longpollid", | result.pushKV("longpollid", | ||||
chainman.ActiveTip()->GetBlockHash().GetHex() + | active_chain.Tip()->GetBlockHash().GetHex() + | ||||
ToString(nTransactionsUpdatedLast)); | ToString(nTransactionsUpdatedLast)); | ||||
result.pushKV("target", hashTarget.GetHex()); | result.pushKV("target", hashTarget.GetHex()); | ||||
result.pushKV("mintime", | result.pushKV("mintime", | ||||
int64_t(pindexPrev->GetMedianTimePast()) + 1); | int64_t(pindexPrev->GetMedianTimePast()) + 1); | ||||
result.pushKV("mutable", aMutable); | result.pushKV("mutable", aMutable); | ||||
result.pushKV("noncerange", "00000000ffffffff"); | result.pushKV("noncerange", "00000000ffffffff"); | ||||
result.pushKV("sigoplimit", | result.pushKV("sigoplimit", | ||||
GetMaxBlockSigChecksCount(DEFAULT_MAX_BLOCK_SIZE)); | GetMaxBlockSigChecksCount(DEFAULT_MAX_BLOCK_SIZE)); | ||||
▲ Show 20 Lines • Show All 189 Lines • Show Last 20 Lines |