diff options
author | MarcoFalke <falke.marco@gmail.com> | 2019-07-09 19:31:44 -0400 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2019-07-09 19:31:52 -0400 |
commit | 357488f660a570dc97d969ae92e026854d167142 (patch) | |
tree | f37c9a7b58547f84b3d1a323ec2cc56d604cb56f /src | |
parent | 8046a3e0befeea641b6309bc0c742b7481e681d9 (diff) | |
parent | b6fb617aaaad5f9cdd7f2ad2825b253ca792055d (diff) | |
download | bitcoin-357488f660a570dc97d969ae92e026854d167142.tar.xz |
Merge #16240: JSONRPCRequest-aware RPCHelpMan
b6fb617aaaad5f9cdd7f2ad2825b253ca792055d rpc: switch to using RPCHelpMan.Check() (Karl-Johan Alm)
c7a9fc234f3ce400ce78b9b434d2d210b2646c50 Make the RPCHelpMan aware of JSONRPCRequest and add Check() helper (Karl-Johan Alm)
5c5e32bbe3dfa790dd8bb421fbd6301ae10b09f5 rpc: migrate JSONRPCRequest functionality into request.cpp (Karl-Johan Alm)
0ab8ba1ac65b70f044a5e323b13d098cef33695a rpc: fix RPC help requirements for getblocktemplate (Karl-Johan Alm)
Pull request description:
Every single RPC call has a helper-section at the start, which throws a help string if the user asks for help or if the user provided too few/many arguments.
```C++
const RPCHelpMan help{...};
if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
throw std::runtime_error(help.ToString());
}
```
or (older version)
```C++
if (request.fHelp || request.params.size() < min || request.params.size() > max)
throw std::runtime_error(
RPCHelpMan{...}.ToString()
);
```
It seems like an obvious improvement, and less copy-pasting, to make `RPCHelpMan` aware of `JSONRPCRequest`, and to let it handle the checks instead. Both of the above become
```C++
RPCHelpMan{...}.Check(request);
```
which means we save roughly 3 lines per RPC command, and the `RPCHelpMan` instance is never referenced afterwards, so the approach is a tiny fraction cleaner.
This is a complete update, sans a few special case locations that had special rules. 623 lines turn into 284 (which includes the addition to `RPCHelpMan`).
ACKs for top commit:
laanwj:
code rview and lightly tested ACK b6fb617aaaad5f9cdd7f2ad2825b253ca792055d
MarcoFalke:
ACK b6fb617aaa, looked at the diff, verified move-only where applicable
Tree-SHA512: eb73f47f812512905b852e313281d1c8df803db40a6188aa39d5a7586631664db6764491152a8a96769946c796dc56d38c6e3a66ddd06ba3fb9d20050e6274e1
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/bitcoin-cli.cpp | 1 | ||||
-rw-r--r-- | src/rest.cpp | 1 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 132 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 41 | ||||
-rw-r--r-- | src/rpc/misc.cpp | 45 | ||||
-rw-r--r-- | src/rpc/net.cpp | 47 | ||||
-rw-r--r-- | src/rpc/protocol.h | 23 | ||||
-rw-r--r-- | src/rpc/rawtransaction.cpp | 102 | ||||
-rw-r--r-- | src/rpc/rawtransaction_util.cpp | 2 | ||||
-rw-r--r-- | src/rpc/request.cpp (renamed from src/rpc/protocol.cpp) | 42 | ||||
-rw-r--r-- | src/rpc/request.h | 42 | ||||
-rw-r--r-- | src/rpc/server.cpp | 43 | ||||
-rw-r--r-- | src/rpc/server.h | 18 | ||||
-rw-r--r-- | src/rpc/util.h | 10 | ||||
-rw-r--r-- | src/wallet/rpcdump.cpp | 42 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 230 | ||||
-rw-r--r-- | src/zmq/zmqrpc.cpp | 5 |
18 files changed, 253 insertions, 578 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 39e8d3d689..e4c542fa25 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -175,9 +175,10 @@ BITCOIN_CORE_H = \ rpc/blockchain.h \ rpc/client.h \ rpc/protocol.h \ - rpc/server.h \ rpc/rawtransaction_util.h \ rpc/register.h \ + rpc/request.h \ + rpc/server.h \ rpc/util.h \ scheduler.h \ script/descriptor.h \ @@ -481,7 +482,7 @@ libbitcoin_util_a_SOURCES = \ interfaces/handler.cpp \ logging.cpp \ random.cpp \ - rpc/protocol.cpp \ + rpc/request.cpp \ support/cleanse.cpp \ sync.cpp \ threadinterrupt.cpp \ diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp index 38010c461e..d3419520a7 100644 --- a/src/bitcoin-cli.cpp +++ b/src/bitcoin-cli.cpp @@ -12,6 +12,7 @@ #include <fs.h> #include <rpc/client.h> #include <rpc/protocol.h> +#include <rpc/request.h> #include <util/system.h> #include <util/strencodings.h> diff --git a/src/rest.cpp b/src/rest.cpp index ab409947d3..eba7aae50f 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -12,6 +12,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> diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 743efc1e65..289c96aa51 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -165,8 +165,6 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn static UniValue getblockcount(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"getblockcount", "\nReturns the height of the most-work fully-validated chain.\n" "The genesis block has height 0.\n", @@ -178,7 +176,7 @@ static UniValue getblockcount(const JSONRPCRequest& request) HelpExampleCli("getblockcount", "") + HelpExampleRpc("getblockcount", "") }, - }.ToString()); + }.Check(request); LOCK(cs_main); return ::ChainActive().Height(); @@ -186,8 +184,6 @@ static UniValue getblockcount(const JSONRPCRequest& request) static UniValue getbestblockhash(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"getbestblockhash", "\nReturns the hash of the best (tip) block in the most-work fully-validated chain.\n", {}, @@ -198,7 +194,7 @@ static UniValue getbestblockhash(const JSONRPCRequest& request) HelpExampleCli("getbestblockhash", "") + HelpExampleRpc("getbestblockhash", "") }, - }.ToString()); + }.Check(request); LOCK(cs_main); return ::ChainActive().Tip()->GetBlockHash().GetHex(); @@ -216,8 +212,6 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex) static UniValue waitfornewblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( RPCHelpMan{"waitfornewblock", "\nWaits for a specific new block and returns useful info about it.\n" "\nReturns the current block on timeout or exit.\n", @@ -234,7 +228,7 @@ static UniValue waitfornewblock(const JSONRPCRequest& request) HelpExampleCli("waitfornewblock", "1000") + HelpExampleRpc("waitfornewblock", "1000") }, - }.ToString()); + }.Check(request); int timeout = 0; if (!request.params[0].isNull()) timeout = request.params[0].get_int(); @@ -257,8 +251,6 @@ static UniValue waitfornewblock(const JSONRPCRequest& request) static UniValue waitforblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"waitforblock", "\nWaits for a specific new block and returns useful info about it.\n" "\nReturns the current block on timeout or exit.\n", @@ -276,7 +268,7 @@ static UniValue waitforblock(const JSONRPCRequest& request) HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000") + HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000") }, - }.ToString()); + }.Check(request); int timeout = 0; uint256 hash(ParseHashV(request.params[0], "blockhash")); @@ -302,8 +294,6 @@ static UniValue waitforblock(const JSONRPCRequest& request) static UniValue waitforblockheight(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"waitforblockheight", "\nWaits for (at least) block height and returns the height and hash\n" "of the current tip.\n" @@ -322,7 +312,7 @@ static UniValue waitforblockheight(const JSONRPCRequest& request) HelpExampleCli("waitforblockheight", "\"100\", 1000") + HelpExampleRpc("waitforblockheight", "\"100\", 1000") }, - }.ToString()); + }.Check(request); int timeout = 0; int height = request.params[0].get_int(); @@ -347,8 +337,6 @@ static UniValue waitforblockheight(const JSONRPCRequest& request) static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 0) { - throw std::runtime_error( RPCHelpMan{"syncwithvalidationinterfacequeue", "\nWaits for the validation interface queue to catch up on everything that was there when we entered this function.\n", {}, @@ -357,16 +345,14 @@ static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request) HelpExampleCli("syncwithvalidationinterfacequeue","") + HelpExampleRpc("syncwithvalidationinterfacequeue","") }, - }.ToString()); - } + }.Check(request); + SyncWithValidationInterfaceQueue(); return NullUniValue; } static UniValue getdifficulty(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"getdifficulty", "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n", {}, @@ -377,7 +363,7 @@ static UniValue getdifficulty(const JSONRPCRequest& request) HelpExampleCli("getdifficulty", "") + HelpExampleRpc("getdifficulty", "") }, - }.ToString()); + }.Check(request); LOCK(cs_main); return GetDifficulty(::ChainActive().Tip()); @@ -504,8 +490,6 @@ UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose) static UniValue getrawmempool(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( RPCHelpMan{"getrawmempool", "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n", @@ -528,7 +512,7 @@ static UniValue getrawmempool(const JSONRPCRequest& request) HelpExampleCli("getrawmempool", "true") + HelpExampleRpc("getrawmempool", "true") }, - }.ToString()); + }.Check(request); bool fVerbose = false; if (!request.params[0].isNull()) @@ -539,8 +523,6 @@ static UniValue getrawmempool(const JSONRPCRequest& request) static UniValue getmempoolancestors(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( RPCHelpMan{"getmempoolancestors", "\nIf txid is in the mempool, returns all in-mempool ancestors.\n", { @@ -566,8 +548,7 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request) HelpExampleCli("getmempoolancestors", "\"mytxid\"") + HelpExampleRpc("getmempoolancestors", "\"mytxid\"") }, - }.ToString()); - } + }.Check(request); bool fVerbose = false; if (!request.params[1].isNull()) @@ -609,8 +590,6 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request) static UniValue getmempooldescendants(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( RPCHelpMan{"getmempooldescendants", "\nIf txid is in the mempool, returns all in-mempool descendants.\n", { @@ -636,8 +615,7 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request) HelpExampleCli("getmempooldescendants", "\"mytxid\"") + HelpExampleRpc("getmempooldescendants", "\"mytxid\"") }, - }.ToString()); - } + }.Check(request); bool fVerbose = false; if (!request.params[1].isNull()) @@ -679,8 +657,6 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request) static UniValue getmempoolentry(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( RPCHelpMan{"getmempoolentry", "\nReturns mempool data for given transaction\n", { @@ -695,8 +671,7 @@ static UniValue getmempoolentry(const JSONRPCRequest& request) HelpExampleCli("getmempoolentry", "\"mytxid\"") + HelpExampleRpc("getmempoolentry", "\"mytxid\"") }, - }.ToString()); - } + }.Check(request); uint256 hash = ParseHashV(request.params[0], "parameter 1"); @@ -715,8 +690,6 @@ static UniValue getmempoolentry(const JSONRPCRequest& request) static UniValue getblockhash(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"getblockhash", "\nReturns hash of block in best-block-chain at height provided.\n", { @@ -729,7 +702,7 @@ static UniValue getblockhash(const JSONRPCRequest& request) HelpExampleCli("getblockhash", "1000") + HelpExampleRpc("getblockhash", "1000") }, - }.ToString()); + }.Check(request); LOCK(cs_main); @@ -743,8 +716,6 @@ static UniValue getblockhash(const JSONRPCRequest& request) static UniValue getblockheader(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"getblockheader", "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" "If verbose is true, returns an Object with information about blockheader <hash>.\n", @@ -780,7 +751,7 @@ static UniValue getblockheader(const JSONRPCRequest& request) HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") }, - }.ToString()); + }.Check(request); uint256 hash(ParseHashV(request.params[0], "hash")); @@ -846,7 +817,7 @@ static CBlockUndo GetUndoChecked(const CBlockIndex* pblockindex) static UniValue getblock(const JSONRPCRequest& request) { - const RPCHelpMan help{"getblock", + RPCHelpMan{"getblock", "\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.\n" "If verbosity is 1, returns an Object with information about block <hash>.\n" "If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n", @@ -898,11 +869,7 @@ static UniValue getblock(const JSONRPCRequest& request) HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); uint256 hash(ParseHashV(request.params[0], "blockhash")); @@ -1013,8 +980,6 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) static UniValue pruneblockchain(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"pruneblockchain", "", { {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block height to prune up to. May be set to a discrete height, or a unix timestamp\n" @@ -1027,7 +992,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request) HelpExampleCli("pruneblockchain", "1000") + HelpExampleRpc("pruneblockchain", "1000") }, - }.ToString()); + }.Check(request); if (!fPruneMode) throw JSONRPCError(RPC_MISC_ERROR, "Cannot prune blocks because node is not in prune mode."); @@ -1071,8 +1036,6 @@ static UniValue pruneblockchain(const JSONRPCRequest& request) static UniValue gettxoutsetinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"gettxoutsetinfo", "\nReturns statistics about the unspent transaction output set.\n" "Note this call may take some time.\n", @@ -1093,7 +1056,7 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request) HelpExampleCli("gettxoutsetinfo", "") + HelpExampleRpc("gettxoutsetinfo", "") }, - }.ToString()); + }.Check(request); UniValue ret(UniValue::VOBJ); @@ -1116,8 +1079,6 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request) UniValue gettxout(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) - throw std::runtime_error( RPCHelpMan{"gettxout", "\nReturns details about an unspent transaction output.\n", { @@ -1151,7 +1112,7 @@ UniValue gettxout(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("gettxout", "\"txid\", 1") }, - }.ToString()); + }.Check(request); LOCK(cs_main); @@ -1197,8 +1158,6 @@ static UniValue verifychain(const JSONRPCRequest& request) { int nCheckLevel = gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL); int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); - if (request.fHelp || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"verifychain", "\nVerifies blockchain database.\n", { @@ -1212,7 +1171,7 @@ static UniValue verifychain(const JSONRPCRequest& request) HelpExampleCli("verifychain", "") + HelpExampleRpc("verifychain", "") }, - }.ToString()); + }.Check(request); LOCK(cs_main); @@ -1297,8 +1256,6 @@ static void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus:: UniValue getblockchaininfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"getblockchaininfo", "Returns an object containing various state info regarding blockchain processing.\n", {}, @@ -1350,7 +1307,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) HelpExampleCli("getblockchaininfo", "") + HelpExampleRpc("getblockchaininfo", "") }, - }.ToString()); + }.Check(request); LOCK(cs_main); @@ -1417,8 +1374,6 @@ struct CompareBlocksByHeight static UniValue getchaintips(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"getchaintips", "Return information about all known tips in the block tree," " including the main chain as well as orphaned branches.\n", @@ -1449,7 +1404,7 @@ static UniValue getchaintips(const JSONRPCRequest& request) HelpExampleCli("getchaintips", "") + HelpExampleRpc("getchaintips", "") }, - }.ToString()); + }.Check(request); LOCK(cs_main); @@ -1540,8 +1495,6 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool) static UniValue getmempoolinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"getmempoolinfo", "\nReturns details on the active state of the TX memory pool.\n", {}, @@ -1560,15 +1513,13 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request) HelpExampleCli("getmempoolinfo", "") + HelpExampleRpc("getmempoolinfo", "") }, - }.ToString()); + }.Check(request); return MempoolInfoToJSON(::mempool); } static UniValue preciousblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"preciousblock", "\nTreats a block as if it were received before others with the same work.\n" "\nA later preciousblock call can override the effect of an earlier one.\n" @@ -1581,7 +1532,7 @@ static UniValue preciousblock(const JSONRPCRequest& request) HelpExampleCli("preciousblock", "\"blockhash\"") + HelpExampleRpc("preciousblock", "\"blockhash\"") }, - }.ToString()); + }.Check(request); uint256 hash(ParseHashV(request.params[0], "blockhash")); CBlockIndex* pblockindex; @@ -1606,8 +1557,6 @@ static UniValue preciousblock(const JSONRPCRequest& request) static UniValue invalidateblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"invalidateblock", "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n", { @@ -1618,7 +1567,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request) HelpExampleCli("invalidateblock", "\"blockhash\"") + HelpExampleRpc("invalidateblock", "\"blockhash\"") }, - }.ToString()); + }.Check(request); uint256 hash(ParseHashV(request.params[0], "blockhash")); CValidationState state; @@ -1646,8 +1595,6 @@ static UniValue invalidateblock(const JSONRPCRequest& request) static UniValue reconsiderblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"reconsiderblock", "\nRemoves invalidity status of a block, its ancestors and its descendants, reconsider them for activation.\n" "This can be used to undo the effects of invalidateblock.\n", @@ -1659,7 +1606,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request) HelpExampleCli("reconsiderblock", "\"blockhash\"") + HelpExampleRpc("reconsiderblock", "\"blockhash\"") }, - }.ToString()); + }.Check(request); uint256 hash(ParseHashV(request.params[0], "blockhash")); @@ -1685,8 +1632,6 @@ static UniValue reconsiderblock(const JSONRPCRequest& request) static UniValue getchaintxstats(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"getchaintxstats", "\nCompute statistics about the total number and rate of transactions in the chain.\n", { @@ -1708,7 +1653,7 @@ static UniValue getchaintxstats(const JSONRPCRequest& request) HelpExampleCli("getchaintxstats", "") + HelpExampleRpc("getchaintxstats", "2016") }, - }.ToString()); + }.Check(request); const CBlockIndex* pindex; int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month @@ -1818,7 +1763,7 @@ static constexpr size_t PER_UTXO_OVERHEAD = sizeof(COutPoint) + sizeof(uint32_t) static UniValue getblockstats(const JSONRPCRequest& request) { - const RPCHelpMan help{"getblockstats", + RPCHelpMan{"getblockstats", "\nCompute per block statistics for a given window. All amounts are in satoshis.\n" "It won't work for some heights with pruning.\n", { @@ -1873,10 +1818,7 @@ static UniValue getblockstats(const JSONRPCRequest& request) HelpExampleCli("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'") + HelpExampleRpc("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'") }, - }; - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); LOCK(cs_main); @@ -2077,8 +2019,6 @@ static UniValue getblockstats(const JSONRPCRequest& request) static UniValue savemempool(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) { - throw std::runtime_error( RPCHelpMan{"savemempool", "\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n", {}, @@ -2087,8 +2027,7 @@ static UniValue savemempool(const JSONRPCRequest& request) HelpExampleCli("savemempool", "") + HelpExampleRpc("savemempool", "") }, - }.ToString()); - } + }.Check(request); if (!::mempool.IsLoaded()) { throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet"); @@ -2163,8 +2102,6 @@ public: UniValue scantxoutset(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"scantxoutset", "\nEXPERIMENTAL warning: this call may be removed or changed in future releases.\n" "\nScans the unspent transaction output set for entries that match certain output descriptors.\n" @@ -2213,8 +2150,7 @@ UniValue scantxoutset(const JSONRPCRequest& request) "]\n" }, RPCExamples{""}, - }.ToString() - ); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}); @@ -2301,8 +2237,6 @@ UniValue scantxoutset(const JSONRPCRequest& request) static UniValue getblockfilter(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( RPCHelpMan{"getblockfilter", "\nRetrieve a BIP 157 content filter for a particular block.\n", { @@ -2318,9 +2252,7 @@ static UniValue getblockfilter(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"") } - }.ToString() - ); - } + }.Check(request); uint256 block_hash = ParseHashV(request.params[0], "blockhash"); std::string filtertype_name = "basic"; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 6636a8a29a..48bc88823a 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -78,8 +78,6 @@ static UniValue GetNetworkHashPS(int lookup, int height) { static UniValue getnetworkhashps(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"getnetworkhashps", "\nReturns the estimated network hashes per second based on the last n blocks.\n" "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n" @@ -95,7 +93,7 @@ static UniValue getnetworkhashps(const JSONRPCRequest& request) HelpExampleCli("getnetworkhashps", "") + HelpExampleRpc("getnetworkhashps", "") }, - }.ToString()); + }.Check(request); LOCK(cs_main); return GetNetworkHashPS(!request.params[0].isNull() ? request.params[0].get_int() : 120, !request.params[1].isNull() ? request.params[1].get_int() : -1); @@ -144,8 +142,6 @@ static UniValue generateBlocks(const CScript& coinbase_script, int nGenerate, ui static UniValue generatetoaddress(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) - throw std::runtime_error( RPCHelpMan{"generatetoaddress", "\nMine blocks immediately to a specified address (before the RPC call returns)\n", { @@ -162,7 +158,7 @@ static UniValue generatetoaddress(const JSONRPCRequest& request) + "If you are running the bitcoin core wallet, you can get a new address to send the newly generated bitcoin to with:\n" + HelpExampleCli("getnewaddress", "") }, - }.ToString()); + }.Check(request); int nGenerate = request.params[0].get_int(); uint64_t nMaxTries = 1000000; @@ -182,8 +178,6 @@ static UniValue generatetoaddress(const JSONRPCRequest& request) static UniValue getmininginfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) { - throw std::runtime_error( RPCHelpMan{"getmininginfo", "\nReturns a json object containing mining-related information.", {}, @@ -203,8 +197,7 @@ static UniValue getmininginfo(const JSONRPCRequest& request) HelpExampleCli("getmininginfo", "") + HelpExampleRpc("getmininginfo", "") }, - }.ToString()); - } + }.Check(request); LOCK(cs_main); @@ -224,8 +217,6 @@ static UniValue getmininginfo(const JSONRPCRequest& request) // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts static UniValue prioritisetransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 3) - throw std::runtime_error( RPCHelpMan{"prioritisetransaction", "Accepts the transaction into mined blocks at a higher (or lower) priority\n", { @@ -244,7 +235,7 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request) HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000") + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000") }, - }.ToString()); + }.Check(request); LOCK(cs_main); @@ -290,8 +281,6 @@ static std::string gbt_vb_name(const Consensus::DeploymentPos pos) { static UniValue getblocktemplate(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( RPCHelpMan{"getblocktemplate", "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n" "It returns data needed to construct a block to work on.\n" @@ -301,7 +290,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) " https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n" " https://github.com/bitcoin/bips/blob/master/bip-0145.mediawiki\n", { - {"template_request", RPCArg::Type::OBJ, RPCArg::Optional::NO, "A json object in the following spec", + {"template_request", RPCArg::Type::OBJ, "{}", "A json object in the following spec", { {"mode", RPCArg::Type::STR, /* treat as named arg */ RPCArg::Optional::OMITTED_NAMED_ARG, "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"}, {"capabilities", RPCArg::Type::ARR, /* treat as named arg */ RPCArg::Optional::OMITTED_NAMED_ARG, "A list of strings", @@ -366,7 +355,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) HelpExampleCli("getblocktemplate", "{\"rules\": [\"segwit\"]}") + HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}") }, - }.ToString()); + }.Check(request); LOCK(cs_main); @@ -696,8 +685,6 @@ protected: static UniValue submitblock(const JSONRPCRequest& request) { // We allow 2 arguments for compliance with BIP22. Argument 2 is ignored. - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( RPCHelpMan{"submitblock", "\nAttempts to submit new block to network.\n" "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n", @@ -710,8 +697,7 @@ static UniValue submitblock(const JSONRPCRequest& request) HelpExampleCli("submitblock", "\"mydata\"") + HelpExampleRpc("submitblock", "\"mydata\"") }, - }.ToString()); - } + }.Check(request); std::shared_ptr<CBlock> blockptr = std::make_shared<CBlock>(); CBlock& block = *blockptr; @@ -761,8 +747,6 @@ static UniValue submitblock(const JSONRPCRequest& request) static UniValue submitheader(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( RPCHelpMan{"submitheader", "\nDecode the given hexdata as a header and submit it as a candidate chain tip if valid." "\nThrows when the header is invalid.\n", @@ -776,8 +760,7 @@ static UniValue submitheader(const JSONRPCRequest& request) HelpExampleCli("submitheader", "\"aabbcc\"") + HelpExampleRpc("submitheader", "\"aabbcc\"") }, - }.ToString()); - } + }.Check(request); CBlockHeader h; if (!DecodeHexBlockHeader(h, request.params[0].get_str())) { @@ -801,8 +784,6 @@ static UniValue submitheader(const JSONRPCRequest& request) static UniValue estimatesmartfee(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"estimatesmartfee", "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" "confirmation within conf_target blocks if possible and return the number of blocks\n" @@ -835,7 +816,7 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("estimatesmartfee", "6") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR}); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); @@ -866,8 +847,6 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request) static UniValue estimaterawfee(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"estimaterawfee", "\nWARNING: This interface is unstable and may disappear or change!\n" "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n" @@ -908,7 +887,7 @@ static UniValue estimaterawfee(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("estimaterawfee", "6 0.9") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 7a1bdec7b9..55d756a826 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -25,8 +25,6 @@ static UniValue validateaddress(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"validateaddress", "\nReturn information about the given bitcoin address.\n", { @@ -47,7 +45,7 @@ static UniValue validateaddress(const JSONRPCRequest& request) HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") }, - }.ToString()); + }.Check(request); CTxDestination dest = DecodeDestination(request.params[0].get_str()); bool isValid = IsValidDestination(dest); @@ -70,9 +68,6 @@ static UniValue validateaddress(const JSONRPCRequest& request) static UniValue createmultisig(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) - { - std::string msg = RPCHelpMan{"createmultisig", "\nCreates a multi-signature address with n signature of m keys required.\n" "It returns a json object with the address and redeemScript.\n", @@ -96,9 +91,7 @@ static UniValue createmultisig(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") }, - }.ToString(); - throw std::runtime_error(msg); - } + }.Check(request); int required = request.params[0].get_int(); @@ -135,8 +128,6 @@ static UniValue createmultisig(const JSONRPCRequest& request) UniValue getdescriptorinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( RPCHelpMan{"getdescriptorinfo", {"\nAnalyses a descriptor.\n"}, { @@ -153,9 +144,7 @@ UniValue getdescriptorinfo(const JSONRPCRequest& request) RPCExamples{ "Analyse a descriptor\n" + HelpExampleCli("getdescriptorinfo", "\"wpkh([d34db33f/84h/0h/0h]0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2dce28d959f2815b16f81798)\"") - }}.ToString() - ); - } + }}.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -175,8 +164,6 @@ UniValue getdescriptorinfo(const JSONRPCRequest& request) UniValue deriveaddresses(const JSONRPCRequest& request) { - if (request.fHelp || request.params.empty() || request.params.size() > 2) { - throw std::runtime_error( RPCHelpMan{"deriveaddresses", {"\nDerives one or more addresses corresponding to an output descriptor.\n" "Examples of output descriptors are:\n" @@ -197,9 +184,7 @@ UniValue deriveaddresses(const JSONRPCRequest& request) RPCExamples{ "First three native segwit receive addresses\n" + HelpExampleCli("deriveaddresses", "\"wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#cjjspncu\" \"[0,2]\"") - }}.ToString() - ); - } + }}.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType()}); // Range argument is checked later const std::string desc_str = request.params[0].get_str(); @@ -254,8 +239,6 @@ UniValue deriveaddresses(const JSONRPCRequest& request) static UniValue verifymessage(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 3) - throw std::runtime_error( RPCHelpMan{"verifymessage", "\nVerify a signed message\n", { @@ -276,7 +259,7 @@ static UniValue verifymessage(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"") }, - }.ToString()); + }.Check(request); LOCK(cs_main); @@ -313,8 +296,6 @@ static UniValue verifymessage(const JSONRPCRequest& request) static UniValue signmessagewithprivkey(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 2) - throw std::runtime_error( RPCHelpMan{"signmessagewithprivkey", "\nSign a message with the private key of an address\n", { @@ -332,7 +313,7 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") }, - }.ToString()); + }.Check(request); std::string strPrivkey = request.params[0].get_str(); std::string strMessage = request.params[1].get_str(); @@ -355,8 +336,6 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request) static UniValue setmocktime(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"setmocktime", "\nSet the local time to given timestamp (-regtest only)\n", { @@ -365,8 +344,7 @@ static UniValue setmocktime(const JSONRPCRequest& request) }, RPCResults{}, RPCExamples{""}, - }.ToString() - ); + }.Check(request); if (!Params().MineBlocksOnDemand()) throw std::runtime_error("setmocktime for regression testing (-regtest mode) only"); @@ -421,8 +399,6 @@ static UniValue getmemoryinfo(const JSONRPCRequest& request) /* Please, avoid using the word "pool" here in the RPC interface or help, * as users will undoubtedly confuse it with the other "memory pool" */ - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( RPCHelpMan{"getmemoryinfo", "Returns an object containing information about memory usage.\n", { @@ -451,7 +427,7 @@ static UniValue getmemoryinfo(const JSONRPCRequest& request) HelpExampleCli("getmemoryinfo", "") + HelpExampleRpc("getmemoryinfo", "") }, - }.ToString()); + }.Check(request); std::string mode = request.params[0].isNull() ? "stats" : request.params[0].get_str(); if (mode == "stats") { @@ -489,8 +465,6 @@ static void EnableOrDisableLogCategories(UniValue cats, bool enable) { UniValue logging(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 2) { - throw std::runtime_error( RPCHelpMan{"logging", "Gets and sets the logging configuration.\n" "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n" @@ -522,8 +496,7 @@ UniValue logging(const JSONRPCRequest& request) HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") + HelpExampleRpc("logging", "[\"all\"], [\"libevent\"]") }, - }.ToString()); - } + }.Check(request); uint32_t original_log_categories = LogInstance().GetCategoryMask(); if (request.params[0].isArray()) { diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index d993a88458..16b59e3d58 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -26,8 +26,6 @@ static UniValue getconnectioncount(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"getconnectioncount", "\nReturns the number of connections to other nodes.\n", {}, @@ -38,7 +36,7 @@ static UniValue getconnectioncount(const JSONRPCRequest& request) HelpExampleCli("getconnectioncount", "") + HelpExampleRpc("getconnectioncount", "") }, - }.ToString()); + }.Check(request); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -48,8 +46,6 @@ static UniValue getconnectioncount(const JSONRPCRequest& request) static UniValue ping(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"ping", "\nRequests that a ping be sent to all other nodes, to measure ping time.\n" "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" @@ -60,7 +56,7 @@ static UniValue ping(const JSONRPCRequest& request) HelpExampleCli("ping", "") + HelpExampleRpc("ping", "") }, - }.ToString()); + }.Check(request); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -74,8 +70,6 @@ static UniValue ping(const JSONRPCRequest& request) static UniValue getpeerinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"getpeerinfo", "\nReturns data about each connected network node as a json array of objects.\n", {}, @@ -131,7 +125,7 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) HelpExampleCli("getpeerinfo", "") + HelpExampleRpc("getpeerinfo", "") }, - }.ToString()); + }.Check(request); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -258,8 +252,6 @@ static UniValue addnode(const JSONRPCRequest& request) static UniValue disconnectnode(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() == 0 || request.params.size() >= 3) - throw std::runtime_error( RPCHelpMan{"disconnectnode", "\nImmediately disconnects from the specified peer node.\n" "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n" @@ -275,7 +267,7 @@ static UniValue disconnectnode(const JSONRPCRequest& request) + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"") + HelpExampleRpc("disconnectnode", "\"\", 1") }, - }.ToString()); + }.Check(request); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -304,8 +296,6 @@ static UniValue disconnectnode(const JSONRPCRequest& request) static UniValue getaddednodeinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( RPCHelpMan{"getaddednodeinfo", "\nReturns information about the given added node, or all added nodes\n" "(note that onetry addnodes are not listed here)\n", @@ -331,7 +321,7 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request) HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"") + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"") }, - }.ToString()); + }.Check(request); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -374,8 +364,6 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request) static UniValue getnettotals(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 0) - throw std::runtime_error( RPCHelpMan{"getnettotals", "\nReturns information about network traffic, including bytes in, bytes out,\n" "and current time.\n", @@ -400,7 +388,7 @@ static UniValue getnettotals(const JSONRPCRequest& request) HelpExampleCli("getnettotals", "") + HelpExampleRpc("getnettotals", "") }, - }.ToString()); + }.Check(request); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -443,8 +431,6 @@ static UniValue GetNetworksInfo() static UniValue getnetworkinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"getnetworkinfo", "Returns an object containing various state info regarding P2P networking.\n", {}, @@ -485,7 +471,7 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request) HelpExampleCli("getnetworkinfo", "") + HelpExampleRpc("getnetworkinfo", "") }, - }.ToString()); + }.Check(request); LOCK(cs_main); UniValue obj(UniValue::VOBJ); @@ -602,8 +588,6 @@ static UniValue setban(const JSONRPCRequest& request) static UniValue listbanned(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"listbanned", "\nList all banned IPs/Subnets.\n", {}, @@ -612,7 +596,7 @@ static UniValue listbanned(const JSONRPCRequest& request) HelpExampleCli("listbanned", "") + HelpExampleRpc("listbanned", "") }, - }.ToString()); + }.Check(request); if(!g_banman) { throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); @@ -639,8 +623,6 @@ static UniValue listbanned(const JSONRPCRequest& request) static UniValue clearbanned(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"clearbanned", "\nClear all banned IPs.\n", {}, @@ -649,7 +631,7 @@ static UniValue clearbanned(const JSONRPCRequest& request) HelpExampleCli("clearbanned", "") + HelpExampleRpc("clearbanned", "") }, - }.ToString()); + }.Check(request); if (!g_banman) { throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); } @@ -661,8 +643,6 @@ static UniValue clearbanned(const JSONRPCRequest& request) static UniValue setnetworkactive(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( RPCHelpMan{"setnetworkactive", "\nDisable/enable all p2p network activity.\n", { @@ -670,9 +650,7 @@ static UniValue setnetworkactive(const JSONRPCRequest& request) }, RPCResults{}, RPCExamples{""}, - }.ToString() - ); - } + }.Check(request); if (!g_connman) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -685,8 +663,6 @@ static UniValue setnetworkactive(const JSONRPCRequest& request) static UniValue getnodeaddresses(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) { - throw std::runtime_error( RPCHelpMan{"getnodeaddresses", "\nReturn known addresses which can potentially be used to find new nodes in the network\n", { @@ -707,8 +683,7 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request) HelpExampleCli("getnodeaddresses", "8") + HelpExampleRpc("getnodeaddresses", "8") }, - }.ToString()); - } + }.Check(request); if (!g_connman) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index 6bcbccbd4f..ef6537e4ec 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -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 { @@ -92,18 +83,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 diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 6ac16622c2..b0855bf6f9 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -71,7 +71,7 @@ static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& static UniValue getrawtransaction(const JSONRPCRequest& request) { - const RPCHelpMan help{ + RPCHelpMan{ "getrawtransaction", "\nReturn the raw transaction data.\n" @@ -149,11 +149,7 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) + HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"") + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); bool in_active_chain = true; uint256 hash = ParseHashV(request.params[0], "parameter 1"); @@ -217,8 +213,6 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) static UniValue gettxoutproof(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2)) - throw std::runtime_error( RPCHelpMan{"gettxoutproof", "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n" "\nNOTE: By default this function only works sometimes. This is when there is an\n" @@ -237,8 +231,7 @@ static UniValue gettxoutproof(const JSONRPCRequest& request) "\"data\" (string) A string that is a serialized, hex-encoded data for the proof.\n" }, RPCExamples{""}, - }.ToString() - ); + }.Check(request); std::set<uint256> setTxids; uint256 oneTxid; @@ -313,8 +306,6 @@ static UniValue gettxoutproof(const JSONRPCRequest& request) static UniValue verifytxoutproof(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"verifytxoutproof", "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n" "and throwing an RPC error if the block is not in our best chain\n", @@ -325,8 +316,7 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request) "[\"txid\"] (array, strings) The txid(s) which the proof commits to, or empty array if the proof can not be validated.\n" }, RPCExamples{""}, - }.ToString() - ); + }.Check(request); CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); CMerkleBlock merkleBlock; @@ -358,8 +348,6 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request) static UniValue createrawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) { - throw std::runtime_error( RPCHelpMan{"createrawtransaction", "\nCreate a transaction spending the given inputs and creating new outputs.\n" "Outputs can be addresses or data.\n" @@ -408,8 +396,7 @@ static UniValue createrawtransaction(const JSONRPCRequest& request) + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"address\\\":0.01}]\"") + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"data\\\":\\\"00010203\\\"}]\"") }, - }.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, { UniValue::VARR, @@ -426,7 +413,7 @@ static UniValue createrawtransaction(const JSONRPCRequest& request) static UniValue decoderawtransaction(const JSONRPCRequest& request) { - const RPCHelpMan help{"decoderawtransaction", + RPCHelpMan{"decoderawtransaction", "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n", { {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction hex string"}, @@ -483,11 +470,7 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request) HelpExampleCli("decoderawtransaction", "\"hexstring\"") + HelpExampleRpc("decoderawtransaction", "\"hexstring\"") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); @@ -518,7 +501,7 @@ static std::string GetAllOutputTypes() static UniValue decodescript(const JSONRPCRequest& request) { - const RPCHelpMan help{"decodescript", + RPCHelpMan{"decodescript", "\nDecode a hex-encoded script.\n", { {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded script"}, @@ -549,11 +532,7 @@ static UniValue decodescript(const JSONRPCRequest& request) HelpExampleCli("decodescript", "\"hexstring\"") + HelpExampleRpc("decodescript", "\"hexstring\"") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -610,8 +589,6 @@ static UniValue decodescript(const JSONRPCRequest& request) static UniValue combinerawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"combinerawtransaction", "\nCombine multiple partially signed transactions into one transaction.\n" "The combined transaction may be another partially signed transaction or a \n" @@ -629,7 +606,7 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("combinerawtransaction", "[\"myhex1\", \"myhex2\", \"myhex3\"]") }, - }.ToString()); + }.Check(request); UniValue txs = request.params[0].get_array(); @@ -694,8 +671,6 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request) static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) - throw std::runtime_error( RPCHelpMan{"signrawtransactionwithkey", "\nSign inputs for raw transaction (serialized, hex-encoded).\n" "The second argument is an array of base58-encoded private\n" @@ -752,7 +727,7 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) HelpExampleCli("signrawtransactionwithkey", "\"myhex\" \"[\\\"key1\\\",\\\"key2\\\"]\"") + HelpExampleRpc("signrawtransactionwithkey", "\"myhex\", \"[\\\"key1\\\",\\\"key2\\\"]\"") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true); @@ -784,7 +759,7 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) static UniValue sendrawtransaction(const JSONRPCRequest& request) { - const RPCHelpMan help{"sendrawtransaction", + RPCHelpMan{"sendrawtransaction", "\nSubmits raw transaction (serialized, hex-encoded) to local node and network.\n" "\nAlso see createrawtransaction and signrawtransactionwithkey calls.\n", { @@ -806,11 +781,7 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("sendrawtransaction", "\"signedhex\"") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, { UniValue::VSTR, @@ -848,7 +819,7 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request) static UniValue testmempoolaccept(const JSONRPCRequest& request) { - const RPCHelpMan help{"testmempoolaccept", + RPCHelpMan{"testmempoolaccept", "\nReturns result of mempool acceptance tests indicating if raw transaction (serialized, hex-encoded) would be accepted by mempool.\n" "\nThis checks if the transaction violates the consensus or policy rules.\n" "\nSee sendrawtransaction call.\n", @@ -881,11 +852,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, { UniValue::VARR, @@ -964,8 +931,6 @@ static std::string WriteHDKeypath(std::vector<uint32_t>& keypath) UniValue decodepsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"decodepsbt", "\nReturn a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction.\n", { @@ -1062,7 +1027,7 @@ UniValue decodepsbt(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("decodepsbt", "\"psbt\"") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -1239,8 +1204,6 @@ UniValue decodepsbt(const JSONRPCRequest& request) UniValue combinepsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"combinepsbt", "\nCombine multiple partially signed Bitcoin transactions into one transaction.\n" "Implements the Combiner role.\n", @@ -1257,7 +1220,7 @@ UniValue combinepsbt(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("combinepsbt", "[\"mybase64_1\", \"mybase64_2\", \"mybase64_3\"]") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VARR}, true); @@ -1289,8 +1252,6 @@ UniValue combinepsbt(const JSONRPCRequest& request) UniValue finalizepsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"finalizepsbt", "Finalize the inputs of a PSBT. If the transaction is fully signed, it will produce a\n" "network serialized transaction which can be broadcast with sendrawtransaction. Otherwise a PSBT will be\n" @@ -1312,7 +1273,7 @@ UniValue finalizepsbt(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("finalizepsbt", "\"psbt\"") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}, true); @@ -1348,8 +1309,6 @@ UniValue finalizepsbt(const JSONRPCRequest& request) UniValue createpsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) - throw std::runtime_error( RPCHelpMan{"createpsbt", "\nCreates a transaction in the Partially Signed Transaction format.\n" "Implements the Creator role.\n", @@ -1392,7 +1351,7 @@ UniValue createpsbt(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, { @@ -1424,7 +1383,7 @@ UniValue createpsbt(const JSONRPCRequest& request) UniValue converttopsbt(const JSONRPCRequest& request) { - const RPCHelpMan help{"converttopsbt", + RPCHelpMan{"converttopsbt", "\nConverts a network serialized transaction to a PSBT. This should be used only with createrawtransaction and fundrawtransaction\n" "createpsbt and walletcreatefundedpsbt should be used for new applications.\n", { @@ -1448,11 +1407,7 @@ UniValue converttopsbt(const JSONRPCRequest& request) "\nConvert the transaction to a PSBT\n" + HelpExampleCli("converttopsbt", "\"rawtransaction\"") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VBOOL}, true); @@ -1495,8 +1450,6 @@ UniValue converttopsbt(const JSONRPCRequest& request) UniValue utxoupdatepsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( RPCHelpMan{"utxoupdatepsbt", "\nUpdates all segwit inputs and outputs in a PSBT with data from output descriptors, the UTXO set or the mempool.\n", { @@ -1514,8 +1467,7 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request) }, RPCExamples { HelpExampleCli("utxoupdatepsbt", "\"psbt\"") - }}.ToString()); - } + }}.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}, true); @@ -1585,8 +1537,6 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request) UniValue joinpsbts(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( RPCHelpMan{"joinpsbts", "\nJoins multiple distinct PSBTs with different inputs and outputs into one PSBT with inputs and outputs from all of the PSBTs\n" "No input in any of the PSBTs can be in more than one of the PSBTs.\n", @@ -1601,8 +1551,7 @@ UniValue joinpsbts(const JSONRPCRequest& request) }, RPCExamples { HelpExampleCli("joinpsbts", "\"psbt\"") - }}.ToString()); - } + }}.Check(request); RPCTypeCheck(request.params, {UniValue::VARR}, true); @@ -1659,8 +1608,6 @@ UniValue joinpsbts(const JSONRPCRequest& request) UniValue analyzepsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( RPCHelpMan{"analyzepsbt", "\nAnalyzes and provides information about the current status of a PSBT and its inputs\n", { @@ -1694,8 +1641,7 @@ UniValue analyzepsbt(const JSONRPCRequest& request) }, RPCExamples { HelpExampleCli("analyzepsbt", "\"psbt\"") - }}.ToString()); - } + }}.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); diff --git a/src/rpc/rawtransaction_util.cpp b/src/rpc/rawtransaction_util.cpp index 14fcb628eb..69ed7ffcbb 100644 --- a/src/rpc/rawtransaction_util.cpp +++ b/src/rpc/rawtransaction_util.cpp @@ -11,7 +11,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 <tinyformat.h> #include <univalue.h> diff --git a/src/rpc/protocol.cpp b/src/rpc/request.cpp index 33b0130a94..56cac6661e 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/request.cpp @@ -1,15 +1,16 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2018 The Bitcoin Core developers +// Copyright (c) 2009-2019 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <rpc/protocol.h> +#include <rpc/request.h> + +#include <fs.h> #include <random.h> -#include <tinyformat.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,36 @@ 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 (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"); +} diff --git a/src/rpc/request.h b/src/rpc/request.h new file mode 100644 index 0000000000..99eb4f9354 --- /dev/null +++ b/src/rpc/request.h @@ -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 diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 145b99b567..18f7426bcf 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -178,8 +178,6 @@ UniValue stop(const JSONRPCRequest& jsonRequest) static UniValue uptime(const JSONRPCRequest& jsonRequest) { - if (jsonRequest.fHelp || jsonRequest.params.size() > 0) - throw std::runtime_error( RPCHelpMan{"uptime", "\nReturns the total uptime of the server.\n", {}, @@ -190,15 +188,13 @@ static UniValue uptime(const JSONRPCRequest& jsonRequest) HelpExampleCli("uptime", "") + HelpExampleRpc("uptime", "") }, - }.ToString()); + }.Check(jsonRequest); return GetTime() - GetStartupTime(); } static UniValue getrpcinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 0) { - throw std::runtime_error( RPCHelpMan{"getrpcinfo", "\nReturns details of the RPC server.\n", {}, @@ -217,9 +213,7 @@ static UniValue getrpcinfo(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("getrpcinfo", "") + HelpExampleRpc("getrpcinfo", "")}, - }.ToString() - ); - } + }.Check(request); LOCK(g_rpc_server_info.mutex); UniValue active_commands(UniValue::VARR); @@ -334,39 +328,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 (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"); diff --git a/src/rpc/server.h b/src/rpc/server.h index 431ff0bb7c..b060db5bf9 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -7,13 +7,14 @@ #define BITCOIN_RPC_SERVER_H #include <amount.h> -#include <rpc/protocol.h> +#include <rpc/request.h> #include <uint256.h> #include <list> #include <map> #include <stdint.h> #include <string> +#include <functional> #include <univalue.h> @@ -27,21 +28,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(); diff --git a/src/rpc/util.h b/src/rpc/util.h index ae3c3d63e0..5f5b398391 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -9,6 +9,7 @@ #include <outputtype.h> #include <pubkey.h> #include <rpc/protocol.h> +#include <rpc/request.h> #include <script/script.h> #include <script/sign.h> #include <script/standard.h> @@ -242,6 +243,15 @@ public: std::string ToString() const; /** 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()); + } + } private: const std::string m_name; diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 3112dca9f5..7e973194d9 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -109,8 +109,6 @@ UniValue importprivkey(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) - throw std::runtime_error( RPCHelpMan{"importprivkey", "\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n" "Hint: use importmulti to import more than one private key.\n" @@ -135,7 +133,7 @@ UniValue importprivkey(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false") }, - }.ToString()); + }.Check(request); if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled"); @@ -217,8 +215,6 @@ UniValue abortrescan(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 0) - throw std::runtime_error( RPCHelpMan{"abortrescan", "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n" "Note: Use \"getwalletinfo\" to query the scanning progress.\n", @@ -232,7 +228,7 @@ UniValue abortrescan(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("abortrescan", "") }, - }.ToString()); + }.Check(request); if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false; pwallet->AbortRescan(); @@ -283,8 +279,6 @@ UniValue importaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) - throw std::runtime_error( RPCHelpMan{"importaddress", "\nAdds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n" "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n" @@ -309,7 +303,7 @@ UniValue importaddress(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false") }, - }.ToString()); + }.Check(request); std::string strLabel; @@ -376,8 +370,6 @@ UniValue importprunedfunds(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 2) - throw std::runtime_error( RPCHelpMan{"importprunedfunds", "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n", { @@ -386,8 +378,7 @@ UniValue importprunedfunds(const JSONRPCRequest& request) }, RPCResults{}, RPCExamples{""}, - }.ToString() - ); + }.Check(request); CMutableTransaction tx; if (!DecodeHexTx(tx, request.params[0].get_str())) @@ -443,8 +434,6 @@ UniValue removeprunedfunds(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"removeprunedfunds", "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will affect wallet balances.\n", { @@ -456,7 +445,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") }, - }.ToString()); + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -485,8 +474,6 @@ UniValue importpubkey(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) - throw std::runtime_error( RPCHelpMan{"importpubkey", "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n" "Hint: use importmulti to import more than one public key.\n" @@ -507,7 +494,7 @@ UniValue importpubkey(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false") }, - }.ToString()); + }.Check(request); std::string strLabel; @@ -570,8 +557,6 @@ UniValue importwallet(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"importwallet", "\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n" "Note: Use \"getwalletinfo\" to query the scanning progress.\n", @@ -587,7 +572,7 @@ UniValue importwallet(const JSONRPCRequest& request) "\nImport using the json rpc call\n" + HelpExampleRpc("importwallet", "\"test\"") }, - }.ToString()); + }.Check(request); if (pwallet->chain().havePruned()) { // Exit early and print an error. @@ -735,8 +720,6 @@ UniValue dumpprivkey(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"dumpprivkey", "\nReveals the private key corresponding to 'address'.\n" "Then the importprivkey can be used with this output\n", @@ -751,7 +734,7 @@ UniValue dumpprivkey(const JSONRPCRequest& request) + HelpExampleCli("importprivkey", "\"mykey\"") + HelpExampleRpc("dumpprivkey", "\"myaddress\"") }, - }.ToString()); + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -783,8 +766,6 @@ UniValue dumpwallet(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"dumpwallet", "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n" "Imported scripts are included in the dumpfile, but corresponding BIP173 addresses, etc. may not be added automatically by importwallet.\n" @@ -802,7 +783,7 @@ UniValue dumpwallet(const JSONRPCRequest& request) HelpExampleCli("dumpwallet", "\"test\"") + HelpExampleRpc("dumpwallet", "\"test\"") }, - }.ToString()); + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -1322,8 +1303,6 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) return NullUniValue; } - if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"importmulti", "\nImport addresses/scripts (with private or public keys, redeem script (P2SH)), optionally rescanning the blockchain from the earliest creation time of the imported scripts. Requires a new wallet backup.\n" "If an address/script is imported without all of the private keys required to spend from that address, it will be watchonly. The 'watchonly' option must be set to true in this case or a warning will be returned.\n" @@ -1384,8 +1363,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") + HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'") }, - }.ToString() - ); + }.Check(mainRequest); RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ}); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index eae5f876ea..3be814bf77 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -159,8 +159,6 @@ static UniValue getnewaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"getnewaddress", "\nReturns a new Bitcoin address for receiving payments.\n" "If 'label' is specified, it is added to the address book \n" @@ -176,7 +174,7 @@ static UniValue getnewaddress(const JSONRPCRequest& request) HelpExampleCli("getnewaddress", "") + HelpExampleRpc("getnewaddress", "") }, - }.ToString()); + }.Check(request); LOCK(pwallet->cs_wallet); @@ -222,8 +220,6 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( RPCHelpMan{"getrawchangeaddress", "\nReturns a new Bitcoin address, for receiving change.\n" "This is for use with raw transactions, NOT normal use.\n", @@ -237,7 +233,7 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request) HelpExampleCli("getrawchangeaddress", "") + HelpExampleRpc("getrawchangeaddress", "") }, - }.ToString()); + }.Check(request); LOCK(pwallet->cs_wallet); @@ -279,8 +275,6 @@ static UniValue setlabel(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 2) - throw std::runtime_error( RPCHelpMan{"setlabel", "\nSets the label associated with the given address.\n", { @@ -292,7 +286,7 @@ static UniValue setlabel(const JSONRPCRequest& request) HelpExampleCli("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"tabby\"") + HelpExampleRpc("setlabel", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"tabby\"") }, - }.ToString()); + }.Check(request); LOCK(pwallet->cs_wallet); @@ -362,8 +356,6 @@ static UniValue sendtoaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 2 || request.params.size() > 9) - throw std::runtime_error( RPCHelpMan{"sendtoaddress", "\nSend an amount to a given address." + HelpRequiringPassphrase(pwallet) + "\n", @@ -395,7 +387,7 @@ static UniValue sendtoaddress(const JSONRPCRequest& request) + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true") + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"") }, - }.ToString()); + }.Check(request); // 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 @@ -460,8 +452,6 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"listaddressgroupings", "\nLists groups of addresses which have had their common ownership\n" "made public by common use as inputs or as the resulting change\n" @@ -484,7 +474,7 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request) HelpExampleCli("listaddressgroupings", "") + HelpExampleRpc("listaddressgroupings", "") }, - }.ToString()); + }.Check(request); // 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 @@ -523,8 +513,6 @@ static UniValue signmessage(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 2) - throw std::runtime_error( RPCHelpMan{"signmessage", "\nSign a message with the private key of an address" + HelpRequiringPassphrase(pwallet) + "\n", @@ -545,7 +533,7 @@ static UniValue signmessage(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"") }, - }.ToString()); + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -591,8 +579,6 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"getreceivedbyaddress", "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n", { @@ -612,7 +598,7 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", 6") }, - }.ToString()); + }.Check(request); // 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 @@ -663,8 +649,6 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"getreceivedbylabel", "\nReturns the total amount received by addresses with <label> in transactions with at least [minconf] confirmations.\n", { @@ -684,7 +668,7 @@ static UniValue getreceivedbylabel(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("getreceivedbylabel", "\"tabby\", 6") }, - }.ToString()); + }.Check(request); // 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 @@ -733,8 +717,6 @@ static UniValue getbalance(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 4) - throw std::runtime_error( RPCHelpMan{"getbalance", "\nReturns the total available balance.\n" "The available balance is what the wallet considers currently spendable, and is\n" @@ -756,7 +738,7 @@ static UniValue getbalance(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("getbalance", "\"*\", 6") }, - }.ToString()); + }.Check(request); // 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 @@ -796,14 +778,12 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request) return NullUniValue; } - if (request.fHelp || request.params.size() > 0) - throw std::runtime_error( RPCHelpMan{"getunconfirmedbalance", "DEPRECATED\nIdentical to getbalances().mine.untrusted_pending\n", {}, RPCResults{}, RPCExamples{""}, - }.ToString()); + }.Check(request); // 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 @@ -825,7 +805,7 @@ static UniValue sendmany(const JSONRPCRequest& request) return NullUniValue; } - const RPCHelpMan help{"sendmany", + RPCHelpMan{"sendmany", "\nSend multiple times. Amounts are double-precision floating point numbers." + HelpRequiringPassphrase(pwallet) + "\n", { @@ -866,11 +846,7 @@ static UniValue sendmany(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("sendmany", "\"\", {\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\":0.01,\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\":0.02}, 6, \"testing\"") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); // 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 @@ -974,8 +950,6 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) { - std::string msg = RPCHelpMan{"addmultisigaddress", "\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n" "Each key is a Bitcoin address or hex-encoded public key.\n" @@ -1004,9 +978,7 @@ static UniValue addmultisigaddress(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") }, - }.ToString(); - throw std::runtime_error(msg); - } + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -1211,8 +1183,6 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 4) - throw std::runtime_error( RPCHelpMan{"listreceivedbyaddress", "\nList balances by receiving address.\n", { @@ -1243,7 +1213,7 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request) + HelpExampleRpc("listreceivedbyaddress", "6, true, true") + HelpExampleRpc("listreceivedbyaddress", "6, true, true, \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\"") }, - }.ToString()); + }.Check(request); // 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 @@ -1264,8 +1234,6 @@ static UniValue listreceivedbylabel(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 3) - throw std::runtime_error( RPCHelpMan{"listreceivedbylabel", "\nList received transactions by label.\n", { @@ -1289,7 +1257,7 @@ static UniValue listreceivedbylabel(const JSONRPCRequest& request) + HelpExampleCli("listreceivedbylabel", "6 true") + HelpExampleRpc("listreceivedbylabel", "6, true, true") }, - }.ToString()); + }.Check(request); // 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 @@ -1404,8 +1372,6 @@ UniValue listtransactions(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 4) - throw std::runtime_error( RPCHelpMan{"listtransactions", "\nIf a label name is provided, this will return only incoming transactions paying to addresses with the specified label.\n" "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions.\n", @@ -1457,7 +1423,7 @@ UniValue listtransactions(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("listtransactions", "\"*\", 20, 100") }, - }.ToString()); + }.Check(request); // 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 @@ -1538,8 +1504,6 @@ static UniValue listsinceblock(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 4) - throw std::runtime_error( RPCHelpMan{"listsinceblock", "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted.\n" "If \"blockhash\" is no longer a part of the main chain, transactions from the fork point onward are included.\n" @@ -1592,7 +1556,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request) + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6") + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6") }, - }.ToString()); + }.Check(request); // 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 @@ -1683,8 +1647,6 @@ static UniValue gettransaction(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"gettransaction", "\nGet detailed information about in-wallet transaction <txid>\n", { @@ -1732,7 +1694,7 @@ static UniValue gettransaction(const JSONRPCRequest& request) + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true") + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") }, - }.ToString()); + }.Check(request); // 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 @@ -1785,8 +1747,6 @@ static UniValue abandontransaction(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( RPCHelpMan{"abandontransaction", "\nMark in-wallet transaction <txid> as abandoned\n" "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n" @@ -1801,8 +1761,7 @@ static UniValue abandontransaction(const JSONRPCRequest& request) HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"") }, - }.ToString()); - } + }.Check(request); // 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 @@ -1833,8 +1792,6 @@ static UniValue backupwallet(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"backupwallet", "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n", { @@ -1845,7 +1802,7 @@ static UniValue backupwallet(const JSONRPCRequest& request) HelpExampleCli("backupwallet", "\"backup.dat\"") + HelpExampleRpc("backupwallet", "\"backup.dat\"") }, - }.ToString()); + }.Check(request); // 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 @@ -1872,8 +1829,6 @@ static UniValue keypoolrefill(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( RPCHelpMan{"keypoolrefill", "\nFills the keypool."+ HelpRequiringPassphrase(pwallet) + "\n", @@ -1885,7 +1840,7 @@ static UniValue keypoolrefill(const JSONRPCRequest& request) HelpExampleCli("keypoolrefill", "") + HelpExampleRpc("keypoolrefill", "") }, - }.ToString()); + }.Check(request); if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet"); @@ -1922,8 +1877,6 @@ static UniValue walletpassphrase(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 2) { - throw std::runtime_error( RPCHelpMan{"walletpassphrase", "\nStores the wallet decryption key in memory for 'timeout' seconds.\n" "This is needed prior to performing transactions related to private keys such as sending bitcoins\n" @@ -1943,8 +1896,7 @@ static UniValue walletpassphrase(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60") }, - }.ToString()); - } + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -2009,8 +1961,6 @@ static UniValue walletpassphrasechange(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 2) { - throw std::runtime_error( RPCHelpMan{"walletpassphrasechange", "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n", { @@ -2022,8 +1972,7 @@ static UniValue walletpassphrasechange(const JSONRPCRequest& request) HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"") + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"") }, - }.ToString()); - } + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -2063,8 +2012,6 @@ static UniValue walletlock(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 0) { - throw std::runtime_error( RPCHelpMan{"walletlock", "\nRemoves the wallet encryption key from memory, locking the wallet.\n" "After calling this method, you will need to call walletpassphrase again\n" @@ -2081,8 +2028,7 @@ static UniValue walletlock(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("walletlock", "") }, - }.ToString()); - } + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -2107,8 +2053,6 @@ static UniValue encryptwallet(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( RPCHelpMan{"encryptwallet", "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n" "After this, any calls that interact with private keys such as sending or signing \n" @@ -2131,8 +2075,7 @@ static UniValue encryptwallet(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("encryptwallet", "\"my pass phrase\"") }, - }.ToString()); - } + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -2171,8 +2114,6 @@ static UniValue lockunspent(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"lockunspent", "\nUpdates list of temporarily unspendable outputs.\n" "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n" @@ -2209,7 +2150,7 @@ static UniValue lockunspent(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") }, - }.ToString()); + }.Check(request); // 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 @@ -2300,8 +2241,6 @@ static UniValue listlockunspent(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 0) - throw std::runtime_error( RPCHelpMan{"listlockunspent", "\nReturns list of temporarily unspendable outputs.\n" "See the lockunspent call to lock and unlock transactions for spending.\n", @@ -2327,7 +2266,7 @@ static UniValue listlockunspent(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("listlockunspent", "") }, - }.ToString()); + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -2357,8 +2296,6 @@ static UniValue settxfee(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 1) { - throw std::runtime_error( RPCHelpMan{"settxfee", "\nSet the transaction fee per kB for this wallet. Overrides the global -paytxfee command line parameter.\n", { @@ -2371,8 +2308,7 @@ static UniValue settxfee(const JSONRPCRequest& request) HelpExampleCli("settxfee", "0.00001") + HelpExampleRpc("settxfee", "0.00001") }, - }.ToString()); - } + }.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -2399,7 +2335,7 @@ static UniValue getbalances(const JSONRPCRequest& request) } CWallet& wallet = *rpc_wallet; - const RPCHelpMan help{ + RPCHelpMan{ "getbalances", "Returns an object with all balances in " + CURRENCY_UNIT + ".\n", {}, @@ -2420,11 +2356,7 @@ static UniValue getbalances(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("getbalances", "") + HelpExampleRpc("getbalances", "")}, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); // 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 @@ -2469,7 +2401,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request) return NullUniValue; } - const RPCHelpMan help{"getwalletinfo", + RPCHelpMan{"getwalletinfo", "Returns an object containing various wallet state info.\n", {}, RPCResult{ @@ -2499,11 +2431,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request) HelpExampleCli("getwalletinfo", "") + HelpExampleRpc("getwalletinfo", "") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); // 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 @@ -2550,8 +2478,6 @@ static UniValue getwalletinfo(const JSONRPCRequest& request) static UniValue listwalletdir(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) { - throw std::runtime_error( RPCHelpMan{"listwalletdir", "Returns a list of wallets in the wallet directory.\n", {}, @@ -2569,8 +2495,7 @@ static UniValue listwalletdir(const JSONRPCRequest& request) HelpExampleCli("listwalletdir", "") + HelpExampleRpc("listwalletdir", "") }, - }.ToString()); - } + }.Check(request); UniValue wallets(UniValue::VARR); for (const auto& path : ListWalletDir()) { @@ -2586,8 +2511,6 @@ static UniValue listwalletdir(const JSONRPCRequest& request) static UniValue listwallets(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"listwallets", "Returns a list of currently loaded wallets.\n" "For full information on the wallet, use \"getwalletinfo\"\n", @@ -2602,7 +2525,7 @@ static UniValue listwallets(const JSONRPCRequest& request) HelpExampleCli("listwallets", "") + HelpExampleRpc("listwallets", "") }, - }.ToString()); + }.Check(request); UniValue obj(UniValue::VARR); @@ -2621,8 +2544,6 @@ static UniValue listwallets(const JSONRPCRequest& request) static UniValue loadwallet(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"loadwallet", "\nLoads a wallet from a wallet file or directory." "\nNote that all wallet command-line options used when starting bitcoind will be" @@ -2640,7 +2561,7 @@ static UniValue loadwallet(const JSONRPCRequest& request) HelpExampleCli("loadwallet", "\"test.dat\"") + HelpExampleRpc("loadwallet", "\"test.dat\"") }, - }.ToString()); + }.Check(request); WalletLocation location(request.params[0].get_str()); @@ -2674,12 +2595,10 @@ static UniValue setwalletflag(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - std::string flags = ""; - for (auto& it : WALLET_FLAG_MAP) - if (it.second & MUTABLE_WALLET_FLAGS) - flags += (flags == "" ? "" : ", ") + it.first; - throw std::runtime_error( + std::string flags = ""; + for (auto& it : WALLET_FLAG_MAP) + if (it.second & MUTABLE_WALLET_FLAGS) + flags += (flags == "" ? "" : ", ") + it.first; RPCHelpMan{"setwalletflag", "\nChange the state of the given wallet flag for a wallet.\n", { @@ -2697,8 +2616,7 @@ static UniValue setwalletflag(const JSONRPCRequest& request) HelpExampleCli("setwalletflag", "avoid_reuse") + HelpExampleRpc("setwalletflag", "\"avoid_reuse\"") }, - }.ToString()); - } + }.Check(request); std::string flag_str = request.params[0].get_str(); bool value = request.params[1].isNull() || request.params[1].get_bool(); @@ -2737,7 +2655,7 @@ static UniValue setwalletflag(const JSONRPCRequest& request) static UniValue createwallet(const JSONRPCRequest& request) { - const RPCHelpMan help{ + RPCHelpMan{ "createwallet", "\nCreates and loads a new wallet.\n", { @@ -2757,11 +2675,8 @@ static UniValue createwallet(const JSONRPCRequest& request) HelpExampleCli("createwallet", "\"testwallet\"") + HelpExampleRpc("createwallet", "\"testwallet\"") }, - }; + }.Check(request); - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } std::string error; std::string warning; @@ -2841,8 +2756,6 @@ static UniValue createwallet(const JSONRPCRequest& request) static UniValue unloadwallet(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) { - throw std::runtime_error( RPCHelpMan{"unloadwallet", "Unloads the wallet referenced by the request endpoint otherwise unloads the wallet specified in the argument.\n" "Specifying the wallet name on a wallet endpoint is invalid.", @@ -2854,8 +2767,7 @@ static UniValue unloadwallet(const JSONRPCRequest& request) HelpExampleCli("unloadwallet", "wallet_name") + HelpExampleRpc("unloadwallet", "wallet_name") }, - }.ToString()); - } + }.Check(request); std::string wallet_name; if (GetWalletNameFromJSONRPCRequest(request, wallet_name)) { @@ -2892,7 +2804,7 @@ static UniValue listunspent(const JSONRPCRequest& request) return NullUniValue; } - const RPCHelpMan help{ + RPCHelpMan{ "listunspent", "\nReturns array of unspent transaction outputs\n" "with between minconf and maxconf (inclusive) confirmations.\n" @@ -2946,11 +2858,7 @@ static UniValue listunspent(const JSONRPCRequest& request) + HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'") + HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); int nMinDepth = 1; if (!request.params[0].isNull()) { @@ -3219,7 +3127,7 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request) return NullUniValue; } - const RPCHelpMan help{"fundrawtransaction", + RPCHelpMan{"fundrawtransaction", "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n" "This will not modify existing inputs, and will add at most one change output to the outputs.\n" "No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n" @@ -3283,11 +3191,7 @@ static UniValue fundrawtransaction(const JSONRPCRequest& request) "\nSend the transaction\n" + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType(), UniValue::VBOOL}); @@ -3320,8 +3224,6 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) - throw std::runtime_error( RPCHelpMan{"signrawtransactionwithwallet", "\nSign inputs for raw transaction (serialized, hex-encoded).\n" "The second optional argument (may be null) is an array of previous transaction outputs that\n" @@ -3371,7 +3273,7 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request) HelpExampleCli("signrawtransactionwithwallet", "\"myhex\"") + HelpExampleRpc("signrawtransactionwithwallet", "\"myhex\"") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VSTR}, true); @@ -3404,8 +3306,6 @@ static UniValue bumpfee(const JSONRPCRequest& request) if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) return NullUniValue; - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( RPCHelpMan{"bumpfee", "\nBumps the fee of an opt-in-RBF transaction T, replacing it with a new transaction B.\n" "An opt-in RBF transaction with the given txid must be in the wallet.\n" @@ -3453,8 +3353,7 @@ static UniValue bumpfee(const JSONRPCRequest& request) "\nBump the fee, get the new transaction\'s txid\n" + HelpExampleCli("bumpfee", "<txid>") }, - }.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ}); uint256 hash(ParseHashV(request.params[0], "txid")); @@ -3567,8 +3466,6 @@ UniValue rescanblockchain(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 2) { - throw std::runtime_error( RPCHelpMan{"rescanblockchain", "\nRescan the local blockchain for wallet related transactions.\n" "Note: Use \"getwalletinfo\" to query the scanning progress.\n", @@ -3586,8 +3483,7 @@ UniValue rescanblockchain(const JSONRPCRequest& request) HelpExampleCli("rescanblockchain", "100000 120000") + HelpExampleRpc("rescanblockchain", "100000, 120000") }, - }.ToString()); - } + }.Check(request); WalletRescanReserver reserver(pwallet); if (!reserver.reserve()) { @@ -3774,8 +3670,6 @@ UniValue getaddressinfo(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( RPCHelpMan{"getaddressinfo", "\nReturn information about the given bitcoin address. Some information requires the address\n" "to be in the wallet.\n", @@ -3824,8 +3718,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request) HelpExampleCli("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + HelpExampleRpc("getaddressinfo", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") }, - }.ToString()); - } + }.Check(request); LOCK(pwallet->cs_wallet); @@ -3902,8 +3795,6 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"getaddressesbylabel", "\nReturns the list of addresses assigned the specified label.\n", { @@ -3920,7 +3811,7 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request) HelpExampleCli("getaddressesbylabel", "\"tabby\"") + HelpExampleRpc("getaddressesbylabel", "\"tabby\"") }, - }.ToString()); + }.Check(request); LOCK(pwallet->cs_wallet); @@ -3961,8 +3852,6 @@ static UniValue listlabels(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( RPCHelpMan{"listlabels", "\nReturns the list of all labels, or labels that are assigned to addresses with a specific purpose.\n", { @@ -3984,7 +3873,7 @@ static UniValue listlabels(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("listlabels", "receive") }, - }.ToString()); + }.Check(request); LOCK(pwallet->cs_wallet); @@ -4018,8 +3907,6 @@ UniValue sethdseed(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 2) { - throw std::runtime_error( RPCHelpMan{"sethdseed", "\nSet or generate a new HD wallet seed. Non-HD wallets will not be upgraded to being a HD wallet. Wallets that are already\n" "HD will have a new HD seed set so that new keys added to the keypool will be derived from this new seed.\n" @@ -4040,8 +3927,7 @@ UniValue sethdseed(const JSONRPCRequest& request) + HelpExampleCli("sethdseed", "true \"wifkey\"") + HelpExampleRpc("sethdseed", "true, \"wifkey\"") }, - }.ToString()); - } + }.Check(request); if (pwallet->chain().isInitialBlockDownload()) { throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Cannot set a new HD seed while still in Initial Block Download"); @@ -4097,8 +3983,6 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) - throw std::runtime_error( RPCHelpMan{"walletprocesspsbt", "\nUpdate a PSBT with input information from our wallet and then sign inputs\n" "that we can sign for." + @@ -4125,7 +4009,7 @@ UniValue walletprocesspsbt(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("walletprocesspsbt", "\"psbt\"") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VSTR}); @@ -4166,8 +4050,6 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() < 2 || request.params.size() > 5) - throw std::runtime_error( RPCHelpMan{"walletcreatefundedpsbt", "\nCreates and funds a transaction in the Partially Signed Transaction format. Inputs will be added if supplied inputs are not enough\n" "Implements the Creator and Updater roles.\n", @@ -4239,7 +4121,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request) "\nCreate a transaction with no inputs\n" + HelpExampleCli("walletcreatefundedpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, { UniValue::VARR, diff --git a/src/zmq/zmqrpc.cpp b/src/zmq/zmqrpc.cpp index a34968ef7d..cf97b7ecce 100644 --- a/src/zmq/zmqrpc.cpp +++ b/src/zmq/zmqrpc.cpp @@ -15,8 +15,6 @@ namespace { UniValue getzmqnotifications(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) { - throw std::runtime_error( RPCHelpMan{"getzmqnotifications", "\nReturns information about the active ZeroMQ notifications.\n", {}, @@ -34,8 +32,7 @@ UniValue getzmqnotifications(const JSONRPCRequest& request) HelpExampleCli("getzmqnotifications", "") + HelpExampleRpc("getzmqnotifications", "") }, - }.ToString()); - } + }.Check(request); UniValue result(UniValue::VARR); if (g_zmq_notification_interface != nullptr) { |