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.cpp90
1 files changed, 63 insertions, 27 deletions
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 75bc983200..623b0bd86a 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2017 The Bitcoin Core developers
+// Copyright (c) 2009-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -10,8 +10,6 @@
#include <consensus/params.h>
#include <consensus/validation.h>
#include <core_io.h>
-#include <init.h>
-#include <validation.h>
#include <key_io.h>
#include <miner.h>
#include <net.h>
@@ -20,9 +18,11 @@
#include <rpc/blockchain.h>
#include <rpc/mining.h>
#include <rpc/server.h>
+#include <shutdown.h>
#include <txmempool.h>
#include <util.h>
#include <utilstrencodings.h>
+#include <validation.h>
#include <validationinterface.h>
#include <warnings.h>
@@ -44,7 +44,7 @@ unsigned int ParseConfirmTarget(const UniValue& value)
* 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.
*/
-UniValue GetNetworkHashPS(int lookup, int height) {
+static UniValue GetNetworkHashPS(int lookup, int height) {
CBlockIndex *pb = chainActive.Tip();
if (height >= 0 && height < chainActive.Height())
@@ -81,7 +81,7 @@ UniValue GetNetworkHashPS(int lookup, int height) {
return workDiff.getdouble() / timeDiff;
}
-UniValue getnetworkhashps(const JSONRPCRequest& request)
+static UniValue getnetworkhashps(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 2)
throw std::runtime_error(
@@ -116,7 +116,7 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen
}
unsigned int nExtraNonce = 0;
UniValue blockHashes(UniValue::VARR);
- while (nHeight < nHeightEnd)
+ while (nHeight < nHeightEnd && !ShutdownRequested())
{
std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript));
if (!pblocktemplate.get())
@@ -151,7 +151,7 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen
return blockHashes;
}
-UniValue generatetoaddress(const JSONRPCRequest& request)
+static UniValue generatetoaddress(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
throw std::runtime_error(
@@ -185,7 +185,7 @@ UniValue generatetoaddress(const JSONRPCRequest& request)
return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false);
}
-UniValue getmininginfo(const JSONRPCRequest& request)
+static UniValue getmininginfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
throw std::runtime_error(
@@ -214,7 +214,7 @@ UniValue getmininginfo(const JSONRPCRequest& request)
obj.pushKV("blocks", (int)chainActive.Height());
obj.pushKV("currentblockweight", (uint64_t)nLastBlockWeight);
obj.pushKV("currentblocktx", (uint64_t)nLastBlockTx);
- obj.pushKV("difficulty", (double)GetDifficulty());
+ obj.pushKV("difficulty", (double)GetDifficulty(chainActive.Tip()));
obj.pushKV("networkhashps", getnetworkhashps(request));
obj.pushKV("pooledtx", (uint64_t)mempool.size());
obj.pushKV("chain", Params().NetworkIDString());
@@ -224,7 +224,7 @@ UniValue getmininginfo(const JSONRPCRequest& request)
// NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
-UniValue prioritisetransaction(const JSONRPCRequest& request)
+static UniValue prioritisetransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 3)
throw std::runtime_error(
@@ -278,7 +278,7 @@ static UniValue BIP22ValidationResult(const CValidationState& state)
return "valid?";
}
-std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
+static std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
std::string s = vbinfo.name;
if (!vbinfo.gbt_force) {
@@ -287,7 +287,7 @@ std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
return s;
}
-UniValue getblocktemplate(const JSONRPCRequest& request)
+static UniValue getblocktemplate(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
@@ -337,7 +337,6 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
" \"fee\": n, (numeric) difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
" \"sigops\" : n, (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n"
" \"weight\" : n, (numeric) total transaction weight, as counted for purposes of block limits\n"
- " \"required\" : true|false (boolean) if provided and true, this transaction must be in the final block\n"
" }\n"
" ,...\n"
" ],\n"
@@ -471,10 +470,10 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
{
checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1);
- WaitableLock lock(csBestBlock);
- while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
+ WaitableLock lock(g_best_block_mutex);
+ while (g_best_block == hashWatchedChain && IsRPCRunning())
{
- if (cvBlockChange.wait_until(lock, checktxtime) == std::cv_status::timeout)
+ if (g_best_block_cv.wait_until(lock, checktxtime) == std::cv_status::timeout)
{
// Timeout: Check transactions for update
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
@@ -525,6 +524,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
// Need to update only after we know CreateNewBlock succeeded
pindexPrev = pindexPrevNew;
}
+ assert(pindexPrev);
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
const Consensus::Params& consensusParams = Params().GetConsensus();
@@ -694,7 +694,7 @@ protected:
}
};
-UniValue submitblock(const JSONRPCRequest& request)
+static UniValue submitblock(const JSONRPCRequest& request)
{
// We allow 2 arguments for compliance with BIP22. Argument 2 is ignored.
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) {
@@ -724,7 +724,6 @@ UniValue submitblock(const JSONRPCRequest& request)
}
uint256 hash = block.GetHash();
- bool fBlockPresent = false;
{
LOCK(cs_main);
const CBlockIndex* pindex = LookupBlockIndex(hash);
@@ -735,8 +734,6 @@ UniValue submitblock(const JSONRPCRequest& request)
if (pindex->nStatus & BLOCK_FAILED_MASK) {
return "duplicate-invalid";
}
- // Otherwise, we might only have the header - process the block before returning
- fBlockPresent = true;
}
}
@@ -748,13 +745,15 @@ UniValue submitblock(const JSONRPCRequest& request)
}
}
+ bool new_block;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
- bool fAccepted = ProcessNewBlock(Params(), blockptr, true, nullptr);
+ bool accepted = ProcessNewBlock(Params(), blockptr, /* fForceProcessing */ true, /* fNewBlock */ &new_block);
UnregisterValidationInterface(&sc);
- if (fBlockPresent) {
- if (fAccepted && !sc.found) {
- return "duplicate-inconclusive";
+ if (!new_block) {
+ if (!accepted) {
+ // TODO Maybe pass down fNewBlock to AcceptBlockHeader, so it is properly set to true in this case?
+ return "invalid";
}
return "duplicate";
}
@@ -764,13 +763,49 @@ UniValue submitblock(const JSONRPCRequest& request)
return BIP22ValidationResult(sc.state);
}
-UniValue estimatefee(const JSONRPCRequest& request)
+static UniValue submitheader(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 1) {
+ throw std::runtime_error(
+ "submitheader \"hexdata\"\n"
+ "\nDecode the given hexdata as a header and submit it as a candidate chain tip if valid."
+ "\nThrows when the header is invalid.\n"
+ "\nArguments\n"
+ "1. \"hexdata\" (string, required) the hex-encoded block header data\n"
+ "\nResult:\n"
+ "None"
+ "\nExamples:\n" +
+ HelpExampleCli("submitheader", "\"aabbcc\"") +
+ HelpExampleRpc("submitheader", "\"aabbcc\""));
+ }
+
+ CBlockHeader h;
+ if (!DecodeHexBlockHeader(h, request.params[0].get_str())) {
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block header decode failed");
+ }
+ {
+ LOCK(cs_main);
+ if (!LookupBlockIndex(h.hashPrevBlock)) {
+ throw JSONRPCError(RPC_VERIFY_ERROR, "Must submit previous header (" + h.hashPrevBlock.GetHex() + ") first");
+ }
+ }
+
+ CValidationState state;
+ ProcessNewBlockHeaders({h}, state, Params(), /* ppindex */ nullptr, /* first_invalid */ nullptr);
+ if (state.IsValid()) return NullUniValue;
+ if (state.IsError()) {
+ throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));
+ }
+ throw JSONRPCError(RPC_VERIFY_ERROR, state.GetRejectReason());
+}
+
+static UniValue estimatefee(const JSONRPCRequest& request)
{
throw JSONRPCError(RPC_METHOD_DEPRECATED, "estimatefee was removed in v0.17.\n"
"Clients should use estimatesmartfee.");
}
-UniValue estimatesmartfee(const JSONRPCRequest& request)
+static UniValue estimatesmartfee(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
@@ -831,7 +866,7 @@ UniValue estimatesmartfee(const JSONRPCRequest& request)
return result;
}
-UniValue estimaterawfee(const JSONRPCRequest& request)
+static UniValue estimaterawfee(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
@@ -941,6 +976,7 @@ static const CRPCCommand commands[] =
{ "mining", "prioritisetransaction", &prioritisetransaction, {"txid","dummy","fee_delta"} },
{ "mining", "getblocktemplate", &getblocktemplate, {"template_request"} },
{ "mining", "submitblock", &submitblock, {"hexdata","dummy"} },
+ { "mining", "submitheader", &submitheader, {"hexdata"} },
{ "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },