diff options
Diffstat (limited to 'src/rpc/mining.cpp')
-rw-r--r-- | src/rpc/mining.cpp | 90 |
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"} }, |