From fac8b65665bc139ef6d6db57bf255084e592518f Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 1 Apr 2020 08:08:14 +0800 Subject: [PATCH 1/2] rpc: Introduce RPCMan --- src/qt/test/rpcnestedtests.cpp | 4 +- src/rest.cpp | 4 +- src/rpc/blockchain.cpp | 304 ++++++--- src/rpc/mining.cpp | 103 ++- src/rpc/misc.cpp | 115 +++- src/rpc/net.cpp | 141 ++-- src/rpc/rawtransaction.cpp | 183 ++++-- src/rpc/server.cpp | 54 +- src/rpc/server.h | 9 +- src/rpc/util.cpp | 10 +- src/rpc/util.h | 9 +- src/wallet/rpcdump.cpp | 219 ++++--- src/wallet/rpcwallet.cpp | 1055 ++++++++++++++++++------------ src/wallet/test/wallet_tests.cpp | 12 +- src/zmq/zmqrpc.cpp | 10 +- 15 files changed, 1407 insertions(+), 825 deletions(-) diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index de1fbcb94cfb6..87480e6d85fe3 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -14,12 +14,14 @@ #include #include -static UniValue rpcNestedTest_rpc(const JSONRPCRequest& request) +static RPCMan rpcNestedTest_rpc() { + return RPCMan{"rpcNestedTest", "test", {}, {}, RPCExamples{""}, [](const RPCMan& self, const JSONRPCRequest& request) -> UniValue { if (request.fHelp) { return "help message"; } return request.params.write(0, 0); + }}; } static const CRPCCommand vRPCCommands[] = diff --git a/src/rest.cpp b/src/rest.cpp index 0629557584853..de00200369ff9 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -286,7 +286,7 @@ static bool rest_block_notxdetails(HTTPRequest* req, const std::string& strURIPa } // A bit of a hack - dependency on a function defined in rpc/blockchain.cpp -UniValue getblockchaininfo(const JSONRPCRequest& request); +RPCMan getblockchaininfo(); static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart) { @@ -299,7 +299,7 @@ static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart) case RetFormat::JSON: { JSONRPCRequest jsonRequest; jsonRequest.params = UniValue(UniValue::VARR); - UniValue chainInfoObject = getblockchaininfo(jsonRequest); + UniValue chainInfoObject = CALL_RPC_METHOD(getblockchaininfo, jsonRequest); std::string strJSON = chainInfoObject.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index c132f265d29df..3d5907d017dda 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -170,9 +170,9 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn return result; } -static UniValue getblockcount(const JSONRPCRequest& request) +static RPCMan getblockcount() { - RPCHelpMan{"getblockcount", + return RPCMan{"getblockcount", "\nReturns the height of the most-work fully-validated chain.\n" "The genesis block has height 0.\n", {}, @@ -182,15 +182,19 @@ static UniValue getblockcount(const JSONRPCRequest& request) HelpExampleCli("getblockcount", "") + HelpExampleRpc("getblockcount", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); return ::ChainActive().Height(); +}, + }; } -static UniValue getbestblockhash(const JSONRPCRequest& request) +static RPCMan getbestblockhash() { - RPCHelpMan{"getbestblockhash", + return RPCMan{"getbestblockhash", "\nReturns the hash of the best (tip) block in the most-work fully-validated chain.\n", {}, RPCResult{ @@ -199,10 +203,14 @@ static UniValue getbestblockhash(const JSONRPCRequest& request) HelpExampleCli("getbestblockhash", "") + HelpExampleRpc("getbestblockhash", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); return ::ChainActive().Tip()->GetBlockHash().GetHex(); +}, + }; } void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex) @@ -215,9 +223,9 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex) cond_blockchange.notify_all(); } -static UniValue waitfornewblock(const JSONRPCRequest& request) +static RPCMan waitfornewblock() { - RPCHelpMan{"waitfornewblock", + return RPCMan{"waitfornewblock", "\nWaits for a specific new block and returns useful info about it.\n" "\nReturns the current block on timeout or exit.\n", { @@ -233,7 +241,9 @@ static UniValue waitfornewblock(const JSONRPCRequest& request) HelpExampleCli("waitfornewblock", "1000") + HelpExampleRpc("waitfornewblock", "1000") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); int timeout = 0; if (!request.params[0].isNull()) timeout = request.params[0].get_int(); @@ -252,11 +262,13 @@ static UniValue waitfornewblock(const JSONRPCRequest& request) ret.pushKV("hash", block.hash.GetHex()); ret.pushKV("height", block.height); return ret; +}, + }; } -static UniValue waitforblock(const JSONRPCRequest& request) +static RPCMan waitforblock() { - RPCHelpMan{"waitforblock", + return RPCMan{"waitforblock", "\nWaits for a specific new block and returns useful info about it.\n" "\nReturns the current block on timeout or exit.\n", { @@ -273,7 +285,9 @@ static UniValue waitforblock(const JSONRPCRequest& request) HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\" 1000") + HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); int timeout = 0; uint256 hash(ParseHashV(request.params[0], "blockhash")); @@ -295,11 +309,13 @@ static UniValue waitforblock(const JSONRPCRequest& request) ret.pushKV("hash", block.hash.GetHex()); ret.pushKV("height", block.height); return ret; +}, + }; } -static UniValue waitforblockheight(const JSONRPCRequest& request) +static RPCMan waitforblockheight() { - RPCHelpMan{"waitforblockheight", + return RPCMan{"waitforblockheight", "\nWaits for (at least) block height and returns the height and hash\n" "of the current tip.\n" "\nReturns the current block on timeout or exit.\n", @@ -317,7 +333,9 @@ static UniValue waitforblockheight(const JSONRPCRequest& request) HelpExampleCli("waitforblockheight", "100 1000") + HelpExampleRpc("waitforblockheight", "100, 1000") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); int timeout = 0; int height = request.params[0].get_int(); @@ -338,11 +356,13 @@ static UniValue waitforblockheight(const JSONRPCRequest& request) ret.pushKV("hash", block.hash.GetHex()); ret.pushKV("height", block.height); return ret; +}, + }; } -static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request) +static RPCMan syncwithvalidationinterfacequeue() { - RPCHelpMan{"syncwithvalidationinterfacequeue", + return RPCMan{"syncwithvalidationinterfacequeue", "\nWaits for the validation interface queue to catch up on everything that was there when we entered this function.\n", {}, RPCResult{RPCResult::Type::NONE, "", ""}, @@ -350,15 +370,19 @@ static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request) HelpExampleCli("syncwithvalidationinterfacequeue","") + HelpExampleRpc("syncwithvalidationinterfacequeue","") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); SyncWithValidationInterfaceQueue(); return NullUniValue; +}, + }; } -static UniValue getdifficulty(const JSONRPCRequest& request) +static RPCMan getdifficulty() { - RPCHelpMan{"getdifficulty", + return RPCMan{"getdifficulty", "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n", {}, RPCResult{ @@ -367,10 +391,14 @@ static UniValue getdifficulty(const JSONRPCRequest& request) HelpExampleCli("getdifficulty", "") + HelpExampleRpc("getdifficulty", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); return GetDifficulty(::ChainActive().Tip()); +}, + }; } static std::vector MempoolEntryDescription() { return { @@ -492,9 +520,9 @@ UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose) } } -static UniValue getrawmempool(const JSONRPCRequest& request) +static RPCMan getrawmempool() { - RPCHelpMan{"getrawmempool", + return RPCMan{"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", { @@ -516,18 +544,22 @@ static UniValue getrawmempool(const JSONRPCRequest& request) HelpExampleCli("getrawmempool", "true") + HelpExampleRpc("getrawmempool", "true") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); bool fVerbose = false; if (!request.params[0].isNull()) fVerbose = request.params[0].get_bool(); return MempoolToJSON(EnsureMemPool(), fVerbose); +}, + }; } -static UniValue getmempoolancestors(const JSONRPCRequest& request) +static RPCMan getmempoolancestors() { - RPCHelpMan{"getmempoolancestors", + return RPCMan{"getmempoolancestors", "\nIf txid is in the mempool, returns all in-mempool ancestors.\n", { {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"}, @@ -544,7 +576,9 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request) HelpExampleCli("getmempoolancestors", "\"mytxid\"") + HelpExampleRpc("getmempoolancestors", "\"mytxid\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); bool fVerbose = false; if (!request.params[1].isNull()) @@ -583,11 +617,13 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request) } return o; } +}, + }; } -static UniValue getmempooldescendants(const JSONRPCRequest& request) +static RPCMan getmempooldescendants() { - RPCHelpMan{"getmempooldescendants", + return RPCMan{"getmempooldescendants", "\nIf txid is in the mempool, returns all in-mempool descendants.\n", { {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"}, @@ -607,7 +643,9 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request) HelpExampleCli("getmempooldescendants", "\"mytxid\"") + HelpExampleRpc("getmempooldescendants", "\"mytxid\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); bool fVerbose = false; if (!request.params[1].isNull()) @@ -646,11 +684,13 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request) } return o; } +}, + }; } -static UniValue getmempoolentry(const JSONRPCRequest& request) +static RPCMan getmempoolentry() { - RPCHelpMan{"getmempoolentry", + return RPCMan{"getmempoolentry", "\nReturns mempool data for given transaction\n", { {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"}, @@ -661,7 +701,9 @@ static UniValue getmempoolentry(const JSONRPCRequest& request) HelpExampleCli("getmempoolentry", "\"mytxid\"") + HelpExampleRpc("getmempoolentry", "\"mytxid\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); uint256 hash = ParseHashV(request.params[0], "parameter 1"); @@ -677,11 +719,13 @@ static UniValue getmempoolentry(const JSONRPCRequest& request) UniValue info(UniValue::VOBJ); entryToJSON(mempool, info, e); return info; +}, + }; } -static UniValue getblockhash(const JSONRPCRequest& request) +static RPCMan getblockhash() { - RPCHelpMan{"getblockhash", + return RPCMan{"getblockhash", "\nReturns hash of block in best-block-chain at height provided.\n", { {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The height index"}, @@ -692,7 +736,9 @@ static UniValue getblockhash(const JSONRPCRequest& request) HelpExampleCli("getblockhash", "1000") + HelpExampleRpc("getblockhash", "1000") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); @@ -702,11 +748,13 @@ static UniValue getblockhash(const JSONRPCRequest& request) CBlockIndex* pblockindex = ::ChainActive()[nHeight]; return pblockindex->GetBlockHash().GetHex(); +}, + }; } -static UniValue getblockheader(const JSONRPCRequest& request) +static RPCMan getblockheader() { - RPCHelpMan{"getblockheader", + return RPCMan{"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 .\n", { @@ -740,7 +788,9 @@ static UniValue getblockheader(const JSONRPCRequest& request) HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); uint256 hash(ParseHashV(request.params[0], "hash")); @@ -769,6 +819,8 @@ static UniValue getblockheader(const JSONRPCRequest& request) } return blockheaderToJSON(tip, pblockindex); +}, + }; } static CBlock GetBlockChecked(const CBlockIndex* pblockindex) @@ -804,9 +856,9 @@ static CBlockUndo GetUndoChecked(const CBlockIndex* pblockindex) return blockUndo; } -static UniValue getblock(const JSONRPCRequest& request) +static RPCMan getblock() { - RPCHelpMan{"getblock", + return RPCMan{"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 .\n" "If verbosity is 2, returns an Object with information about block and information about each transaction. \n", @@ -859,7 +911,9 @@ static UniValue getblock(const JSONRPCRequest& request) HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); uint256 hash(ParseHashV(request.params[0], "blockhash")); @@ -895,11 +949,13 @@ static UniValue getblock(const JSONRPCRequest& request) } return blockToJSON(block, tip, pblockindex, verbosity >= 2); +}, + }; } -static UniValue pruneblockchain(const JSONRPCRequest& request) +static RPCMan pruneblockchain() { - RPCHelpMan{"pruneblockchain", "", + return RPCMan{"pruneblockchain", "", { {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block height to prune up to. May be set to a discrete height, or to a " + UNIX_EPOCH_TIME + "\n" " to prune blocks whose block time is at least 2 hours older than the provided timestamp."}, @@ -910,7 +966,9 @@ static UniValue pruneblockchain(const JSONRPCRequest& request) HelpExampleCli("pruneblockchain", "1000") + HelpExampleRpc("pruneblockchain", "1000") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if (!fPruneMode) throw JSONRPCError(RPC_MISC_ERROR, "Cannot prune blocks because node is not in prune mode."); @@ -950,11 +1008,13 @@ static UniValue pruneblockchain(const JSONRPCRequest& request) block = block->pprev; } return uint64_t(block->nHeight); +}, + }; } -static UniValue gettxoutsetinfo(const JSONRPCRequest& request) +static RPCMan gettxoutsetinfo() { - RPCHelpMan{"gettxoutsetinfo", + return RPCMan{"gettxoutsetinfo", "\nReturns statistics about the unspent transaction output set.\n" "Note this call may take some time.\n", {}, @@ -974,7 +1034,9 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request) HelpExampleCli("gettxoutsetinfo", "") + HelpExampleRpc("gettxoutsetinfo", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); UniValue ret(UniValue::VOBJ); @@ -995,11 +1057,13 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request) throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set"); } return ret; +}, + }; } -UniValue gettxout(const JSONRPCRequest& request) +static RPCMan gettxout() { - RPCHelpMan{"gettxout", + return RPCMan{"gettxout", "\nReturns details about an unspent transaction output.\n", { {"txid", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction id"}, @@ -1031,7 +1095,9 @@ UniValue gettxout(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("gettxout", "\"txid\", 1") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); @@ -1074,13 +1140,15 @@ UniValue gettxout(const JSONRPCRequest& request) ret.pushKV("coinbase", (bool)coin.fCoinBase); return ret; +}, + }; } -static UniValue verifychain(const JSONRPCRequest& request) +static RPCMan verifychain() { int nCheckLevel = gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL); int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); - RPCHelpMan{"verifychain", + return RPCMan{"verifychain", "\nVerifies blockchain database.\n", { {"checklevel", RPCArg::Type::NUM, /* default */ strprintf("%d, range=0-4", nCheckLevel), "How thorough the block verification is."}, @@ -1092,7 +1160,9 @@ static UniValue verifychain(const JSONRPCRequest& request) HelpExampleCli("verifychain", "") + HelpExampleRpc("verifychain", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); @@ -1103,6 +1173,8 @@ static UniValue verifychain(const JSONRPCRequest& request) return CVerifyDB().VerifyDB( Params(), &::ChainstateActive().CoinsTip(), nCheckLevel, nCheckDepth); +}, + }; } static void BuriedForkDescPushBack(UniValue& softforks, const std::string &name, int height) EXCLUSIVE_LOCKS_REQUIRED(cs_main) @@ -1171,9 +1243,9 @@ static void BIP9SoftForkDescPushBack(UniValue& softforks, const std::string &nam softforks.pushKV(name, rv); } -UniValue getblockchaininfo(const JSONRPCRequest& request) +RPCMan getblockchaininfo() { - RPCHelpMan{"getblockchaininfo", + return RPCMan{"getblockchaininfo", "Returns an object containing various state info regarding blockchain processing.\n", {}, RPCResult{ @@ -1224,7 +1296,9 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) HelpExampleCli("getblockchaininfo", "") + HelpExampleRpc("getblockchaininfo", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); @@ -1270,6 +1344,8 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) obj.pushKV("warnings", GetWarnings(false)); return obj; +}, + }; } /** Comparison function for sorting the getchaintips heads. */ @@ -1287,9 +1363,9 @@ struct CompareBlocksByHeight } }; -static UniValue getchaintips(const JSONRPCRequest& request) +static RPCMan getchaintips() { - RPCHelpMan{"getchaintips", + return RPCMan{"getchaintips", "Return information about all known tips in the block tree," " including the main chain as well as orphaned branches.\n", {}, @@ -1312,7 +1388,9 @@ static UniValue getchaintips(const JSONRPCRequest& request) HelpExampleCli("getchaintips", "") + HelpExampleRpc("getchaintips", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); @@ -1382,6 +1460,8 @@ static UniValue getchaintips(const JSONRPCRequest& request) } return res; +}, + }; } UniValue MempoolInfoToJSON(const CTxMemPool& pool) @@ -1401,9 +1481,9 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool) return ret; } -static UniValue getmempoolinfo(const JSONRPCRequest& request) +static RPCMan getmempoolinfo() { - RPCHelpMan{"getmempoolinfo", + return RPCMan{"getmempoolinfo", "\nReturns details on the active state of the TX memory pool.\n", {}, RPCResult{ @@ -1421,14 +1501,18 @@ static UniValue getmempoolinfo(const JSONRPCRequest& request) HelpExampleCli("getmempoolinfo", "") + HelpExampleRpc("getmempoolinfo", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); return MempoolInfoToJSON(EnsureMemPool()); +}, + }; } -static UniValue preciousblock(const JSONRPCRequest& request) +static RPCMan preciousblock() { - RPCHelpMan{"preciousblock", + return RPCMan{"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" "\nThe effects of preciousblock are not retained across restarts.\n", @@ -1440,7 +1524,9 @@ static UniValue preciousblock(const JSONRPCRequest& request) HelpExampleCli("preciousblock", "\"blockhash\"") + HelpExampleRpc("preciousblock", "\"blockhash\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); uint256 hash(ParseHashV(request.params[0], "blockhash")); CBlockIndex* pblockindex; @@ -1461,11 +1547,13 @@ static UniValue preciousblock(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } -static UniValue invalidateblock(const JSONRPCRequest& request) +static RPCMan invalidateblock() { - RPCHelpMan{"invalidateblock", + return RPCMan{"invalidateblock", "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n", { {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as invalid"}, @@ -1475,7 +1563,9 @@ static UniValue invalidateblock(const JSONRPCRequest& request) HelpExampleCli("invalidateblock", "\"blockhash\"") + HelpExampleRpc("invalidateblock", "\"blockhash\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); uint256 hash(ParseHashV(request.params[0], "blockhash")); BlockValidationState state; @@ -1499,11 +1589,13 @@ static UniValue invalidateblock(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } -static UniValue reconsiderblock(const JSONRPCRequest& request) +static RPCMan reconsiderblock() { - RPCHelpMan{"reconsiderblock", + return RPCMan{"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", { @@ -1514,7 +1606,9 @@ static UniValue reconsiderblock(const JSONRPCRequest& request) HelpExampleCli("reconsiderblock", "\"blockhash\"") + HelpExampleRpc("reconsiderblock", "\"blockhash\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); uint256 hash(ParseHashV(request.params[0], "blockhash")); @@ -1536,11 +1630,13 @@ static UniValue reconsiderblock(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } -static UniValue getchaintxstats(const JSONRPCRequest& request) +static RPCMan getchaintxstats() { - RPCHelpMan{"getchaintxstats", + return RPCMan{"getchaintxstats", "\nCompute statistics about the total number and rate of transactions in the chain.\n", { {"nblocks", RPCArg::Type::NUM, /* default */ "one month", "Size of the window in number of blocks"}, @@ -1562,7 +1658,9 @@ static UniValue getchaintxstats(const JSONRPCRequest& request) HelpExampleCli("getchaintxstats", "") + HelpExampleRpc("getchaintxstats", "2016") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); const CBlockIndex* pindex; int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month @@ -1613,6 +1711,8 @@ static UniValue getchaintxstats(const JSONRPCRequest& request) } return ret; +}, + }; } template @@ -1671,9 +1771,9 @@ static inline bool SetHasKeys(const std::set& set, const Tk& key, const Args& // outpoint (needed for the utxo index) + nHeight + fCoinBase static constexpr size_t PER_UTXO_OVERHEAD = sizeof(COutPoint) + sizeof(uint32_t) + sizeof(bool); -static UniValue getblockstats(const JSONRPCRequest& request) +static RPCMan getblockstats() { - RPCHelpMan{"getblockstats", + return RPCMan{"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", { @@ -1729,7 +1829,9 @@ static UniValue getblockstats(const JSONRPCRequest& request) HelpExampleCli("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'") + HelpExampleRpc("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); @@ -1926,11 +2028,13 @@ static UniValue getblockstats(const JSONRPCRequest& request) ret.pushKV(stat, value); } return ret; +}, + }; } -static UniValue savemempool(const JSONRPCRequest& request) +static RPCMan savemempool() { - RPCHelpMan{"savemempool", + return RPCMan{"savemempool", "\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n", {}, RPCResult{RPCResult::Type::NONE, "", ""}, @@ -1938,7 +2042,9 @@ static UniValue savemempool(const JSONRPCRequest& request) HelpExampleCli("savemempool", "") + HelpExampleRpc("savemempool", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); const CTxMemPool& mempool = EnsureMemPool(); @@ -1951,6 +2057,8 @@ static UniValue savemempool(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } //! Search for a given set of pubkey scripts @@ -2012,9 +2120,9 @@ class CoinsViewScanReserver } }; -UniValue scantxoutset(const JSONRPCRequest& request) +static RPCMan scantxoutset() { - RPCHelpMan{"scantxoutset", + return RPCMan{"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" "Examples of output descriptors are:\n" @@ -2068,7 +2176,9 @@ UniValue scantxoutset(const JSONRPCRequest& request) {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of all found unspent outputs in " + CURRENCY_UNIT}, }}, RPCExamples{""}, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}); @@ -2161,11 +2271,13 @@ UniValue scantxoutset(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid command"); } return result; +}, + }; } -static UniValue getblockfilter(const JSONRPCRequest& request) +static RPCMan getblockfilter() { - RPCHelpMan{"getblockfilter", + return RPCMan{"getblockfilter", "\nRetrieve a BIP 157 content filter for a particular block.\n", { {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hash of the block"}, @@ -2180,8 +2292,10 @@ static UniValue getblockfilter(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"") + HelpExampleRpc("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\", \"basic\"") - } - }.Check(request); + }, + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); uint256 block_hash = ParseHashV(request.params[0], "blockhash"); std::string filtertype_name = "basic"; @@ -2237,6 +2351,8 @@ static UniValue getblockfilter(const JSONRPCRequest& request) ret.pushKV("filter", HexStr(filter.GetEncodedFilter())); ret.pushKV("header", filter_header.GetHex()); return ret; +}, + }; } /** @@ -2244,9 +2360,9 @@ static UniValue getblockfilter(const JSONRPCRequest& request) * * @see SnapshotMetadata */ -UniValue dumptxoutset(const JSONRPCRequest& request) +static RPCMan dumptxoutset() { - RPCHelpMan{ + return RPCMan{ "dumptxoutset", "\nWrite the serialized UTXO set to disk.\n" "Incidentally flushes the latest coinsdb (leveldb) to disk.\n", @@ -2268,8 +2384,10 @@ UniValue dumptxoutset(const JSONRPCRequest& request) }, RPCExamples{ HelpExampleCli("dumptxoutset", "utxo.dat") - } - }.Check(request); + }, + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); fs::path path = fs::absolute(request.params[0].get_str(), GetDataDir()); // Write to a temporary path and then move into `path` on completion @@ -2345,6 +2463,8 @@ UniValue dumptxoutset(const JSONRPCRequest& request) result.pushKV("base_height", tip->nHeight); result.pushKV("path", path.string()); return result; +}, + }; } // clang-format off diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index bde19d8e791ef..cfaf55024d811 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -79,9 +79,9 @@ static UniValue GetNetworkHashPS(int lookup, int height) { return workDiff.getdouble() / timeDiff; } -static UniValue getnetworkhashps(const JSONRPCRequest& request) +static RPCMan getnetworkhashps() { - RPCHelpMan{"getnetworkhashps", + return RPCMan{"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" "Pass in [height] to estimate the network speed at the time when a certain block was found.\n", @@ -95,10 +95,14 @@ static UniValue getnetworkhashps(const JSONRPCRequest& request) HelpExampleCli("getnetworkhashps", "") + HelpExampleRpc("getnetworkhashps", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.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); +}, + }; } static UniValue generateBlocks(const CTxMemPool& mempool, const CScript& coinbase_script, int nGenerate, uint64_t nMaxTries) @@ -142,9 +146,9 @@ static UniValue generateBlocks(const CTxMemPool& mempool, const CScript& coinbas return blockHashes; } -static UniValue generatetodescriptor(const JSONRPCRequest& request) +static RPCMan generatetodescriptor() { - RPCHelpMan{ + return RPCMan{ "generatetodescriptor", "\nMine blocks immediately to a specified descriptor (before the RPC call returns)\n", { @@ -160,8 +164,9 @@ static UniValue generatetodescriptor(const JSONRPCRequest& request) }, RPCExamples{ "\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")}, - } - .Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); const int num_blocks{request.params[0].get_int()}; const int64_t max_tries{request.params[2].isNull() ? 1000000 : request.params[2].get_int()}; @@ -187,11 +192,13 @@ static UniValue generatetodescriptor(const JSONRPCRequest& request) CHECK_NONFATAL(coinbase_script.size() == 1); return generateBlocks(mempool, coinbase_script.at(0), num_blocks, max_tries); +}, + }; } -static UniValue generatetoaddress(const JSONRPCRequest& request) +static RPCMan generatetoaddress() { - RPCHelpMan{"generatetoaddress", + return RPCMan{"generatetoaddress", "\nMine blocks immediately to a specified address (before the RPC call returns)\n", { {"nblocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated immediately."}, @@ -209,7 +216,9 @@ 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", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); int nGenerate = request.params[0].get_int(); uint64_t nMaxTries = 1000000; @@ -227,11 +236,13 @@ static UniValue generatetoaddress(const JSONRPCRequest& request) CScript coinbase_script = GetScriptForDestination(destination); return generateBlocks(mempool, coinbase_script, nGenerate, nMaxTries); +}, + }; } -static UniValue getmininginfo(const JSONRPCRequest& request) +static RPCMan getmininginfo() { - RPCHelpMan{"getmininginfo", + return RPCMan{"getmininginfo", "\nReturns a json object containing mining-related information.", {}, RPCResult{ @@ -250,7 +261,9 @@ static UniValue getmininginfo(const JSONRPCRequest& request) HelpExampleCli("getmininginfo", "") + HelpExampleRpc("getmininginfo", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); const CTxMemPool& mempool = EnsureMemPool(); @@ -260,18 +273,20 @@ static UniValue getmininginfo(const JSONRPCRequest& request) if (BlockAssembler::m_last_block_weight) obj.pushKV("currentblockweight", *BlockAssembler::m_last_block_weight); if (BlockAssembler::m_last_block_num_txs) obj.pushKV("currentblocktx", *BlockAssembler::m_last_block_num_txs); obj.pushKV("difficulty", (double)GetDifficulty(::ChainActive().Tip())); - obj.pushKV("networkhashps", getnetworkhashps(request)); + obj.pushKV("networkhashps", CALL_RPC_METHOD(getnetworkhashps, request)); obj.pushKV("pooledtx", (uint64_t)mempool.size()); obj.pushKV("chain", Params().NetworkIDString()); obj.pushKV("warnings", GetWarnings(false)); return obj; +}, + }; } // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts -static UniValue prioritisetransaction(const JSONRPCRequest& request) +static RPCMan prioritisetransaction() { - RPCHelpMan{"prioritisetransaction", + return RPCMan{"prioritisetransaction", "Accepts the transaction into mined blocks at a higher (or lower) priority\n", { {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id."}, @@ -288,7 +303,9 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request) HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000") + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); @@ -301,6 +318,8 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request) EnsureMemPool().PrioritiseTransaction(hash, nAmount); return true; +}, + }; } @@ -332,9 +351,9 @@ static std::string gbt_vb_name(const Consensus::DeploymentPos pos) { return s; } -static UniValue getblocktemplate(const JSONRPCRequest& request) +static RPCMan getblocktemplate() { - RPCHelpMan{"getblocktemplate", + return RPCMan{"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" "For full specification, see BIPs 22, 23, 9, and 145:\n" @@ -416,7 +435,9 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) HelpExampleCli("getblocktemplate", "'{\"rules\": [\"segwit\"]}'") + HelpExampleRpc("getblocktemplate", "{\"rules\": [\"segwit\"]}") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); @@ -722,6 +743,8 @@ static UniValue getblocktemplate(const JSONRPCRequest& request) } return result; +}, + }; } class submitblock_StateCatcher : public CValidationInterface @@ -742,10 +765,10 @@ class submitblock_StateCatcher : public CValidationInterface } }; -static UniValue submitblock(const JSONRPCRequest& request) +static RPCMan submitblock() { // We allow 2 arguments for compliance with BIP22. Argument 2 is ignored. - RPCHelpMan{"submitblock", + return RPCMan{"submitblock", "\nAttempts to submit new block to network.\n" "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n", { @@ -757,7 +780,9 @@ static UniValue submitblock(const JSONRPCRequest& request) HelpExampleCli("submitblock", "\"mydata\"") + HelpExampleRpc("submitblock", "\"mydata\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); std::shared_ptr blockptr = std::make_shared(); CBlock& block = *blockptr; @@ -803,11 +828,13 @@ static UniValue submitblock(const JSONRPCRequest& request) return "inconclusive"; } return BIP22ValidationResult(sc.state); +}, + }; } -static UniValue submitheader(const JSONRPCRequest& request) +static RPCMan submitheader() { - RPCHelpMan{"submitheader", + return RPCMan{"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", { @@ -819,7 +846,9 @@ static UniValue submitheader(const JSONRPCRequest& request) HelpExampleCli("submitheader", "\"aabbcc\"") + HelpExampleRpc("submitheader", "\"aabbcc\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); CBlockHeader h; if (!DecodeHexBlockHeader(h, request.params[0].get_str())) { @@ -839,11 +868,13 @@ static UniValue submitheader(const JSONRPCRequest& request) throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString()); } throw JSONRPCError(RPC_VERIFY_ERROR, state.GetRejectReason()); +}, + }; } -static UniValue estimatesmartfee(const JSONRPCRequest& request) +static RPCMan estimatesmartfee() { - RPCHelpMan{"estimatesmartfee", + return RPCMan{"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" "for which the estimate is valid. Uses virtual transaction size as defined\n" @@ -877,7 +908,9 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("estimatesmartfee", "6") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR}); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); @@ -904,11 +937,13 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request) } result.pushKV("blocks", feeCalc.returnedTarget); return result; +}, + }; } -static UniValue estimaterawfee(const JSONRPCRequest& request) +static RPCMan estimaterawfee() { - RPCHelpMan{"estimaterawfee", + return RPCMan{"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" " implementation of fee estimation. The parameters it can be called with\n" @@ -960,7 +995,9 @@ static UniValue estimaterawfee(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("estimaterawfee", "6 0.9") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); @@ -1020,6 +1057,8 @@ static UniValue estimaterawfee(const JSONRPCRequest& request) result.pushKV(StringForFeeEstimateHorizon(horizon), horizon_result); } return result; +}, + }; } // clang-format off diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index c87c1a54189f0..a6e039510b9da 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -25,9 +25,9 @@ #include -static UniValue validateaddress(const JSONRPCRequest& request) +static RPCMan validateaddress() { - RPCHelpMan{"validateaddress", + return RPCMan{"validateaddress", "\nReturn information about the given bitcoin address.\n", { {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to validate"}, @@ -48,7 +48,9 @@ static UniValue validateaddress(const JSONRPCRequest& request) HelpExampleCli("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") + HelpExampleRpc("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); CTxDestination dest = DecodeDestination(request.params[0].get_str()); bool isValid = IsValidDestination(dest); @@ -67,11 +69,13 @@ static UniValue validateaddress(const JSONRPCRequest& request) ret.pushKVs(detail); } return ret; +}, + }; } -static UniValue createmultisig(const JSONRPCRequest& request) +static RPCMan createmultisig() { - RPCHelpMan{"createmultisig", + return RPCMan{"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,7 +100,9 @@ static UniValue createmultisig(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); int required = request.params[0].get_int(); @@ -133,11 +139,13 @@ static UniValue createmultisig(const JSONRPCRequest& request) result.pushKV("descriptor", descriptor->ToString()); return result; +}, + }; } -UniValue getdescriptorinfo(const JSONRPCRequest& request) +static RPCMan getdescriptorinfo() { - RPCHelpMan{"getdescriptorinfo", + return RPCMan{"getdescriptorinfo", {"\nAnalyses a descriptor.\n"}, { {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."}, @@ -155,7 +163,10 @@ UniValue getdescriptorinfo(const JSONRPCRequest& request) RPCExamples{ "Analyse a descriptor\n" + HelpExampleCli("getdescriptorinfo", "\"wpkh([d34db33f/84h/0h/0h]0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2dce28d959f2815b16f81798)\"") - }}.Check(request); + }, + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -173,11 +184,13 @@ UniValue getdescriptorinfo(const JSONRPCRequest& request) result.pushKV("issolvable", desc->IsSolvable()); result.pushKV("hasprivatekeys", provider.keys.size() > 0); return result; +}, + }; } -UniValue deriveaddresses(const JSONRPCRequest& request) +static RPCMan deriveaddresses() { - RPCHelpMan{"deriveaddresses", + return RPCMan{"deriveaddresses", {"\nDerives one or more addresses corresponding to an output descriptor.\n" "Examples of output descriptors are:\n" " pkh() P2PKH outputs for the given pubkey\n" @@ -200,7 +213,10 @@ 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]\"") - }}.Check(request); + }, + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType()}); // Range argument is checked later const std::string desc_str = request.params[0].get_str(); @@ -252,11 +268,13 @@ UniValue deriveaddresses(const JSONRPCRequest& request) } return addresses; +}, + }; } -static UniValue verifymessage(const JSONRPCRequest& request) +static RPCMan verifymessage() { - RPCHelpMan{"verifymessage", + return RPCMan{"verifymessage", "\nVerify a signed message\n", { {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the signature."}, @@ -276,7 +294,9 @@ static UniValue verifymessage(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); @@ -299,11 +319,13 @@ static UniValue verifymessage(const JSONRPCRequest& request) } return false; +}, + }; } -static UniValue signmessagewithprivkey(const JSONRPCRequest& request) +static RPCMan signmessagewithprivkey() { - RPCHelpMan{"signmessagewithprivkey", + return RPCMan{"signmessagewithprivkey", "\nSign a message with the private key of an address\n", { {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."}, @@ -320,7 +342,9 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); std::string strPrivkey = request.params[0].get_str(); std::string strMessage = request.params[1].get_str(); @@ -337,11 +361,13 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request) } return signature; +}, + }; } -static UniValue setmocktime(const JSONRPCRequest& request) +static RPCMan setmocktime() { - RPCHelpMan{"setmocktime", + return RPCMan{"setmocktime", "\nSet the local time to given timestamp (-regtest only)\n", { {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, UNIX_EPOCH_TIME + "\n" @@ -349,7 +375,9 @@ static UniValue setmocktime(const JSONRPCRequest& request) }, RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{""}, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if (!Params().IsMockableChain()) { throw std::runtime_error("setmocktime is for regression testing (-regtest mode) only"); @@ -366,18 +394,22 @@ static UniValue setmocktime(const JSONRPCRequest& request) SetMockTime(request.params[0].get_int64()); return NullUniValue; +}, + }; } -static UniValue mockscheduler(const JSONRPCRequest& request) +static RPCMan mockscheduler() { - RPCHelpMan{"mockscheduler", + return RPCMan{"mockscheduler", "\nBump the scheduler into the future (-regtest only)\n", { {"delta_time", RPCArg::Type::NUM, RPCArg::Optional::NO, "Number of seconds to forward the scheduler into the future." }, }, RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{""}, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if (!Params().IsMockableChain()) { throw std::runtime_error("mockscheduler is for regression testing (-regtest mode) only"); @@ -396,6 +428,8 @@ static UniValue mockscheduler(const JSONRPCRequest& request) g_rpc_node->scheduler->MockForward(std::chrono::seconds(delta_seconds)); return NullUniValue; +}, + }; } static UniValue RPCLockedMemoryInfo() @@ -430,12 +464,12 @@ static std::string RPCMallocInfo() } #endif -static UniValue getmemoryinfo(const JSONRPCRequest& request) +static RPCMan getmemoryinfo() { /* Please, avoid using the word "pool" here in the RPC interface or help, * as users will undoubtedly confuse it with the other "memory pool" */ - RPCHelpMan{"getmemoryinfo", + return RPCMan{"getmemoryinfo", "Returns an object containing information about memory usage.\n", { {"mode", RPCArg::Type::STR, /* default */ "\"stats\"", "determines what kind of information is returned.\n" @@ -465,7 +499,9 @@ static UniValue getmemoryinfo(const JSONRPCRequest& request) HelpExampleCli("getmemoryinfo", "") + HelpExampleRpc("getmemoryinfo", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); std::string mode = request.params[0].isNull() ? "stats" : request.params[0].get_str(); if (mode == "stats") { @@ -481,6 +517,8 @@ static UniValue getmemoryinfo(const JSONRPCRequest& request) } else { throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown mode " + mode); } +}, + }; } static void EnableOrDisableLogCategories(UniValue cats, bool enable) { @@ -501,9 +539,9 @@ static void EnableOrDisableLogCategories(UniValue cats, bool enable) { } } -UniValue logging(const JSONRPCRequest& request) +static RPCMan logging() { - RPCHelpMan{"logging", + return RPCMan{"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" "When called with arguments, adds or removes categories from debug logging and return the lists above.\n" @@ -534,7 +572,9 @@ UniValue logging(const JSONRPCRequest& request) HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") + HelpExampleRpc("logging", "[\"all\"], [\"libevent\"]") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); uint32_t original_log_categories = LogInstance().GetCategoryMask(); if (request.params[0].isArray()) { @@ -567,13 +607,13 @@ UniValue logging(const JSONRPCRequest& request) } return result; +}, + }; } -static UniValue echo(const JSONRPCRequest& request) +static RPCMan echo() { - if (request.fHelp) - throw std::runtime_error( - RPCHelpMan{"echo|echojson ...", + return RPCMan{"echo|echojson ...", "\nSimply echo back the input arguments. This command is for testing.\n" "\nIt will return an internal bug report when exactly 100 arguments are passed.\n" "\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in " @@ -581,12 +621,15 @@ static UniValue echo(const JSONRPCRequest& request) {}, RPCResult{RPCResult::Type::NONE, "", "Returns whatever was passed in"}, RPCExamples{""}, - }.ToString() - ); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + if (request.fHelp) throw std::runtime_error(self.ToString()); CHECK_NONFATAL(request.params.size() != 100); return request.params; +}, + }; } // clang-format off diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index caa62ca958870..0b52c6b90786e 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -28,9 +28,9 @@ #include -static UniValue getconnectioncount(const JSONRPCRequest& request) +static RPCMan getconnectioncount() { - RPCHelpMan{"getconnectioncount", + return RPCMan{"getconnectioncount", "\nReturns the number of connections to other nodes.\n", {}, RPCResult{ @@ -40,17 +40,21 @@ static UniValue getconnectioncount(const JSONRPCRequest& request) HelpExampleCli("getconnectioncount", "") + HelpExampleRpc("getconnectioncount", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); return (int)g_rpc_node->connman->GetNodeCount(CConnman::CONNECTIONS_ALL); +}, + }; } -static UniValue ping(const JSONRPCRequest& request) +static RPCMan ping() { - RPCHelpMan{"ping", + return RPCMan{"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" "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n", @@ -60,7 +64,9 @@ static UniValue ping(const JSONRPCRequest& request) HelpExampleCli("ping", "") + HelpExampleRpc("ping", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -70,11 +76,13 @@ static UniValue ping(const JSONRPCRequest& request) pnode->fPingQueued = true; }); return NullUniValue; +}, + }; } -static UniValue getpeerinfo(const JSONRPCRequest& request) +static RPCMan getpeerinfo() { - RPCHelpMan{"getpeerinfo", + return RPCMan{"getpeerinfo", "\nReturns data about each connected network node as a json array of objects.\n", {}, RPCResult{ @@ -137,7 +145,9 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) HelpExampleCli("getpeerinfo", "") + HelpExampleRpc("getpeerinfo", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -222,17 +232,13 @@ static UniValue getpeerinfo(const JSONRPCRequest& request) } return ret; +}, + }; } -static UniValue addnode(const JSONRPCRequest& request) +static RPCMan addnode() { - std::string strCommand; - if (!request.params[1].isNull()) - strCommand = request.params[1].get_str(); - if (request.fHelp || request.params.size() != 2 || - (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) - throw std::runtime_error( - RPCHelpMan{"addnode", + return RPCMan{"addnode", "\nAttempts to add or remove a node from the addnode list.\n" "Or try a connection to a node once.\n" "Nodes added using addnode (or -connect) are protected from DoS disconnection and are not required to be\n" @@ -246,7 +252,15 @@ static UniValue addnode(const JSONRPCRequest& request) HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"") + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"") }, - }.ToString()); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::string strCommand; + if (!request.params[1].isNull()) + strCommand = request.params[1].get_str(); + if (request.fHelp || request.params.size() != 2 || + (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) + throw std::runtime_error( + self.ToString()); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -272,11 +286,13 @@ static UniValue addnode(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } -static UniValue disconnectnode(const JSONRPCRequest& request) +static RPCMan disconnectnode() { - RPCHelpMan{"disconnectnode", + return RPCMan{"disconnectnode", "\nImmediately disconnects from the specified peer node.\n" "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n" "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n", @@ -291,7 +307,9 @@ static UniValue disconnectnode(const JSONRPCRequest& request) + HelpExampleRpc("disconnectnode", "\"192.168.0.6:8333\"") + HelpExampleRpc("disconnectnode", "\"\", 1") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -316,11 +334,13 @@ static UniValue disconnectnode(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } -static UniValue getaddednodeinfo(const JSONRPCRequest& request) +static RPCMan getaddednodeinfo() { - RPCHelpMan{"getaddednodeinfo", + return RPCMan{"getaddednodeinfo", "\nReturns information about the given added node, or all added nodes\n" "(note that onetry addnodes are not listed here)\n", { @@ -348,7 +368,9 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request) HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"") + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -387,11 +409,13 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request) } return ret; +}, + }; } -static UniValue getnettotals(const JSONRPCRequest& request) +static RPCMan getnettotals() { - RPCHelpMan{"getnettotals", + return RPCMan{"getnettotals", "\nReturns information about network traffic, including bytes in, bytes out,\n" "and current time.\n", {}, @@ -416,7 +440,9 @@ static UniValue getnettotals(const JSONRPCRequest& request) HelpExampleCli("getnettotals", "") + HelpExampleRpc("getnettotals", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -434,6 +460,8 @@ static UniValue getnettotals(const JSONRPCRequest& request) outboundLimit.pushKV("time_left_in_cycle", g_rpc_node->connman->GetMaxOutboundTimeLeftInCycle()); obj.pushKV("uploadtarget", outboundLimit); return obj; +}, + }; } static UniValue GetNetworksInfo() @@ -457,9 +485,9 @@ static UniValue GetNetworksInfo() return networks; } -static UniValue getnetworkinfo(const JSONRPCRequest& request) +static RPCMan getnetworkinfo() { - RPCHelpMan{"getnetworkinfo", + return RPCMan{"getnetworkinfo", "Returns an object containing various state info regarding P2P networking.\n", {}, RPCResult{ @@ -506,7 +534,9 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request) HelpExampleCli("getnetworkinfo", "") + HelpExampleRpc("getnetworkinfo", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(cs_main); UniValue obj(UniValue::VOBJ); @@ -542,11 +572,13 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request) obj.pushKV("localaddresses", localAddresses); obj.pushKV("warnings", GetWarnings(false)); return obj; +}, + }; } -static UniValue setban(const JSONRPCRequest& request) +static RPCMan setban() { - const RPCHelpMan help{"setban", + return RPCMan{"setban", "\nAttempts to add or remove an IP/Subnet from the banned list.\n", { {"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"}, @@ -560,7 +592,8 @@ static UniValue setban(const JSONRPCRequest& request) + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400") }, - }; + [&](const RPCMan& help, const JSONRPCRequest& request) -> UniValue +{ std::string strCommand; if (!request.params[1].isNull()) strCommand = request.params[1].get_str(); @@ -622,11 +655,13 @@ static UniValue setban(const JSONRPCRequest& request) } } return NullUniValue; +}, + }; } -static UniValue listbanned(const JSONRPCRequest& request) +static RPCMan listbanned() { - RPCHelpMan{"listbanned", + return RPCMan{"listbanned", "\nList all banned IPs/Subnets.\n", {}, RPCResult{RPCResult::Type::ARR, "", "", @@ -643,7 +678,9 @@ static UniValue listbanned(const JSONRPCRequest& request) HelpExampleCli("listbanned", "") + HelpExampleRpc("listbanned", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if(!g_rpc_node->banman) { throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); @@ -666,11 +703,13 @@ static UniValue listbanned(const JSONRPCRequest& request) } return bannedAddresses; +}, + }; } -static UniValue clearbanned(const JSONRPCRequest& request) +static RPCMan clearbanned() { - RPCHelpMan{"clearbanned", + return RPCMan{"clearbanned", "\nClear all banned IPs.\n", {}, RPCResult{RPCResult::Type::NONE, "", ""}, @@ -678,7 +717,9 @@ static UniValue clearbanned(const JSONRPCRequest& request) HelpExampleCli("clearbanned", "") + HelpExampleRpc("clearbanned", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if (!g_rpc_node->banman) { throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); } @@ -686,18 +727,22 @@ static UniValue clearbanned(const JSONRPCRequest& request) g_rpc_node->banman->ClearBanned(); return NullUniValue; +}, + }; } -static UniValue setnetworkactive(const JSONRPCRequest& request) +static RPCMan setnetworkactive() { - RPCHelpMan{"setnetworkactive", + return RPCMan{"setnetworkactive", "\nDisable/enable all p2p network activity.\n", { {"state", RPCArg::Type::BOOL, RPCArg::Optional::NO, "true to enable networking, false to disable"}, }, RPCResult{RPCResult::Type::BOOL, "", "The value that was passed in"}, RPCExamples{""}, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if (!g_rpc_node->connman) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -706,11 +751,13 @@ static UniValue setnetworkactive(const JSONRPCRequest& request) g_rpc_node->connman->SetNetworkActive(request.params[0].get_bool()); return g_rpc_node->connman->GetNetworkActive(); +}, + }; } -static UniValue getnodeaddresses(const JSONRPCRequest& request) +static RPCMan getnodeaddresses() { - RPCHelpMan{"getnodeaddresses", + return RPCMan{"getnodeaddresses", "\nReturn known addresses which can potentially be used to find new nodes in the network\n", { {"count", RPCArg::Type::NUM, /* default */ "1", "How many addresses to return. Limited to the smaller of " + ToString(ADDRMAN_GETADDR_MAX) + " or " + ToString(ADDRMAN_GETADDR_MAX_PCT) + "% of all known addresses."}, @@ -731,7 +778,9 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request) HelpExampleCli("getnodeaddresses", "8") + HelpExampleRpc("getnodeaddresses", "8") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); if (!g_rpc_node->connman) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } @@ -758,6 +807,8 @@ static UniValue getnodeaddresses(const JSONRPCRequest& request) ret.push_back(obj); } return ret; +}, + }; } // clang-format off diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index ae3f15cec2d5d..7450d59ea3da2 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -72,9 +72,9 @@ static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& } } -static UniValue getrawtransaction(const JSONRPCRequest& request) +static RPCMan getrawtransaction() { - RPCHelpMan{ + return RPCMan{ "getrawtransaction", "\nReturn the raw transaction data.\n" @@ -160,7 +160,9 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) + HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"") + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); bool in_active_chain = true; uint256 hash = ParseHashV(request.params[0], "parameter 1"); @@ -220,11 +222,13 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) if (blockindex) result.pushKV("in_active_chain", in_active_chain); TxToJSON(*tx, hash_block, result); return result; +}, + }; } -static UniValue gettxoutproof(const JSONRPCRequest& request) +static RPCMan gettxoutproof() { - RPCHelpMan{"gettxoutproof", + return RPCMan{"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" "unspent output in the utxo for this transaction. To make it always work,\n" @@ -242,7 +246,9 @@ static UniValue gettxoutproof(const JSONRPCRequest& request) RPCResult::Type::STR, "data", "A string that is a serialized, hex-encoded data for the proof." }, RPCExamples{""}, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); std::set setTxids; uint256 oneTxid; @@ -313,11 +319,13 @@ static UniValue gettxoutproof(const JSONRPCRequest& request) ssMB << mb; std::string strHex = HexStr(ssMB.begin(), ssMB.end()); return strHex; +}, + }; } -static UniValue verifytxoutproof(const JSONRPCRequest& request) +static RPCMan verifytxoutproof() { - RPCHelpMan{"verifytxoutproof", + return RPCMan{"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", { @@ -330,7 +338,9 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request) } }, RPCExamples{""}, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); CMerkleBlock merkleBlock; @@ -358,11 +368,13 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request) } return res; +}, + }; } -static UniValue createrawtransaction(const JSONRPCRequest& request) +static RPCMan createrawtransaction() { - RPCHelpMan{"createrawtransaction", + return RPCMan{"createrawtransaction", "\nCreate a transaction spending the given inputs and creating new outputs.\n" "Outputs can be addresses or data.\n" "Returns hex-encoded raw transaction.\n" @@ -410,7 +422,9 @@ static UniValue createrawtransaction(const JSONRPCRequest& request) + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"address\\\":0.01}]\"") + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"data\\\":\\\"00010203\\\"}]\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, { UniValue::VARR, @@ -427,11 +441,13 @@ static UniValue createrawtransaction(const JSONRPCRequest& request) CMutableTransaction rawTx = ConstructTransaction(request.params[0], request.params[1], request.params[2], rbf); return EncodeHexTx(CTransaction(rawTx)); +}, + }; } -static UniValue decoderawtransaction(const JSONRPCRequest& request) +static RPCMan decoderawtransaction() { - RPCHelpMan{"decoderawtransaction", + return RPCMan{"decoderawtransaction", "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n", { {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction hex string"}, @@ -496,7 +512,9 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request) HelpExampleCli("decoderawtransaction", "\"hexstring\"") + HelpExampleRpc("decoderawtransaction", "\"hexstring\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}); @@ -513,6 +531,8 @@ static UniValue decoderawtransaction(const JSONRPCRequest& request) TxToUniv(CTransaction(std::move(mtx)), uint256(), result, false); return result; +}, + }; } static std::string GetAllOutputTypes() @@ -525,9 +545,9 @@ static std::string GetAllOutputTypes() return ret; } -static UniValue decodescript(const JSONRPCRequest& request) +static RPCMan decodescript() { - RPCHelpMan{"decodescript", + return RPCMan{"decodescript", "\nDecode a hex-encoded script.\n", { {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded script"}, @@ -561,7 +581,9 @@ static UniValue decodescript(const JSONRPCRequest& request) HelpExampleCli("decodescript", "\"hexstring\"") + HelpExampleRpc("decodescript", "\"hexstring\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -614,11 +636,13 @@ static UniValue decodescript(const JSONRPCRequest& request) } return r; +}, + }; } -static UniValue combinerawtransaction(const JSONRPCRequest& request) +static RPCMan combinerawtransaction() { - RPCHelpMan{"combinerawtransaction", + return RPCMan{"combinerawtransaction", "\nCombine multiple partially signed transactions into one transaction.\n" "The combined transaction may be another partially signed transaction or a \n" "fully signed transaction.", @@ -635,7 +659,9 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); UniValue txs = request.params[0].get_array(); @@ -697,11 +723,13 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request) } return EncodeHexTx(CTransaction(mergedTx)); +}, + }; } -static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) +static RPCMan signrawtransactionwithkey() { - RPCHelpMan{"signrawtransactionwithkey", + return RPCMan{"signrawtransactionwithkey", "\nSign inputs for raw transaction (serialized, hex-encoded).\n" "The second argument is an array of base58-encoded private\n" "keys that will be the only keys used to sign the transaction.\n" @@ -759,7 +787,9 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) HelpExampleCli("signrawtransactionwithkey", "\"myhex\" \"[\\\"key1\\\",\\\"key2\\\"]\"") + HelpExampleRpc("signrawtransactionwithkey", "\"myhex\", \"[\\\"key1\\\",\\\"key2\\\"]\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true); @@ -792,11 +822,13 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) UniValue result(UniValue::VOBJ); SignTransaction(mtx, &keystore, coins, request.params[3], result); return result; +}, + }; } -static UniValue sendrawtransaction(const JSONRPCRequest& request) +static RPCMan sendrawtransaction() { - RPCHelpMan{"sendrawtransaction", + return RPCMan{"sendrawtransaction", "\nSubmit a raw transaction (serialized, hex-encoded) to local node and network.\n" "\nNote that the transaction will be sent unconditionally to all peers, so using this\n" "for manual rebroadcast may degrade privacy by leaking the transaction's origin, as\n" @@ -821,7 +853,9 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("sendrawtransaction", "\"signedhex\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, { UniValue::VSTR, @@ -853,11 +887,13 @@ static UniValue sendrawtransaction(const JSONRPCRequest& request) } return tx->GetHash().GetHex(); +}, + }; } -static UniValue testmempoolaccept(const JSONRPCRequest& request) +static RPCMan testmempoolaccept() { - RPCHelpMan{"testmempoolaccept", + return RPCMan{"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", @@ -892,7 +928,9 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, { UniValue::VARR, @@ -948,6 +986,8 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) result.push_back(std::move(result_0)); return result; +}, + }; } static std::string WriteHDKeypath(std::vector& keypath) @@ -969,9 +1009,9 @@ static std::string WriteHDKeypath(std::vector& keypath) return keypath_str; } -UniValue decodepsbt(const JSONRPCRequest& request) +static RPCMan decodepsbt() { - RPCHelpMan{"decodepsbt", + return RPCMan{"decodepsbt", "\nReturn a JSON object representing the serialized, base64-encoded partially signed Bitcoin transaction.\n", { {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The PSBT base64 string"}, @@ -1083,7 +1123,9 @@ UniValue decodepsbt(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("decodepsbt", "\"psbt\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -1272,11 +1314,13 @@ UniValue decodepsbt(const JSONRPCRequest& request) } return result; +}, + }; } -UniValue combinepsbt(const JSONRPCRequest& request) +static RPCMan combinepsbt() { - RPCHelpMan{"combinepsbt", + return RPCMan{"combinepsbt", "\nCombine multiple partially signed Bitcoin transactions into one transaction.\n" "Implements the Combiner role.\n", { @@ -1292,7 +1336,9 @@ UniValue combinepsbt(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VARR}, true); @@ -1320,11 +1366,13 @@ UniValue combinepsbt(const JSONRPCRequest& request) CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << merged_psbt; return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size()); +}, + }; } -UniValue finalizepsbt(const JSONRPCRequest& request) +static RPCMan finalizepsbt() { - RPCHelpMan{"finalizepsbt", + return RPCMan{"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" "created which has the final_scriptSig and final_scriptWitness fields filled for inputs that are complete.\n" @@ -1345,7 +1393,9 @@ UniValue finalizepsbt(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("finalizepsbt", "\"psbt\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}, true); @@ -1377,11 +1427,13 @@ UniValue finalizepsbt(const JSONRPCRequest& request) result.pushKV("complete", complete); return result; +}, + }; } -UniValue createpsbt(const JSONRPCRequest& request) +static RPCMan createpsbt() { - RPCHelpMan{"createpsbt", + return RPCMan{"createpsbt", "\nCreates a transaction in the Partially Signed Transaction format.\n" "Implements the Creator role.\n", { @@ -1423,7 +1475,9 @@ UniValue createpsbt(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, { @@ -1455,11 +1509,13 @@ UniValue createpsbt(const JSONRPCRequest& request) ssTx << psbtx; return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size()); +}, + }; } -UniValue converttopsbt(const JSONRPCRequest& request) +static RPCMan converttopsbt() { - RPCHelpMan{"converttopsbt", + return RPCMan{"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", { @@ -1483,7 +1539,9 @@ UniValue converttopsbt(const JSONRPCRequest& request) "\nConvert the transaction to a PSBT\n" + HelpExampleCli("converttopsbt", "\"rawtransaction\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VBOOL}, true); @@ -1522,11 +1580,13 @@ UniValue converttopsbt(const JSONRPCRequest& request) ssTx << psbtx; return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size()); +}, + }; } -UniValue utxoupdatepsbt(const JSONRPCRequest& request) +static RPCMan utxoupdatepsbt() { - RPCHelpMan{"utxoupdatepsbt", + return RPCMan{"utxoupdatepsbt", "\nUpdates all segwit inputs and outputs in a PSBT with data from output descriptors, the UTXO set or the mempool.\n", { {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"}, @@ -1543,7 +1603,10 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request) }, RPCExamples { HelpExampleCli("utxoupdatepsbt", "\"psbt\"") - }}.Check(request); + }, + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}, true); @@ -1610,11 +1673,13 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request) CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << psbtx; return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size()); +}, + }; } -UniValue joinpsbts(const JSONRPCRequest& request) +static RPCMan joinpsbts() { - RPCHelpMan{"joinpsbts", + return RPCMan{"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", { @@ -1628,7 +1693,10 @@ UniValue joinpsbts(const JSONRPCRequest& request) }, RPCExamples { HelpExampleCli("joinpsbts", "\"psbt\"") - }}.Check(request); + }, + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VARR}, true); @@ -1703,11 +1771,13 @@ UniValue joinpsbts(const JSONRPCRequest& request) CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << shuffled_psbt; return EncodeBase64((unsigned char*)ssTx.data(), ssTx.size()); +}, + }; } -UniValue analyzepsbt(const JSONRPCRequest& request) +static RPCMan analyzepsbt() { - RPCHelpMan{"analyzepsbt", + return RPCMan{"analyzepsbt", "\nAnalyzes and provides information about the current status of a PSBT and its inputs\n", { {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"} @@ -1746,7 +1816,10 @@ UniValue analyzepsbt(const JSONRPCRequest& request) }, RPCExamples { HelpExampleCli("analyzepsbt", "\"psbt\"") - }}.Check(request); + }, + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -1811,6 +1884,8 @@ UniValue analyzepsbt(const JSONRPCRequest& request) } return result; +}, + }; } // clang-format off diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index e2618c16dad91..8f972bc88088e 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -127,11 +127,9 @@ std::string CRPCTable::help(const std::string& strCommand, const JSONRPCRequest& return strRet; } -UniValue help(const JSONRPCRequest& jsonRequest) +static RPCMan help() { - if (jsonRequest.fHelp || jsonRequest.params.size() > 1) - throw std::runtime_error( - RPCHelpMan{"help", + return RPCMan{"help", "\nList all commands, or get help for a specified command.\n", { {"command", RPCArg::Type::STR, /* default */ "all commands", "The command to get help on"}, @@ -140,7 +138,12 @@ UniValue help(const JSONRPCRequest& jsonRequest) RPCResult::Type::STR, "", "The help text" }, RPCExamples{""}, - }.ToString() + [&](const RPCMan& self, const JSONRPCRequest& jsonRequest) -> UniValue +{ + self.Check(jsonRequest); + if (jsonRequest.fHelp || jsonRequest.params.size() > 1) + throw std::runtime_error( + self.ToString() ); std::string strCommand; @@ -148,24 +151,27 @@ UniValue help(const JSONRPCRequest& jsonRequest) strCommand = jsonRequest.params[0].get_str(); return tableRPC.help(strCommand, jsonRequest); +}, + }; } - -UniValue stop(const JSONRPCRequest& jsonRequest) +static RPCMan stop() { static const std::string RESULT{PACKAGE_NAME " stopping"}; + return RPCMan{"stop", + "\nRequest a graceful shutdown of " PACKAGE_NAME ".", + {}, + RPCResult{RPCResult::Type::STR, "", "A string with the content '" + RESULT + "'"}, + RPCExamples{""}, + [&](const RPCMan& self, const JSONRPCRequest& jsonRequest) -> UniValue +{ // Accept the deprecated and ignored 'detach' boolean argument // Also accept the hidden 'wait' integer argument (milliseconds) // For instance, 'stop 1000' makes the call wait 1 second before returning // to the client (intended for testing) if (jsonRequest.fHelp || jsonRequest.params.size() > 1) throw std::runtime_error( - RPCHelpMan{"stop", - "\nRequest a graceful shutdown of " PACKAGE_NAME ".", - {}, - RPCResult{RPCResult::Type::STR, "", "A string with the content '" + RESULT + "'"}, - RPCExamples{""}, - }.ToString()); + self.ToString()); // Event loop will exit after current HTTP requests have been handled, so // this reply will get back to the client. StartShutdown(); @@ -173,11 +179,13 @@ UniValue stop(const JSONRPCRequest& jsonRequest) UninterruptibleSleep(std::chrono::milliseconds{jsonRequest.params[0].get_int()}); } return RESULT; +}, + }; } -static UniValue uptime(const JSONRPCRequest& jsonRequest) +static RPCMan uptime() { - RPCHelpMan{"uptime", + return RPCMan{"uptime", "\nReturns the total uptime of the server.\n", {}, RPCResult{ @@ -187,14 +195,18 @@ static UniValue uptime(const JSONRPCRequest& jsonRequest) HelpExampleCli("uptime", "") + HelpExampleRpc("uptime", "") }, - }.Check(jsonRequest); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); return GetTime() - GetStartupTime(); } + }; +} -static UniValue getrpcinfo(const JSONRPCRequest& request) +static RPCMan getrpcinfo() { - RPCHelpMan{"getrpcinfo", + return RPCMan{"getrpcinfo", "\nReturns details of the RPC server.\n", {}, RPCResult{ @@ -214,7 +226,9 @@ static UniValue getrpcinfo(const JSONRPCRequest& request) RPCExamples{ HelpExampleCli("getrpcinfo", "") + HelpExampleRpc("getrpcinfo", "")}, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + self.Check(request); LOCK(g_rpc_server_info.mutex); UniValue active_commands(UniValue::VARR); @@ -234,6 +248,8 @@ static UniValue getrpcinfo(const JSONRPCRequest& request) return result; } + }; +} // clang-format off static const CRPCCommand vRPCCommands[] = diff --git a/src/rpc/server.h b/src/rpc/server.h index c91bf1f613b76..30f351a5be2a4 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -8,11 +8,12 @@ #include #include +#include +#include #include #include #include -#include #include @@ -81,7 +82,7 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface); */ void RPCRunLater(const std::string& name, std::function func, int64_t nSeconds); -typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest); +typedef RPCMan (*rpcfn_type)(); class CRPCCommand { @@ -101,7 +102,7 @@ class CRPCCommand //! Simplified constructor taking plain rpcfn_type function pointer. CRPCCommand(const char* category, const char* name, rpcfn_type fn, std::initializer_list args) : CRPCCommand(category, name, - [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = fn(request); return true; }, + [fn](const JSONRPCRequest& request, UniValue& result, bool) { result = CALL_RPC_METHOD(fn, request); return true; }, {args.begin(), args.end()}, intptr_t(fn)) { } @@ -114,7 +115,7 @@ class CRPCCommand }; /** - * Bitcoin RPC command dispatcher. + * RPC command dispatcher. */ class CRPCTable { diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 7e1fb7a59dba1..ba093eca8c37c 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -410,8 +410,9 @@ struct Sections { } }; -RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector args, RPCResults results, RPCExamples examples) - : m_name{std::move(name)}, +RPCMan::RPCMan(std::string name, std::string description, std::vector args, RPCResults results, RPCExamples examples, RPCMethod fun) + : m_fun{std::move(fun)}, + m_name{std::move(name)}, m_description{std::move(description)}, m_args{std::move(args)}, m_results{std::move(results)}, @@ -445,7 +446,7 @@ std::string RPCExamples::ToDescriptionString() const return m_examples.empty() ? m_examples : "\nExamples:\n" + m_examples; } -bool RPCHelpMan::IsValidNumArgs(size_t num_args) const +bool RPCMan::IsValidNumArgs(size_t num_args) const { size_t num_required_args = 0; for (size_t n = m_args.size(); n > 0; --n) { @@ -456,7 +457,8 @@ bool RPCHelpMan::IsValidNumArgs(size_t num_args) const } return num_required_args <= num_args && num_args <= m_args.size(); } -std::string RPCHelpMan::ToString() const + +std::string RPCMan::ToString() const { std::string ret; diff --git a/src/rpc/util.h b/src/rpc/util.h index f65ad1246b8b6..3ca5810f54071 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -316,10 +316,13 @@ struct RPCExamples { std::string ToDescriptionString() const; }; -class RPCHelpMan +#define CALL_RPC_METHOD(rpc_name, json_request) [&] { const RPCMan& man = rpc_name(); return man.m_fun(man, json_request); }() + +class RPCMan { public: - RPCHelpMan(std::string name, std::string description, std::vector args, RPCResults results, RPCExamples examples); + using RPCMethod = std::function; + RPCMan(std::string name, std::string description, std::vector args, RPCResults results, RPCExamples examples, RPCMethod fun); std::string ToString() const; /** If the supplied number of args is neither too small nor too high */ @@ -334,6 +337,8 @@ class RPCHelpMan } } + const RPCMethod m_fun; + private: const std::string m_name; const std::string m_description; diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index e4d0a3fa6d5fd..56be8c38a7805 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -87,15 +87,9 @@ static void RescanWallet(CWallet& wallet, const WalletRescanReserver& reserver, } } -UniValue importprivkey(const JSONRPCRequest& request) +RPCMan importprivkey() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"importprivkey", + return RPCMan{"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" "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n" @@ -119,7 +113,15 @@ UniValue importprivkey(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet* const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.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"); @@ -189,17 +191,13 @@ UniValue importprivkey(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } -UniValue abortrescan(const JSONRPCRequest& request) +RPCMan abortrescan() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"abortrescan", + return RPCMan{"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", {}, @@ -212,14 +210,7 @@ UniValue abortrescan(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("abortrescan", "") }, - }.Check(request); - - if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false; - pwallet->AbortRescan(); - return true; -} - -UniValue importaddress(const JSONRPCRequest& request) + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue { std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); CWallet* const pwallet = wallet.get(); @@ -227,7 +218,18 @@ UniValue importaddress(const JSONRPCRequest& request) return NullUniValue; } - RPCHelpMan{"importaddress", + self.Check(request); + + if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false; + pwallet->AbortRescan(); + return true; +}, + }; +} + +RPCMan importaddress() +{ + return RPCMan{"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" "may report that the imported address exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n" @@ -251,7 +253,15 @@ UniValue importaddress(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet* const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); EnsureLegacyScriptPubKeyMan(*pwallet, true); @@ -321,17 +331,13 @@ UniValue importaddress(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } -UniValue importprunedfunds(const JSONRPCRequest& request) +RPCMan importprunedfunds() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"importprunedfunds", + return RPCMan{"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", { {"rawtransaction", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A raw transaction in hex funding an already-existing address in wallet"}, @@ -339,7 +345,15 @@ UniValue importprunedfunds(const JSONRPCRequest& request) }, RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{""}, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet* const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); CMutableTransaction tx; if (!DecodeHexTx(tx, request.params[0].get_str())) @@ -382,17 +396,13 @@ UniValue importprunedfunds(const JSONRPCRequest& request) } throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No addresses in wallet correspond to included transaction"); +}, + }; } -UniValue removeprunedfunds(const JSONRPCRequest& request) +RPCMan removeprunedfunds() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"removeprunedfunds", + return RPCMan{"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", { {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded id of the transaction you are deleting"}, @@ -403,7 +413,15 @@ UniValue removeprunedfunds(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet* const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -422,17 +440,13 @@ UniValue removeprunedfunds(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } -UniValue importpubkey(const JSONRPCRequest& request) +RPCMan importpubkey() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"importpubkey", + return RPCMan{"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" "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n" @@ -452,7 +466,15 @@ UniValue importpubkey(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet* const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); EnsureLegacyScriptPubKeyMan(*wallet, true); @@ -510,18 +532,14 @@ UniValue importpubkey(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } -UniValue importwallet(const JSONRPCRequest& request) +RPCMan importwallet() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"importwallet", + return RPCMan{"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", { @@ -536,7 +554,15 @@ UniValue importwallet(const JSONRPCRequest& request) "\nImport using the json rpc call\n" + HelpExampleRpc("importwallet", "\"test\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet* const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); EnsureLegacyScriptPubKeyMan(*wallet, true); @@ -671,17 +697,13 @@ UniValue importwallet(const JSONRPCRequest& request) throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys/scripts to wallet"); return NullUniValue; +}, + }; } -UniValue dumpprivkey(const JSONRPCRequest& request) +RPCMan dumpprivkey() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - const CWallet* const pwallet = wallet.get(); - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"dumpprivkey", + return RPCMan{"dumpprivkey", "\nReveals the private key corresponding to 'address'.\n" "Then the importprivkey can be used with this output\n", { @@ -695,7 +717,15 @@ UniValue dumpprivkey(const JSONRPCRequest& request) + HelpExampleCli("importprivkey", "\"mykey\"") + HelpExampleRpc("dumpprivkey", "\"myaddress\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + const CWallet* const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*wallet); @@ -718,18 +748,14 @@ UniValue dumpprivkey(const JSONRPCRequest& request) throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known"); } return EncodeSecret(vchSecret); +}, + }; } -UniValue dumpwallet(const JSONRPCRequest& request) +RPCMan dumpwallet() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - const CWallet* const pwallet = wallet.get(); - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"dumpwallet", + return RPCMan{"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" "Note that if your wallet contains keys which are not derived from your HD seed (e.g. imported keys), these are not covered by\n" @@ -747,7 +773,15 @@ UniValue dumpwallet(const JSONRPCRequest& request) HelpExampleCli("dumpwallet", "\"test\"") + HelpExampleRpc("dumpwallet", "\"test\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + const CWallet* const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); LegacyScriptPubKeyMan& spk_man = EnsureLegacyScriptPubKeyMan(*wallet); @@ -852,6 +886,8 @@ UniValue dumpwallet(const JSONRPCRequest& request) reply.pushKV("filename", filepath.string()); return reply; +}, + }; } struct ImportData @@ -1262,15 +1298,9 @@ static int64_t GetImportTimestamp(const UniValue& data, int64_t now) throw JSONRPCError(RPC_TYPE_ERROR, "Missing required timestamp field for key"); } -UniValue importmulti(const JSONRPCRequest& mainRequest) +RPCMan importmulti() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(mainRequest); - CWallet* const pwallet = wallet.get(); - if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"importmulti", + return RPCMan{"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" "Conversely, if all the private keys are provided and the address/script is spendable, the watchonly option must be set to false, or a warning will be returned.\n" @@ -1343,8 +1373,15 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) "{ \"scriptPubKey\": { \"address\": \"\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") + HelpExampleCli("importmulti", "'[{ \"scriptPubKey\": { \"address\": \"\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'") }, - }.Check(mainRequest); + [&](const RPCMan& self, const JSONRPCRequest& mainRequest) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(mainRequest); + CWallet* const pwallet = wallet.get(); + if (!EnsureWalletIsAvailable(pwallet, mainRequest.fHelp)) { + return NullUniValue; + } + self.Check(mainRequest); RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ}); @@ -1458,4 +1495,6 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) } return response; +}, + }; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d8b3b57b618fb..721c1f05f7009 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -181,16 +181,9 @@ static std::string LabelFromValue(const UniValue& value) return label; } -static UniValue getnewaddress(const JSONRPCRequest& request) +static RPCMan getnewaddress() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"getnewaddress", + return RPCMan{"getnewaddress", "\nReturns a new Bitcoin address for receiving payments.\n" "If 'label' is specified, it is added to the address book \n" "so payments received with the address will be associated with 'label'.\n", @@ -205,7 +198,16 @@ static UniValue getnewaddress(const JSONRPCRequest& request) HelpExampleCli("getnewaddress", "") + HelpExampleRpc("getnewaddress", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet* const pwallet = wallet.get(); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); LOCK(pwallet->cs_wallet); @@ -232,18 +234,13 @@ static UniValue getnewaddress(const JSONRPCRequest& request) } return EncodeDestination(dest); +}, + }; } -static UniValue getrawchangeaddress(const JSONRPCRequest& request) +static RPCMan getrawchangeaddress() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"getrawchangeaddress", + return RPCMan{"getrawchangeaddress", "\nReturns a new Bitcoin address, for receiving change.\n" "This is for use with raw transactions, NOT normal use.\n", { @@ -256,7 +253,16 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request) HelpExampleCli("getrawchangeaddress", "") + HelpExampleRpc("getrawchangeaddress", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet* const pwallet = wallet.get(); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); LOCK(pwallet->cs_wallet); @@ -277,19 +283,14 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request) throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error); } return EncodeDestination(dest); +}, + }; } -static UniValue setlabel(const JSONRPCRequest& request) +static RPCMan setlabel() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"setlabel", + return RPCMan{"setlabel", "\nSets the label associated with the given address.\n", { {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to be associated with a label."}, @@ -300,7 +301,16 @@ static UniValue setlabel(const JSONRPCRequest& request) HelpExampleCli("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\" \"tabby\"") + HelpExampleRpc("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\", \"tabby\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet* const pwallet = wallet.get(); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); LOCK(pwallet->cs_wallet); @@ -318,6 +328,8 @@ static UniValue setlabel(const JSONRPCRequest& request) } return NullUniValue; +}, + }; } @@ -352,16 +364,9 @@ static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet return tx; } -static UniValue sendtoaddress(const JSONRPCRequest& request) +static RPCMan sendtoaddress() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - CWallet* const pwallet = wallet.get(); - - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"sendtoaddress", + return RPCMan{"sendtoaddress", "\nSend an amount to a given address." + HELP_REQUIRING_PASSPHRASE, { @@ -392,7 +397,16 @@ static UniValue sendtoaddress(const JSONRPCRequest& request) + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" true") + HelpExampleRpc("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 0.1, \"donation\", \"seans outpost\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + CWallet* const pwallet = wallet.get(); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.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 @@ -446,18 +460,13 @@ static UniValue sendtoaddress(const JSONRPCRequest& request) CTransactionRef tx = SendMoney(*locked_chain, pwallet, dest, nAmount, fSubtractFeeFromAmount, coin_control, std::move(mapValue)); return tx->GetHash().GetHex(); +}, + }; } -static UniValue listaddressgroupings(const JSONRPCRequest& request) +static RPCMan listaddressgroupings() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - const CWallet* const pwallet = wallet.get(); - - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"listaddressgroupings", + return RPCMan{"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" "in past transactions\n", @@ -480,7 +489,16 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request) HelpExampleCli("listaddressgroupings", "") + HelpExampleRpc("listaddressgroupings", "") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + const CWallet* const pwallet = wallet.get(); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.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 @@ -508,18 +526,13 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request) jsonGroupings.push_back(jsonGrouping); } return jsonGroupings; +}, + }; } -static UniValue signmessage(const JSONRPCRequest& request) +static RPCMan signmessage() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - const CWallet* const pwallet = wallet.get(); - - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"signmessage", + return RPCMan{"signmessage", "\nSign a message with the private key of an address" + HELP_REQUIRING_PASSPHRASE, { @@ -539,7 +552,16 @@ static UniValue signmessage(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"my message\"") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + const CWallet* const pwallet = wallet.get(); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.Check(request); auto locked_chain = pwallet->chain().lock(); LOCK(pwallet->cs_wallet); @@ -568,18 +590,13 @@ static UniValue signmessage(const JSONRPCRequest& request) } return signature; +}, + }; } -static UniValue getreceivedbyaddress(const JSONRPCRequest& request) +static RPCMan getreceivedbyaddress() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - const CWallet* const pwallet = wallet.get(); - - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"getreceivedbyaddress", + return RPCMan{"getreceivedbyaddress", "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n", { {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address for transactions."}, @@ -598,7 +615,16 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 6") }, - }.Check(request); + [&](const RPCMan& self, const JSONRPCRequest& request) -> UniValue +{ + std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); + const CWallet* const pwallet = wallet.get(); + + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + self.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 @@ -637,19 +663,14 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request) } return ValueFromAmount(nAmount); +}, + }; } -static UniValue getreceivedbylabel(const JSONRPCRequest& request) +static RPCMan getreceivedbylabel() { - std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); - const CWallet* const pwallet = wallet.get(); - - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { - return NullUniValue; - } - - RPCHelpMan{"getreceivedbylabel", + return RPCMan{"getreceivedbylabel", "\nReturns the total amount received by addresses with