Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/mining.cpp
Show All 34 Lines | |||||
#include <memory> | #include <memory> | ||||
/** | /** | ||||
* Return average network hashes per second based on the last 'lookup' blocks, | * Return average network hashes per second based on the last 'lookup' blocks, | ||||
* or from the last difficulty change if 'lookup' is nonpositive. If 'height' is | * or from the last difficulty change if 'lookup' is nonpositive. If 'height' is | ||||
* nonnegative, compute the estimate at the time when a given block was found. | * nonnegative, compute the estimate at the time when a given block was found. | ||||
*/ | */ | ||||
static UniValue GetNetworkHashPS(int lookup, int height) { | static UniValue GetNetworkHashPS(int lookup, int height) { | ||||
CBlockIndex *pb = chainActive.Tip(); | CBlockIndex *pb = ::ChainActive().Tip(); | ||||
if (height >= 0 && height < chainActive.Height()) { | if (height >= 0 && height < ::ChainActive().Height()) { | ||||
pb = chainActive[height]; | pb = ::ChainActive()[height]; | ||||
} | } | ||||
if (pb == nullptr || !pb->nHeight) { | if (pb == nullptr || !pb->nHeight) { | ||||
return 0; | return 0; | ||||
} | } | ||||
// If lookup is -1, then use blocks since last difficulty change. | // If lookup is -1, then use blocks since last difficulty change. | ||||
if (lookup <= 0) { | if (lookup <= 0) { | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | UniValue generateBlocks(const Config &config, | ||||
int nGenerate, uint64_t nMaxTries, bool keepScript) { | int nGenerate, uint64_t nMaxTries, bool keepScript) { | ||||
static const int nInnerLoopCount = 0x100000; | static const int nInnerLoopCount = 0x100000; | ||||
int nHeightEnd = 0; | int nHeightEnd = 0; | ||||
int nHeight = 0; | 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; | ||||
} | } | ||||
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) | BlockAssembler(config, g_mempool) | ||||
.CreateNewBlock(coinbaseScript->reserveScript)); | .CreateNewBlock(coinbaseScript->reserveScript)); | ||||
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; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
IncrementExtraNonce(pblock, chainActive.Tip(), | IncrementExtraNonce(pblock, ::ChainActive().Tip(), | ||||
config.GetMaxBlockSize(), nExtraNonce); | config.GetMaxBlockSize(), nExtraNonce); | ||||
} | } | ||||
while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && | while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && | ||||
!CheckProofOfWork(pblock->GetHash(), pblock->nBits, | !CheckProofOfWork(pblock->GetHash(), pblock->nBits, | ||||
config.GetChainParams().GetConsensus())) { | config.GetChainParams().GetConsensus())) { | ||||
++pblock->nNonce; | ++pblock->nNonce; | ||||
--nMaxTries; | --nMaxTries; | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() != 0) { | ||||
"\nExamples:\n" + | "\nExamples:\n" + | ||||
HelpExampleCli("getmininginfo", "") + | HelpExampleCli("getmininginfo", "") + | ||||
HelpExampleRpc("getmininginfo", "")); | HelpExampleRpc("getmininginfo", "")); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
UniValue obj(UniValue::VOBJ); | UniValue obj(UniValue::VOBJ); | ||||
obj.pushKV("blocks", int(chainActive.Height())); | obj.pushKV("blocks", int(::ChainActive().Height())); | ||||
obj.pushKV("currentblocksize", uint64_t(nLastBlockSize)); | obj.pushKV("currentblocksize", uint64_t(nLastBlockSize)); | ||||
obj.pushKV("currentblocktx", uint64_t(nLastBlockTx)); | obj.pushKV("currentblocktx", uint64_t(nLastBlockTx)); | ||||
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(g_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; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 215 Lines • ▼ Show 20 Lines | if (!request.params[0].isNull()) { | ||||
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 = chainActive.Tip(); | CBlockIndex *const pindexPrev = ::ChainActive().Tip(); | ||||
// TestBlockValidity only supports blocks built on the current Tip | // TestBlockValidity only supports blocks built on the current Tip | ||||
if (block.hashPrevBlock != pindexPrev->GetBlockHash()) { | if (block.hashPrevBlock != pindexPrev->GetBlockHash()) { | ||||
return "inconclusive-not-best-prevblk"; | return "inconclusive-not-best-prevblk"; | ||||
} | } | ||||
CValidationState state; | CValidationState state; | ||||
TestBlockValidity(state, config.GetChainParams(), block, pindexPrev, | TestBlockValidity(state, config.GetChainParams(), block, pindexPrev, | ||||
BlockValidationOptions(config) | BlockValidationOptions(config) | ||||
.withCheckPoW(false) | .withCheckPoW(false) | ||||
Show All 35 Lines | if (!lpval.isNull()) { | ||||
// Format: <hashBestChain><nTransactionsUpdatedLast> | // Format: <hashBestChain><nTransactionsUpdatedLast> | ||||
std::string lpstr = lpval.get_str(); | std::string lpstr = lpval.get_str(); | ||||
hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid"); | hashWatchedChain = 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 longpollid, | // NOTE: Spec does not specify behaviour for non-string longpollid, | ||||
// but this makes testing easier | // but this makes testing easier | ||||
hashWatchedChain = chainActive.Tip()->GetBlockHash(); | hashWatchedChain = ::ChainActive().Tip()->GetBlockHash(); | ||||
nTransactionsUpdatedLastLP = nTransactionsUpdatedLast; | nTransactionsUpdatedLastLP = nTransactionsUpdatedLast; | ||||
} | } | ||||
// Release the wallet and main lock while waiting | // Release the wallet and main lock while waiting | ||||
LEAVE_CRITICAL_SECTION(cs_main); | LEAVE_CRITICAL_SECTION(cs_main); | ||||
{ | { | ||||
checktxtime = | checktxtime = | ||||
std::chrono::steady_clock::now() + std::chrono::minutes(1); | std::chrono::steady_clock::now() + std::chrono::minutes(1); | ||||
Show All 19 Lines | if (!lpval.isNull()) { | ||||
// 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 && | (g_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 = g_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, g_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"); | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | static UniValue getblocktemplate(const Config &config, | ||||
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("coinbasevalue", | result.pushKV("coinbasevalue", | ||||
int64_t(pblock->vtx[0]->vout[0].nValue / SATOSHI)); | int64_t(pblock->vtx[0]->vout[0].nValue / SATOSHI)); | ||||
result.pushKV("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + | result.pushKV("longpollid", ::ChainActive().Tip()->GetBlockHash().GetHex() + | ||||
i64tostr(nTransactionsUpdatedLast)); | i64tostr(nTransactionsUpdatedLast)); | ||||
result.pushKV("target", hashTarget.GetHex()); | result.pushKV("target", hashTarget.GetHex()); | ||||
result.pushKV("mintime", int64_t(pindexPrev->GetMedianTimePast()) + 1); | result.pushKV("mintime", int64_t(pindexPrev->GetMedianTimePast()) + 1); | ||||
result.pushKV("mutable", aMutable); | result.pushKV("mutable", aMutable); | ||||
result.pushKV("noncerange", "00000000ffffffff"); | result.pushKV("noncerange", "00000000ffffffff"); | ||||
// FIXME: Allow for mining block greater than 1M. | // FIXME: Allow for mining block greater than 1M. | ||||
result.pushKV("sigoplimit", GetMaxBlockSigOpsCount(DEFAULT_MAX_BLOCK_SIZE)); | result.pushKV("sigoplimit", GetMaxBlockSigOpsCount(DEFAULT_MAX_BLOCK_SIZE)); | ||||
result.pushKV("sizelimit", DEFAULT_MAX_BLOCK_SIZE); | result.pushKV("sizelimit", DEFAULT_MAX_BLOCK_SIZE); | ||||
▲ Show 20 Lines • Show All 178 Lines • Show Last 20 Lines |