mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Merge pull request #4708 from kittywhiskers/json_cleanup
merge bitcoin 15746, 16240, 17192, 17318, 17809, 18098, 18444, 18607, 19100, 19386: rpc backports
This commit is contained in:
commit
f1a64744cd
@ -257,9 +257,10 @@ BITCOIN_CORE_H = \
|
||||
rpc/client.h \
|
||||
rpc/mining.h \
|
||||
rpc/protocol.h \
|
||||
rpc/server.h \
|
||||
rpc/rawtransaction_util.h \
|
||||
rpc/register.h \
|
||||
rpc/request.h \
|
||||
rpc/server.h \
|
||||
rpc/util.h \
|
||||
saltedhasher.h \
|
||||
scheduler.h \
|
||||
@ -292,6 +293,7 @@ BITCOIN_CORE_H = \
|
||||
unordered_lru_cache.h \
|
||||
util/bip32.h \
|
||||
util/bytevectorhash.h \
|
||||
util/check.h \
|
||||
util/error.h \
|
||||
util/fees.h \
|
||||
util/spanparsing.h \
|
||||
@ -678,7 +680,7 @@ libdash_util_a_SOURCES = \
|
||||
interfaces/handler.cpp \
|
||||
logging.cpp \
|
||||
random.cpp \
|
||||
rpc/protocol.cpp \
|
||||
rpc/request.cpp \
|
||||
stacktraces.cpp \
|
||||
support/cleanse.cpp \
|
||||
sync.cpp \
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <clientversion.h>
|
||||
#include <rpc/client.h>
|
||||
#include <rpc/protocol.h>
|
||||
#include <rpc/request.h>
|
||||
#include <stacktraces.h>
|
||||
#include <util/system.h>
|
||||
#include <util/strencodings.h>
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <primitives/block.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <rpc/blockchain.h>
|
||||
#include <rpc/protocol.h>
|
||||
#include <rpc/server.h>
|
||||
#include <streams.h>
|
||||
#include <sync.h>
|
||||
|
@ -11,12 +11,12 @@
|
||||
#include <chain.h>
|
||||
#include <chainparams.h>
|
||||
#include <coins.h>
|
||||
#include <node/coinstats.h>
|
||||
#include <core_io.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <index/blockfilterindex.h>
|
||||
#include <key_io.h>
|
||||
#include <index/txindex.h>
|
||||
#include <key_io.h>
|
||||
#include <node/coinstats.h>
|
||||
#include <policy/feerate.h>
|
||||
#include <policy/policy.h>
|
||||
#include <primitives/transaction.h>
|
||||
@ -40,7 +40,6 @@
|
||||
#include <llmq/chainlocks.h>
|
||||
#include <llmq/instantsend.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <univalue.h>
|
||||
@ -67,7 +66,7 @@ extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue&
|
||||
*/
|
||||
double GetDifficulty(const CBlockIndex* blockindex)
|
||||
{
|
||||
assert(blockindex);
|
||||
CHECK_NONFATAL(blockindex);
|
||||
|
||||
int nShift = (blockindex->nBits >> 24) & 0xff;
|
||||
double dDiff =
|
||||
@ -190,8 +189,7 @@ static UniValue getblockcount(const JSONRPCRequest& request)
|
||||
"The genesis block has height 0.\n",
|
||||
{},
|
||||
RPCResult{
|
||||
"n (numeric) The current block count\n"
|
||||
},
|
||||
RPCResult::Type::NUM, "", "The current block count"},
|
||||
RPCExamples{
|
||||
HelpExampleCli("getblockcount", "")
|
||||
+ HelpExampleRpc("getblockcount", "")
|
||||
@ -210,8 +208,7 @@ static UniValue getbestblockhash(const JSONRPCRequest& request)
|
||||
"\nReturns the hash of the best (tip) block in the most-work fully-validated chain.\n",
|
||||
{},
|
||||
RPCResult{
|
||||
"\"hex\" (string) the block hash, hex-encoded\n"
|
||||
},
|
||||
RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"},
|
||||
RPCExamples{
|
||||
HelpExampleCli("getbestblockhash", "")
|
||||
+ HelpExampleRpc("getbestblockhash", "")
|
||||
@ -278,11 +275,11 @@ static UniValue waitfornewblock(const JSONRPCRequest& request)
|
||||
{"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."},
|
||||
},
|
||||
RPCResult{
|
||||
"{ (json object)\n"
|
||||
" \"hash\" : { (string) The blockhash\n"
|
||||
" \"height\" : { (int) Block height\n"
|
||||
"}\n"
|
||||
},
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR_HEX, "hash", "The blockhash"},
|
||||
{RPCResult::Type::NUM, "height", "Block height"},
|
||||
}},
|
||||
RPCExamples{
|
||||
HelpExampleCli("waitfornewblock", "1000")
|
||||
+ HelpExampleRpc("waitfornewblock", "1000")
|
||||
@ -320,11 +317,11 @@ static UniValue waitforblock(const JSONRPCRequest& request)
|
||||
{"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."},
|
||||
},
|
||||
RPCResult{
|
||||
"{ (json object)\n"
|
||||
" \"hash\" : { (string) The blockhash\n"
|
||||
" \"height\" : { (int) Block height\n"
|
||||
"}\n"
|
||||
},
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR_HEX, "hash", "The blockhash"},
|
||||
{RPCResult::Type::NUM, "height", "Block height"},
|
||||
}},
|
||||
RPCExamples{
|
||||
HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\" 1000")
|
||||
+ HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000")
|
||||
@ -366,11 +363,11 @@ static UniValue waitforblockheight(const JSONRPCRequest& request)
|
||||
{"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."},
|
||||
},
|
||||
RPCResult{
|
||||
"{ (json object)\n"
|
||||
" \"hash\" : { (string) The blockhash\n"
|
||||
" \"height\" : { (int) Block height\n"
|
||||
"}\n"
|
||||
},
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR_HEX, "hash", "The blockhash"},
|
||||
{RPCResult::Type::NUM, "height", "Block height"},
|
||||
}},
|
||||
RPCExamples{
|
||||
HelpExampleCli("waitforblockheight", "100 1000")
|
||||
+ HelpExampleRpc("waitforblockheight", "100, 1000")
|
||||
@ -425,8 +422,7 @@ static UniValue getdifficulty(const JSONRPCRequest& request)
|
||||
"\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n",
|
||||
{},
|
||||
RPCResult{
|
||||
"n.nnn (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty.\n"
|
||||
},
|
||||
RPCResult::Type::NUM, "", "the proof-of-work difficulty as a multiple of the minimum difficulty."},
|
||||
RPCExamples{
|
||||
HelpExampleCli("getdifficulty", "")
|
||||
+ HelpExampleRpc("getdifficulty", "")
|
||||
@ -458,10 +454,10 @@ static std::string EntryDescriptionString()
|
||||
" \"ancestor\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) in " + CURRENCY_UNIT + "\n"
|
||||
" \"descendant\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) in " + CURRENCY_UNIT + "\n"
|
||||
" }\n"
|
||||
" \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n"
|
||||
" \"depends\" : [ (json array) unconfirmed transactions used as inputs for this transaction\n"
|
||||
" \"transactionid\", (string) parent transaction id\n"
|
||||
" ... ],\n"
|
||||
" \"spentby\" : [ (array) unconfirmed transactions spending outputs from this transaction\n"
|
||||
" \"spentby\" : [ (json array) unconfirmed transactions spending outputs from this transaction\n"
|
||||
" \"transactionid\", (string) child transaction id\n"
|
||||
" ... ]\n"
|
||||
" \"instantlock\" : true|false (boolean) True if this transaction was locked via InstantSend\n";
|
||||
@ -802,8 +798,7 @@ static UniValue getblockhash(const JSONRPCRequest& request)
|
||||
{"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The height index"},
|
||||
},
|
||||
RPCResult{
|
||||
"\"hash\" (string) The block hash\n"
|
||||
},
|
||||
RPCResult::Type::STR_HEX, "", "The block hash"},
|
||||
RPCExamples{
|
||||
HelpExampleCli("getblockhash", "1000")
|
||||
+ HelpExampleRpc("getblockhash", "1000")
|
||||
@ -1093,12 +1088,11 @@ static UniValue getblock(const JSONRPCRequest& request)
|
||||
"If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n",
|
||||
{
|
||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
|
||||
{"verbosity", RPCArg::Type::NUM, /* default */ "1", "0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data"},
|
||||
{"verbosity|verbose", RPCArg::Type::NUM, /* default */ "1", "0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data"},
|
||||
},
|
||||
{
|
||||
RPCResult{"for verbosity = 0",
|
||||
"\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
|
||||
},
|
||||
RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"},
|
||||
RPCResult{"for verbosity = 1",
|
||||
"{\n"
|
||||
" \"hash\" : \"hash\", (string) the block hash (same as provided)\n"
|
||||
@ -1186,8 +1180,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
|
||||
" to prune blocks whose block time is at least 2 hours older than the provided timestamp."},
|
||||
},
|
||||
RPCResult{
|
||||
"n (numeric) Height of the last block pruned.\n"
|
||||
},
|
||||
RPCResult::Type::NUM, "", "Height of the last block pruned"},
|
||||
RPCExamples{
|
||||
HelpExampleCli("pruneblockchain", "1000")
|
||||
+ HelpExampleRpc("pruneblockchain", "1000")
|
||||
@ -1227,7 +1220,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;
|
||||
}
|
||||
@ -1243,17 +1236,17 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
|
||||
"Note this call may take some time.\n",
|
||||
{},
|
||||
RPCResult{
|
||||
"{\n"
|
||||
" \"height\":n, (numeric) The current block height (index)\n"
|
||||
" \"bestblock\": \"hex\", (string) The hash of the block at the tip of the chain\n"
|
||||
" \"transactions\": n, (numeric) The number of transactions with unspent outputs\n"
|
||||
" \"txouts\": n, (numeric) The number of unspent transaction outputs\n"
|
||||
" \"bogosize\": n, (numeric) A meaningless metric for UTXO set size\n"
|
||||
" \"hash_serialized_2\": \"hash\", (string) The serialized hash\n"
|
||||
" \"disk_size\": n, (numeric) The estimated size of the chainstate on disk\n"
|
||||
" \"total_amount\": x.xxx (numeric) The total amount\n"
|
||||
"}\n"
|
||||
},
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::NUM, "height", "The current block height (index)"},
|
||||
{RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"},
|
||||
{RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs"},
|
||||
{RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"},
|
||||
{RPCResult::Type::NUM, "bogosize", "A meaningless metric for UTXO set size"},
|
||||
{RPCResult::Type::STR_HEX, "hash_serialized_2", "The serialized hash"},
|
||||
{RPCResult::Type::NUM, "disk_size", "The estimated size of the chainstate on disk"},
|
||||
{RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount"},
|
||||
}},
|
||||
RPCExamples{
|
||||
HelpExampleCli("gettxoutsetinfo", "")
|
||||
+ HelpExampleRpc("gettxoutsetinfo", "")
|
||||
@ -1376,8 +1369,7 @@ static UniValue verifychain(const JSONRPCRequest& request)
|
||||
{"nblocks", RPCArg::Type::NUM, /* default */ strprintf("%d, 0=all", nCheckDepth), "The number of blocks to check."},
|
||||
},
|
||||
RPCResult{
|
||||
"true|false (boolean) Verified or not\n"
|
||||
},
|
||||
RPCResult::Type::BOOL, "", "Verified or not"},
|
||||
RPCExamples{
|
||||
HelpExampleCli("verifychain", "")
|
||||
+ HelpExampleRpc("verifychain", "")
|
||||
@ -1483,30 +1475,30 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
|
||||
" \"difficulty\" : xxxxxx, (numeric) the current difficulty\n"
|
||||
" \"mediantime\" : xxxxxx, (numeric) median time for the current best block\n"
|
||||
" \"verificationprogress\" : xxxx, (numeric) estimate of verification progress [0..1]\n"
|
||||
" \"initialblockdownload\": xxxx, (bool) (debug information) estimate of whether this node is in Initial Block Download mode.\n"
|
||||
" \"initialblockdownload\" : xxxx, (boolean) (debug information) estimate of whether this node is in Initial Block Download mode.\n"
|
||||
" \"chainwork\" : \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n"
|
||||
" \"size_on_disk\" : xxxxxx, (numeric) the estimated size of the block and undo files on disk\n"
|
||||
" \"pruned\" : xx, (boolean) if the blocks are subject to pruning\n"
|
||||
" \"pruneheight\" : xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n"
|
||||
" \"automatic_pruning\" : xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n"
|
||||
" \"prune_target_size\" : xxxxxx, (numeric) the target size used by pruning (only present if automatic pruning is enabled)\n"
|
||||
" \"softforks\": [ (array) status of softforks in progress\n"
|
||||
" \"softforks\" : [ (json array) status of softforks in progress\n"
|
||||
" {\n"
|
||||
" \"id\" : \"xxxx\", (string) name of softfork\n"
|
||||
" \"version\" : xx, (numeric) block version\n"
|
||||
" \"reject\": { (object) progress toward rejecting pre-softfork blocks\n"
|
||||
" \"reject\" : { (json object) progress toward rejecting pre-softfork blocks\n"
|
||||
" \"status\" : xx, (boolean) true if threshold reached\n"
|
||||
" },\n"
|
||||
" }, ...\n"
|
||||
" ],\n"
|
||||
" \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n"
|
||||
" \"bip9_softforks\": { (json object) status of BIP9 softforks in progress\n"
|
||||
" \"xxxx\" : { (string) name of the softfork\n"
|
||||
" \"status\" : \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n"
|
||||
" \"bit\" : xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n"
|
||||
" \"start_time\" : xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n"
|
||||
" \"timeout\" : xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n"
|
||||
" \"since\" : xx, (numeric) height of the first block to which the status applies\n"
|
||||
" \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n"
|
||||
" \"statistics\" : { (json object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n"
|
||||
" \"period\" : xx, (numeric) the length in blocks of the BIP9 signalling period \n"
|
||||
" \"threshold\" : xx, (numeric) the number of blocks with the version bit set required to activate the feature \n"
|
||||
" \"elapsed\" : xx, (numeric) the number of blocks elapsed since the beginning of the current period \n"
|
||||
@ -1543,7 +1535,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;
|
||||
}
|
||||
@ -1937,7 +1929,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));
|
||||
@ -2119,7 +2111,7 @@ static UniValue getblockstats(const JSONRPCRequest& request)
|
||||
}
|
||||
}
|
||||
|
||||
assert(pindex != nullptr);
|
||||
CHECK_NONFATAL(pindex != nullptr);
|
||||
|
||||
std::set<std::string> stats;
|
||||
if (!request.params[1].isNull()) {
|
||||
@ -2208,7 +2200,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);
|
||||
}
|
||||
@ -2448,7 +2440,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;
|
||||
@ -2503,24 +2495,26 @@ UniValue scantxoutset(const JSONRPCRequest& request)
|
||||
"[scanobjects,...]"},
|
||||
},
|
||||
RPCResult{
|
||||
"{\n"
|
||||
" \"success\": true|false, (boolean) Whether the scan was completed\n"
|
||||
" \"txouts\": n, (numeric) The number of unspent transaction outputs scanned\n"
|
||||
" \"height\": n, (numeric) The current block height (index)\n"
|
||||
" \"bestblock\": \"hex\", (string) The hash of the block at the tip of the chain\n"
|
||||
" \"unspents\": [\n"
|
||||
" {\n"
|
||||
" \"txid\": \"hash\", (string) The transaction id\n"
|
||||
" \"vout\": n, (numeric) The vout value\n"
|
||||
" \"scriptPubKey\": \"script\", (string) The script key\n"
|
||||
" \"desc\": \"descriptor\", (string) A specialized descriptor for the matched scriptPubKey\n"
|
||||
" \"amount\": x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " of the unspent output\n"
|
||||
" \"height\": n, (numeric) Height of the unspent transaction output\n"
|
||||
" }\n"
|
||||
" ,...],\n"
|
||||
" \"total_amount\": x.xxx, (numeric) The total amount of all found unspent outputs in " + CURRENCY_UNIT + "\n"
|
||||
"]\n"
|
||||
},
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::BOOL, "success", "Whether the scan was completed"},
|
||||
{RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs scanned"},
|
||||
{RPCResult::Type::NUM, "height", "The current block height (index)"},
|
||||
{RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"},
|
||||
{RPCResult::Type::ARR, "unspents", "",
|
||||
{
|
||||
{RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR_HEX, "txid", "The transaction id"},
|
||||
{RPCResult::Type::NUM, "vout", "The vout value"},
|
||||
{RPCResult::Type::STR_HEX, "scriptPubKey", "The script key"},
|
||||
{RPCResult::Type::STR, "desc", "A specialized descriptor for the matched scriptPubKey"},
|
||||
{RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the unspent output"},
|
||||
{RPCResult::Type::NUM, "height", "Height of the unspent transaction output"},
|
||||
}},
|
||||
}},
|
||||
{RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of all found unspent outputs in " + CURRENCY_UNIT},
|
||||
}},
|
||||
RPCExamples{""},
|
||||
}.ToString()
|
||||
);
|
||||
@ -2613,9 +2607,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);
|
||||
|
@ -18,11 +18,6 @@
|
||||
#ifdef ENABLE_WALLET
|
||||
static UniValue coinjoin(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"coinjoin",
|
||||
@ -37,6 +32,10 @@ static UniValue coinjoin(const JSONRPCRequest& request)
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (fMasternodeMode)
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Client-side mixing is not supported on masternodes");
|
||||
|
||||
@ -103,15 +102,15 @@ static UniValue getcoinjoininfo(const JSONRPCRequest& request)
|
||||
RPCResults{
|
||||
{"for regular nodes",
|
||||
"{\n"
|
||||
" \"enabled\": true|false, (bool) Whether mixing functionality is enabled\n"
|
||||
" \"multisession\": true|false, (bool) Whether CoinJoin Multisession option is enabled\n"
|
||||
" \"enabled\" : true|false, (boolean) Whether mixing functionality is enabled\n"
|
||||
" \"multisession\" : true|false, (boolean) Whether CoinJoin Multisession option is enabled\n"
|
||||
" \"max_sessions\" : xxx, (numeric) How many parallel mixing sessions can there be at once\n"
|
||||
" \"max_rounds\" : xxx, (numeric) How many rounds to mix\n"
|
||||
" \"max_amount\" : xxx, (numeric) Target CoinJoin balance in " + CURRENCY_UNIT + "\n"
|
||||
" \"denoms_goal\" : xxx, (numeric) How many inputs of each denominated amount to target\n"
|
||||
" \"denoms_hardcap\" : xxx, (numeric) Maximum limit of how many inputs of each denominated amount to create\n"
|
||||
" \"queue_size\" : xxx, (numeric) How many queues there are currently on the network\n"
|
||||
" \"running\": true|false, (bool) Whether mixing is currently running\n"
|
||||
" \"running\" : true|false, (boolean) Whether mixing is currently running\n"
|
||||
" \"sessions\" : (array of json objects)\n"
|
||||
" [\n"
|
||||
" {\n"
|
||||
|
@ -24,9 +24,8 @@
|
||||
#include <wallet/wallet.h>
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
static void gobject_count_help()
|
||||
static void gobject_count_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject count",
|
||||
"Count governance objects and votes\n",
|
||||
{
|
||||
@ -34,13 +33,13 @@ static void gobject_count_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_count(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 2)
|
||||
gobject_count_help();
|
||||
gobject_count_help(request);
|
||||
|
||||
std::string strMode{"json"};
|
||||
|
||||
@ -49,14 +48,13 @@ static UniValue gobject_count(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
if (strMode != "json" && strMode != "all")
|
||||
gobject_count_help();
|
||||
gobject_count_help(request);
|
||||
|
||||
return strMode == "json" ? governance.ToJson() : governance.ToString();
|
||||
}
|
||||
|
||||
static void gobject_deserialize_help()
|
||||
static void gobject_deserialize_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan {"gobject deserialize",
|
||||
"Deserialize governance object from hex string to JSON\n",
|
||||
{
|
||||
@ -64,13 +62,13 @@ static void gobject_deserialize_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_deserialize(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 2)
|
||||
gobject_deserialize_help();
|
||||
gobject_deserialize_help(request);
|
||||
|
||||
std::string strHex = request.params[1].get_str();
|
||||
|
||||
@ -83,9 +81,8 @@ static UniValue gobject_deserialize(const JSONRPCRequest& request)
|
||||
return u.write().c_str();
|
||||
}
|
||||
|
||||
static void gobject_check_help()
|
||||
static void gobject_check_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject check",
|
||||
"Validate governance object data (proposal only)\n",
|
||||
{
|
||||
@ -93,13 +90,13 @@ static void gobject_check_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_check(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 2)
|
||||
gobject_check_help();
|
||||
gobject_check_help(request);
|
||||
|
||||
// ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
|
||||
|
||||
@ -132,12 +129,11 @@ static UniValue gobject_check(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
static void gobject_prepare_help(CWallet* const pwallet)
|
||||
static void gobject_prepare_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject prepare",
|
||||
"Prepare governance object by signing and creating tx\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n",
|
||||
+ HelpRequiringPassphrase() + "\n",
|
||||
{
|
||||
{"parent-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "hash of the parent object, \"0\" is root"},
|
||||
{"revision", RPCArg::Type::NUM, RPCArg::Optional::NO, "object revision in the system"},
|
||||
@ -149,18 +145,17 @@ static void gobject_prepare_help(CWallet* const pwallet)
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_prepare(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || (request.params.size() != 5 && request.params.size() != 6 && request.params.size() != 8))
|
||||
gobject_prepare_help(pwallet);
|
||||
gobject_prepare_help(request);
|
||||
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
|
||||
@ -260,31 +255,29 @@ static UniValue gobject_prepare(const JSONRPCRequest& request)
|
||||
return tx->GetHash().ToString();
|
||||
}
|
||||
|
||||
static void gobject_list_prepared_help(CWallet* const pwallet)
|
||||
static void gobject_list_prepared_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject list-prepared",
|
||||
"Returns a list of governance objects prepared by this wallet with \"gobject prepare\" sorted by their creation time.\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n",
|
||||
+ HelpRequiringPassphrase() + "\n",
|
||||
{
|
||||
{"count", RPCArg::Type::NUM, /* default */ "10", "Maximum number of objects to return."},
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_list_prepared(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || (request.params.size() > 2)) {
|
||||
gobject_list_prepared_help(pwallet);
|
||||
gobject_list_prepared_help(request);
|
||||
}
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
|
||||
int64_t nCount = request.params.size() > 1 ? ParseInt64V(request.params[1], "count") : 10;
|
||||
@ -312,9 +305,8 @@ static UniValue gobject_list_prepared(const JSONRPCRequest& request)
|
||||
}
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
static void gobject_submit_help()
|
||||
static void gobject_submit_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject submit",
|
||||
"Submit governance object to network\n",
|
||||
{
|
||||
@ -326,13 +318,13 @@ static void gobject_submit_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_submit(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || ((request.params.size() < 5) || (request.params.size() > 6)))
|
||||
gobject_submit_help();
|
||||
gobject_submit_help(request);
|
||||
|
||||
if(!masternodeSync.IsBlockchainSynced()) {
|
||||
throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Must wait for client to sync with masternode network. Try again in a minute or so.");
|
||||
@ -430,9 +422,8 @@ static UniValue gobject_submit(const JSONRPCRequest& request)
|
||||
return govobj.GetHash().ToString();
|
||||
}
|
||||
|
||||
static void gobject_vote_conf_help()
|
||||
static void gobject_vote_conf_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject vote-conf",
|
||||
"Vote on a governance object by masternode configured in dash.conf\n",
|
||||
{
|
||||
@ -442,13 +433,13 @@ static void gobject_vote_conf_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_vote_conf(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 4)
|
||||
gobject_vote_conf_help();
|
||||
gobject_vote_conf_help(request);
|
||||
|
||||
uint256 hash;
|
||||
|
||||
@ -604,12 +595,11 @@ static UniValue VoteWithMasternodes(const std::map<uint256, CKey>& keys,
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
static void gobject_vote_many_help(CWallet* const pwallet)
|
||||
static void gobject_vote_many_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject vote-many",
|
||||
"Vote on a governance object by all masternodes for which the voting key is present in the local wallet\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n",
|
||||
+ HelpRequiringPassphrase() + "\n",
|
||||
{
|
||||
{"governance-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "hash of the governance object"},
|
||||
{"vote", RPCArg::Type::STR, RPCArg::Optional::NO, "vote, possible values: [funding|valid|delete|endorsed]"},
|
||||
@ -617,18 +607,17 @@ static void gobject_vote_many_help(CWallet* const pwallet)
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_vote_many(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || request.params.size() != 4)
|
||||
gobject_vote_many_help(pwallet);
|
||||
gobject_vote_many_help(request);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
uint256 hash = ParseHashV(request.params[1], "Object hash");
|
||||
std::string strVoteSignal = request.params[2].get_str();
|
||||
@ -661,12 +650,11 @@ static UniValue gobject_vote_many(const JSONRPCRequest& request)
|
||||
return VoteWithMasternodes(votingKeys, hash, eVoteSignal, eVoteOutcome);
|
||||
}
|
||||
|
||||
static void gobject_vote_alias_help(CWallet* const pwallet)
|
||||
static void gobject_vote_alias_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject vote-alias",
|
||||
"Vote on a governance object by masternode's voting key (if present in local wallet)\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n",
|
||||
+ HelpRequiringPassphrase() + "\n",
|
||||
{
|
||||
{"governance-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "hash of the governance object"},
|
||||
{"vote", RPCArg::Type::STR, RPCArg::Optional::NO, "vote, possible values: [funding|valid|delete|endorsed]"},
|
||||
@ -675,18 +663,17 @@ static void gobject_vote_alias_help(CWallet* const pwallet)
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_vote_alias(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || request.params.size() != 5)
|
||||
gobject_vote_alias_help(pwallet);
|
||||
gobject_vote_alias_help(request);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
uint256 hash = ParseHashV(request.params[1], "Object hash");
|
||||
std::string strVoteSignal = request.params[2].get_str();
|
||||
@ -782,9 +769,8 @@ static UniValue ListObjects(const std::string& strCachedSignal, const std::strin
|
||||
return objResult;
|
||||
}
|
||||
|
||||
static void gobject_list_help()
|
||||
static void gobject_list_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject list",
|
||||
"List governance objects (can be filtered by signal and/or object type)\n",
|
||||
{
|
||||
@ -793,13 +779,13 @@ static void gobject_list_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_list(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 3)
|
||||
gobject_list_help();
|
||||
gobject_list_help(request);
|
||||
|
||||
std::string strCachedSignal = "valid";
|
||||
if (!request.params[1].isNull()) {
|
||||
@ -818,9 +804,8 @@ static UniValue gobject_list(const JSONRPCRequest& request)
|
||||
return ListObjects(strCachedSignal, strType, 0);
|
||||
}
|
||||
|
||||
static void gobject_diff_help()
|
||||
static void gobject_diff_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject diff",
|
||||
"List differences since last diff or list\n",
|
||||
{
|
||||
@ -829,13 +814,13 @@ static void gobject_diff_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_diff(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 3)
|
||||
gobject_diff_help();
|
||||
gobject_diff_help(request);
|
||||
|
||||
std::string strCachedSignal = "valid";
|
||||
if (!request.params[1].isNull()) {
|
||||
@ -854,9 +839,8 @@ static UniValue gobject_diff(const JSONRPCRequest& request)
|
||||
return ListObjects(strCachedSignal, strType, governance.GetLastDiffTime());
|
||||
}
|
||||
|
||||
static void gobject_get_help()
|
||||
static void gobject_get_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject get",
|
||||
"Get governance object by hash\n",
|
||||
{
|
||||
@ -864,13 +848,13 @@ static void gobject_get_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_get(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 2)
|
||||
gobject_get_help();
|
||||
gobject_get_help(request);
|
||||
|
||||
// COLLECT VARIABLES FROM OUR USER
|
||||
uint256 hash = ParseHashV(request.params[1], "GovObj hash");
|
||||
@ -946,9 +930,8 @@ static UniValue gobject_get(const JSONRPCRequest& request)
|
||||
return objResult;
|
||||
}
|
||||
|
||||
static void gobject_getcurrentvotes_help()
|
||||
static void gobject_getcurrentvotes_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"gobject getcurrentvotes",
|
||||
"Get only current (tallying) votes for a governance object hash (does not include old votes)\n",
|
||||
{
|
||||
@ -958,13 +941,13 @@ static void gobject_getcurrentvotes_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue gobject_getcurrentvotes(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || (request.params.size() != 2 && request.params.size() != 4))
|
||||
gobject_getcurrentvotes_help();
|
||||
gobject_getcurrentvotes_help(request);
|
||||
|
||||
// COLLECT PARAMETERS FROM USER
|
||||
|
||||
@ -1003,7 +986,6 @@ static UniValue gobject_getcurrentvotes(const JSONRPCRequest& request)
|
||||
|
||||
[[ noreturn ]] static void gobject_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan {"gobject",
|
||||
"Set of commands to manage governance objects.\n"
|
||||
"\nAvailable commands:\n"
|
||||
@ -1030,7 +1012,7 @@ static UniValue gobject_getcurrentvotes(const JSONRPCRequest& request)
|
||||
{},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Throw();
|
||||
}
|
||||
|
||||
static UniValue gobject(const JSONRPCRequest& request)
|
||||
|
@ -25,9 +25,8 @@
|
||||
|
||||
static UniValue masternodelist(const JSONRPCRequest& request);
|
||||
|
||||
static void masternode_list_help()
|
||||
static void masternode_list_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"masternodelist",
|
||||
"Get a list of masternodes in different modes. This call is identical to 'masternode list' call.\n"
|
||||
"Available modes:\n"
|
||||
@ -52,13 +51,13 @@ static void masternode_list_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue masternode_list(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp)
|
||||
masternode_list_help();
|
||||
masternode_list_help(request);
|
||||
JSONRPCRequest newRequest = request;
|
||||
newRequest.params.setArray();
|
||||
// forward params but skip "list"
|
||||
@ -68,9 +67,8 @@ static UniValue masternode_list(const JSONRPCRequest& request)
|
||||
return masternodelist(newRequest);
|
||||
}
|
||||
|
||||
static void masternode_connect_help()
|
||||
static void masternode_connect_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"masternode connect",
|
||||
"Connect to given masternode\n",
|
||||
{
|
||||
@ -78,13 +76,13 @@ static void masternode_connect_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue masternode_connect(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() < 2)
|
||||
masternode_connect_help();
|
||||
masternode_connect_help(request);
|
||||
|
||||
std::string strAddress = request.params[1].get_str();
|
||||
|
||||
@ -100,21 +98,20 @@ static UniValue masternode_connect(const JSONRPCRequest& request)
|
||||
return "successfully connected";
|
||||
}
|
||||
|
||||
static void masternode_count_help()
|
||||
static void masternode_count_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"masternode count",
|
||||
"Get information about number of masternodes.\n",
|
||||
{},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue masternode_count(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 1)
|
||||
masternode_count_help();
|
||||
masternode_count_help(request);
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
int total = mnList.GetAllMNsCount();
|
||||
@ -148,74 +145,69 @@ static UniValue GetNextMasternodeForPayment(int heightShift)
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void masternode_winner_help()
|
||||
static void masternode_winner_help(const JSONRPCRequest& request)
|
||||
{
|
||||
if (!IsDeprecatedRPCEnabled("masternode_winner")) {
|
||||
throw std::runtime_error("DEPRECATED: set -deprecatedrpc=masternode_winner to enable it");
|
||||
}
|
||||
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"masternode winner",
|
||||
"Print info on next masternode winner to vote for\n",
|
||||
{},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue masternode_winner(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || !IsDeprecatedRPCEnabled("masternode_winner"))
|
||||
masternode_winner_help();
|
||||
masternode_winner_help(request);
|
||||
|
||||
return GetNextMasternodeForPayment(10);
|
||||
}
|
||||
|
||||
static void masternode_current_help()
|
||||
static void masternode_current_help(const JSONRPCRequest& request)
|
||||
{
|
||||
if (!IsDeprecatedRPCEnabled("masternode_current")) {
|
||||
throw std::runtime_error("DEPRECATED: set -deprecatedrpc=masternode_current to enable it");
|
||||
}
|
||||
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"masternode current",
|
||||
"Print info on current masternode winner to be paid the next block (calculated locally)\n",
|
||||
{},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue masternode_current(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || !IsDeprecatedRPCEnabled("masternode_current"))
|
||||
masternode_current_help();
|
||||
masternode_current_help(request);
|
||||
|
||||
return GetNextMasternodeForPayment(1);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
static void masternode_outputs_help()
|
||||
static void masternode_outputs_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"masternode outputs",
|
||||
"Print masternode compatible outputs\n",
|
||||
{},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue masternode_outputs(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp)
|
||||
masternode_outputs_help();
|
||||
masternode_outputs_help(request);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
// Find possible candidates
|
||||
std::vector<COutput> vPossibleCoins;
|
||||
@ -236,21 +228,20 @@ static UniValue masternode_outputs(const JSONRPCRequest& request)
|
||||
|
||||
#endif // ENABLE_WALLET
|
||||
|
||||
static void masternode_status_help()
|
||||
static void masternode_status_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"masternode status",
|
||||
"Print masternode status information\n",
|
||||
{},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue masternode_status(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp)
|
||||
masternode_status_help();
|
||||
masternode_status_help(request);
|
||||
|
||||
if (!fMasternodeMode)
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "This is not a masternode");
|
||||
@ -286,12 +277,12 @@ static std::string GetRequiredPaymentsString(int nBlockHeight, const CDeterminis
|
||||
if (payee) {
|
||||
CTxDestination dest;
|
||||
if (!ExtractDestination(payee->pdmnState->scriptPayout, dest)) {
|
||||
assert(false);
|
||||
CHECK_NONFATAL(false);
|
||||
}
|
||||
strPayments = EncodeDestination(dest);
|
||||
if (payee->nOperatorReward != 0 && payee->pdmnState->scriptOperatorPayout != CScript()) {
|
||||
if (!ExtractDestination(payee->pdmnState->scriptOperatorPayout, dest)) {
|
||||
assert(false);
|
||||
CHECK_NONFATAL(false);
|
||||
}
|
||||
strPayments += ", " + EncodeDestination(dest);
|
||||
}
|
||||
@ -316,9 +307,8 @@ static std::string GetRequiredPaymentsString(int nBlockHeight, const CDeterminis
|
||||
return strPayments;
|
||||
}
|
||||
|
||||
static void masternode_winners_help()
|
||||
static void masternode_winners_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"masternode winners",
|
||||
"Print list of masternode winners\n",
|
||||
{
|
||||
@ -327,13 +317,13 @@ static void masternode_winners_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue masternode_winners(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 3)
|
||||
masternode_winners_help();
|
||||
masternode_winners_help(request);
|
||||
|
||||
const CBlockIndex* pindexTip{nullptr};
|
||||
{
|
||||
@ -375,9 +365,8 @@ static UniValue masternode_winners(const JSONRPCRequest& request)
|
||||
|
||||
return obj;
|
||||
}
|
||||
static void masternode_payments_help()
|
||||
static void masternode_payments_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"masternode payments",
|
||||
"\nReturns an array of deterministic masternodes and their payments for the specified block\n",
|
||||
{
|
||||
@ -385,16 +374,16 @@ static void masternode_payments_help()
|
||||
{"count", RPCArg::Type::NUM, /* default */ "1", "The number of blocks to return. Will return <count> previous blocks if <count> is negative. Both 1 and -1 correspond to the chain tip."},
|
||||
},
|
||||
RPCResult {
|
||||
" [ (array) Blocks\n"
|
||||
" [ (json array) Blocks\n"
|
||||
" {\n"
|
||||
" \"height\" : n, (numeric) The height of the block\n"
|
||||
" \"blockhash\" : \"hash\", (string) The hash of the block\n"
|
||||
" \"amount\" : n (numeric) Amount received in this block by all masternodes\n"
|
||||
" \"masternodes\": [ (array) Masternodes that received payments in this block\n"
|
||||
" \"masternodes\" : [ (json array) Masternodes that received payments in this block\n"
|
||||
" {\n"
|
||||
" \"proTxHash\" : \"xxxx\", (string) The hash of the corresponding ProRegTx\n"
|
||||
" \"amount\" : n (numeric) Amount received by this masternode\n"
|
||||
" \"payees\": [ (array) Payees who received a share of this payment\n"
|
||||
" \"payees\" : [ (json array) Payees who received a share of this payment\n"
|
||||
" {\n"
|
||||
" \"address\" : \"xxx\", (string) Payee address\n"
|
||||
" \"script\" : \"xxx\", (string) Payee scriptPubKey\n"
|
||||
@ -407,13 +396,13 @@ static void masternode_payments_help()
|
||||
" ]"
|
||||
},
|
||||
RPCExamples{""}
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue masternode_payments(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() > 3) {
|
||||
masternode_payments_help();
|
||||
masternode_payments_help(request);
|
||||
}
|
||||
|
||||
CBlockIndex* pindex{nullptr};
|
||||
@ -522,7 +511,6 @@ static UniValue masternode_payments(const JSONRPCRequest& request)
|
||||
|
||||
[[ noreturn ]] static void masternode_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"masternode",
|
||||
"Set of commands to execute masternode related actions\n"
|
||||
"\nAvailable commands:\n"
|
||||
@ -541,7 +529,7 @@ static UniValue masternode_payments(const JSONRPCRequest& request)
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Throw();
|
||||
}
|
||||
|
||||
static UniValue masternode(const JSONRPCRequest& request)
|
||||
@ -597,7 +585,7 @@ static UniValue masternodelist(const JSONRPCRequest& request)
|
||||
strMode != "payee" && strMode != "pubkeyoperator" &&
|
||||
strMode != "status"))
|
||||
{
|
||||
masternode_list_help();
|
||||
masternode_list_help(request);
|
||||
}
|
||||
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
|
@ -93,8 +93,7 @@ static UniValue getnetworkhashps(const JSONRPCRequest& request)
|
||||
{"height", RPCArg::Type::NUM, /* default */ "-1", "To estimate at the time of the given height."},
|
||||
},
|
||||
RPCResult{
|
||||
"x (numeric) Hashes per second estimated\n"
|
||||
},
|
||||
RPCResult::Type::NUM, "", "Hashes per second estimated"},
|
||||
RPCExamples{
|
||||
HelpExampleCli("getnetworkhashps", "")
|
||||
+ HelpExampleRpc("getnetworkhashps", "")
|
||||
@ -166,8 +165,10 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
|
||||
{"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."},
|
||||
},
|
||||
RPCResult{
|
||||
"[ blockhashes ] (array) hashes of blocks generated\n"
|
||||
},
|
||||
RPCResult::Type::ARR, "", "hashes of blocks generated",
|
||||
{
|
||||
{RPCResult::Type::STR_HEX, "", "blockhash"},
|
||||
}},
|
||||
RPCExamples{
|
||||
"\nGenerate 11 blocks to myaddress\n"
|
||||
+ HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
|
||||
@ -253,8 +254,7 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request)
|
||||
" considers the transaction as it would have paid a higher (or lower) fee."},
|
||||
},
|
||||
RPCResult{
|
||||
"true (boolean) Returns true\n"
|
||||
},
|
||||
RPCResult::Type::BOOL, "", "Returns true"},
|
||||
RPCExamples{
|
||||
HelpExampleCli("prioritisetransaction", "\"txid\" 10000")
|
||||
+ HelpExampleRpc("prioritisetransaction", "\"txid\", 10000")
|
||||
@ -338,11 +338,11 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||
" },\n"
|
||||
" \"vbrequired\" : n, (numeric) bit mask of versionbits the server requires set in submissions\n"
|
||||
" \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n"
|
||||
" \"transactions\" : [ (array) contents of non-coinbase transactions that should be included in the next block\n"
|
||||
" \"transactions\" : [ (json array) contents of non-coinbase transactions that should be included in the next block\n"
|
||||
" {\n"
|
||||
" \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
|
||||
" \"hash\" : \"xxxx\", (string) hash/id encoded in little-endian hexadecimal\n"
|
||||
" \"depends\" : [ (array) array of numbers \n"
|
||||
" \"depends\" : [ (json array) array of numbers \n"
|
||||
" n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
|
||||
" ,...\n"
|
||||
" ],\n"
|
||||
@ -367,7 +367,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||
" \"bits\" : \"xxxxxxxx\", (string) compressed target of next block\n"
|
||||
" \"previousbits\" : \"xxxxxxxx\", (string) compressed target of current highest block\n"
|
||||
" \"height\" : n (numeric) The height of the next block\n"
|
||||
" \"masternode\" : [ (array) required masternode payments that must be included in the next block\n"
|
||||
" \"masternode\" : [ (json array) required masternode payments that must be included in the next block\n"
|
||||
" {\n"
|
||||
" \"payee\" : \"xxxx\", (string) payee address\n"
|
||||
" \"script\" : \"xxxx\", (string) payee scriptPubKey\n"
|
||||
@ -376,7 +376,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||
" },\n"
|
||||
" \"masternode_payments_started\" : true|false, (boolean) true, if masternode payments started\n"
|
||||
" \"masternode_payments_enforced\" : true|false, (boolean) true, if masternode payments are enforced\n"
|
||||
" \"superblock\" : [ (array) required superblock payees that must be included in the next block\n"
|
||||
" \"superblock\" : [ (json array) required superblock payees that must be included in the next block\n"
|
||||
" {\n"
|
||||
" \"payee\" : \"xxxx\", (string) payee address\n"
|
||||
" \"script\" : \"xxxx\", (string) payee scriptPubKey\n"
|
||||
@ -549,7 +549,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
||||
// 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();
|
||||
|
||||
@ -798,8 +798,7 @@ static UniValue submitheader(const JSONRPCRequest& request)
|
||||
{"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block header data"},
|
||||
},
|
||||
RPCResult{
|
||||
"None"
|
||||
},
|
||||
RPCResult::Type::NONE, "", "None"},
|
||||
RPCExamples{
|
||||
HelpExampleCli("submitheader", "\"aabbcc\"") +
|
||||
HelpExampleRpc("submitheader", "\"aabbcc\"")
|
||||
@ -848,17 +847,19 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request)
|
||||
" \"CONSERVATIVE\""},
|
||||
},
|
||||
RPCResult{
|
||||
"{\n"
|
||||
" \"feerate\" : x.x, (numeric, optional) estimate fee rate in " + CURRENCY_UNIT + "/kB\n"
|
||||
" \"errors\": [ str... ] (json array of strings, optional) Errors encountered during processing\n"
|
||||
" \"blocks\" : n (numeric) block number where estimate was found\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::NUM, "feerate", /* optional */ true, "estimate fee rate in " + CURRENCY_UNIT + "/kB (only present if no errors were encountered)"},
|
||||
{RPCResult::Type::ARR, "errors", "Errors encountered during processing",
|
||||
{
|
||||
{RPCResult::Type::STR, "", "error"},
|
||||
}},
|
||||
{RPCResult::Type::NUM, "blocks", "block number where estimate was found\n"
|
||||
"The request target will be clamped between 2 and the highest target\n"
|
||||
"fee estimation is able to return based on how long it has been running.\n"
|
||||
"An error is returned if not enough transactions and blocks\n"
|
||||
"have been observed to make an estimate for any number of blocks.\n"
|
||||
},
|
||||
"have been observed to make an estimate for any number of blocks."},
|
||||
}},
|
||||
RPCExamples{
|
||||
HelpExampleCli("estimatesmartfee", "6")
|
||||
},
|
||||
|
@ -15,8 +15,9 @@
|
||||
#include <rpc/util.h>
|
||||
#include <script/descriptor.h>
|
||||
#include <txmempool.h>
|
||||
#include <util/system.h>
|
||||
#include <util/check.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <util/system.h>
|
||||
#include <validation.h>
|
||||
#include <util/validation.h>
|
||||
|
||||
@ -302,13 +303,14 @@ UniValue getdescriptorinfo(const JSONRPCRequest& request)
|
||||
{"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor"},
|
||||
},
|
||||
RPCResult{
|
||||
"{\n"
|
||||
" \"descriptor\" : \"desc\", (string) The descriptor in canonical form, without private keys\n"
|
||||
" \"checksum\" : \"chksum\", (string) The checksum for the input descriptor\n"
|
||||
" \"isrange\" : true|false, (boolean) Whether the descriptor is ranged\n"
|
||||
" \"issolvable\" : true|false, (boolean) Whether the descriptor is solvable\n"
|
||||
" \"hasprivatekeys\" : true|false, (boolean) Whether the input descriptor contained at least one private key\n"
|
||||
"}\n"
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR, "descriptor", "The descriptor in canonical form, without private keys"},
|
||||
{RPCResult::Type::STR, "checksum", "The checksum for the input descriptor"},
|
||||
{RPCResult::Type::BOOL, "isrange", "Whether the descriptor is ranged"},
|
||||
{RPCResult::Type::BOOL, "issolvable", "Whether the descriptor is solvable"},
|
||||
{RPCResult::Type::BOOL, "hasprivatekeys", "Whether the input descriptor contained at least one private key"},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
"\nAnalyse a descriptor\n"
|
||||
@ -353,7 +355,7 @@ UniValue deriveaddresses(const JSONRPCRequest& request)
|
||||
{"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."},
|
||||
},
|
||||
RPCResult{
|
||||
"\"address\" (array) A json array of the derived addresses\n"
|
||||
"\"address\" (json array) A json array of the derived addresses\n"
|
||||
" [\n"
|
||||
" ...\n"
|
||||
" ]\n"
|
||||
@ -429,7 +431,7 @@ static UniValue verifymessage(const JSONRPCRequest& request)
|
||||
{"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."},
|
||||
},
|
||||
RPCResult{
|
||||
"true|false (boolean) If the signature is verified or not.\n"
|
||||
RPCResult::Type::BOOL, "", "If the signature is verified or not."
|
||||
},
|
||||
RPCExamples{
|
||||
"\nUnlock the wallet for 30 seconds\n"
|
||||
@ -487,7 +489,7 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request)
|
||||
{"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
|
||||
},
|
||||
RPCResult{
|
||||
"\"signature\" (string) The signature of the message encoded in base 64\n"
|
||||
RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64"
|
||||
},
|
||||
RPCExamples{
|
||||
"\nCreate the signature\n"
|
||||
@ -1136,19 +1138,21 @@ static UniValue getmemoryinfo(const JSONRPCRequest& request)
|
||||
},
|
||||
{
|
||||
RPCResult{"mode \"stats\"",
|
||||
"{\n"
|
||||
" \"locked\": { (json object) Information about locked memory manager\n"
|
||||
" \"used\": xxxxx, (numeric) Number of bytes used\n"
|
||||
" \"free\": xxxxx, (numeric) Number of bytes available in current arenas\n"
|
||||
" \"total\": xxxxxxx, (numeric) Total number of bytes managed\n"
|
||||
" \"locked\": xxxxxx, (numeric) Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk.\n"
|
||||
" \"chunks_used\": xxxxx, (numeric) Number allocated chunks\n"
|
||||
" \"chunks_free\": xxxxx, (numeric) Number unused chunks\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::OBJ, "locked", "Information about locked memory manager",
|
||||
{
|
||||
{RPCResult::Type::NUM, "used", "Number of bytes used"},
|
||||
{RPCResult::Type::NUM, "free", "Number of bytes available in current arenas"},
|
||||
{RPCResult::Type::NUM, "total", "Total number of bytes managed"},
|
||||
{RPCResult::Type::NUM, "locked", "Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk."},
|
||||
{RPCResult::Type::NUM, "chunks_used", "Number allocated chunks"},
|
||||
{RPCResult::Type::NUM, "chunks_free", "Number unused chunks"},
|
||||
}},
|
||||
}
|
||||
},
|
||||
RPCResult{"mode \"mallocinfo\"",
|
||||
"\"<malloc version=\"1\">...\"\n"
|
||||
RPCResult::Type::STR, "", "\"<malloc version=\"1\">...\""
|
||||
},
|
||||
},
|
||||
RPCExamples{
|
||||
@ -1219,10 +1223,10 @@ static UniValue logging(const JSONRPCRequest& request)
|
||||
}},
|
||||
},
|
||||
RPCResult{
|
||||
"{ (json object where keys are the logging categories, and values indicates its status\n"
|
||||
" \"category\": true|false, (bool) if being debug logged or not. false:inactive, true:active\n"
|
||||
" ...\n"
|
||||
"}\n"
|
||||
RPCResult::Type::OBJ_DYN, "", "keys are the logging categories, and values indicates its status",
|
||||
{
|
||||
{RPCResult::Type::BOOL, "category", "if being debug logged or not. false:inactive, true:active"},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"")
|
||||
@ -1270,6 +1274,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 "
|
||||
"dash-cli and the GUI. There is no server-side difference.",
|
||||
{},
|
||||
@ -1278,6 +1283,8 @@ static UniValue echo(const JSONRPCRequest& request)
|
||||
}.ToString()
|
||||
);
|
||||
|
||||
CHECK_NONFATAL(request.params.size() != 100);
|
||||
|
||||
return request.params;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ static UniValue getconnectioncount(const JSONRPCRequest& request)
|
||||
"\nReturns the number of connections to other nodes.\n",
|
||||
{},
|
||||
RPCResult{
|
||||
"n (numeric) The connection count\n"
|
||||
RPCResult::Type::NUM, "", "The connection count"
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("getconnectioncount", "")
|
||||
@ -96,7 +96,7 @@ static UniValue getpeerinfo(const JSONRPCRequest& request)
|
||||
" \"verified_pubkey_hash\" : h, (hex) Only present when the peer is a masternode and successfully\n"
|
||||
" authenticated via MNAUTH. In this case, this field contains the\n"
|
||||
" hash of the masternode's operator public key\n"
|
||||
" \"servicesnames\":[ (array) the services offered, in human-readable form\n"
|
||||
" \"servicesnames\" : [ (json array) the services offered, in human-readable form\n"
|
||||
" \"SERVICE_NAME\", (string) the service name if it is recognised\n"
|
||||
" ...\n"
|
||||
" ],\n"
|
||||
@ -413,20 +413,21 @@ static UniValue getnettotals(const JSONRPCRequest& request)
|
||||
"and current time.\n",
|
||||
{},
|
||||
RPCResult{
|
||||
"{\n"
|
||||
" \"totalbytesrecv\": n, (numeric) Total bytes received\n"
|
||||
" \"totalbytessent\": n, (numeric) Total bytes sent\n"
|
||||
" \"timemillis\": t, (numeric) Current UNIX time in milliseconds\n"
|
||||
" \"uploadtarget\":\n"
|
||||
" {\n"
|
||||
" \"timeframe\": n, (numeric) Length of the measuring timeframe in seconds\n"
|
||||
" \"target\": n, (numeric) Target in bytes\n"
|
||||
" \"target_reached\": true|false, (boolean) True if target is reached\n"
|
||||
" \"serve_historical_blocks\": true|false, (boolean) True if serving historical blocks\n"
|
||||
" \"bytes_left_in_cycle\": t, (numeric) Bytes left in current time cycle\n"
|
||||
" \"time_left_in_cycle\": t (numeric) Seconds left in current time cycle\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"},
|
||||
{RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"},
|
||||
{RPCResult::Type::NUM_TIME, "timemillis", "Current UNIX time in milliseconds"},
|
||||
{RPCResult::Type::OBJ, "uploadtarget", "",
|
||||
{
|
||||
{RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"},
|
||||
{RPCResult::Type::NUM, "target", "Target in bytes"},
|
||||
{RPCResult::Type::BOOL, "target_reached", "True if target is reached"},
|
||||
{RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"},
|
||||
{RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"},
|
||||
{RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"},
|
||||
}},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("getnettotals", "")
|
||||
@ -487,16 +488,16 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
|
||||
" \"subversion\" : \"/Dash Core:x.x.x.x/\", (string) the server subversion string\n"
|
||||
" \"protocolversion\" : xxxxx, (numeric) the protocol version\n"
|
||||
" \"localservices\" : \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n"
|
||||
" \"localservicesnames\": [ (array) the services we offer to the network, in human-readable form\n"
|
||||
" \"localservicesnames\" : [ (json array) the services we offer to the network, in human-readable form\n"
|
||||
" \"SERVICE_NAME\", (string) the service name\n"
|
||||
" ...\n"
|
||||
" ],\n"
|
||||
" \"localrelay\": true|false, (bool) true if transaction relay is requested from peers\n"
|
||||
" \"localrelay\" : true|false, (boolean) true if transaction relay is requested from peers\n"
|
||||
" \"timeoffset\" : xxxxx, (numeric) the time offset\n"
|
||||
" \"connections\" : xxxxx, (numeric) the number of connections\n"
|
||||
" \"networkactive\": true|false, (bool) whether p2p networking is enabled\n"
|
||||
" \"networkactive\" : true|false, (boolean) whether p2p networking is enabled\n"
|
||||
" \"socketevents\" : \"xxx/\", (string) the socket events mode, either kqueue, epoll, poll or select\n"
|
||||
" \"networks\": [ (array) information per network\n"
|
||||
" \"networks\" : [ (json array) information per network\n"
|
||||
" {\n"
|
||||
" \"name\" : \"xxx\", (string) network (ipv4, ipv6 or onion)\n"
|
||||
" \"limited\" : true|false, (boolean) is the network limited using -onlynet?\n"
|
||||
@ -508,7 +509,7 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
|
||||
" ],\n"
|
||||
" \"relayfee\" : x.xxxxxxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n"
|
||||
" \"incrementalfee\" : x.xxxxxxxx, (numeric) minimum fee increment for mempool limiting in " + CURRENCY_UNIT + "/kB\n"
|
||||
" \"localaddresses\": [ (array) list of local addresses\n"
|
||||
" \"localaddresses\" : [ (json array) list of local addresses\n"
|
||||
" {\n"
|
||||
" \"address\" : \"xxxx\", (string) network address\n"
|
||||
" \"port\" : xxx, (numeric) network port\n"
|
||||
@ -556,7 +557,7 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
|
||||
strSocketEvents = "kqueue";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
CHECK_NONFATAL(false);
|
||||
}
|
||||
obj.pushKV("socketevents", strSocketEvents);
|
||||
}
|
||||
|
@ -6,15 +6,6 @@
|
||||
#ifndef BITCOIN_RPC_PROTOCOL_H
|
||||
#define BITCOIN_RPC_PROTOCOL_H
|
||||
|
||||
#include <fs.h>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
//! HTTP status codes
|
||||
enum HTTPStatusCode
|
||||
{
|
||||
@ -93,18 +84,4 @@ enum RPCErrorCode
|
||||
RPC_FORBIDDEN_BY_SAFE_MODE = -2, //!< Server is in safe mode, and command is not allowed in safe mode
|
||||
};
|
||||
|
||||
UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id);
|
||||
UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id);
|
||||
std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id);
|
||||
UniValue JSONRPCError(int code, const std::string& message);
|
||||
|
||||
/** Generate a new RPC authentication cookie and write it to disk */
|
||||
bool GenerateAuthCookie(std::string *cookie_out);
|
||||
/** Read the RPC authentication cookie from disk */
|
||||
bool GetAuthCookie(std::string *cookie_out);
|
||||
/** Delete RPC authentication cookie from disk */
|
||||
void DeleteAuthCookie();
|
||||
/** Parse JSON-RPC batch reply into a vector */
|
||||
std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue &in, size_t num);
|
||||
|
||||
#endif // BITCOIN_RPC_PROTOCOL_H
|
||||
|
@ -133,11 +133,11 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
|
||||
},
|
||||
{
|
||||
RPCResult{"if verbose is not set or set to false",
|
||||
"\"data\" (string) The serialized, hex-encoded data for 'txid'\n"
|
||||
RPCResult::Type::STR, "data", "The serialized, hex-encoded data for 'txid'"
|
||||
},
|
||||
RPCResult{"if verbose is set to true",
|
||||
"{\n"
|
||||
" \"in_active_chain\": b, (bool) Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)\n"
|
||||
" \"in_active_chain\" : b, (boolean) Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)\n"
|
||||
" \"txid\" : \"id\", (string) The transaction id (same as provided)\n"
|
||||
" \"size\" : n, (numeric) The transaction size\n"
|
||||
" \"version\" : n, (numeric) The version\n"
|
||||
@ -179,9 +179,9 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
|
||||
" \"confirmations\" : n, (numeric) The confirmations\n"
|
||||
" \"blocktime\" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
|
||||
" \"time\" : ttt, (numeric) Same as \"blocktime\"\n"
|
||||
" \"instantlock\" : true|false, (bool) Current transaction lock state\n"
|
||||
" \"instantlock_internal\" : true|false, (bool) Current internal transaction lock state\n"
|
||||
" \"chainlock\" : true|false, (bool) The state of the corresponding block chainlock\n"
|
||||
" \"instantlock\" : true|false, (boolean) Current transaction lock state\n"
|
||||
" \"instantlock_internal\" : true|false, (boolean) Current internal transaction lock state\n"
|
||||
" \"chainlock\" : true|false, (boolean) The state of the corresponding block chainlock\n"
|
||||
"}\n"
|
||||
},
|
||||
},
|
||||
@ -273,7 +273,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request)
|
||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "If specified, looks for txid in the block with this hash"},
|
||||
},
|
||||
RPCResult{
|
||||
"\"data\" (string) A string that is a serialized, hex-encoded data for the proof.\n"
|
||||
RPCResult::Type::STR, "data", "A string that is a serialized, hex-encoded data for the proof."
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("gettxoutproof", "'[\"mytxid\",...]'")
|
||||
@ -367,7 +367,10 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request)
|
||||
{"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded proof generated by gettxoutproof"},
|
||||
},
|
||||
RPCResult{
|
||||
"[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof can not be validated.\n"
|
||||
RPCResult::Type::ARR, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR_HEX, "txid", "The txid(s) which the proof commits to, or empty array if the proof can not be validated."},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("verifytxoutproof", "\"proof\"")
|
||||
@ -446,7 +449,7 @@ static UniValue createrawtransaction(const JSONRPCRequest& request)
|
||||
{"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
|
||||
},
|
||||
RPCResult{
|
||||
"\"transaction\" (string) hex string of the transaction\n"
|
||||
RPCResult::Type::STR_HEX, "transaction", "hex string of the transaction"
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"")
|
||||
@ -617,7 +620,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
|
||||
},
|
||||
},
|
||||
RPCResult{
|
||||
"\"hex\" (string) The hex-encoded raw transaction with signature(s)\n"
|
||||
RPCResult::Type::STR, "", "The hex-encoded raw transaction with signature(s)"
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("combinerawtransaction", "'[\"myhex1\", \"myhex2\", \"myhex3\"]'")
|
||||
@ -725,20 +728,22 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
|
||||
},
|
||||
},
|
||||
RPCResult{
|
||||
"{\n"
|
||||
" \"hex\" : \"value\", (string) The hex-encoded raw transaction with signature(s)\n"
|
||||
" \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n"
|
||||
" \"errors\" : [ (json array of objects) Script verification errors (if there are any)\n"
|
||||
" {\n"
|
||||
" \"txid\" : \"hash\", (string) The hash of the referenced, previous transaction\n"
|
||||
" \"vout\" : n, (numeric) The index of the output to spent and used as input\n"
|
||||
" \"scriptSig\" : \"hex\", (string) The hex-encoded signature script\n"
|
||||
" \"sequence\" : n, (numeric) Script sequence number\n"
|
||||
" \"error\" : \"text\" (string) Verification or signing error related to the input\n"
|
||||
" }\n"
|
||||
" ,...\n"
|
||||
" ]\n"
|
||||
"}\n"
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"},
|
||||
{RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"},
|
||||
{RPCResult::Type::ARR, "errors", "Script verification errors (if there are any)",
|
||||
{
|
||||
{RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"},
|
||||
{RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"},
|
||||
{RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"},
|
||||
{RPCResult::Type::NUM, "sequence", "Script sequence number"},
|
||||
{RPCResult::Type::STR, "error", "Verification or signing error related to the input"},
|
||||
}},
|
||||
}},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("signrawtransactionwithkey", "\"myhex\" \"[\\\"key1\\\",\\\"key2\\\"]\"")
|
||||
@ -788,7 +793,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
|
||||
{"bypasslimits", RPCArg::Type::BOOL, /* default_val */ "false", "Bypass transaction policy limits"},
|
||||
},
|
||||
RPCResult{
|
||||
"\"hex\" (string) The transaction hash in hex\n"
|
||||
RPCResult::Type::STR_HEX, "", "The transaction hash in hex"
|
||||
},
|
||||
RPCExamples{
|
||||
"\nCreate a transaction\n"
|
||||
@ -856,14 +861,16 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
|
||||
{"maxfeerate", RPCArg::Type::AMOUNT, /* default */ FormatMoney(DEFAULT_MAX_RAW_TX_FEE), "Reject transactions whose fee rate is higher than the specified value, expressed in " + CURRENCY_UNIT + "/kB\n"},
|
||||
},
|
||||
RPCResult{
|
||||
"[ (array) The result of the mempool acceptance test for each raw transaction in the input array.\n"
|
||||
" Length is exactly one for now.\n"
|
||||
" {\n"
|
||||
" \"txid\" (string) The transaction hash in hex\n"
|
||||
" \"allowed\" (boolean) If the mempool allows this tx to be inserted\n"
|
||||
" \"reject-reason\" (string) Rejection string (only present when 'allowed' is false)\n"
|
||||
" }\n"
|
||||
"]\n"
|
||||
RPCResult::Type::ARR, "", "The result of the mempool acceptance test for each raw transaction in the input array.\n"
|
||||
"Length is exactly one for now.",
|
||||
{
|
||||
{RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR_HEX, "txid", "The transaction hash in hex"},
|
||||
{RPCResult::Type::BOOL, "allowed", "If the mempool allows this tx to be inserted"},
|
||||
{RPCResult::Type::STR, "reject-reason", "Rejection string (only present when 'allowed' is false)"},
|
||||
}},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
"\nCreate a transaction\n"
|
||||
@ -1195,7 +1202,7 @@ UniValue combinepsbt(const JSONRPCRequest& request)
|
||||
},
|
||||
},
|
||||
RPCResult{
|
||||
" \"psbt\" (string) The base64-encoded partially signed transaction\n"
|
||||
RPCResult::Type::STR, "", "The base64-encoded partially signed transaction"
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("combinepsbt", "[\"mybase64_1\", \"mybase64_2\", \"mybase64_3\"]")
|
||||
@ -1328,7 +1335,7 @@ UniValue createpsbt(const JSONRPCRequest& request)
|
||||
{"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"},
|
||||
},
|
||||
RPCResult{
|
||||
" \"psbt\" (string) The resulting raw transaction (base64-encoded string)\n"
|
||||
RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)"
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"")
|
||||
@ -1375,7 +1382,7 @@ UniValue converttopsbt(const JSONRPCRequest& request)
|
||||
" will continue. If false, RPC will fail if any signatures are present."},
|
||||
},
|
||||
RPCResult{
|
||||
" \"psbt\" (string) The resulting raw transaction (base64-encoded string)\n"
|
||||
RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)"
|
||||
},
|
||||
RPCExamples{
|
||||
"\nCreate a transaction\n"
|
||||
@ -1430,7 +1437,7 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request)
|
||||
{"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}
|
||||
},
|
||||
RPCResult {
|
||||
" \"psbt\" (string) The base64-encoded partially signed transaction with inputs updated\n"
|
||||
RPCResult::Type::STR, "", "The base64-encoded partially signed transaction with inputs updated"
|
||||
},
|
||||
RPCExamples {
|
||||
HelpExampleCli("utxoupdatepsbt", "\"psbt\"")
|
||||
@ -1495,7 +1502,7 @@ UniValue joinpsbts(const JSONRPCRequest& request)
|
||||
}}
|
||||
},
|
||||
RPCResult {
|
||||
" \"psbt\" (string) The base64-encoded partially signed transaction\n"
|
||||
RPCResult::Type::STR, "", "The base64-encoded partially signed transaction"
|
||||
},
|
||||
RPCExamples {
|
||||
HelpExampleCli("joinpsbts", "\"psbt\"")
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <keystore.h>
|
||||
#include <policy/policy.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <rpc/protocol.h>
|
||||
#include <rpc/request.h>
|
||||
#include <rpc/util.h>
|
||||
#include <univalue.h>
|
||||
#include <util/strencodings.h>
|
||||
|
@ -1,15 +1,16 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
// Copyright (c) 2014-2020 The Dash Core developers
|
||||
// Copyright (c) 2009-2019 The Bitcoin Core developers
|
||||
// Copyright (c) 2014-2022 The Dash Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <rpc/protocol.h>
|
||||
#include <rpc/request.h>
|
||||
|
||||
#include <fs.h>
|
||||
#include <random.h>
|
||||
#include <rpc/protocol.h>
|
||||
#include <util/system.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <util/time.h>
|
||||
|
||||
/**
|
||||
* JSON-RPC protocol. Bitcoin speaks version 1.0 for maximum compatibility,
|
||||
@ -148,3 +149,38 @@ std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue &in, size_t num)
|
||||
}
|
||||
return batch;
|
||||
}
|
||||
|
||||
void JSONRPCRequest::parse(const UniValue& valRequest)
|
||||
{
|
||||
// Parse request
|
||||
if (!valRequest.isObject())
|
||||
throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
|
||||
const UniValue& request = valRequest.get_obj();
|
||||
|
||||
// Parse id now so errors from here on will have the id
|
||||
id = find_value(request, "id");
|
||||
|
||||
// Parse method
|
||||
UniValue valMethod = find_value(request, "method");
|
||||
if (valMethod.isNull())
|
||||
throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
|
||||
if (!valMethod.isStr())
|
||||
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
|
||||
strMethod = valMethod.get_str();
|
||||
if (strMethod != "getblocktemplate") {
|
||||
if (fLogIPs)
|
||||
LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n", SanitizeString(strMethod),
|
||||
this->authUser, this->peerAddr);
|
||||
else
|
||||
LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);
|
||||
}
|
||||
|
||||
// Parse params
|
||||
UniValue valParams = find_value(request, "params");
|
||||
if (valParams.isArray() || valParams.isObject())
|
||||
params = valParams;
|
||||
else if (valParams.isNull())
|
||||
params = UniValue(UniValue::VARR);
|
||||
else
|
||||
throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object");
|
||||
}
|
42
src/rpc/request.h
Normal file
42
src/rpc/request.h
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// 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.
|
||||
|
||||
#ifndef BITCOIN_RPC_REQUEST_H
|
||||
#define BITCOIN_RPC_REQUEST_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id);
|
||||
UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id);
|
||||
std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id);
|
||||
UniValue JSONRPCError(int code, const std::string& message);
|
||||
|
||||
/** Generate a new RPC authentication cookie and write it to disk */
|
||||
bool GenerateAuthCookie(std::string *cookie_out);
|
||||
/** Read the RPC authentication cookie from disk */
|
||||
bool GetAuthCookie(std::string *cookie_out);
|
||||
/** Delete RPC authentication cookie from disk */
|
||||
void DeleteAuthCookie();
|
||||
/** Parse JSON-RPC batch reply into a vector */
|
||||
std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue &in, size_t num);
|
||||
|
||||
class JSONRPCRequest
|
||||
{
|
||||
public:
|
||||
UniValue id;
|
||||
std::string strMethod;
|
||||
UniValue params;
|
||||
bool fHelp;
|
||||
std::string URI;
|
||||
std::string authUser;
|
||||
std::string peerAddr;
|
||||
|
||||
JSONRPCRequest() : id(NullUniValue), params(NullUniValue), fHelp(false) {}
|
||||
void parse(const UniValue& valRequest);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_RPC_REQUEST_H
|
@ -175,7 +175,7 @@ static CBLSSecretKey ParseBLSSecretKey(const std::string& hexKey, const std::str
|
||||
template<typename SpecialTxPayload>
|
||||
static void FundSpecialTx(CWallet* pwallet, CMutableTransaction& tx, const SpecialTxPayload& payload, const CTxDestination& fundDest)
|
||||
{
|
||||
assert(pwallet != nullptr);
|
||||
CHECK_NONFATAL(pwallet != nullptr);
|
||||
|
||||
// Make sure the results are valid at least up to the most recent block
|
||||
// the user could have gotten from another RPC command prior to now
|
||||
@ -242,7 +242,7 @@ static void FundSpecialTx(CWallet* pwallet, CMutableTransaction& tx, const Speci
|
||||
// CreateTransaction added a change output, so we don't need the dummy txout anymore.
|
||||
// Removing it results in slight overpayment of fees, but we ignore this for now (as it's a very low amount).
|
||||
auto it = std::find(tx.vout.begin(), tx.vout.end(), dummyTxOut);
|
||||
assert(it != tx.vout.end());
|
||||
CHECK_NONFATAL(it != tx.vout.end());
|
||||
tx.vout.erase(it);
|
||||
}
|
||||
}
|
||||
@ -315,16 +315,15 @@ static std::string SignAndSendSpecialTx(const CMutableTransaction& tx, bool fSub
|
||||
return sendrawtransaction(sendRequest).get_str();
|
||||
}
|
||||
|
||||
static void protx_register_fund_help(CWallet* const pwallet)
|
||||
static void protx_register_fund_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx register_fund",
|
||||
"\nCreates, funds and sends a ProTx to the network. The resulting transaction will move 1000 Dash\n"
|
||||
"to the address specified by collateralAddress and will then function as the collateral of your\n"
|
||||
"masternode.\n"
|
||||
"A few of the limitations you see in the arguments are temporary and might be lifted after DIP3\n"
|
||||
"is fully deployed.\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n",
|
||||
+ HelpRequiringPassphrase() + "\n",
|
||||
{
|
||||
GetRpcArg("collateralAddress"),
|
||||
GetRpcArg("ipAndPort"),
|
||||
@ -345,17 +344,16 @@ static void protx_register_fund_help(CWallet* const pwallet)
|
||||
RPCExamples{
|
||||
HelpExampleCli("protx", "register_fund \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static void protx_register_help(CWallet* const pwallet)
|
||||
static void protx_register_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx register",
|
||||
"\nSame as \"protx register_fund\", but with an externally referenced collateral.\n"
|
||||
"The collateral is specified through \"collateralHash\" and \"collateralIndex\" and must be an unspent\n"
|
||||
"transaction output spendable by this wallet. It must also not be used by any other masternode.\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n",
|
||||
+ HelpRequiringPassphrase() + "\n",
|
||||
{
|
||||
GetRpcArg("collateralHash"),
|
||||
GetRpcArg("collateralIndex"),
|
||||
@ -377,12 +375,11 @@ static void protx_register_help(CWallet* const pwallet)
|
||||
RPCExamples{
|
||||
HelpExampleCli("protx", "register \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static void protx_register_prepare_help()
|
||||
static void protx_register_prepare_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx register_prepare",
|
||||
"\nCreates an unsigned ProTx and a message that must be signed externally\n"
|
||||
"with the private key that corresponds to collateralAddress to prove collateral ownership.\n"
|
||||
@ -409,17 +406,16 @@ static void protx_register_prepare_help()
|
||||
RPCExamples{
|
||||
HelpExampleCli("protx", "register_prepare \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static void protx_register_submit_help(CWallet* const pwallet)
|
||||
static void protx_register_submit_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx register_submit",
|
||||
"\nCombines the unsigned ProTx and a signature of the signMessage, signs all inputs\n"
|
||||
"which were added to cover fees and submits the resulting transaction to the network.\n"
|
||||
"Note: See \"help protx register_prepare\" for more info about creating a ProTx and a message to sign.\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n",
|
||||
+ HelpRequiringPassphrase() + "\n",
|
||||
{
|
||||
{"tx", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The serialized unsigned ProTx in hex format."},
|
||||
{"sig", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature signed with the collateral key. Must be in base64 format."},
|
||||
@ -430,29 +426,28 @@ static void protx_register_submit_help(CWallet* const pwallet)
|
||||
RPCExamples{
|
||||
HelpExampleCli("protx", "register_submit \"tx\" \"sig\"")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
// handles register, register_prepare and register_fund in one method
|
||||
static UniValue protx_register(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
bool isExternalRegister = request.params[0].get_str() == "register";
|
||||
bool isFundRegister = request.params[0].get_str() == "register_fund";
|
||||
bool isPrepareRegister = request.params[0].get_str() == "register_prepare";
|
||||
|
||||
if (isFundRegister && (request.fHelp || (request.params.size() < 8 || request.params.size() > 10))) {
|
||||
protx_register_fund_help(pwallet);
|
||||
protx_register_fund_help(request);
|
||||
} else if (isExternalRegister && (request.fHelp || (request.params.size() < 9 || request.params.size() > 11))) {
|
||||
protx_register_help(pwallet);
|
||||
protx_register_help(request);
|
||||
} else if (isPrepareRegister && (request.fHelp || (request.params.size() != 9 && request.params.size() != 10))) {
|
||||
protx_register_prepare_help();
|
||||
protx_register_prepare_help(request);
|
||||
}
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (isExternalRegister || isFundRegister) {
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
}
|
||||
@ -554,7 +549,7 @@ static UniValue protx_register(const JSONRPCRequest& request)
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(collateralIndex != (uint32_t) -1);
|
||||
CHECK_NONFATAL(collateralIndex != (uint32_t) -1);
|
||||
ptx.collateralOutpoint.n = collateralIndex;
|
||||
|
||||
SetTxPayload(tx, ptx);
|
||||
@ -598,15 +593,14 @@ static UniValue protx_register(const JSONRPCRequest& request)
|
||||
|
||||
static UniValue protx_register_submit(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || request.params.size() != 3) {
|
||||
protx_register_submit_help(pwallet);
|
||||
protx_register_submit_help(request);
|
||||
}
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
|
||||
CMutableTransaction tx;
|
||||
@ -630,14 +624,13 @@ static UniValue protx_register_submit(const JSONRPCRequest& request)
|
||||
return SignAndSendSpecialTx(tx);
|
||||
}
|
||||
|
||||
static void protx_update_service_help(CWallet* const pwallet)
|
||||
static void protx_update_service_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx update_service",
|
||||
"\nCreates and sends a ProUpServTx to the network. This will update the IP address\n"
|
||||
"of a masternode.\n"
|
||||
"If this is done for a masternode that got PoSe-banned, the ProUpServTx will also revive this masternode.\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n",
|
||||
+ HelpRequiringPassphrase() + "\n",
|
||||
{
|
||||
GetRpcArg("proTxHash"),
|
||||
GetRpcArg("ipAndPort"),
|
||||
@ -651,18 +644,17 @@ static void protx_update_service_help(CWallet* const pwallet)
|
||||
RPCExamples{
|
||||
HelpExampleCli("protx", "update_service \"0123456701234567012345670123456701234567012345670123456701234567\" \"1.2.3.4:1234\" 5a2e15982e62f1e0b7cf9783c64cf7e3af3f90a52d6c40f6f95d624c0b1621cd")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue protx_update_service(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || (request.params.size() < 4 || request.params.size() > 6))
|
||||
protx_update_service_help(pwallet);
|
||||
protx_update_service_help(request);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
|
||||
@ -729,14 +721,13 @@ static UniValue protx_update_service(const JSONRPCRequest& request)
|
||||
return SignAndSendSpecialTx(tx);
|
||||
}
|
||||
|
||||
static void protx_update_registrar_help(CWallet* const pwallet)
|
||||
static void protx_update_registrar_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx update_registrar",
|
||||
"\nCreates and sends a ProUpRegTx to the network. This will update the operator key, voting key and payout\n"
|
||||
"address of the masternode specified by \"proTxHash\".\n"
|
||||
"The owner key of the masternode must be known to your wallet.\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n",
|
||||
+ HelpRequiringPassphrase() + "\n",
|
||||
{
|
||||
GetRpcArg("proTxHash"),
|
||||
GetRpcArg("operatorPubKey_update"),
|
||||
@ -750,20 +741,19 @@ static void protx_update_registrar_help(CWallet* const pwallet)
|
||||
RPCExamples{
|
||||
HelpExampleCli("protx", "update_registrar \"0123456701234567012345670123456701234567012345670123456701234567\" \"982eb34b7c7f614f29e5c665bc3605f1beeef85e3395ca12d3be49d2868ecfea5566f11cedfad30c51b2403f2ad95b67\" \"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\"")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue protx_update_registrar(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || (request.params.size() != 5 && request.params.size() != 6)) {
|
||||
protx_update_registrar_help(pwallet);
|
||||
protx_update_registrar_help(request);
|
||||
}
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
|
||||
CProUpRegTx ptx;
|
||||
@ -821,15 +811,14 @@ static UniValue protx_update_registrar(const JSONRPCRequest& request)
|
||||
return SignAndSendSpecialTx(tx);
|
||||
}
|
||||
|
||||
static void protx_revoke_help(CWallet* const pwallet)
|
||||
static void protx_revoke_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx revoke",
|
||||
"\nCreates and sends a ProUpRevTx to the network. This will revoke the operator key of the masternode and\n"
|
||||
"put it into the PoSe-banned state. It will also set the service field of the masternode\n"
|
||||
"to zero. Use this in case your operator key got compromised or you want to stop providing your service\n"
|
||||
"to the masternode owner.\n"
|
||||
+ HelpRequiringPassphrase(pwallet) + "\n",
|
||||
+ HelpRequiringPassphrase() + "\n",
|
||||
{
|
||||
GetRpcArg("proTxHash"),
|
||||
GetRpcArg("operatorKey"),
|
||||
@ -842,20 +831,19 @@ static void protx_revoke_help(CWallet* const pwallet)
|
||||
RPCExamples{
|
||||
HelpExampleCli("protx", "revoke \"0123456701234567012345670123456701234567012345670123456701234567\" \"072f36a77261cdd5d64c32d97bac417540eddca1d5612f416feb07ff75a8e240\"")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue protx_revoke(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || (request.params.size() < 3 || request.params.size() > 5)) {
|
||||
protx_revoke_help(pwallet);
|
||||
protx_revoke_help(request);
|
||||
}
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
|
||||
CProUpRevTx ptx;
|
||||
@ -911,9 +899,8 @@ static UniValue protx_revoke(const JSONRPCRequest& request)
|
||||
}
|
||||
#endif//ENABLE_WALLET
|
||||
|
||||
static void protx_list_help()
|
||||
static void protx_list_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx list",
|
||||
"\nLists all ProTxs in your wallet or on-chain, depending on the given type.\n",
|
||||
{
|
||||
@ -932,7 +919,7 @@ static void protx_list_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WALLET
|
||||
@ -1003,14 +990,19 @@ static UniValue BuildDMNListEntry(CWallet* pwallet, const CDeterministicMN& dmn,
|
||||
static UniValue protx_list(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp) {
|
||||
protx_list_help();
|
||||
protx_list_help(request);
|
||||
}
|
||||
|
||||
CWallet* pwallet;
|
||||
#ifdef ENABLE_WALLET
|
||||
try {
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
pwallet = wallet.get();
|
||||
} catch (...) {
|
||||
pwallet = nullptr;
|
||||
}
|
||||
#else
|
||||
CWallet* const pwallet = nullptr;
|
||||
pwallet = nullptr;
|
||||
#endif
|
||||
|
||||
std::string type = "registered";
|
||||
@ -1032,7 +1024,7 @@ static UniValue protx_list(const JSONRPCRequest& request)
|
||||
LOCK2(cs_main, pwallet->cs_wallet);
|
||||
|
||||
if (request.params.size() > 4) {
|
||||
protx_list_help();
|
||||
protx_list_help(request);
|
||||
}
|
||||
|
||||
bool detailed = !request.params[2].isNull() ? ParseBoolV(request.params[2], "detailed") : false;
|
||||
@ -1062,7 +1054,7 @@ static UniValue protx_list(const JSONRPCRequest& request)
|
||||
#endif
|
||||
} else if (type == "valid" || type == "registered") {
|
||||
if (request.params.size() > 4) {
|
||||
protx_list_help();
|
||||
protx_list_help(request);
|
||||
}
|
||||
|
||||
LOCK(cs_main);
|
||||
@ -1086,9 +1078,8 @@ static UniValue protx_list(const JSONRPCRequest& request)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void protx_info_help()
|
||||
static void protx_info_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx info",
|
||||
"\nReturns detailed information about a deterministic masternode.\n",
|
||||
{
|
||||
@ -1101,20 +1092,25 @@ static void protx_info_help()
|
||||
RPCExamples{
|
||||
HelpExampleCli("protx", "info \"0123456701234567012345670123456701234567012345670123456701234567\"")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue protx_info(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 2) {
|
||||
protx_info_help();
|
||||
protx_info_help(request);
|
||||
}
|
||||
|
||||
CWallet* pwallet;
|
||||
#ifdef ENABLE_WALLET
|
||||
try {
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
pwallet = wallet.get();
|
||||
} catch (...) {
|
||||
pwallet = nullptr;
|
||||
}
|
||||
#else
|
||||
CWallet* const pwallet = nullptr;
|
||||
pwallet = nullptr;
|
||||
#endif
|
||||
|
||||
if (g_txindex) {
|
||||
@ -1130,9 +1126,8 @@ static UniValue protx_info(const JSONRPCRequest& request)
|
||||
return BuildDMNListEntry(pwallet, *dmn, true);
|
||||
}
|
||||
|
||||
static void protx_diff_help()
|
||||
static void protx_diff_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx diff",
|
||||
"\nCalculates a diff between two deterministic masternode lists. The result also contains proof data.\n",
|
||||
{
|
||||
@ -1141,7 +1136,7 @@ static void protx_diff_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static uint256 ParseBlock(const UniValue& v, std::string strName) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
@ -1161,7 +1156,7 @@ static uint256 ParseBlock(const UniValue& v, std::string strName) EXCLUSIVE_LOCK
|
||||
static UniValue protx_diff(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 3) {
|
||||
protx_diff_help();
|
||||
protx_diff_help(request);
|
||||
}
|
||||
|
||||
LOCK(cs_main);
|
||||
@ -1181,7 +1176,6 @@ static UniValue protx_diff(const JSONRPCRequest& request)
|
||||
|
||||
[[ noreturn ]] static void protx_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"protx",
|
||||
"Set of commands to execute ProTx related actions.\n"
|
||||
"To get help on individual commands, use \"help protx command\".\n"
|
||||
@ -1205,7 +1199,7 @@ static UniValue protx_diff(const JSONRPCRequest& request)
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Throw();
|
||||
}
|
||||
|
||||
static UniValue protx(const JSONRPCRequest& request)
|
||||
@ -1243,9 +1237,8 @@ static UniValue protx(const JSONRPCRequest& request)
|
||||
}
|
||||
}
|
||||
|
||||
static void bls_generate_help()
|
||||
static void bls_generate_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"bls generate",
|
||||
"\nReturns a BLS secret/public key pair.\n",
|
||||
{},
|
||||
@ -1258,13 +1251,13 @@ static void bls_generate_help()
|
||||
RPCExamples{
|
||||
HelpExampleCli("bls generate", "")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue bls_generate(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 1) {
|
||||
bls_generate_help();
|
||||
bls_generate_help(request);
|
||||
}
|
||||
|
||||
CBLSSecretKey sk;
|
||||
@ -1276,9 +1269,8 @@ static UniValue bls_generate(const JSONRPCRequest& request)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void bls_fromsecret_help()
|
||||
static void bls_fromsecret_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"bls fromsecret",
|
||||
"\nParses a BLS secret key and returns the secret/public key pair.\n",
|
||||
{
|
||||
@ -1293,13 +1285,13 @@ static void bls_fromsecret_help()
|
||||
RPCExamples{
|
||||
HelpExampleCli("bls fromsecret", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue bls_fromsecret(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 2) {
|
||||
bls_fromsecret_help();
|
||||
bls_fromsecret_help(request);
|
||||
}
|
||||
|
||||
CBLSSecretKey sk;
|
||||
@ -1315,7 +1307,6 @@ static UniValue bls_fromsecret(const JSONRPCRequest& request)
|
||||
|
||||
[[ noreturn ]] static void bls_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"bls",
|
||||
"Set of commands to execute BLS related actions.\n"
|
||||
"To get help on individual commands, use \"help bls command\".\n"
|
||||
@ -1327,7 +1318,7 @@ static UniValue bls_fromsecret(const JSONRPCRequest& request)
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Throw();
|
||||
}
|
||||
|
||||
static UniValue _bls(const JSONRPCRequest& request)
|
||||
|
@ -23,9 +23,8 @@ namespace llmq {
|
||||
extern const std::string CLSIG_REQUESTID_PREFIX;
|
||||
}
|
||||
|
||||
static void quorum_list_help()
|
||||
static void quorum_list_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum list",
|
||||
"List of on-chain quorums\n",
|
||||
{
|
||||
@ -44,13 +43,13 @@ static void quorum_list_help()
|
||||
+ HelpExampleCli("quorum", "list 10")
|
||||
+ HelpExampleRpc("quorum", "list, 10")
|
||||
},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue quorum_list(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2))
|
||||
quorum_list_help();
|
||||
quorum_list_help(request);
|
||||
|
||||
int count = -1;
|
||||
if (!request.params[1].isNull()) {
|
||||
@ -80,9 +79,8 @@ static UniValue quorum_list(const JSONRPCRequest& request)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void quorum_info_help()
|
||||
static void quorum_info_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum info",
|
||||
"Return information about a quorum\n",
|
||||
{
|
||||
@ -92,7 +90,7 @@ static void quorum_info_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue BuildQuorumInfo(const llmq::CQuorumCPtr& quorum, bool includeMembers, bool includeSkShare)
|
||||
@ -134,7 +132,7 @@ static UniValue BuildQuorumInfo(const llmq::CQuorumCPtr& quorum, bool includeMem
|
||||
static UniValue quorum_info(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || (request.params.size() != 3 && request.params.size() != 4))
|
||||
quorum_info_help();
|
||||
quorum_info_help(request);
|
||||
|
||||
Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[1], "llmqType");
|
||||
if (!Params().HasLLMQ(llmqType)) {
|
||||
@ -155,9 +153,8 @@ static UniValue quorum_info(const JSONRPCRequest& request)
|
||||
return BuildQuorumInfo(quorum, true, includeSkShare);
|
||||
}
|
||||
|
||||
static void quorum_dkgstatus_help()
|
||||
static void quorum_dkgstatus_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum dkgstatus",
|
||||
"Return the status of the current DKG process.\n"
|
||||
"Works only when SPORK_17_QUORUM_DKG_ENABLED spork is ON.\n",
|
||||
@ -168,13 +165,13 @@ static void quorum_dkgstatus_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue quorum_dkgstatus(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || (request.params.size() < 1 || request.params.size() > 2)) {
|
||||
quorum_dkgstatus_help();
|
||||
quorum_dkgstatus_help(request);
|
||||
}
|
||||
|
||||
int detailLevel = 0;
|
||||
@ -241,9 +238,8 @@ static UniValue quorum_dkgstatus(const JSONRPCRequest& request)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void quorum_memberof_help()
|
||||
static void quorum_memberof_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum memberof",
|
||||
"Checks which quorums the given masternode is a member of.\n",
|
||||
{
|
||||
@ -254,13 +250,13 @@ static void quorum_memberof_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue quorum_memberof(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || (request.params.size() < 2 || request.params.size() > 3)) {
|
||||
quorum_memberof_help();
|
||||
quorum_memberof_help(request);
|
||||
}
|
||||
|
||||
uint256 protxHash = ParseHashV(request.params[1], "proTxHash");
|
||||
@ -302,9 +298,8 @@ static UniValue quorum_memberof(const JSONRPCRequest& request)
|
||||
return result;
|
||||
}
|
||||
|
||||
static void quorum_sign_help()
|
||||
static void quorum_sign_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum sign",
|
||||
"Threshold-sign a message\n",
|
||||
{
|
||||
@ -318,12 +313,11 @@ static void quorum_sign_help()
|
||||
"\nReturns an object containing the signature share if this is false.\n"
|
||||
},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static void quorum_verify_help()
|
||||
static void quorum_verify_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum verify",
|
||||
"Test if a quorum signature is valid for a request id and a message hash\n",
|
||||
{
|
||||
@ -340,12 +334,11 @@ static void quorum_verify_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static void quorum_hasrecsig_help()
|
||||
static void quorum_hasrecsig_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum hasrecsig",
|
||||
"Test if a valid recovered signature is present\n",
|
||||
{
|
||||
@ -355,12 +348,11 @@ static void quorum_hasrecsig_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static void quorum_getrecsig_help()
|
||||
static void quorum_getrecsig_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum getrecsig",
|
||||
"Get a recovered signature\n",
|
||||
{
|
||||
@ -370,12 +362,11 @@ static void quorum_getrecsig_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static void quorum_isconflicting_help()
|
||||
static void quorum_isconflicting_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum isconflicting",
|
||||
"Test if a conflict exists\n",
|
||||
{
|
||||
@ -385,7 +376,7 @@ static void quorum_isconflicting_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue quorum_sigs_cmd(const JSONRPCRequest& request)
|
||||
@ -394,18 +385,18 @@ static UniValue quorum_sigs_cmd(const JSONRPCRequest& request)
|
||||
if (request.fHelp || (request.params.size() != 4)) {
|
||||
if (cmd == "sign") {
|
||||
if ((request.params.size() < 4) || (request.params.size() > 6)) {
|
||||
quorum_sign_help();
|
||||
quorum_sign_help(request);
|
||||
}
|
||||
} else if (cmd == "verify") {
|
||||
if (request.params.size() < 5 || request.params.size() > 7) {
|
||||
quorum_verify_help();
|
||||
quorum_verify_help(request);
|
||||
}
|
||||
} else if (cmd == "hasrecsig") {
|
||||
quorum_hasrecsig_help();
|
||||
quorum_hasrecsig_help(request);
|
||||
} else if (cmd == "getrecsig") {
|
||||
quorum_getrecsig_help();
|
||||
quorum_getrecsig_help(request);
|
||||
} else if (cmd == "isconflicting") {
|
||||
quorum_isconflicting_help();
|
||||
quorum_isconflicting_help(request);
|
||||
} else {
|
||||
// shouldn't happen as it's already handled by the caller
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid cmd");
|
||||
@ -507,9 +498,8 @@ static UniValue quorum_sigs_cmd(const JSONRPCRequest& request)
|
||||
}
|
||||
}
|
||||
|
||||
static void quorum_selectquorum_help()
|
||||
static void quorum_selectquorum_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum selectquorum",
|
||||
"Returns the quorum that would/should sign a request\n",
|
||||
{
|
||||
@ -518,13 +508,13 @@ static void quorum_selectquorum_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue quorum_selectquorum(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 3) {
|
||||
quorum_selectquorum_help();
|
||||
quorum_selectquorum_help(request);
|
||||
}
|
||||
|
||||
Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[1], "llmqType");
|
||||
@ -552,9 +542,8 @@ static UniValue quorum_selectquorum(const JSONRPCRequest& request)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void quorum_dkgsimerror_help()
|
||||
static void quorum_dkgsimerror_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum dkgsimerror",
|
||||
"This enables simulation of errors and malicious behaviour in the DKG. Do NOT use this on mainnet\n"
|
||||
"as you will get yourself very likely PoSe banned for this.\n",
|
||||
@ -564,13 +553,13 @@ static void quorum_dkgsimerror_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue quorum_dkgsimerror(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || (request.params.size() != 3)) {
|
||||
quorum_dkgsimerror_help();
|
||||
quorum_dkgsimerror_help(request);
|
||||
}
|
||||
|
||||
std::string type = request.params[1].get_str();
|
||||
@ -585,9 +574,8 @@ static UniValue quorum_dkgsimerror(const JSONRPCRequest& request)
|
||||
return UniValue();
|
||||
}
|
||||
|
||||
static void quorum_getdata_help()
|
||||
static void quorum_getdata_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum getdata",
|
||||
"Send a QGETDATA message to the specified peer.\n",
|
||||
{
|
||||
@ -603,13 +591,13 @@ static void quorum_getdata_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue quorum_getdata(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || (request.params.size() < 5 || request.params.size() > 6)) {
|
||||
quorum_getdata_help();
|
||||
quorum_getdata_help(request);
|
||||
}
|
||||
|
||||
NodeId nodeId = ParseInt64V(request.params[1], "nodeId");
|
||||
@ -639,7 +627,6 @@ static UniValue quorum_getdata(const JSONRPCRequest& request)
|
||||
|
||||
[[ noreturn ]] static void quorum_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"quorum",
|
||||
"Set of commands for quorums/LLMQs.\n"
|
||||
"To get help on individual commands, use \"help quorum command\".\n"
|
||||
@ -661,7 +648,7 @@ static UniValue quorum_getdata(const JSONRPCRequest& request)
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Throw();
|
||||
}
|
||||
|
||||
static UniValue _quorum(const JSONRPCRequest& request)
|
||||
@ -696,9 +683,8 @@ static UniValue _quorum(const JSONRPCRequest& request)
|
||||
}
|
||||
}
|
||||
|
||||
static void verifychainlock_help()
|
||||
static void verifychainlock_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"verifychainlock",
|
||||
"Test if a quorum signature is valid for a ChainLock.\n",
|
||||
{
|
||||
@ -708,13 +694,13 @@ static void verifychainlock_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue verifychainlock(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) {
|
||||
verifychainlock_help();
|
||||
verifychainlock_help(request);
|
||||
}
|
||||
|
||||
const uint256 nBlockHash = ParseHashV(request.params[0], "blockHash");
|
||||
@ -740,9 +726,8 @@ static UniValue verifychainlock(const JSONRPCRequest& request)
|
||||
return llmq::CSigningManager::VerifyRecoveredSig(llmqType, nBlockHeight, nRequestId, nBlockHash, chainLockSig);
|
||||
}
|
||||
|
||||
static void verifyislock_help()
|
||||
static void verifyislock_help(const JSONRPCRequest& request)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"verifyislock",
|
||||
"Test if a quorum signature is valid for an InstantSend Lock\n",
|
||||
{
|
||||
@ -753,13 +738,13 @@ static void verifyislock_help()
|
||||
},
|
||||
RPCResults{},
|
||||
RPCExamples{""},
|
||||
}.ToString());
|
||||
}.Check(request);
|
||||
}
|
||||
|
||||
static UniValue verifyislock(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() < 3 || request.params.size() > 4) {
|
||||
verifyislock_help();
|
||||
verifyislock_help(request);
|
||||
}
|
||||
|
||||
uint256 id = ParseHashV(request.params[0], "id");
|
||||
|
@ -161,7 +161,7 @@ UniValue help(const JSONRPCRequest& jsonRequest)
|
||||
{"subcommand", RPCArg::Type::STR, /* default */ "all subcommands", "The subcommand to get help on. Please note that not all subcommands support this at the moment"},
|
||||
},
|
||||
RPCResult{
|
||||
"\"text\" (string) The help text\n"
|
||||
RPCResult::Type::STR, "", "The help text"
|
||||
},
|
||||
RPCExamples{""},
|
||||
}.ToString()
|
||||
@ -208,7 +208,7 @@ static UniValue uptime(const JSONRPCRequest& jsonRequest)
|
||||
"\nReturns the total uptime of the server.\n",
|
||||
{},
|
||||
RPCResult{
|
||||
"ttt (numeric) The number of seconds that the server has been running\n"
|
||||
RPCResult::Type::NUM, "", "The number of seconds that the server has been running"
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("uptime", "")
|
||||
@ -341,41 +341,6 @@ bool RPCIsInWarmup(std::string *outStatus)
|
||||
return fRPCInWarmup;
|
||||
}
|
||||
|
||||
void JSONRPCRequest::parse(const UniValue& valRequest)
|
||||
{
|
||||
// Parse request
|
||||
if (!valRequest.isObject())
|
||||
throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
|
||||
const UniValue& request = valRequest.get_obj();
|
||||
|
||||
// Parse id now so errors from here on will have the id
|
||||
id = find_value(request, "id");
|
||||
|
||||
// Parse method
|
||||
UniValue valMethod = find_value(request, "method");
|
||||
if (valMethod.isNull())
|
||||
throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
|
||||
if (!valMethod.isStr())
|
||||
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
|
||||
strMethod = valMethod.get_str();
|
||||
if (strMethod != "getblocktemplate") {
|
||||
if (fLogIPs)
|
||||
LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n", SanitizeString(strMethod),
|
||||
this->authUser, this->peerAddr);
|
||||
else
|
||||
LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);
|
||||
}
|
||||
|
||||
// Parse params
|
||||
UniValue valParams = find_value(request, "params");
|
||||
if (valParams.isArray() || valParams.isObject())
|
||||
params = valParams;
|
||||
else if (valParams.isNull())
|
||||
params = UniValue(UniValue::VARR);
|
||||
else
|
||||
throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object");
|
||||
}
|
||||
|
||||
bool IsDeprecatedRPCEnabled(const std::string& method)
|
||||
{
|
||||
const std::vector<std::string> enabled_methods = gArgs.GetArgs("-deprecatedrpc");
|
||||
|
@ -7,11 +7,13 @@
|
||||
#define BITCOIN_RPC_SERVER_H
|
||||
|
||||
#include <amount.h>
|
||||
#include <rpc/protocol.h>
|
||||
#include <rpc/request.h>
|
||||
#include <rpc/util.h>
|
||||
|
||||
#include <map>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
@ -23,21 +25,6 @@ namespace RPCServer
|
||||
void OnStopped(std::function<void ()> slot);
|
||||
}
|
||||
|
||||
class JSONRPCRequest
|
||||
{
|
||||
public:
|
||||
UniValue id;
|
||||
std::string strMethod;
|
||||
UniValue params;
|
||||
bool fHelp;
|
||||
std::string URI;
|
||||
std::string authUser;
|
||||
std::string peerAddr;
|
||||
|
||||
JSONRPCRequest() : id(NullUniValue), params(NullUniValue), fHelp(false) {}
|
||||
void parse(const UniValue& valRequest);
|
||||
};
|
||||
|
||||
/** Query whether RPC is running */
|
||||
bool IsRPCRunning();
|
||||
|
||||
@ -94,6 +81,7 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface);
|
||||
void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nSeconds);
|
||||
|
||||
typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest);
|
||||
typedef RPCHelpMan (*RpcMethodFnType)();
|
||||
|
||||
class CRPCCommand
|
||||
{
|
||||
@ -110,6 +98,19 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
//! Simplified constructor taking plain RpcMethodFnType function pointer.
|
||||
CRPCCommand(std::string category, std::string name_in, RpcMethodFnType fn, std::vector<std::string> args_in)
|
||||
: CRPCCommand(
|
||||
category,
|
||||
fn().m_name,
|
||||
[fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn().HandleRequest(request); return true; },
|
||||
fn().GetArgNames(),
|
||||
intptr_t(fn))
|
||||
{
|
||||
CHECK_NONFATAL(fn().m_name == name_in);
|
||||
CHECK_NONFATAL(fn().GetArgNames() == args_in);
|
||||
}
|
||||
|
||||
//! Simplified constructor taking plain rpcfn_type function pointer.
|
||||
CRPCCommand(const char* category, const char* name, rpcfn_type fn, std::initializer_list<const char*> args)
|
||||
: CRPCCommand(category, name,
|
||||
@ -126,7 +127,7 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Dash RPC command dispatcher.
|
||||
* RPC command dispatcher.
|
||||
*/
|
||||
class CRPCTable
|
||||
{
|
||||
|
217
src/rpc/util.cpp
217
src/rpc/util.cpp
@ -13,6 +13,9 @@
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
||||
InitInterfaces* g_rpc_interfaces = nullptr;
|
||||
|
||||
void RPCTypeCheck(const UniValue& params,
|
||||
@ -263,13 +266,21 @@ unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target)
|
||||
return (unsigned int)target;
|
||||
}
|
||||
|
||||
/**
|
||||
* A pair of strings that can be aligned (through padding) with other Sections
|
||||
* later on
|
||||
*/
|
||||
struct Section {
|
||||
Section(const std::string& left, const std::string& right)
|
||||
: m_left{left}, m_right{right} {}
|
||||
const std::string m_left;
|
||||
std::string m_left;
|
||||
const std::string m_right;
|
||||
};
|
||||
|
||||
/**
|
||||
* Keeps track of RPCArgs by transforming them into sections for the purpose
|
||||
* of serializing everything to a single string
|
||||
*/
|
||||
struct Sections {
|
||||
std::vector<Section> m_sections;
|
||||
size_t m_max_pad{0};
|
||||
@ -280,16 +291,15 @@ struct Sections {
|
||||
m_sections.push_back(s);
|
||||
}
|
||||
|
||||
enum class OuterType {
|
||||
ARR,
|
||||
OBJ,
|
||||
NAMED_ARG, // Only set on first recursion
|
||||
};
|
||||
|
||||
void Push(const RPCArg& arg, const size_t current_indent = 5, const OuterType outer_type = OuterType::NAMED_ARG)
|
||||
/**
|
||||
* Recursive helper to translate an RPCArg into sections
|
||||
*/
|
||||
void Push(const RPCArg& arg, const size_t current_indent = 5, const OuterType outer_type = OuterType::NONE)
|
||||
{
|
||||
const auto indent = std::string(current_indent, ' ');
|
||||
const auto indent_next = std::string(current_indent + 2, ' ');
|
||||
const bool push_name{outer_type == OuterType::OBJ}; // Dictionary keys must have a name
|
||||
|
||||
switch (arg.m_type) {
|
||||
case RPCArg::Type::STR_HEX:
|
||||
case RPCArg::Type::STR:
|
||||
@ -297,12 +307,12 @@ struct Sections {
|
||||
case RPCArg::Type::AMOUNT:
|
||||
case RPCArg::Type::RANGE:
|
||||
case RPCArg::Type::BOOL: {
|
||||
if (outer_type == OuterType::NAMED_ARG) return; // Nothing more to do for non-recursive types on first recursion
|
||||
if (outer_type == OuterType::NONE) return; // Nothing more to do for non-recursive types on first recursion
|
||||
auto left = indent;
|
||||
if (arg.m_type_str.size() != 0 && outer_type == OuterType::OBJ) {
|
||||
left += "\"" + arg.m_name + "\": " + arg.m_type_str.at(0);
|
||||
if (arg.m_type_str.size() != 0 && push_name) {
|
||||
left += "\"" + arg.GetName() + "\": " + arg.m_type_str.at(0);
|
||||
} else {
|
||||
left += outer_type == OuterType::OBJ ? arg.ToStringObj(/* oneline */ false) : arg.ToString(/* oneline */ false);
|
||||
left += push_name ? arg.ToStringObj(/* oneline */ false) : arg.ToString(/* oneline */ false);
|
||||
}
|
||||
left += ",";
|
||||
PushSection({left, arg.ToDescriptionString()});
|
||||
@ -310,40 +320,44 @@ struct Sections {
|
||||
}
|
||||
case RPCArg::Type::OBJ:
|
||||
case RPCArg::Type::OBJ_USER_KEYS: {
|
||||
const auto right = outer_type == OuterType::NAMED_ARG ? "" : arg.ToDescriptionString();
|
||||
PushSection({indent + "{", right});
|
||||
const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
|
||||
PushSection({indent + (push_name ? "\"" + arg.GetName() + "\": " : "") + "{", right});
|
||||
for (const auto& arg_inner : arg.m_inner) {
|
||||
Push(arg_inner, current_indent + 2, OuterType::OBJ);
|
||||
}
|
||||
if (arg.m_type != RPCArg::Type::OBJ) {
|
||||
PushSection({indent_next + "...", ""});
|
||||
}
|
||||
PushSection({indent + "}" + (outer_type != OuterType::NAMED_ARG ? "," : ""), ""});
|
||||
PushSection({indent + "}" + (outer_type != OuterType::NONE ? "," : ""), ""});
|
||||
break;
|
||||
}
|
||||
case RPCArg::Type::ARR: {
|
||||
auto left = indent;
|
||||
left += outer_type == OuterType::OBJ ? "\"" + arg.m_name + "\": " : "";
|
||||
left += push_name ? "\"" + arg.GetName() + "\": " : "";
|
||||
left += "[";
|
||||
const auto right = outer_type == OuterType::NAMED_ARG ? "" : arg.ToDescriptionString();
|
||||
const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
|
||||
PushSection({left, right});
|
||||
for (const auto& arg_inner : arg.m_inner) {
|
||||
Push(arg_inner, current_indent + 2, OuterType::ARR);
|
||||
}
|
||||
PushSection({indent_next + "...", ""});
|
||||
PushSection({indent + "]" + (outer_type != OuterType::NAMED_ARG ? "," : ""), ""});
|
||||
PushSection({indent + "]" + (outer_type != OuterType::NONE ? "," : ""), ""});
|
||||
break;
|
||||
}
|
||||
|
||||
// no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
} // no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate all sections with proper padding
|
||||
*/
|
||||
std::string ToString() const
|
||||
{
|
||||
std::string ret;
|
||||
const size_t pad = m_max_pad + 4;
|
||||
for (const auto& s : m_sections) {
|
||||
// The left part of a section is assumed to be a single line, usually it is the name of the JSON struct or a
|
||||
// brace like {, }, [, or ]
|
||||
CHECK_NONFATAL(s.m_left.find('\n') == std::string::npos);
|
||||
if (s.m_right.empty()) {
|
||||
ret += s.m_left;
|
||||
ret += "\n";
|
||||
@ -378,7 +392,11 @@ struct Sections {
|
||||
};
|
||||
|
||||
RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples)
|
||||
: RPCHelpMan{std::move(name), std::move(description), std::move(args), std::move(results), std::move(examples), nullptr} {}
|
||||
|
||||
RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples, RPCMethodImpl fun)
|
||||
: m_name{std::move(name)},
|
||||
m_fun{std::move(fun)},
|
||||
m_description{std::move(description)},
|
||||
m_args{std::move(args)},
|
||||
m_results{std::move(results)},
|
||||
@ -386,8 +404,12 @@ RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector<RP
|
||||
{
|
||||
std::set<std::string> named_args;
|
||||
for (const auto& arg : m_args) {
|
||||
std::vector<std::string> names;
|
||||
boost::split(names, arg.m_names, boost::is_any_of("|"));
|
||||
// Should have unique named arguments
|
||||
assert(named_args.insert(arg.m_name).second);
|
||||
for (const std::string& name : names) {
|
||||
CHECK_NONFATAL(named_args.insert(name).second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -400,7 +422,13 @@ std::string RPCResults::ToDescriptionString() const
|
||||
} else {
|
||||
result += "\nResult (" + r.m_cond + "):\n";
|
||||
}
|
||||
if (r.m_legacy) {
|
||||
result += r.m_result;
|
||||
} else {
|
||||
Sections sections;
|
||||
r.ToSections(sections);
|
||||
result += sections.ToString();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -421,6 +449,16 @@ bool RPCHelpMan::IsValidNumArgs(size_t num_args) const
|
||||
}
|
||||
return num_required_args <= num_args && num_args <= m_args.size();
|
||||
}
|
||||
|
||||
std::vector<std::string> RPCHelpMan::GetArgNames() const
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
for (const auto& arg : m_args) {
|
||||
ret.emplace_back(arg.m_names);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string RPCHelpMan::ToString() const
|
||||
{
|
||||
std::string ret;
|
||||
@ -429,6 +467,7 @@ std::string RPCHelpMan::ToString() const
|
||||
ret += m_name;
|
||||
bool was_optional{false};
|
||||
for (const auto& arg : m_args) {
|
||||
if (arg.m_hidden) continue;
|
||||
const bool optional = arg.IsOptional();
|
||||
ret += " ";
|
||||
if (optional) {
|
||||
@ -450,11 +489,12 @@ std::string RPCHelpMan::ToString() const
|
||||
Sections sections;
|
||||
for (size_t i{0}; i < m_args.size(); ++i) {
|
||||
const auto& arg = m_args.at(i);
|
||||
if (arg.m_hidden) continue;
|
||||
|
||||
if (i == 0) ret += "\nArguments:\n";
|
||||
|
||||
// Push named argument name and description
|
||||
sections.m_sections.emplace_back(std::to_string(i + 1) + ". " + arg.m_name, arg.ToDescriptionString());
|
||||
sections.m_sections.emplace_back(std::to_string(i + 1) + ". " + arg.GetFirstName(), arg.ToDescriptionString());
|
||||
sections.m_max_pad = std::max(sections.m_max_pad, sections.m_sections.back().m_left.size());
|
||||
|
||||
// Recursively push nested args
|
||||
@ -471,6 +511,17 @@ std::string RPCHelpMan::ToString() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string RPCArg::GetFirstName() const
|
||||
{
|
||||
return m_names.substr(0, m_names.find("|"));
|
||||
}
|
||||
|
||||
std::string RPCArg::GetName() const
|
||||
{
|
||||
CHECK_NONFATAL(std::string::npos == m_names.find("|"));
|
||||
return m_names;
|
||||
}
|
||||
|
||||
bool RPCArg::IsOptional() const
|
||||
{
|
||||
if (m_fallback.which() == 1) {
|
||||
@ -518,9 +569,7 @@ std::string RPCArg::ToDescriptionString() const
|
||||
ret += "json array";
|
||||
break;
|
||||
}
|
||||
|
||||
// no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
} // no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
if (m_fallback.which() == 1) {
|
||||
ret += ", optional, default=" + boost::get<std::string>(m_fallback);
|
||||
@ -538,20 +587,110 @@ std::string RPCArg::ToDescriptionString() const
|
||||
ret += ", required";
|
||||
break;
|
||||
}
|
||||
|
||||
// no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
} // no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
ret += ")";
|
||||
ret += m_description.empty() ? "" : " " + m_description;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const int current_indent) const
|
||||
{
|
||||
// Indentation
|
||||
const std::string indent(current_indent, ' ');
|
||||
const std::string indent_next(current_indent + 2, ' ');
|
||||
|
||||
// Elements in a JSON structure (dictionary or array) are separated by a comma
|
||||
const std::string maybe_separator{outer_type != OuterType::NONE ? "," : ""};
|
||||
|
||||
// The key name if recursed into an dictionary
|
||||
const std::string maybe_key{
|
||||
outer_type == OuterType::OBJ ?
|
||||
"\"" + this->m_key_name + "\" : " :
|
||||
""};
|
||||
|
||||
// Format description with type
|
||||
const auto Description = [&](const std::string& type) {
|
||||
return "(" + type + (this->m_optional ? ", optional" : "") + ")" +
|
||||
(this->m_description.empty() ? "" : " " + this->m_description);
|
||||
};
|
||||
|
||||
switch (m_type) {
|
||||
case Type::ELISION: {
|
||||
// If the inner result is empty, use three dots for elision
|
||||
sections.PushSection({indent_next + "...", m_description});
|
||||
return;
|
||||
}
|
||||
case Type::NONE: {
|
||||
sections.PushSection({indent + "None", Description("json null")});
|
||||
return;
|
||||
}
|
||||
case Type::STR: {
|
||||
sections.PushSection({indent + maybe_key + "\"str\"" + maybe_separator, Description("string")});
|
||||
return;
|
||||
}
|
||||
case Type::STR_AMOUNT: {
|
||||
sections.PushSection({indent + maybe_key + "n" + maybe_separator, Description("numeric")});
|
||||
return;
|
||||
}
|
||||
case Type::STR_HEX: {
|
||||
sections.PushSection({indent + maybe_key + "\"hex\"" + maybe_separator, Description("string")});
|
||||
return;
|
||||
}
|
||||
case Type::NUM: {
|
||||
sections.PushSection({indent + maybe_key + "n" + maybe_separator, Description("numeric")});
|
||||
return;
|
||||
}
|
||||
case Type::NUM_TIME: {
|
||||
sections.PushSection({indent + maybe_key + "xxx" + maybe_separator, Description("numeric")});
|
||||
return;
|
||||
}
|
||||
case Type::BOOL: {
|
||||
sections.PushSection({indent + maybe_key + "true|false" + maybe_separator, Description("boolean")});
|
||||
return;
|
||||
}
|
||||
case Type::ARR_FIXED:
|
||||
case Type::ARR: {
|
||||
sections.PushSection({indent + maybe_key + "[", Description("json array")});
|
||||
for (const auto& i : m_inner) {
|
||||
i.ToSections(sections, OuterType::ARR, current_indent + 2);
|
||||
}
|
||||
if (m_type == Type::ARR) {
|
||||
sections.PushSection({indent_next + "...", ""});
|
||||
} else {
|
||||
CHECK_NONFATAL(!m_inner.empty());
|
||||
// Remove final comma, which would be invalid JSON
|
||||
sections.m_sections.back().m_left.pop_back();
|
||||
}
|
||||
sections.PushSection({indent + "]" + maybe_separator, ""});
|
||||
return;
|
||||
}
|
||||
case Type::OBJ_DYN:
|
||||
case Type::OBJ: {
|
||||
sections.PushSection({indent + maybe_key + "{", Description("json object")});
|
||||
for (const auto& i : m_inner) {
|
||||
i.ToSections(sections, OuterType::OBJ, current_indent + 2);
|
||||
}
|
||||
if (m_type == Type::OBJ_DYN) {
|
||||
// If the dictionary keys are dynamic, use three dots for continuation
|
||||
sections.PushSection({indent_next + "...", ""});
|
||||
} else {
|
||||
CHECK_NONFATAL(!m_inner.empty());
|
||||
// Remove final comma, which would be invalid JSON
|
||||
sections.m_sections.back().m_left.pop_back();
|
||||
}
|
||||
sections.PushSection({indent + "}" + maybe_separator, ""});
|
||||
return;
|
||||
}
|
||||
} // no default case, so the compiler can warn about missing cases
|
||||
CHECK_NONFATAL(false);
|
||||
}
|
||||
|
||||
std::string RPCArg::ToStringObj(const bool oneline) const
|
||||
{
|
||||
std::string res;
|
||||
res += "\"";
|
||||
res += m_name;
|
||||
res += GetFirstName();
|
||||
if (oneline) {
|
||||
res += "\":";
|
||||
} else {
|
||||
@ -579,11 +718,9 @@ 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);
|
||||
|
||||
// no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
assert(false);
|
||||
CHECK_NONFATAL(false);
|
||||
} // no default case, so the compiler can warn about missing cases
|
||||
CHECK_NONFATAL(false);
|
||||
}
|
||||
|
||||
std::string RPCArg::ToString(const bool oneline) const
|
||||
@ -593,13 +730,13 @@ std::string RPCArg::ToString(const bool oneline) const
|
||||
switch (m_type) {
|
||||
case Type::STR_HEX:
|
||||
case Type::STR: {
|
||||
return "\"" + m_name + "\"";
|
||||
return "\"" + GetFirstName() + "\"";
|
||||
}
|
||||
case Type::NUM:
|
||||
case Type::RANGE:
|
||||
case Type::AMOUNT:
|
||||
case Type::BOOL: {
|
||||
return m_name;
|
||||
return GetFirstName();
|
||||
}
|
||||
case Type::OBJ:
|
||||
case Type::OBJ_USER_KEYS: {
|
||||
@ -621,10 +758,8 @@ std::string RPCArg::ToString(const bool oneline) const
|
||||
}
|
||||
return "[" + res + "...]";
|
||||
}
|
||||
|
||||
// no default case, so the compiler can warn about missing cases
|
||||
}
|
||||
assert(false);
|
||||
} // no default case, so the compiler can warn about missing cases
|
||||
CHECK_NONFATAL(false);
|
||||
}
|
||||
|
||||
static std::pair<int64_t, int64_t> ParseRange(const UniValue& value)
|
||||
|
222
src/rpc/util.h
222
src/rpc/util.h
@ -6,11 +6,13 @@
|
||||
#define BITCOIN_RPC_UTIL_H
|
||||
|
||||
#include <node/transaction.h>
|
||||
#include <pubkey.h>
|
||||
#include <protocol.h>
|
||||
#include <pubkey.h>
|
||||
#include <rpc/protocol.h>
|
||||
#include <rpc/request.h>
|
||||
#include <script/standard.h>
|
||||
#include <univalue.h>
|
||||
#include <util/check.h>
|
||||
#include <util/strencodings.h>
|
||||
|
||||
#include <string>
|
||||
@ -21,6 +23,7 @@
|
||||
class CKeyStore;
|
||||
class CPubKey;
|
||||
class CScript;
|
||||
struct Sections;
|
||||
struct InitInterfaces;
|
||||
|
||||
//! Pointers to interfaces that need to be accessible from RPC methods. Due to
|
||||
@ -90,6 +93,16 @@ UniValue GetServicesNames(ServiceFlags services);
|
||||
//! Parse a JSON range specified as int64, or [int64, int64]
|
||||
std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue& value);
|
||||
|
||||
/**
|
||||
* Serializing JSON objects depends on the outer type. Only arrays and
|
||||
* dictionaries can be nested in json. The top-level outer type is "NONE".
|
||||
*/
|
||||
enum class OuterType {
|
||||
ARR,
|
||||
OBJ,
|
||||
NONE, // Only set on first recursion
|
||||
};
|
||||
|
||||
struct RPCArg {
|
||||
enum class Type {
|
||||
OBJ,
|
||||
@ -120,8 +133,9 @@ struct RPCArg {
|
||||
OMITTED,
|
||||
};
|
||||
using Fallback = boost::variant<Optional, /* default value for optional args */ std::string>;
|
||||
const std::string m_name; //!< The name of the arg (can be empty for inner args)
|
||||
const std::string m_names; //!< The name of the arg (can be empty for inner args, can contain multiple aliases separated by | for named request arguments)
|
||||
const Type m_type;
|
||||
const bool m_hidden;
|
||||
const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts
|
||||
const Fallback m_fallback;
|
||||
const std::string m_description;
|
||||
@ -129,43 +143,52 @@ struct RPCArg {
|
||||
const std::vector<std::string> m_type_str; //!< Should be empty unless it is supposed to override the auto-generated type strings. Vector length is either 0 or 2, m_type_str.at(0) will override the type of the value in a key-value pair, m_type_str.at(1) will override the type in the argument description.
|
||||
|
||||
RPCArg(
|
||||
const std::string& name,
|
||||
const Type& type,
|
||||
const Fallback& fallback,
|
||||
const std::string& description,
|
||||
const std::string& oneline_description = "",
|
||||
const std::vector<std::string>& type_str = {})
|
||||
: m_name{name},
|
||||
m_type{type},
|
||||
m_fallback{fallback},
|
||||
m_description{description},
|
||||
m_oneline_description{oneline_description},
|
||||
m_type_str{type_str}
|
||||
const std::string name,
|
||||
const Type type,
|
||||
const Fallback fallback,
|
||||
const std::string description,
|
||||
const std::string oneline_description = "",
|
||||
const std::vector<std::string> type_str = {},
|
||||
const bool hidden = false)
|
||||
: m_names{std::move(name)},
|
||||
m_type{std::move(type)},
|
||||
m_hidden{hidden},
|
||||
m_fallback{std::move(fallback)},
|
||||
m_description{std::move(description)},
|
||||
m_oneline_description{std::move(oneline_description)},
|
||||
m_type_str{std::move(type_str)}
|
||||
{
|
||||
assert(type != Type::ARR && type != Type::OBJ);
|
||||
CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ);
|
||||
}
|
||||
|
||||
RPCArg(
|
||||
const std::string& name,
|
||||
const Type& type,
|
||||
const Fallback& fallback,
|
||||
const std::string& description,
|
||||
const std::vector<RPCArg>& inner,
|
||||
const std::string& oneline_description = "",
|
||||
const std::vector<std::string>& type_str = {})
|
||||
: m_name{name},
|
||||
m_type{type},
|
||||
m_inner{inner},
|
||||
m_fallback{fallback},
|
||||
m_description{description},
|
||||
m_oneline_description{oneline_description},
|
||||
m_type_str{type_str}
|
||||
const std::string name,
|
||||
const Type type,
|
||||
const Fallback fallback,
|
||||
const std::string description,
|
||||
const std::vector<RPCArg> inner,
|
||||
const std::string oneline_description = "",
|
||||
const std::vector<std::string> type_str = {})
|
||||
: m_names{std::move(name)},
|
||||
m_type{std::move(type)},
|
||||
m_hidden{false},
|
||||
m_inner{std::move(inner)},
|
||||
m_fallback{std::move(fallback)},
|
||||
m_description{std::move(description)},
|
||||
m_oneline_description{std::move(oneline_description)},
|
||||
m_type_str{std::move(type_str)}
|
||||
{
|
||||
assert(type == Type::ARR || type == Type::OBJ);
|
||||
CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ);
|
||||
}
|
||||
|
||||
bool IsOptional() const;
|
||||
|
||||
/** Return the first of all aliases */
|
||||
std::string GetFirstName() const;
|
||||
|
||||
/** Return the name, throws when there are aliases */
|
||||
std::string GetName() const;
|
||||
|
||||
/**
|
||||
* Return the type string of the argument.
|
||||
* Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description).
|
||||
@ -184,21 +207,120 @@ struct RPCArg {
|
||||
};
|
||||
|
||||
struct RPCResult {
|
||||
enum class Type {
|
||||
OBJ,
|
||||
ARR,
|
||||
STR,
|
||||
NUM,
|
||||
BOOL,
|
||||
NONE,
|
||||
STR_AMOUNT, //!< Special string to represent a floating point amount
|
||||
STR_HEX, //!< Special string with only hex chars
|
||||
OBJ_DYN, //!< Special dictionary with keys that are not literals
|
||||
ARR_FIXED, //!< Special array that has a fixed number of entries
|
||||
NUM_TIME, //!< Special numeric to denote unix epoch time
|
||||
ELISION, //!< Special type to denote elision (...)
|
||||
};
|
||||
|
||||
const Type m_type;
|
||||
const std::string m_key_name; //!< Only used for dicts
|
||||
const std::vector<RPCResult> m_inner; //!< Only used for arrays or dicts
|
||||
const bool m_optional;
|
||||
const std::string m_description;
|
||||
const std::string m_cond;
|
||||
const std::string m_result;
|
||||
const bool m_legacy; //!< Used for legacy support
|
||||
const std::string m_result; //!< Used for legacy support
|
||||
|
||||
explicit RPCResult(std::string result)
|
||||
: m_cond{}, m_result{std::move(result)}
|
||||
RPCResult(
|
||||
const std::string cond,
|
||||
const Type type,
|
||||
const std::string m_key_name,
|
||||
const bool optional,
|
||||
const std::string description,
|
||||
const std::vector<RPCResult> inner = {})
|
||||
: m_type{std::move(type)},
|
||||
m_key_name{std::move(m_key_name)},
|
||||
m_inner{std::move(inner)},
|
||||
m_optional{optional},
|
||||
m_description{std::move(description)},
|
||||
m_cond{std::move(cond)},
|
||||
m_result{},
|
||||
m_legacy{false}
|
||||
{
|
||||
assert(!m_result.empty());
|
||||
CHECK_NONFATAL(!m_cond.empty());
|
||||
const bool inner_needed{type == Type::ARR || type == Type::ARR_FIXED || type == Type::OBJ || type == Type::OBJ_DYN};
|
||||
CHECK_NONFATAL(inner_needed != inner.empty());
|
||||
}
|
||||
|
||||
// start legacy support logic
|
||||
RPCResult(std::string cond, std::string result)
|
||||
: m_cond{std::move(cond)}, m_result{std::move(result)}
|
||||
: m_type{Type::NONE},
|
||||
m_key_name{},
|
||||
m_inner{},
|
||||
m_optional{false},
|
||||
m_description{},
|
||||
m_cond{std::move(cond)},
|
||||
m_result{std::move(result)},
|
||||
m_legacy{true}
|
||||
{
|
||||
assert(!m_cond.empty());
|
||||
assert(!m_result.empty());
|
||||
CHECK_NONFATAL(!m_cond.empty());
|
||||
CHECK_NONFATAL(!m_result.empty());
|
||||
}
|
||||
|
||||
RPCResult(std::string result)
|
||||
: m_type{Type::NONE},
|
||||
m_key_name{},
|
||||
m_inner{},
|
||||
m_optional{false},
|
||||
m_description{},
|
||||
m_cond{},
|
||||
m_result{std::move(result)},
|
||||
m_legacy{true}
|
||||
{
|
||||
CHECK_NONFATAL(!m_result.empty());
|
||||
}
|
||||
// end legacy support logic
|
||||
|
||||
RPCResult(
|
||||
const std::string cond,
|
||||
const Type type,
|
||||
const std::string m_key_name,
|
||||
const std::string description,
|
||||
const std::vector<RPCResult> inner = {})
|
||||
: RPCResult{cond, type, m_key_name, false, description, inner} {}
|
||||
|
||||
RPCResult(
|
||||
const Type type,
|
||||
const std::string m_key_name,
|
||||
const bool optional,
|
||||
const std::string description,
|
||||
const std::vector<RPCResult> inner = {})
|
||||
: m_type{std::move(type)},
|
||||
m_key_name{std::move(m_key_name)},
|
||||
m_inner{std::move(inner)},
|
||||
m_optional{optional},
|
||||
m_description{std::move(description)},
|
||||
m_cond{},
|
||||
m_result{},
|
||||
m_legacy{false}
|
||||
{
|
||||
const bool inner_needed{type == Type::ARR || type == Type::ARR_FIXED || type == Type::OBJ || type == Type::OBJ_DYN};
|
||||
CHECK_NONFATAL(inner_needed != inner.empty());
|
||||
}
|
||||
|
||||
RPCResult(
|
||||
const Type type,
|
||||
const std::string m_key_name,
|
||||
const std::string description,
|
||||
const std::vector<RPCResult> inner = {})
|
||||
: RPCResult{type, m_key_name, false, description, inner} {}
|
||||
|
||||
/** Append the sections of the result. */
|
||||
void ToSections(Sections& sections, OuterType outer_type = OuterType::NONE, const int current_indent = 0) const;
|
||||
/** Return the type string of the result when it is in an object (dict). */
|
||||
std::string ToStringObj() const;
|
||||
/** Return the description string, including the result type. */
|
||||
std::string ToDescriptionString() const;
|
||||
};
|
||||
|
||||
struct RPCResults {
|
||||
@ -239,13 +361,37 @@ class RPCHelpMan
|
||||
{
|
||||
public:
|
||||
RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples);
|
||||
using RPCMethodImpl = std::function<UniValue(const RPCHelpMan&, const JSONRPCRequest&)>;
|
||||
RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples, RPCMethodImpl fun);
|
||||
|
||||
std::string ToString() const;
|
||||
UniValue HandleRequest(const JSONRPCRequest& request)
|
||||
{
|
||||
Check(request);
|
||||
return m_fun(*this, request);
|
||||
}
|
||||
/** If the supplied number of args is neither too small nor too high */
|
||||
bool IsValidNumArgs(size_t num_args) const;
|
||||
/**
|
||||
* Check if the given request is valid according to this command or if
|
||||
* the user is asking for help information, and throw help when appropriate.
|
||||
*/
|
||||
inline void Check(const JSONRPCRequest& request) const {
|
||||
if (request.fHelp || !IsValidNumArgs(request.params.size())) {
|
||||
throw std::runtime_error(ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[[ noreturn ]] inline void Throw() const {
|
||||
throw std::runtime_error(ToString());
|
||||
}
|
||||
|
||||
std::vector<std::string> GetArgNames() const;
|
||||
|
||||
const std::string m_name;
|
||||
|
||||
private:
|
||||
const std::string m_name;
|
||||
const RPCMethodImpl m_fun;
|
||||
const std::string m_description;
|
||||
const std::vector<RPCArg> m_args;
|
||||
const RPCResults m_results;
|
||||
|
41
src/util/check.h
Normal file
41
src/util/check.h
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (c) 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.
|
||||
|
||||
#ifndef BITCOIN_UTIL_CHECK_H
|
||||
#define BITCOIN_UTIL_CHECK_H
|
||||
|
||||
#include <tinyformat.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
class NonFatalCheckError : public std::runtime_error
|
||||
{
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
/**
|
||||
* Throw a NonFatalCheckError when the condition evaluates to false
|
||||
*
|
||||
* This should only be used
|
||||
* - where the condition is assumed to be true, not for error handling or validating user input
|
||||
* - where a failure to fulfill the condition is recoverable and does not abort the program
|
||||
*
|
||||
* For example in RPC code, where it is undersirable to crash the whole program, this can be generally used to replace
|
||||
* asserts or recoverable logic errors. A NonFatalCheckError in RPC code is caught and passed as a string to the RPC
|
||||
* caller, which can then report the issue to the developers.
|
||||
*/
|
||||
#define CHECK_NONFATAL(condition) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
throw NonFatalCheckError( \
|
||||
strprintf("%s:%d (%s)\n" \
|
||||
"Internal bug detected: '%s'\n" \
|
||||
"You may report this issue here: %s\n", \
|
||||
__FILE__, __LINE__, __func__, \
|
||||
(#condition), \
|
||||
PACKAGE_BUGREPORT)); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#endif // BITCOIN_UTIL_CHECK_H
|
@ -83,12 +83,6 @@ static void RescanWallet(CWallet& wallet, const WalletRescanReserver& reserver,
|
||||
|
||||
UniValue importprivkey(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"importprivkey",
|
||||
@ -116,6 +110,10 @@ UniValue importprivkey(const JSONRPCRequest& request)
|
||||
},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled");
|
||||
}
|
||||
@ -153,7 +151,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
|
||||
if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
|
||||
|
||||
CPubKey pubkey = key.GetPubKey();
|
||||
assert(key.VerifyPubKey(pubkey));
|
||||
CHECK_NONFATAL(key.VerifyPubKey(pubkey));
|
||||
CKeyID vchAddress = pubkey.GetID();
|
||||
{
|
||||
pwallet->MarkDirty();
|
||||
@ -184,12 +182,6 @@ UniValue importprivkey(const JSONRPCRequest& request)
|
||||
|
||||
UniValue abortrescan(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() > 0)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"abortrescan",
|
||||
@ -206,6 +198,10 @@ UniValue abortrescan(const JSONRPCRequest& request)
|
||||
},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false;
|
||||
pwallet->AbortRescan();
|
||||
return true;
|
||||
@ -251,12 +247,6 @@ static void ImportAddress(CWallet * const pwallet, const CTxDestination& dest, c
|
||||
|
||||
UniValue importaddress(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"importaddress",
|
||||
@ -284,6 +274,9 @@ UniValue importaddress(const JSONRPCRequest& request)
|
||||
},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
std::string strLabel;
|
||||
if (!request.params[1].isNull())
|
||||
@ -343,12 +336,6 @@ UniValue importaddress(const JSONRPCRequest& request)
|
||||
|
||||
UniValue importprunedfunds(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() != 2)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"importprunedfunds",
|
||||
@ -362,6 +349,10 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
|
||||
}.ToString()
|
||||
);
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
CMutableTransaction tx;
|
||||
if (!DecodeHexTx(tx, request.params[0].get_str()))
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
|
||||
@ -412,12 +403,6 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
|
||||
|
||||
UniValue removeprunedfunds(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"removeprunedfunds",
|
||||
@ -433,6 +418,10 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
|
||||
},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
auto locked_chain = pwallet->chain().lock();
|
||||
LOCK(pwallet->cs_wallet);
|
||||
|
||||
@ -455,12 +444,6 @@ UniValue removeprunedfunds(const JSONRPCRequest& request)
|
||||
|
||||
UniValue importpubkey(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"importpubkey",
|
||||
@ -484,6 +467,9 @@ UniValue importpubkey(const JSONRPCRequest& request)
|
||||
},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
std::string strLabel;
|
||||
if (!request.params[1].isNull())
|
||||
@ -536,12 +522,6 @@ UniValue importpubkey(const JSONRPCRequest& request)
|
||||
|
||||
UniValue importwallet(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"importwallet",
|
||||
@ -561,6 +541,10 @@ UniValue importwallet(const JSONRPCRequest& request)
|
||||
},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (pwallet->chain().havePruned()) {
|
||||
// Exit early and print an error.
|
||||
// If a block is pruned after this check, we will import the key(s),
|
||||
@ -650,7 +634,7 @@ UniValue importwallet(const JSONRPCRequest& request)
|
||||
std::string label = std::get<3>(key_tuple);
|
||||
|
||||
CPubKey pubkey = key.GetPubKey();
|
||||
assert(key.VerifyPubKey(pubkey));
|
||||
CHECK_NONFATAL(key.VerifyPubKey(pubkey));
|
||||
CKeyID keyid = pubkey.GetID();
|
||||
if (pwallet->HaveKey(keyid)) {
|
||||
pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
|
||||
@ -702,11 +686,6 @@ UniValue importwallet(const JSONRPCRequest& request)
|
||||
|
||||
UniValue importelectrumwallet(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"importselectrumwallet",
|
||||
@ -726,6 +705,10 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
|
||||
},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
if (fPruneMode)
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled in pruned mode");
|
||||
|
||||
@ -777,7 +760,7 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
|
||||
continue;
|
||||
}
|
||||
CPubKey pubkey = key.GetPubKey();
|
||||
assert(key.VerifyPubKey(pubkey));
|
||||
CHECK_NONFATAL(key.VerifyPubKey(pubkey));
|
||||
CKeyID keyid = pubkey.GetID();
|
||||
if (pwallet->HaveKey(keyid)) {
|
||||
pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
|
||||
@ -809,7 +792,7 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
|
||||
continue;
|
||||
}
|
||||
CPubKey pubkey = key.GetPubKey();
|
||||
assert(key.VerifyPubKey(pubkey));
|
||||
CHECK_NONFATAL(key.VerifyPubKey(pubkey));
|
||||
CKeyID keyid = pubkey.GetID();
|
||||
if (pwallet->HaveKey(keyid)) {
|
||||
pwallet->WalletLogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
|
||||
@ -853,12 +836,6 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
|
||||
|
||||
UniValue dumpprivkey(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"dumpprivkey",
|
||||
@ -868,7 +845,7 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
|
||||
{"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The dash address for the private key"},
|
||||
},
|
||||
RPCResult{
|
||||
"\"key\" (string) The private key\n"
|
||||
RPCResult::Type::STR, "key", "The private key"
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("dumpprivkey", "\"myaddress\"")
|
||||
@ -877,6 +854,10 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
|
||||
},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
auto locked_chain = pwallet->chain().lock();
|
||||
LOCK(pwallet->cs_wallet);
|
||||
|
||||
@ -900,11 +881,6 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
|
||||
|
||||
UniValue dumphdinfo(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||
return NullUniValue;
|
||||
|
||||
if (request.fHelp || request.params.size() != 0)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"dumphdinfo",
|
||||
@ -923,6 +899,10 @@ UniValue dumphdinfo(const JSONRPCRequest& request)
|
||||
},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
LOCK(pwallet->cs_wallet);
|
||||
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
@ -948,12 +928,6 @@ UniValue dumphdinfo(const JSONRPCRequest& request)
|
||||
|
||||
UniValue dumpwallet(const JSONRPCRequest& request)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (request.fHelp || request.params.size() != 1)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"dumpwallet",
|
||||
@ -966,7 +940,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
|
||||
},
|
||||
RPCResult{
|
||||
"{ (json object)\n"
|
||||
" \"keys\" : { (int) The number of keys contained in the wallet dump\n"
|
||||
" \"keys\" : { (numeric) The number of keys contained in the wallet dump\n"
|
||||
" \"filename\" : { (string) The filename with full absolute path\n"
|
||||
" \"warning\" : { (string) A warning about not sharing the wallet dump with anyone\n"
|
||||
"}\n"
|
||||
@ -977,6 +951,10 @@ UniValue dumpwallet(const JSONRPCRequest& request)
|
||||
},
|
||||
}.ToString());
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
auto locked_chain = pwallet->chain().lock();
|
||||
LockAnnotation lock(::cs_main);
|
||||
LOCK(pwallet->cs_wallet);
|
||||
@ -1153,7 +1131,7 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
|
||||
}
|
||||
case TX_SCRIPTHASH: {
|
||||
if (script_ctx == ScriptContext::P2SH) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Trying to nest P2SH inside another P2SH");
|
||||
assert(script_ctx == ScriptContext::TOP);
|
||||
CHECK_NONFATAL(script_ctx == ScriptContext::TOP);
|
||||
CScriptID id = CScriptID(uint160(solverdata[0]));
|
||||
auto subscript = std::move(import_data.redeemscript); // Remove redeemscript from import_data to check for superfluous script later.
|
||||
if (!subscript) return "missing redeemscript";
|
||||
@ -1487,12 +1465,6 @@ static int64_t GetImportTimestamp(const UniValue& data, int64_t now)
|
||||
|
||||
UniValue importmulti(const JSONRPCRequest& mainRequest)
|
||||
{
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(mainRequest);
|
||||
CWallet* const pwallet = wallet.get();
|
||||
if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) {
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2)
|
||||
throw std::runtime_error(
|
||||
RPCHelpMan{"importmulti",
|
||||
@ -1562,6 +1534,10 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
|
||||
|
||||
const UniValue& requests = mainRequest.params[0];
|
||||
|
||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(mainRequest);
|
||||
if (!wallet) return NullUniValue;
|
||||
CWallet* const pwallet = wallet.get();
|
||||
|
||||
//Default options
|
||||
bool fRescan = true;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,9 +31,8 @@ void RegisterWalletRPCCommands(interfaces::Chain& chain, std::vector<std::unique
|
||||
*/
|
||||
std::shared_ptr<CWallet> GetWalletForJSONRPCRequest(const JSONRPCRequest& request);
|
||||
|
||||
std::string HelpRequiringPassphrase(CWallet *);
|
||||
std::string HelpRequiringPassphrase();
|
||||
void EnsureWalletIsUnlocked(CWallet *);
|
||||
bool EnsureWalletIsAvailable(CWallet *, bool avoidException);
|
||||
|
||||
UniValue getaddressinfo(const JSONRPCRequest& request);
|
||||
UniValue signrawtransactionwithwallet(const JSONRPCRequest& request);
|
||||
|
@ -21,14 +21,15 @@ UniValue getzmqnotifications(const JSONRPCRequest& request)
|
||||
"\nReturns information about the active ZeroMQ notifications.\n",
|
||||
{},
|
||||
RPCResult{
|
||||
"[\n"
|
||||
" { (json object)\n"
|
||||
" \"type\": \"pubhashtx\", (string) Type of notification\n"
|
||||
" \"address\": \"...\", (string) Address of the publisher\n"
|
||||
" \"hwm\": n (numeric) Outbound message high water mark\n"
|
||||
" },\n"
|
||||
" ...\n"
|
||||
"]\n"
|
||||
RPCResult::Type::ARR, "", "",
|
||||
{
|
||||
{RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR, "type", "Type of notification"},
|
||||
{RPCResult::Type::STR, "address", "Address of the publisher"},
|
||||
{RPCResult::Type::NUM, "hwm", "Outbound message high water mark"},
|
||||
}},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
HelpExampleCli("getzmqnotifications", "")
|
||||
|
@ -17,6 +17,8 @@ class HelpRpcTest(BitcoinTestFramework):
|
||||
def run_test(self):
|
||||
self.test_categories()
|
||||
self.dump_help()
|
||||
if self.is_wallet_compiled():
|
||||
self.wallet_help()
|
||||
|
||||
def test_categories(self):
|
||||
node = self.nodes[0]
|
||||
@ -52,6 +54,11 @@ class HelpRpcTest(BitcoinTestFramework):
|
||||
# Make sure the node can generate the help at runtime without crashing
|
||||
f.write(self.nodes[0].help(call))
|
||||
|
||||
def wallet_help(self):
|
||||
assert 'getnewaddress ( "label" )' in self.nodes[0].help('getnewaddress')
|
||||
self.restart_node(0, extra_args=['-nowallet=1'])
|
||||
assert 'getnewaddress ( "label" )' in self.nodes[0].help('getnewaddress')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
HelpRpcTest().main()
|
||||
|
@ -23,6 +23,13 @@ class RpcMiscTest(BitcoinTestFramework):
|
||||
def run_test(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
self.log.info("test CHECK_NONFATAL")
|
||||
assert_raises_rpc_error(
|
||||
-1,
|
||||
"Internal bug detected: 'request.params.size() != 100'",
|
||||
lambda: node.echo(*[0] * 100),
|
||||
)
|
||||
|
||||
self.log.info("test getmemoryinfo")
|
||||
memory = node.getmemoryinfo()['locked']
|
||||
assert_greater_than(memory['used'], 0)
|
||||
|
@ -6,7 +6,7 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_array_result
|
||||
from test_framework.util import assert_array_result, assert_equal
|
||||
|
||||
class ListTransactionsTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
@ -83,6 +83,8 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||
txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
|
||||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
assert_equal(len(self.nodes[0].listtransactions(label="watchonly", include_watchonly=True)), 1)
|
||||
assert_equal(len(self.nodes[0].listtransactions(dummy="watchonly", include_watchonly=True)), 1)
|
||||
assert len(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=False)) == 0
|
||||
assert_array_result(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=True),
|
||||
{"category": "receive", "amount": Decimal("0.1")},
|
||||
|
@ -20,4 +20,15 @@ if [[ ${OUTPUT} != "" ]]; then
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
|
||||
# Macro CHECK_NONFATAL(condition) should be used instead of assert for RPC code, where it
|
||||
# is undesirable to crash the whole program. See: src/util/check.h
|
||||
# src/rpc/server.cpp is excluded from this check since it's mostly meta-code.
|
||||
OUTPUT=$(git grep -nE 'assert *\(.*\);' -- "src/rpc/" "src/wallet/rpc*" ":(exclude)src/rpc/server.cpp")
|
||||
if [[ ${OUTPUT} != "" ]]; then
|
||||
echo "CHECK_NONFATAL(condition) should be used instead of assert for RPC code."
|
||||
echo
|
||||
echo "${OUTPUT}"
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
|
||||
exit ${EXIT_CODE}
|
||||
|
Loading…
Reference in New Issue
Block a user