Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/mining.cpp
Show First 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | int nHeight = 0; | ||||
// Don't keep cs_main locked. | // Don't keep cs_main locked. | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
nHeight = ::ChainActive().Height(); | nHeight = ::ChainActive().Height(); | ||||
nHeightEnd = nHeight + nGenerate; | nHeightEnd = nHeight + nGenerate; | ||||
} | } | ||||
const uint64_t nExcessiveBlockSize = config.GetMaxBlockSize(); | const uint64_t nExcessiveBlockSize = config.GetMaxBlockSize(); | ||||
const CTxMemPool &mempool = EnsureMemPool(); | |||||
unsigned int nExtraNonce = 0; | unsigned int nExtraNonce = 0; | ||||
UniValue blockHashes(UniValue::VARR); | UniValue blockHashes(UniValue::VARR); | ||||
while (nHeight < nHeightEnd && !ShutdownRequested()) { | while (nHeight < nHeightEnd && !ShutdownRequested()) { | ||||
std::unique_ptr<CBlockTemplate> pblocktemplate( | std::unique_ptr<CBlockTemplate> pblocktemplate( | ||||
BlockAssembler(config, g_mempool).CreateNewBlock(coinbase_script)); | BlockAssembler(config, mempool).CreateNewBlock(coinbase_script)); | ||||
if (!pblocktemplate.get()) { | if (!pblocktemplate.get()) { | ||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); | throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); | ||||
} | } | ||||
CBlock *pblock = &pblocktemplate->block; | CBlock *pblock = &pblocktemplate->block; | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | RPCHelpMan{ | ||||
"blockchain warnings\n" | "blockchain warnings\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli("getmininginfo", "") + | RPCExamples{HelpExampleCli("getmininginfo", "") + | ||||
HelpExampleRpc("getmininginfo", "")}, | HelpExampleRpc("getmininginfo", "")}, | ||||
} | } | ||||
.Check(request); | .Check(request); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CTxMemPool &mempool = EnsureMemPool(); | |||||
UniValue obj(UniValue::VOBJ); | UniValue obj(UniValue::VOBJ); | ||||
obj.pushKV("blocks", int(::ChainActive().Height())); | obj.pushKV("blocks", int(::ChainActive().Height())); | ||||
if (BlockAssembler::m_last_block_size) { | if (BlockAssembler::m_last_block_size) { | ||||
obj.pushKV("currentblocksize", *BlockAssembler::m_last_block_size); | obj.pushKV("currentblocksize", *BlockAssembler::m_last_block_size); | ||||
} | } | ||||
if (BlockAssembler::m_last_block_num_txs) { | if (BlockAssembler::m_last_block_num_txs) { | ||||
obj.pushKV("currentblocktx", *BlockAssembler::m_last_block_num_txs); | obj.pushKV("currentblocktx", *BlockAssembler::m_last_block_num_txs); | ||||
} | } | ||||
obj.pushKV("difficulty", double(GetDifficulty(::ChainActive().Tip()))); | obj.pushKV("difficulty", double(GetDifficulty(::ChainActive().Tip()))); | ||||
obj.pushKV("networkhashps", getnetworkhashps(config, request)); | obj.pushKV("networkhashps", getnetworkhashps(config, request)); | ||||
obj.pushKV("pooledtx", uint64_t(g_mempool.size())); | obj.pushKV("pooledtx", uint64_t(mempool.size())); | ||||
obj.pushKV("chain", config.GetChainParams().NetworkIDString()); | obj.pushKV("chain", config.GetChainParams().NetworkIDString()); | ||||
obj.pushKV("warnings", GetWarnings("statusbar")); | obj.pushKV("warnings", GetWarnings("statusbar")); | ||||
return obj; | return obj; | ||||
} | } | ||||
// NOTE: Unlike wallet RPC (which use BCH values), mining RPCs follow GBT (BIP | // NOTE: Unlike wallet RPC (which use BCH values), mining RPCs follow GBT (BIP | ||||
// 22) in using satoshi amounts | // 22) in using satoshi amounts | ||||
Show All 30 Lines | static UniValue prioritisetransaction(const Config &config, | ||||
Amount nAmount = request.params[2].get_int64() * SATOSHI; | Amount nAmount = request.params[2].get_int64() * SATOSHI; | ||||
if (!(request.params[1].isNull() || request.params[1].get_real() == 0)) { | if (!(request.params[1].isNull() || request.params[1].get_real() == 0)) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Priority is no longer supported, dummy argument to " | "Priority is no longer supported, dummy argument to " | ||||
"prioritisetransaction must be 0."); | "prioritisetransaction must be 0."); | ||||
} | } | ||||
g_mempool.PrioritiseTransaction(txid, nAmount); | EnsureMemPool().PrioritiseTransaction(txid, nAmount); | ||||
return true; | return true; | ||||
} | } | ||||
// NOTE: Assumes a conclusive result; if result is inconclusive, it must be | // NOTE: Assumes a conclusive result; if result is inconclusive, it must be | ||||
// handled by caller | // handled by caller | ||||
static UniValue BIP22ValidationResult(const Config &config, | static UniValue BIP22ValidationResult(const Config &config, | ||||
const BlockValidationState &state) { | const BlockValidationState &state) { | ||||
if (state.IsValid()) { | if (state.IsValid()) { | ||||
▲ Show 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | static UniValue getblocktemplate(const Config &config, | ||||
} | } | ||||
if (::ChainstateActive().IsInitialBlockDownload()) { | if (::ChainstateActive().IsInitialBlockDownload()) { | ||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME | throw JSONRPCError(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(); | |||||
if (!lpval.isNull()) { | if (!lpval.isNull()) { | ||||
// Wait to respond until either the best block changes, OR a minute has | // Wait to respond until either the best block changes, OR a minute has | ||||
// passed and there are more transactions | // passed and there are more transactions | ||||
uint256 hashWatchedChain; | uint256 hashWatchedChain; | ||||
std::chrono::steady_clock::time_point checktxtime; | std::chrono::steady_clock::time_point checktxtime; | ||||
unsigned int nTransactionsUpdatedLastLP; | unsigned int nTransactionsUpdatedLastLP; | ||||
Show All 16 Lines | if (!lpval.isNull()) { | ||||
checktxtime = | checktxtime = | ||||
std::chrono::steady_clock::now() + std::chrono::minutes(1); | std::chrono::steady_clock::now() + std::chrono::minutes(1); | ||||
WAIT_LOCK(g_best_block_mutex, lock); | WAIT_LOCK(g_best_block_mutex, lock); | ||||
while (g_best_block == hashWatchedChain && IsRPCRunning()) { | while (g_best_block == hashWatchedChain && IsRPCRunning()) { | ||||
if (g_best_block_cv.wait_until(lock, checktxtime) == | if (g_best_block_cv.wait_until(lock, checktxtime) == | ||||
std::cv_status::timeout) { | std::cv_status::timeout) { | ||||
// Timeout: Check transactions for update | // Timeout: Check transactions for update | ||||
// without holding ::mempool.cs to avoid deadlocks | // without holding the mempool look to avoid deadlocks | ||||
if (g_mempool.GetTransactionsUpdated() != | if (mempool.GetTransactionsUpdated() != | ||||
nTransactionsUpdatedLastLP) { | nTransactionsUpdatedLastLP) { | ||||
break; | break; | ||||
} | } | ||||
checktxtime += std::chrono::seconds(10); | checktxtime += std::chrono::seconds(10); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
ENTER_CRITICAL_SECTION(cs_main); | ENTER_CRITICAL_SECTION(cs_main); | ||||
if (!IsRPCRunning()) { | if (!IsRPCRunning()) { | ||||
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down"); | throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down"); | ||||
} | } | ||||
// TODO: Maybe recheck connections/IBD and (if something wrong) send an | // TODO: Maybe recheck connections/IBD and (if something wrong) send an | ||||
// expires-immediately template to stop miners? | // 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 != ::ChainActive().Tip() || | if (pindexPrev != ::ChainActive().Tip() || | ||||
(g_mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && | (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && | ||||
GetTime() - nStart > 5)) { | GetTime() - nStart > 5)) { | ||||
// Clear pindexPrev so future calls make a new block, despite any | // Clear pindexPrev so future calls make a new block, despite any | ||||
// failures from here on | // failures from here on | ||||
pindexPrev = nullptr; | pindexPrev = nullptr; | ||||
// Store the pindexBest used before CreateNewBlock, to avoid races | // Store the pindexBest used before CreateNewBlock, to avoid races | ||||
nTransactionsUpdatedLast = g_mempool.GetTransactionsUpdated(); | nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); | ||||
CBlockIndex *pindexPrevNew = ::ChainActive().Tip(); | CBlockIndex *pindexPrevNew = ::ChainActive().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, g_mempool).CreateNewBlock(scriptDummy); | BlockAssembler(config, mempool).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 236 Lines • ▼ Show 20 Lines | RPCHelpMan{ | ||||
"Estimates the approximate fee per kilobyte needed for a " | "Estimates the approximate fee per kilobyte needed for a " | ||||
"transaction\n", | "transaction\n", | ||||
{}, | {}, | ||||
RPCResult{"n (numeric) estimated fee-per-kilobyte\n"}, | RPCResult{"n (numeric) estimated fee-per-kilobyte\n"}, | ||||
RPCExamples{HelpExampleCli("estimatefee", "")}, | RPCExamples{HelpExampleCli("estimatefee", "")}, | ||||
} | } | ||||
.Check(request); | .Check(request); | ||||
return ValueFromAmount(g_mempool.estimateFee().GetFeePerK()); | const CTxMemPool &mempool = EnsureMemPool(); | ||||
return ValueFromAmount(mempool.estimateFee().GetFeePerK()); | |||||
} | } | ||||
// clang-format off | // clang-format off | ||||
static const CRPCCommand commands[] = { | static const CRPCCommand commands[] = { | ||||
// category name actor (function) argNames | // category name actor (function) argNames | ||||
// ---------- ------------------------ ---------------------- ---------- | // ---------- ------------------------ ---------------------- ---------- | ||||
{"mining", "getnetworkhashps", getnetworkhashps, {"nblocks", "height"}}, | {"mining", "getnetworkhashps", getnetworkhashps, {"nblocks", "height"}}, | ||||
{"mining", "getmininginfo", getmininginfo, {}}, | {"mining", "getmininginfo", getmininginfo, {}}, | ||||
Show All 16 Lines |