aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/blockchain.cpp195
-rw-r--r--src/rpc/blockchain.h10
-rw-r--r--src/rpc/client.cpp5
-rw-r--r--src/rpc/mining.cpp102
-rw-r--r--src/rpc/misc.cpp13
-rw-r--r--src/rpc/net.cpp116
-rw-r--r--src/rpc/protocol.h5
-rw-r--r--src/rpc/rawtransaction.cpp46
-rw-r--r--src/rpc/rawtransaction_util.cpp8
-rw-r--r--src/rpc/rawtransaction_util.h10
-rw-r--r--src/rpc/server.cpp6
-rw-r--r--src/rpc/server.h4
-rw-r--r--src/rpc/util.cpp16
-rw-r--r--src/rpc/util.h27
14 files changed, 381 insertions, 182 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 3463145f75..eb5148eebd 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -10,11 +10,13 @@
#include <chain.h>
#include <chainparams.h>
#include <coins.h>
-#include <node/coinstats.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <hash.h>
#include <index/blockfilterindex.h>
+#include <node/coinstats.h>
+#include <node/context.h>
+#include <node/utxo_snapshot.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <policy/rbf.h>
@@ -32,16 +34,12 @@
#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
-#include <versionbitsinfo.h>
#include <warnings.h>
-#include <assert.h>
#include <stdint.h>
#include <univalue.h>
-#include <boost/thread/thread.hpp> // boost::thread::interrupt
-
#include <condition_variable>
#include <memory>
#include <mutex>
@@ -56,11 +54,20 @@ static Mutex cs_blockchange;
static std::condition_variable cond_blockchange;
static CUpdatedBlock latestblock;
+CTxMemPool& EnsureMemPool()
+{
+ CHECK_NONFATAL(g_rpc_node);
+ if (!g_rpc_node->mempool) {
+ throw JSONRPCError(RPC_CLIENT_MEMPOOL_DISABLED, "Mempool disabled or instance not found");
+ }
+ return *g_rpc_node->mempool;
+}
+
/* Calculate the difficulty for a given block index.
*/
double GetDifficulty(const CBlockIndex* blockindex)
{
- assert(blockindex);
+ CHECK_NONFATAL(blockindex);
int nShift = (blockindex->nBits >> 24) & 0xff;
double dDiff =
@@ -521,7 +528,7 @@ static UniValue getrawmempool(const JSONRPCRequest& request)
if (!request.params[0].isNull())
fVerbose = request.params[0].get_bool();
- return MempoolToJSON(::mempool, fVerbose);
+ return MempoolToJSON(EnsureMemPool(), fVerbose);
}
static UniValue getmempoolancestors(const JSONRPCRequest& request)
@@ -559,6 +566,7 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request)
uint256 hash = ParseHashV(request.params[0], "parameter 1");
+ const CTxMemPool& mempool = EnsureMemPool();
LOCK(mempool.cs);
CTxMemPool::txiter it = mempool.mapTx.find(hash);
@@ -584,7 +592,7 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request)
const CTxMemPoolEntry &e = *ancestorIt;
const uint256& _hash = e.GetTx().GetHash();
UniValue info(UniValue::VOBJ);
- entryToJSON(::mempool, info, e);
+ entryToJSON(mempool, info, e);
o.pushKV(_hash.ToString(), info);
}
return o;
@@ -626,6 +634,7 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request)
uint256 hash = ParseHashV(request.params[0], "parameter 1");
+ const CTxMemPool& mempool = EnsureMemPool();
LOCK(mempool.cs);
CTxMemPool::txiter it = mempool.mapTx.find(hash);
@@ -651,7 +660,7 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request)
const CTxMemPoolEntry &e = *descendantIt;
const uint256& _hash = e.GetTx().GetHash();
UniValue info(UniValue::VOBJ);
- entryToJSON(::mempool, info, e);
+ entryToJSON(mempool, info, e);
o.pushKV(_hash.ToString(), info);
}
return o;
@@ -678,6 +687,7 @@ static UniValue getmempoolentry(const JSONRPCRequest& request)
uint256 hash = ParseHashV(request.params[0], "parameter 1");
+ const CTxMemPool& mempool = EnsureMemPool();
LOCK(mempool.cs);
CTxMemPool::txiter it = mempool.mapTx.find(hash);
@@ -687,7 +697,7 @@ static UniValue getmempoolentry(const JSONRPCRequest& request)
const CTxMemPoolEntry &e = *it;
UniValue info(UniValue::VOBJ);
- entryToJSON(::mempool, info, e);
+ entryToJSON(mempool, info, e);
return info;
}
@@ -735,8 +745,8 @@ static UniValue getblockheader(const JSONRPCRequest& request)
" \"version\" : n, (numeric) The block version\n"
" \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
- " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
- " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
+ " \"time\" : ttt, (numeric) The block time expressed in " + UNIX_EPOCH_TIME + "\n"
+ " \"mediantime\" : ttt, (numeric) The median block time expressed in " + UNIX_EPOCH_TIME + "\n"
" \"nonce\" : n, (numeric) The nonce\n"
" \"bits\" : \"1d00ffff\", (string) The bits\n"
" \"difficulty\" : x.xxx, (numeric) The difficulty\n"
@@ -847,8 +857,8 @@ static UniValue getblock(const JSONRPCRequest& request)
" \"transactionid\" (string) The transaction id\n"
" ,...\n"
" ],\n"
- " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
- " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
+ " \"time\" : ttt, (numeric) The block time expressed in " + UNIX_EPOCH_TIME + "\n"
+ " \"mediantime\" : ttt, (numeric) The median block time expressed in " + UNIX_EPOCH_TIME + "\n"
" \"nonce\" : n, (numeric) The nonce\n"
" \"bits\" : \"1d00ffff\", (string) The bits\n"
" \"difficulty\" : x.xxx, (numeric) The difficulty\n"
@@ -914,7 +924,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
{
RPCHelpMan{"pruneblockchain", "",
{
- {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block height to prune up to. May be set to a discrete height, or a unix timestamp\n"
+ {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block height to prune up to. May be set to a discrete height, or to a " + UNIX_EPOCH_TIME + "\n"
" to prune blocks whose block time is at least 2 hours older than the provided timestamp."},
},
RPCResult{
@@ -959,7 +969,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
PruneBlockFilesManual(height);
const CBlockIndex* block = ::ChainActive().Tip();
- assert(block);
+ CHECK_NONFATAL(block);
while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
block = block->pprev;
}
@@ -1063,6 +1073,7 @@ UniValue gettxout(const JSONRPCRequest& request)
CCoinsViewCache* coins_view = &::ChainstateActive().CoinsTip();
if (fMempool) {
+ const CTxMemPool& mempool = EnsureMemPool();
LOCK(mempool.cs);
CCoinsViewMemPool view(coins_view, mempool);
if (!view.GetCoin(out, coin) || mempool.isSpent(out)) {
@@ -1193,7 +1204,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
{},
RPCResult{
"{\n"
- " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
+ " \"chain\": \"xxxx\", (string) current network name (main, test, regtest)\n"
" \"blocks\": xxxxxx, (numeric) the height of the most-work fully-validated chain. The genesis block has height 0\n"
" \"headers\": xxxxxx, (numeric) the current number of headers we have validated\n"
" \"bestblockhash\": \"...\", (string) the hash of the currently best block\n"
@@ -1254,7 +1265,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
obj.pushKV("pruned", fPruneMode);
if (fPruneMode) {
const CBlockIndex* block = tip;
- assert(block);
+ CHECK_NONFATAL(block);
while (block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA)) {
block = block->pprev;
}
@@ -1279,7 +1290,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
BIP9SoftForkDescPushBack(softforks, "testdummy", consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
obj.pushKV("softforks", softforks);
- obj.pushKV("warnings", GetWarnings("statusbar"));
+ obj.pushKV("warnings", GetWarnings(false));
return obj;
}
@@ -1441,7 +1452,7 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request)
},
}.Check(request);
- return MempoolInfoToJSON(::mempool);
+ return MempoolInfoToJSON(EnsureMemPool());
}
static UniValue preciousblock(const JSONRPCRequest& request)
@@ -1471,7 +1482,7 @@ static UniValue preciousblock(const JSONRPCRequest& request)
}
}
- CValidationState state;
+ BlockValidationState state;
PreciousBlock(state, Params(), pblockindex);
if (!state.IsValid()) {
@@ -1496,7 +1507,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
}.Check(request);
uint256 hash(ParseHashV(request.params[0], "blockhash"));
- CValidationState state;
+ BlockValidationState state;
CBlockIndex* pblockindex;
{
@@ -1546,7 +1557,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
ResetBlockFailureFlags(pblockindex);
}
- CValidationState state;
+ BlockValidationState state;
ActivateBestChain(state, Params());
if (!state.IsValid()) {
@@ -1566,7 +1577,7 @@ static UniValue getchaintxstats(const JSONRPCRequest& request)
},
RPCResult{
"{\n"
- " \"time\": xxxxx, (numeric) The timestamp for the final block in the window in UNIX format.\n"
+ " \"time\": xxxxx, (numeric) The timestamp for the final block in the window, expressed in " + UNIX_EPOCH_TIME + ".\n"
" \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
" \"window_final_block_hash\": \"...\", (string) The hash of the final block in the window.\n"
" \"window_final_block_height\": xxxxx, (numeric) The height of the final block in the window.\n"
@@ -1600,7 +1611,7 @@ static UniValue getchaintxstats(const JSONRPCRequest& request)
}
}
- assert(pindex != nullptr);
+ CHECK_NONFATAL(pindex != nullptr);
if (request.params[0].isNull()) {
blockcount = std::max(0, std::min(blockcount, pindex->nHeight - 1));
@@ -1773,7 +1784,7 @@ static UniValue getblockstats(const JSONRPCRequest& request)
}
}
- assert(pindex != nullptr);
+ CHECK_NONFATAL(pindex != nullptr);
std::set<std::string> stats;
if (!request.params[1].isNull()) {
@@ -1873,7 +1884,7 @@ static UniValue getblockstats(const JSONRPCRequest& request)
}
CAmount txfee = tx_total_in - tx_total_out;
- assert(MoneyRange(txfee));
+ CHECK_NONFATAL(MoneyRange(txfee));
if (do_medianfee) {
fee_array.push_back(txfee);
}
@@ -1957,11 +1968,13 @@ static UniValue savemempool(const JSONRPCRequest& request)
},
}.Check(request);
- if (!::mempool.IsLoaded()) {
+ const CTxMemPool& mempool = EnsureMemPool();
+
+ if (!mempool.IsLoaded()) {
throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet");
}
- if (!DumpMempool(::mempool)) {
+ if (!DumpMempool(mempool)) {
throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk");
}
@@ -1977,7 +1990,6 @@ bool FindScriptPubKey(std::atomic<int>& scan_progress, const std::atomic<bool>&
Coin coin;
if (!cursor->GetKey(key) || !cursor->GetValue(coin)) return false;
if (++count % 8192 == 0) {
- boost::this_thread::interruption_point();
if (should_abort) {
// allow to abort the scan via the abort reference
return false;
@@ -2010,7 +2022,7 @@ public:
explicit CoinsViewScanReserver() : m_could_reserve(false) {}
bool reserve() {
- assert (!m_could_reserve);
+ CHECK_NONFATAL(!m_could_reserve);
std::lock_guard<std::mutex> lock(g_utxosetscan);
if (g_scan_in_progress) {
return false;
@@ -2049,7 +2061,7 @@ UniValue scantxoutset(const JSONRPCRequest& request)
" \"start\" for starting a scan\n"
" \"abort\" for aborting the current scan (returns true when abort was successful)\n"
" \"status\" for progress report (in %) of the current scan"},
- {"scanobjects", RPCArg::Type::ARR, RPCArg::Optional::NO, "Array of scan objects\n"
+ {"scanobjects", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "Array of scan objects. Required for \"start\" action\n"
" Every scan object is either a string descriptor or an object:",
{
{"descriptor", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "An output descriptor"},
@@ -2109,6 +2121,11 @@ UniValue scantxoutset(const JSONRPCRequest& request)
if (!reserver.reserve()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" or \"status\"");
}
+
+ if (request.params.size() < 2) {
+ throw JSONRPCError(RPC_MISC_ERROR, "scanobjects argument is required for the start action");
+ }
+
std::set<CScript> needles;
std::map<CScript, std::string> descriptors;
CAmount total_in = 0;
@@ -2137,9 +2154,9 @@ UniValue scantxoutset(const JSONRPCRequest& request)
LOCK(cs_main);
::ChainstateActive().ForceFlushStateToDisk();
pcursor = std::unique_ptr<CCoinsViewCursor>(::ChainstateActive().CoinsDB().Cursor());
- assert(pcursor);
+ CHECK_NONFATAL(pcursor);
tip = ::ChainActive().Tip();
- assert(tip);
+ CHECK_NONFATAL(tip);
}
bool res = FindScriptPubKey(g_scan_progress, g_should_abort_scan, count, pcursor.get(), needles, coins);
result.pushKV("success", res);
@@ -2247,6 +2264,113 @@ static UniValue getblockfilter(const JSONRPCRequest& request)
return ret;
}
+/**
+ * Serialize the UTXO set to a file for loading elsewhere.
+ *
+ * @see SnapshotMetadata
+ */
+UniValue dumptxoutset(const JSONRPCRequest& request)
+{
+ RPCHelpMan{
+ "dumptxoutset",
+ "\nWrite the serialized UTXO set to disk.\n"
+ "Incidentally flushes the latest coinsdb (leveldb) to disk.\n",
+ {
+ {"path",
+ RPCArg::Type::STR,
+ RPCArg::Optional::NO,
+ /* default_val */ "",
+ "path to the output file. If relative, will be prefixed by datadir."},
+ },
+ RPCResult{
+ "{\n"
+ " \"coins_written\": n, (numeric) the number of coins written in the snapshot\n"
+ " \"base_hash\": \"...\", (string) the hash of the base of the snapshot\n"
+ " \"base_height\": n, (string) the height of the base of the snapshot\n"
+ " \"path\": \"...\" (string) the absolute path that the snapshot was written to\n"
+ "]\n"
+ },
+ RPCExamples{
+ HelpExampleCli("dumptxoutset", "utxo.dat")
+ }
+ }.Check(request);
+
+ fs::path path = fs::absolute(request.params[0].get_str(), GetDataDir());
+ // Write to a temporary path and then move into `path` on completion
+ // to avoid confusion due to an interruption.
+ fs::path temppath = fs::absolute(request.params[0].get_str() + ".incomplete", GetDataDir());
+
+ if (fs::exists(path)) {
+ throw JSONRPCError(
+ RPC_INVALID_PARAMETER,
+ path.string() + " already exists. If you are sure this is what you want, "
+ "move it out of the way first");
+ }
+
+ FILE* file{fsbridge::fopen(temppath, "wb")};
+ CAutoFile afile{file, SER_DISK, CLIENT_VERSION};
+ std::unique_ptr<CCoinsViewCursor> pcursor;
+ CCoinsStats stats;
+ CBlockIndex* tip;
+
+ {
+ // We need to lock cs_main to ensure that the coinsdb isn't written to
+ // between (i) flushing coins cache to disk (coinsdb), (ii) getting stats
+ // based upon the coinsdb, and (iii) constructing a cursor to the
+ // coinsdb for use below this block.
+ //
+ // Cursors returned by leveldb iterate over snapshots, so the contents
+ // of the pcursor will not be affected by simultaneous writes during
+ // use below this block.
+ //
+ // See discussion here:
+ // https://github.com/bitcoin/bitcoin/pull/15606#discussion_r274479369
+ //
+ LOCK(::cs_main);
+
+ ::ChainstateActive().ForceFlushStateToDisk();
+
+ if (!GetUTXOStats(&::ChainstateActive().CoinsDB(), stats)) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
+ }
+
+ pcursor = std::unique_ptr<CCoinsViewCursor>(::ChainstateActive().CoinsDB().Cursor());
+ tip = LookupBlockIndex(stats.hashBlock);
+ CHECK_NONFATAL(tip);
+ }
+
+ SnapshotMetadata metadata{tip->GetBlockHash(), stats.coins_count, tip->nChainTx};
+
+ afile << metadata;
+
+ COutPoint key;
+ Coin coin;
+ unsigned int iter{0};
+
+ while (pcursor->Valid()) {
+ if (iter % 5000 == 0 && !IsRPCRunning()) {
+ throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
+ }
+ ++iter;
+ if (pcursor->GetKey(key) && pcursor->GetValue(coin)) {
+ afile << key;
+ afile << coin;
+ }
+
+ pcursor->Next();
+ }
+
+ afile.fclose();
+ fs::rename(temppath, path);
+
+ UniValue result(UniValue::VOBJ);
+ result.pushKV("coins_written", stats.coins_count);
+ result.pushKV("base_hash", tip->GetBlockHash().ToString());
+ result.pushKV("base_height", tip->nHeight);
+ result.pushKV("path", path.string());
+ return result;
+}
+
// clang-format off
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
@@ -2283,6 +2407,7 @@ static const CRPCCommand commands[] =
{ "hidden", "waitforblock", &waitforblock, {"blockhash","timeout"} },
{ "hidden", "waitforblockheight", &waitforblockheight, {"height","timeout"} },
{ "hidden", "syncwithvalidationinterfacequeue", &syncwithvalidationinterfacequeue, {} },
+ { "hidden", "dumptxoutset", &dumptxoutset, {"path"} },
};
// clang-format on
@@ -2291,3 +2416,5 @@ void RegisterBlockchainRPCCommands(CRPCTable &t)
for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
t.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
+
+NodeContext* g_rpc_node = nullptr;
diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h
index ff461fbcbc..a02e5fae0e 100644
--- a/src/rpc/blockchain.h
+++ b/src/rpc/blockchain.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -17,6 +17,7 @@ class CBlock;
class CBlockIndex;
class CTxMemPool;
class UniValue;
+struct NodeContext;
static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5;
@@ -46,4 +47,11 @@ UniValue blockheaderToJSON(const CBlockIndex* tip, const CBlockIndex* blockindex
/** Used by getblockstats to get feerates at different percentiles by weight */
void CalculatePercentilesByWeight(CAmount result[NUM_GETBLOCKSTATS_PERCENTILES], std::vector<std::pair<CAmount, int64_t>>& scores, int64_t total_weight);
+//! Pointer to node state that needs to be declared as a global to be accessible
+//! RPC methods. Due to limitations of the RPC framework, there's currently no
+//! direct way to pass in state to RPC methods without globals.
+extern NodeContext* g_rpc_node;
+
+CTxMemPool& EnsureMemPool();
+
#endif
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index c2714f9c83..2eaa3427eb 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -1,10 +1,9 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <rpc/client.h>
-#include <rpc/protocol.h>
#include <util/system.h>
#include <set>
@@ -31,6 +30,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "utxoupdatepsbt", 1, "descriptors" },
{ "generatetoaddress", 0, "nblocks" },
{ "generatetoaddress", 2, "maxtries" },
+ { "generatetodescriptor", 0, "num_blocks" },
+ { "generatetodescriptor", 2, "maxtries" },
{ "getnetworkhashps", 0, "nblocks" },
{ "getnetworkhashps", 1, "height" },
{ "sendtoaddress", 1, "amount" },
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 07c2958635..e5994b172b 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -13,12 +13,15 @@
#include <key_io.h>
#include <miner.h>
#include <net.h>
+#include <node/context.h>
#include <policy/fees.h>
#include <pow.h>
#include <rpc/blockchain.h>
#include <rpc/server.h>
#include <rpc/util.h>
+#include <script/descriptor.h>
#include <script/script.h>
+#include <script/signingprovider.h>
#include <shutdown.h>
#include <txmempool.h>
#include <univalue.h>
@@ -99,7 +102,7 @@ static UniValue getnetworkhashps(const JSONRPCRequest& request)
return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].get_int() : 120, !request.params[1].isNull() ? request.params[1].get_int() : -1);
}
-static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
+static UniValue generateBlocks(const CTxMemPool& mempool, const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries)
{
int nHeightEnd = 0;
int nHeight = 0;
@@ -113,7 +116,7 @@ static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, ui
UniValue blockHashes(UniValue::VARR);
while (nHeight < nHeightEnd && !ShutdownRequested())
{
- std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbase_script));
+ std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(mempool, Params()).CreateNewBlock(coinbase_script));
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
CBlock *pblock = &pblocktemplate->block;
@@ -140,6 +143,49 @@ static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, ui
return blockHashes;
}
+static UniValue generatetodescriptor(const JSONRPCRequest& request)
+{
+ RPCHelpMan{
+ "generatetodescriptor",
+ "\nMine blocks immediately to a specified descriptor (before the RPC call returns)\n",
+ {
+ {"num_blocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated immediately."},
+ {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor to send the newly generated bitcoin to."},
+ {"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."},
+ },
+ RPCResult{
+ "[ blockhashes ] (array) hashes of blocks generated\n"},
+ RPCExamples{
+ "\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")},
+ }
+ .Check(request);
+
+ const int num_blocks{request.params[0].get_int()};
+ const int64_t max_tries{request.params[2].isNull() ? 1000000 : request.params[2].get_int()};
+
+ FlatSigningProvider key_provider;
+ std::string error;
+ const auto desc = Parse(request.params[1].get_str(), key_provider, error, /* require_checksum = */ false);
+ if (!desc) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error);
+ }
+ if (desc->IsRange()) {
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Ranged descriptor not accepted. Maybe pass through deriveaddresses first?");
+ }
+
+ FlatSigningProvider provider;
+ std::vector<CScript> coinbase_script;
+ if (!desc->Expand(0, key_provider, coinbase_script, provider)) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys"));
+ }
+
+ const CTxMemPool& mempool = EnsureMemPool();
+
+ CHECK_NONFATAL(coinbase_script.size() == 1);
+
+ return generateBlocks(mempool, coinbase_script.at(0), num_blocks, max_tries);
+}
+
static UniValue generatetoaddress(const JSONRPCRequest& request)
{
RPCHelpMan{"generatetoaddress",
@@ -171,9 +217,11 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
}
+ const CTxMemPool& mempool = EnsureMemPool();
+
CScript coinbase_script = GetScriptForDestination(destination);
- return generateBlocks(coinbase_script, nGenerate, nMaxTries);
+ return generateBlocks(mempool, coinbase_script, nGenerate, nMaxTries);
}
static UniValue getmininginfo(const JSONRPCRequest& request)
@@ -189,7 +237,7 @@ static UniValue getmininginfo(const JSONRPCRequest& request)
" \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
" \"networkhashps\": nnn, (numeric) The network hashes per second\n"
" \"pooledtx\": n (numeric) The size of the mempool\n"
- " \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
+ " \"chain\": \"xxxx\", (string) current network name (main, test, regtest)\n"
" \"warnings\": \"...\" (string) any network and blockchain warnings\n"
"}\n"
},
@@ -200,6 +248,7 @@ static UniValue getmininginfo(const JSONRPCRequest& request)
}.Check(request);
LOCK(cs_main);
+ const CTxMemPool& mempool = EnsureMemPool();
UniValue obj(UniValue::VOBJ);
obj.pushKV("blocks", (int)::ChainActive().Height());
@@ -209,7 +258,7 @@ static UniValue getmininginfo(const JSONRPCRequest& request)
obj.pushKV("networkhashps", getnetworkhashps(request));
obj.pushKV("pooledtx", (uint64_t)mempool.size());
obj.pushKV("chain", Params().NetworkIDString());
- obj.pushKV("warnings", GetWarnings("statusbar"));
+ obj.pushKV("warnings", GetWarnings(false));
return obj;
}
@@ -246,13 +295,13 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.");
}
- mempool.PrioritiseTransaction(hash, nAmount);
+ EnsureMemPool().PrioritiseTransaction(hash, nAmount);
return true;
}
// NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
-static UniValue BIP22ValidationResult(const CValidationState& state)
+static UniValue BIP22ValidationResult(const BlockValidationState& state)
{
if (state.IsValid())
return NullUniValue;
@@ -331,13 +380,11 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
" }\n"
" ,...\n"
" ],\n"
- " \"coinbaseaux\" : { (json object) data that should be included in the coinbase's scriptSig content\n"
- " \"flags\" : \"xx\" (string) key name is to be ignored, and value included in scriptSig\n"
- " },\n"
+ " \"coinbaseaux\" : { ... }, (json object) data that should be included in the coinbase's scriptSig content\n"
" \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)\n"
" \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n"
" \"target\" : \"xxxx\", (string) The hash target\n"
- " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
+ " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for the next block time, expressed in " + UNIX_EPOCH_TIME + "\n"
" \"mutable\" : [ (array of string) list of ways the block template may be changed \n"
" \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
" ,...\n"
@@ -346,7 +393,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
" \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n"
" \"sizelimit\" : n, (numeric) limit of block size\n"
" \"weightlimit\" : n, (numeric) limit of block weight\n"
- " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
+ " \"curtime\" : ttt, (numeric) current timestamp in " + UNIX_EPOCH_TIME + "\n"
" \"bits\" : \"xxxxxxxx\", (string) compressed target of next block\n"
" \"height\" : n (numeric) The height of the next block\n"
"}\n"
@@ -401,7 +448,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
// TestBlockValidity only supports blocks built on the current Tip
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
return "inconclusive-not-best-prevblk";
- CValidationState state;
+ BlockValidationState state;
TestBlockValidity(state, Params(), block, pindexPrev, false, true);
return BIP22ValidationResult(state);
}
@@ -424,16 +471,17 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
if (strMode != "template")
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
+ if (g_rpc_node->connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, PACKAGE_NAME " is not connected!");
if (::ChainstateActive().IsInitialBlockDownload())
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, PACKAGE_NAME " is in initial sync and waiting for blocks...");
static unsigned int nTransactionsUpdatedLast;
+ const CTxMemPool& mempool = EnsureMemPool();
if (!lpval.isNull())
{
@@ -468,7 +516,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
if (g_best_block_cv.wait_until(lock, checktxtime) == std::cv_status::timeout)
{
// Timeout: Check transactions for update
- // without holding ::mempool.cs to avoid deadlocks
+ // without holding the mempool lock to avoid deadlocks
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
break;
checktxtime += std::chrono::seconds(10);
@@ -504,14 +552,14 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
// Create new block
CScript scriptDummy = CScript() << OP_TRUE;
- pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy);
+ pblocktemplate = BlockAssembler(mempool, Params()).CreateNewBlock(scriptDummy);
if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
// Need to update only after we know CreateNewBlock succeeded
pindexPrev = pindexPrevNew;
}
- assert(pindexPrev);
+ CHECK_NONFATAL(pindexPrev);
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
const Consensus::Params& consensusParams = Params().GetConsensus();
@@ -553,7 +601,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
entry.pushKV("fee", pblocktemplate->vTxFees[index_in_template]);
int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template];
if (fPreSegWit) {
- assert(nTxSigOps % WITNESS_SCALE_FACTOR == 0);
+ CHECK_NONFATAL(nTxSigOps % WITNESS_SCALE_FACTOR == 0);
nTxSigOps /= WITNESS_SCALE_FACTOR;
}
entry.pushKV("sigops", nTxSigOps);
@@ -563,7 +611,6 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
}
UniValue aux(UniValue::VOBJ);
- aux.pushKV("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end()));
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
@@ -642,9 +689,9 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST;
int64_t nSizeLimit = MAX_BLOCK_SERIALIZED_SIZE;
if (fPreSegWit) {
- assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0);
+ CHECK_NONFATAL(nSigOpLimit % WITNESS_SCALE_FACTOR == 0);
nSigOpLimit /= WITNESS_SCALE_FACTOR;
- assert(nSizeLimit % WITNESS_SCALE_FACTOR == 0);
+ CHECK_NONFATAL(nSizeLimit % WITNESS_SCALE_FACTOR == 0);
nSizeLimit /= WITNESS_SCALE_FACTOR;
}
result.pushKV("sigoplimit", nSigOpLimit);
@@ -668,12 +715,12 @@ class submitblock_StateCatcher : public CValidationInterface
public:
uint256 hash;
bool found;
- CValidationState state;
+ BlockValidationState state;
explicit submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {}
protected:
- void BlockChecked(const CBlock& block, const CValidationState& stateIn) override {
+ void BlockChecked(const CBlock& block, const BlockValidationState& stateIn) override {
if (block.GetHash() != hash)
return;
found = true;
@@ -772,8 +819,8 @@ static UniValue submitheader(const JSONRPCRequest& request)
}
}
- CValidationState state;
- ProcessNewBlockHeaders({h}, state, Params(), /* ppindex */ nullptr, /* first_invalid */ nullptr);
+ BlockValidationState state;
+ ProcessNewBlockHeaders({h}, state, Params());
if (state.IsValid()) return NullUniValue;
if (state.IsError()) {
throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));
@@ -961,6 +1008,7 @@ static const CRPCCommand commands[] =
{ "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },
+ { "generating", "generatetodescriptor", &generatetodescriptor, {"num_blocks","descriptor","maxtries"} },
{ "util", "estimatesmartfee", &estimatesmartfee, {"conf_target", "estimate_mode"} },
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 1516007201..56bd33b0ec 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -1,18 +1,18 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <crypto/ripemd160.h>
-#include <key_io.h>
#include <httpserver.h>
+#include <key_io.h>
#include <outputtype.h>
#include <rpc/blockchain.h>
#include <rpc/server.h>
#include <rpc/util.h>
#include <script/descriptor.h>
-#include <util/system.h>
+#include <util/check.h>
#include <util/strencodings.h>
+#include <util/system.h>
#include <util/validation.h>
#include <stdint.h>
@@ -343,7 +343,7 @@ static UniValue setmocktime(const JSONRPCRequest& request)
RPCHelpMan{"setmocktime",
"\nSet the local time to given timestamp (-regtest only)\n",
{
- {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Unix seconds-since-epoch timestamp\n"
+ {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, UNIX_EPOCH_TIME + "\n"
" Pass 0 to go back to using the system time."},
},
RPCResults{},
@@ -541,6 +541,7 @@ static UniValue echo(const JSONRPCRequest& request)
throw std::runtime_error(
RPCHelpMan{"echo|echojson ...",
"\nSimply echo back the input arguments. This command is for testing.\n"
+ "\nIt will return an internal bug report when exactly 100 arguments are passed.\n"
"\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in "
"bitcoin-cli and the GUI. There is no server-side difference.",
{},
@@ -549,6 +550,8 @@ static UniValue echo(const JSONRPCRequest& request)
}.ToString()
);
+ CHECK_NONFATAL(request.params.size() != 100);
+
return request.params;
}
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 7c4b3d0cc6..e0c1976f1a 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -8,11 +8,13 @@
#include <clientversion.h>
#include <core_io.h>
#include <net.h>
-#include <net_processing.h>
#include <net_permissions.h>
+#include <net_processing.h>
+#include <net_types.h> // For banmap_t
#include <netbase.h>
-#include <policy/policy.h>
+#include <node/context.h>
#include <policy/settings.h>
+#include <rpc/blockchain.h>
#include <rpc/protocol.h>
#include <rpc/util.h>
#include <sync.h>
@@ -39,10 +41,10 @@ static UniValue getconnectioncount(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- return (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
+ return (int)g_rpc_node->connman->GetNodeCount(CConnman::CONNECTIONS_ALL);
}
static UniValue ping(const JSONRPCRequest& request)
@@ -59,11 +61,11 @@ static UniValue ping(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
// Request that each node send a ping during next message processing pass
- g_connman->ForEachNode([](CNode* pnode) {
+ g_rpc_node->connman->ForEachNode([](CNode* pnode) {
pnode->fPingQueued = true;
});
return NullUniValue;
@@ -87,11 +89,11 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
" ...\n"
" ],\n"
" \"relaytxes\":true|false, (boolean) Whether peer has asked us to relay transactions to it\n"
- " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n"
- " \"lastrecv\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n"
+ " \"lastsend\": ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the last send\n"
+ " \"lastrecv\": ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the last receive\n"
" \"bytessent\": n, (numeric) The total bytes sent\n"
" \"bytesrecv\": n, (numeric) The total bytes received\n"
- " \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
+ " \"conntime\": ttt, (numeric) The " + UNIX_EPOCH_TIME + " of the connection\n"
" \"timeoffset\": ttt, (numeric) The time offset in seconds\n"
" \"pingtime\": n, (numeric) ping time (if available)\n"
" \"minping\": n, (numeric) minimum observed ping time (if any at all)\n"
@@ -132,11 +134,11 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
std::vector<CNodeStats> vstats;
- g_connman->GetNodeStats(vstats);
+ g_rpc_node->connman->GetNodeStats(vstats);
UniValue ret(UniValue::VARR);
@@ -235,7 +237,7 @@ static UniValue addnode(const JSONRPCRequest& request)
},
}.ToString());
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
std::string strNode = request.params[0].get_str();
@@ -243,18 +245,18 @@ static UniValue addnode(const JSONRPCRequest& request)
if (strCommand == "onetry")
{
CAddress addr;
- g_connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), false, false, true);
+ g_rpc_node->connman->OpenNetworkConnection(addr, false, nullptr, strNode.c_str(), false, false, true);
return NullUniValue;
}
if (strCommand == "add")
{
- if(!g_connman->AddNode(strNode))
+ if(!g_rpc_node->connman->AddNode(strNode))
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Node already added");
}
else if(strCommand == "remove")
{
- if(!g_connman->RemoveAddedNode(strNode))
+ if(!g_rpc_node->connman->RemoveAddedNode(strNode))
throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added.");
}
@@ -280,7 +282,7 @@ static UniValue disconnectnode(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
bool success;
@@ -289,11 +291,11 @@ static UniValue disconnectnode(const JSONRPCRequest& request)
if (!address_arg.isNull() && id_arg.isNull()) {
/* handle disconnect-by-address */
- success = g_connman->DisconnectNode(address_arg.get_str());
+ success = g_rpc_node->connman->DisconnectNode(address_arg.get_str());
} else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) {
/* handle disconnect-by-id */
NodeId nodeid = (NodeId) id_arg.get_int64();
- success = g_connman->DisconnectNode(nodeid);
+ success = g_rpc_node->connman->DisconnectNode(nodeid);
} else {
throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided.");
}
@@ -334,10 +336,10 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
- std::vector<AddedNodeInfo> vInfo = g_connman->GetAddedNodeInfo();
+ std::vector<AddedNodeInfo> vInfo = g_rpc_node->connman->GetAddedNodeInfo();
if (!request.params[0].isNull()) {
bool found = false;
@@ -400,21 +402,21 @@ static UniValue getnettotals(const JSONRPCRequest& request)
+ HelpExampleRpc("getnettotals", "")
},
}.Check(request);
- if(!g_connman)
+ if(!g_rpc_node->connman)
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
UniValue obj(UniValue::VOBJ);
- obj.pushKV("totalbytesrecv", g_connman->GetTotalBytesRecv());
- obj.pushKV("totalbytessent", g_connman->GetTotalBytesSent());
+ obj.pushKV("totalbytesrecv", g_rpc_node->connman->GetTotalBytesRecv());
+ obj.pushKV("totalbytessent", g_rpc_node->connman->GetTotalBytesSent());
obj.pushKV("timemillis", GetTimeMillis());
UniValue outboundLimit(UniValue::VOBJ);
- outboundLimit.pushKV("timeframe", g_connman->GetMaxOutboundTimeframe());
- outboundLimit.pushKV("target", g_connman->GetMaxOutboundTarget());
- outboundLimit.pushKV("target_reached", g_connman->OutboundTargetReached(false));
- outboundLimit.pushKV("serve_historical_blocks", !g_connman->OutboundTargetReached(true));
- outboundLimit.pushKV("bytes_left_in_cycle", g_connman->GetOutboundTargetBytesLeft());
- outboundLimit.pushKV("time_left_in_cycle", g_connman->GetMaxOutboundTimeLeftInCycle());
+ outboundLimit.pushKV("timeframe", g_rpc_node->connman->GetMaxOutboundTimeframe());
+ outboundLimit.pushKV("target", g_rpc_node->connman->GetMaxOutboundTarget());
+ outboundLimit.pushKV("target_reached", g_rpc_node->connman->OutboundTargetReached(false));
+ outboundLimit.pushKV("serve_historical_blocks", !g_rpc_node->connman->OutboundTargetReached(true));
+ outboundLimit.pushKV("bytes_left_in_cycle", g_rpc_node->connman->GetOutboundTargetBytesLeft());
+ outboundLimit.pushKV("time_left_in_cycle", g_rpc_node->connman->GetMaxOutboundTimeLeftInCycle());
obj.pushKV("uploadtarget", outboundLimit);
return obj;
}
@@ -493,16 +495,16 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
obj.pushKV("version", CLIENT_VERSION);
obj.pushKV("subversion", strSubVersion);
obj.pushKV("protocolversion",PROTOCOL_VERSION);
- if (g_connman) {
- ServiceFlags services = g_connman->GetLocalServices();
+ if (g_rpc_node->connman) {
+ ServiceFlags services = g_rpc_node->connman->GetLocalServices();
obj.pushKV("localservices", strprintf("%016x", services));
obj.pushKV("localservicesnames", GetServicesNames(services));
}
obj.pushKV("localrelay", g_relay_txes);
obj.pushKV("timeoffset", GetTimeOffset());
- if (g_connman) {
- obj.pushKV("networkactive", g_connman->GetNetworkActive());
- obj.pushKV("connections", (int)g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
+ if (g_rpc_node->connman) {
+ obj.pushKV("networkactive", g_rpc_node->connman->GetNetworkActive());
+ obj.pushKV("connections", (int)g_rpc_node->connman->GetNodeCount(CConnman::CONNECTIONS_ALL));
}
obj.pushKV("networks", GetNetworksInfo());
obj.pushKV("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK()));
@@ -520,7 +522,7 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
}
}
obj.pushKV("localaddresses", localAddresses);
- obj.pushKV("warnings", GetWarnings("statusbar"));
+ obj.pushKV("warnings", GetWarnings(false));
return obj;
}
@@ -532,7 +534,7 @@ static UniValue setban(const JSONRPCRequest& request)
{"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},
{"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add an IP/Subnet to the list, 'remove' to remove an IP/Subnet from the list"},
{"bantime", RPCArg::Type::NUM, /* default */ "0", "time in seconds how long (or until when if [absolute] is set) the IP is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)"},
- {"absolute", RPCArg::Type::BOOL, /* default */ "false", "If set, the bantime must be an absolute timestamp in seconds since epoch (Jan 1 1970 GMT)"},
+ {"absolute", RPCArg::Type::BOOL, /* default */ "false", "If set, the bantime must be an absolute timestamp expressed in " + UNIX_EPOCH_TIME},
},
RPCResults{},
RPCExamples{
@@ -547,7 +549,7 @@ static UniValue setban(const JSONRPCRequest& request)
if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) {
throw std::runtime_error(help.ToString());
}
- if (!g_banman) {
+ if (!g_rpc_node->banman) {
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
}
@@ -560,18 +562,18 @@ static UniValue setban(const JSONRPCRequest& request)
if (!isSubnet) {
CNetAddr resolved;
- LookupHost(request.params[0].get_str().c_str(), resolved, false);
+ LookupHost(request.params[0].get_str(), resolved, false);
netAddr = resolved;
}
else
- LookupSubNet(request.params[0].get_str().c_str(), subNet);
+ LookupSubNet(request.params[0].get_str(), subNet);
if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet");
if (strCommand == "add")
{
- if (isSubnet ? g_banman->IsBanned(subNet) : g_banman->IsBanned(netAddr)) {
+ if (isSubnet ? g_rpc_node->banman->IsBanned(subNet) : g_rpc_node->banman->IsBanned(netAddr)) {
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
}
@@ -584,20 +586,20 @@ static UniValue setban(const JSONRPCRequest& request)
absolute = true;
if (isSubnet) {
- g_banman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute);
- if (g_connman) {
- g_connman->DisconnectNode(subNet);
+ g_rpc_node->banman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute);
+ if (g_rpc_node->connman) {
+ g_rpc_node->connman->DisconnectNode(subNet);
}
} else {
- g_banman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
- if (g_connman) {
- g_connman->DisconnectNode(netAddr);
+ g_rpc_node->banman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
+ if (g_rpc_node->connman) {
+ g_rpc_node->connman->DisconnectNode(netAddr);
}
}
}
else if(strCommand == "remove")
{
- if (!( isSubnet ? g_banman->Unban(subNet) : g_banman->Unban(netAddr) )) {
+ if (!( isSubnet ? g_rpc_node->banman->Unban(subNet) : g_rpc_node->banman->Unban(netAddr) )) {
throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously banned.");
}
}
@@ -616,12 +618,12 @@ static UniValue listbanned(const JSONRPCRequest& request)
},
}.Check(request);
- if(!g_banman) {
+ if(!g_rpc_node->banman) {
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
}
banmap_t banMap;
- g_banman->GetBanned(banMap);
+ g_rpc_node->banman->GetBanned(banMap);
UniValue bannedAddresses(UniValue::VARR);
for (const auto& entry : banMap)
@@ -650,11 +652,11 @@ static UniValue clearbanned(const JSONRPCRequest& request)
+ HelpExampleRpc("clearbanned", "")
},
}.Check(request);
- if (!g_banman) {
+ if (!g_rpc_node->banman) {
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
}
- g_banman->ClearBanned();
+ g_rpc_node->banman->ClearBanned();
return NullUniValue;
}
@@ -670,13 +672,13 @@ static UniValue setnetworkactive(const JSONRPCRequest& request)
RPCExamples{""},
}.Check(request);
- if (!g_connman) {
+ if (!g_rpc_node->connman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
}
- g_connman->SetNetworkActive(request.params[0].get_bool());
+ g_rpc_node->connman->SetNetworkActive(request.params[0].get_bool());
- return g_connman->GetNetworkActive();
+ return g_rpc_node->connman->GetNetworkActive();
}
static UniValue getnodeaddresses(const JSONRPCRequest& request)
@@ -689,7 +691,7 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
RPCResult{
"[\n"
" {\n"
- " \"time\": ttt, (numeric) Timestamp in seconds since epoch (Jan 1 1970 GMT) keeping track of when the node was last seen\n"
+ " \"time\": ttt, (numeric) The " + UNIX_EPOCH_TIME + " of when the node was last seen\n"
" \"services\": n, (numeric) The services offered\n"
" \"address\": \"host\", (string) The address of the node\n"
" \"port\": n (numeric) The port of the node\n"
@@ -702,7 +704,7 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
+ HelpExampleRpc("getnodeaddresses", "8")
},
}.Check(request);
- if (!g_connman) {
+ if (!g_rpc_node->connman) {
throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
}
@@ -714,7 +716,7 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request)
}
}
// returns a shuffled list of CAddress
- std::vector<CAddress> vAddr = g_connman->GetAddresses();
+ std::vector<CAddress> vAddr = g_rpc_node->connman->GetAddresses();
UniValue ret(UniValue::VARR);
int address_return_count = std::min<int>(count, vAddr.size());
diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h
index ef6537e4ec..d1475f452d 100644
--- a/src/rpc/protocol.h
+++ b/src/rpc/protocol.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -63,6 +63,9 @@ enum RPCErrorCode
RPC_CLIENT_INVALID_IP_OR_SUBNET = -30, //!< Invalid IP/Subnet
RPC_CLIENT_P2P_DISABLED = -31, //!< No valid connection manager instance found
+ //! Chain errors
+ RPC_CLIENT_MEMPOOL_DISABLED = -33, //!< No mempool instance found
+
//! Wallet errors
RPC_WALLET_ERROR = -4, //!< Unspecified problem with wallet (key not found etc.)
RPC_WALLET_INSUFFICIENT_FUNDS = -6, //!< Not enough funds in wallet or account
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index f548d356cf..5be7acce1c 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -5,13 +5,13 @@
#include <chain.h>
#include <coins.h>
-#include <compat/byteswap.h>
#include <consensus/validation.h>
#include <core_io.h>
#include <index/txindex.h>
#include <key_io.h>
#include <merkleblock.h>
#include <node/coin.h>
+#include <node/context.h>
#include <node/psbt.h>
#include <node/transaction.h>
#include <policy/policy.h>
@@ -19,11 +19,11 @@
#include <primitives/transaction.h>
#include <psbt.h>
#include <random.h>
+#include <rpc/blockchain.h>
#include <rpc/rawtransaction_util.h>
#include <rpc/server.h>
#include <rpc/util.h>
#include <script/script.h>
-#include <script/script_error.h>
#include <script/sign.h>
#include <script/signingprovider.h>
#include <script/standard.h>
@@ -139,7 +139,7 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
" ],\n"
" \"blockhash\" : \"hash\", (string) the block hash\n"
" \"confirmations\" : n, (numeric) The confirmations\n"
- " \"blocktime\" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
+ " \"blocktime\" : ttt (numeric) The block time expressed in " + UNIX_EPOCH_TIME + "\n"
" \"time\" : ttt, (numeric) Same as \"blocktime\"\n"
"}\n"
},
@@ -610,7 +610,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
"\"hex\" (string) The hex-encoded raw transaction with signature(s)\n"
},
RPCExamples{
- HelpExampleCli("combinerawtransaction", "[\"myhex1\", \"myhex2\", \"myhex3\"]")
+ HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')")
},
}.Check(request);
@@ -636,6 +636,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
CCoinsView viewDummy;
CCoinsViewCache view(&viewDummy);
{
+ const CTxMemPool& mempool = EnsureMemPool();
LOCK(cs_main);
LOCK(mempool.cs);
CCoinsViewCache &viewChain = ::ChainstateActive().CoinsTip();
@@ -758,12 +759,14 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
for (const CTxIn& txin : mtx.vin) {
coins[txin.prevout]; // Create empty map entry keyed by prevout.
}
- FindCoins(coins);
+ FindCoins(*g_rpc_node, coins);
// Parse the prevtxs array
ParsePrevouts(request.params[2], &keystore, coins);
- return SignTransaction(mtx, &keystore, coins, request.params[3]);
+ UniValue result(UniValue::VOBJ);
+ SignTransaction(mtx, &keystore, coins, request.params[3], result);
+ return result;
}
static UniValue sendrawtransaction(const JSONRPCRequest& request)
@@ -819,7 +822,7 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request)
std::string err_string;
AssertLockNotHeld(cs_main);
- const TransactionError err = BroadcastTransaction(tx, err_string, max_raw_tx_fee, /*relay*/ true, /*wait_callback*/ true);
+ const TransactionError err = BroadcastTransaction(*g_rpc_node, tx, err_string, max_raw_tx_fee, /*relay*/ true, /*wait_callback*/ true);
if (TransactionError::OK != err) {
throw JSONRPCTransactionError(err, err_string);
}
@@ -858,7 +861,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
"Sign the transaction, and get back the hex\n"
+ HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") +
"\nTest acceptance of the transaction (signed hex)\n"
- + HelpExampleCli("testmempoolaccept", "[\"signedhex\"]") +
+ + HelpExampleCli("testmempoolaccept", R"('["signedhex"]')") +
"\nAs a JSON-RPC call\n"
+ HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]")
},
@@ -888,6 +891,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
max_raw_tx_fee_rate = CFeeRate(AmountFromValue(request.params[1]));
}
+ CTxMemPool& mempool = EnsureMemPool();
int64_t virtual_size = GetVirtualTransactionSize(*tx);
CAmount max_raw_tx_fee = max_raw_tx_fee_rate.GetFee(virtual_size);
@@ -895,20 +899,21 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
UniValue result_0(UniValue::VOBJ);
result_0.pushKV("txid", tx_hash.GetHex());
- CValidationState state;
- bool missing_inputs;
+ TxValidationState state;
bool test_accept_res;
{
LOCK(cs_main);
- test_accept_res = AcceptToMemoryPool(mempool, state, std::move(tx), &missing_inputs,
+ test_accept_res = AcceptToMemoryPool(mempool, state, std::move(tx),
nullptr /* plTxnReplaced */, false /* bypass_limits */, max_raw_tx_fee, /* test_accept */ true);
}
result_0.pushKV("allowed", test_accept_res);
if (!test_accept_res) {
if (state.IsInvalid()) {
- result_0.pushKV("reject-reason", strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
- } else if (missing_inputs) {
- result_0.pushKV("reject-reason", "missing-inputs");
+ if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
+ result_0.pushKV("reject-reason", "missing-inputs");
+ } else {
+ result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason()));
+ }
} else {
result_0.pushKV("reject-reason", state.GetRejectReason());
}
@@ -1226,7 +1231,7 @@ UniValue combinepsbt(const JSONRPCRequest& request)
" \"psbt\" (string) The base64-encoded partially signed transaction\n"
},
RPCExamples{
- HelpExampleCli("combinepsbt", "[\"mybase64_1\", \"mybase64_2\", \"mybase64_3\"]")
+ HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')")
},
}.Check(request);
@@ -1505,6 +1510,7 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request)
CCoinsView viewDummy;
CCoinsViewCache view(&viewDummy);
{
+ const CTxMemPool& mempool = EnsureMemPool();
LOCK2(cs_main, mempool.cs);
CCoinsViewCache &viewChain = ::ChainstateActive().CoinsTip();
CCoinsViewMemPool viewMempool(&viewChain, mempool);
@@ -1604,7 +1610,7 @@ UniValue joinpsbts(const JSONRPCRequest& request)
for (auto& psbt : psbtxs) {
for (unsigned int i = 0; i < psbt.tx->vin.size(); ++i) {
if (!merged_psbt.AddInput(psbt.tx->vin[i], psbt.inputs[i])) {
- throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input %s:%d exists in multiple PSBTs", psbt.tx->vin[i].prevout.hash.ToString().c_str(), psbt.tx->vin[i].prevout.n));
+ throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input %s:%d exists in multiple PSBTs", psbt.tx->vin[i].prevout.hash.ToString(), psbt.tx->vin[i].prevout.n));
}
}
for (unsigned int i = 0; i < psbt.tx->vout.size(); ++i) {
@@ -1619,7 +1625,7 @@ UniValue joinpsbts(const JSONRPCRequest& request)
std::vector<int> output_indices(merged_psbt.outputs.size());
std::iota(output_indices.begin(), output_indices.end(), 0);
- // Shuffle input and output indicies lists
+ // Shuffle input and output indices lists
Shuffle(input_indices.begin(), input_indices.end(), FastRandomContext());
Shuffle(output_indices.begin(), output_indices.end(), FastRandomContext());
@@ -1671,6 +1677,7 @@ UniValue analyzepsbt(const JSONRPCRequest& request)
" \"estimated_feerate\" : feerate (numeric, optional) Estimated feerate of the final signed transaction in " + CURRENCY_UNIT + "/kB. Shown only if all UTXO slots in the PSBT have been filled.\n"
" \"fee\" : fee (numeric, optional) The transaction fee paid. Shown only if all UTXO slots in the PSBT have been filled.\n"
" \"next\" : \"role\" (string) Role of the next person that this psbt needs to go to\n"
+ " \"error\" : \"error\" (string) Error message if there is one\n"
"}\n"
},
RPCExamples {
@@ -1723,7 +1730,7 @@ UniValue analyzepsbt(const JSONRPCRequest& request)
}
inputs_result.push_back(input_univ);
}
- result.pushKV("inputs", inputs_result);
+ if (!inputs_result.empty()) result.pushKV("inputs", inputs_result);
if (psbta.estimated_vsize != nullopt) {
result.pushKV("estimated_vsize", (int)*psbta.estimated_vsize);
@@ -1735,6 +1742,9 @@ UniValue analyzepsbt(const JSONRPCRequest& request)
result.pushKV("fee", ValueFromAmount(*psbta.fee));
}
result.pushKV("next", PSBTRoleName(psbta.next));
+ if (!psbta.error.empty()) {
+ result.pushKV("error", psbta.error);
+ }
return result;
}
diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp
index fe98fff4bb..40334883c5 100644
--- a/src/rpc/rawtransaction_util.cpp
+++ b/src/rpc/rawtransaction_util.cpp
@@ -268,7 +268,7 @@ void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keyst
}
}
-UniValue SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType)
+void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType, UniValue& result)
{
int nHashType = ParseSighashString(hashType);
@@ -319,12 +319,12 @@ UniValue SignTransaction(CMutableTransaction& mtx, const SigningProvider* keysto
}
bool fComplete = vErrors.empty();
- UniValue result(UniValue::VOBJ);
result.pushKV("hex", EncodeHexTx(CTransaction(mtx)));
result.pushKV("complete", fComplete);
if (!vErrors.empty()) {
+ if (result.exists("errors")) {
+ vErrors.push_backV(result["errors"].getValues());
+ }
result.pushKV("errors", vErrors);
}
-
- return result;
}
diff --git a/src/rpc/rawtransaction_util.h b/src/rpc/rawtransaction_util.h
index 5b92650764..4750fd64ed 100644
--- a/src/rpc/rawtransaction_util.h
+++ b/src/rpc/rawtransaction_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Copyright (c) 2017-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -21,15 +21,15 @@ class SigningProvider;
* @param keystore Temporary keystore containing signing keys
* @param coins Map of unspent outputs
* @param hashType The signature hash type
- * @returns JSON object with details of signed transaction
+ * @param result JSON object where signed transaction results accumulate
*/
-UniValue SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType);
+void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType, UniValue& result);
/**
* Parse a prevtxs UniValue array and get the map of coins from it
*
- * @param prevTxs Array of previous txns outputs that tx depends on but may not yet be in the block chain
- * @param keystore A pointer to the temprorary keystore if there is one
+ * @param prevTxsUnival Array of previous txns outputs that tx depends on but may not yet be in the block chain
+ * @param keystore A pointer to the temporary keystore if there is one
* @param coins Map of unspent outputs - coins in mempool and current chain UTXO set, may be extended by previous txns outputs after call
*/
void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keystore, std::map<COutPoint, Coin>& coins);
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index 3e5bb85c1c..df8e687d82 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -1,12 +1,10 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2019 The Bitcoin Core developers
+// Copyright (c) 2009-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <rpc/server.h>
-#include <fs.h>
-#include <key_io.h>
#include <rpc/util.h>
#include <shutdown.h>
#include <sync.h>
@@ -20,7 +18,7 @@
#include <memory> // for unique_ptr
#include <unordered_map>
-static CCriticalSection cs_rpcWarmup;
+static RecursiveMutex cs_rpcWarmup;
static std::atomic<bool> g_rpc_running{false};
static bool fRPCInWarmup GUARDED_BY(cs_rpcWarmup) = true;
static std::string rpcWarmupStatus GUARDED_BY(cs_rpcWarmup) = "RPC server started";
diff --git a/src/rpc/server.h b/src/rpc/server.h
index b060db5bf9..c91bf1f613 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Copyright (c) 2009-2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -8,9 +8,7 @@
#include <amount.h>
#include <rpc/request.h>
-#include <uint256.h>
-#include <list>
#include <map>
#include <stdint.h>
#include <string>
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index adda90c104..78586c22f9 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -13,7 +13,7 @@
#include <tuple>
-InitInterfaces* g_rpc_interfaces = nullptr;
+const std::string UNIX_EPOCH_TIME = "UNIX epoch time";
void RPCTypeCheck(const UniValue& params,
const std::list<UniValueType>& typesExpected,
@@ -133,18 +133,18 @@ CPubKey HexToPubKey(const std::string& hex_in)
}
// Retrieves a public key for an address from the given FillableSigningProvider
-CPubKey AddrToPubKey(FillableSigningProvider* const keystore, const std::string& addr_in)
+CPubKey AddrToPubKey(const FillableSigningProvider& keystore, const std::string& addr_in)
{
CTxDestination dest = DecodeDestination(addr_in);
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address: " + addr_in);
}
- CKeyID key = GetKeyForDestination(*keystore, dest);
+ CKeyID key = GetKeyForDestination(keystore, dest);
if (key.IsNull()) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in));
}
CPubKey vchPubKey;
- if (!keystore->GetPubKey(key, vchPubKey)) {
+ if (!keystore.GetPubKey(key, vchPubKey)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in));
}
if (!vchPubKey.IsFullyValid()) {
@@ -430,7 +430,7 @@ RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector<RP
std::set<std::string> named_args;
for (const auto& arg : m_args) {
// Should have unique named arguments
- assert(named_args.insert(arg.m_name).second);
+ CHECK_NONFATAL(named_args.insert(arg.m_name).second);
}
}
@@ -622,11 +622,11 @@ std::string RPCArg::ToStringObj(const bool oneline) const
case Type::OBJ:
case Type::OBJ_USER_KEYS:
// Currently unused, so avoid writing dead code
- assert(false);
+ CHECK_NONFATAL(false);
// no default case, so the compiler can warn about missing cases
}
- assert(false);
+ CHECK_NONFATAL(false);
}
std::string RPCArg::ToString(const bool oneline) const
@@ -663,7 +663,7 @@ std::string RPCArg::ToString(const bool oneline) const
// no default case, so the compiler can warn about missing cases
}
- assert(false);
+ CHECK_NONFATAL(false);
}
static std::pair<int64_t, int64_t> ParseRange(const UniValue& value)
diff --git a/src/rpc/util.h b/src/rpc/util.h
index 72fc7b6286..065a992a88 100644
--- a/src/rpc/util.h
+++ b/src/rpc/util.h
@@ -7,29 +7,30 @@
#include <node/transaction.h>
#include <outputtype.h>
-#include <pubkey.h>
#include <protocol.h>
+#include <pubkey.h>
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <script/script.h>
#include <script/sign.h>
#include <script/standard.h>
#include <univalue.h>
+#include <util/check.h>
#include <string>
#include <vector>
#include <boost/variant.hpp>
+/**
+ * String used to describe UNIX epoch time in documentation, factored out to a
+ * constant for consistency.
+ */
+extern const std::string UNIX_EPOCH_TIME;
+
class FillableSigningProvider;
class CPubKey;
class CScript;
-struct InitInterfaces;
-
-//! Pointers to interfaces that need to be accessible from RPC methods. Due to
-//! limitations of the RPC framework, there's currently no direct way to pass in
-//! state to RPC method implementations.
-extern InitInterfaces* g_rpc_interfaces;
/** Wrapper for UniValue::VType, which includes typeAny:
* Used to denote don't care type. */
@@ -74,7 +75,7 @@ extern std::string HelpExampleCli(const std::string& methodname, const std::stri
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
CPubKey HexToPubKey(const std::string& hex_in);
-CPubKey AddrToPubKey(FillableSigningProvider* const keystore, const std::string& addr_in);
+CPubKey AddrToPubKey(const FillableSigningProvider& keystore, const std::string& addr_in);
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector<CPubKey>& pubkeys, OutputType type, FillableSigningProvider& keystore, CScript& script_out);
UniValue DescribeAddress(const CTxDestination& dest);
@@ -146,7 +147,7 @@ struct RPCArg {
m_oneline_description{oneline_description},
m_type_str{type_str}
{
- assert(type != Type::ARR && type != Type::OBJ);
+ CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ);
}
RPCArg(
@@ -165,7 +166,7 @@ struct RPCArg {
m_oneline_description{oneline_description},
m_type_str{type_str}
{
- assert(type == Type::ARR || type == Type::OBJ);
+ CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ);
}
bool IsOptional() const;
@@ -194,14 +195,14 @@ struct RPCResult {
explicit RPCResult(std::string result)
: m_cond{}, m_result{std::move(result)}
{
- assert(!m_result.empty());
+ CHECK_NONFATAL(!m_result.empty());
}
RPCResult(std::string cond, std::string result)
: m_cond{std::move(cond)}, m_result{std::move(result)}
{
- assert(!m_cond.empty());
- assert(!m_result.empty());
+ CHECK_NONFATAL(!m_cond.empty());
+ CHECK_NONFATAL(!m_result.empty());
}
};