diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 71a630eb3ca1..90fd9678920e 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -191,19 +191,17 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn static UniValue getblockcount(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"getblockcount", - "\nReturns the height of the most-work fully-validated chain.\n" - "The genesis block has height 0.\n", - {}, - RPCResult{ - RPCResult::Type::NUM, "", "The current block count"}, - RPCExamples{ - HelpExampleCli("getblockcount", "") - + HelpExampleRpc("getblockcount", "") - }, - }.ToString()); + RPCHelpMan{"getblockcount", + "\nReturns the height of the most-work fully-validated chain.\n" + "The genesis block has height 0.\n", + {}, + RPCResult{ + RPCResult::Type::NUM, "", "The current block count"}, + RPCExamples{ + HelpExampleCli("getblockcount", "") + + HelpExampleRpc("getblockcount", "") + }, + }.Check(request); LOCK(cs_main); return ::ChainActive().Height(); @@ -211,18 +209,16 @@ static UniValue getblockcount(const JSONRPCRequest& request) static UniValue getbestblockhash(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"getbestblockhash", - "\nReturns the hash of the best (tip) block in the most-work fully-validated chain.\n", - {}, - RPCResult{ - RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"}, - RPCExamples{ - HelpExampleCli("getbestblockhash", "") - + HelpExampleRpc("getbestblockhash", "") - }, - }.ToString()); + RPCHelpMan{"getbestblockhash", + "\nReturns the hash of the best (tip) block in the most-work fully-validated chain.\n", + {}, + RPCResult{ + RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"}, + RPCExamples{ + HelpExampleCli("getbestblockhash", "") + + HelpExampleRpc("getbestblockhash", "") + }, + }.Check(request); LOCK(cs_main); return ::ChainActive().Tip()->GetBlockHash().GetHex(); @@ -230,24 +226,22 @@ static UniValue getbestblockhash(const JSONRPCRequest& request) static UniValue getbestchainlock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"getbestchainlock", - "\nReturns information about the best chainlock. Throws an error if there is no known chainlock yet.", - {}, - RPCResult{ - "{\n" - " \"blockhash\" : \"hash\", (string) The block hash hex-encoded\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"signature\" : \"hash\", (string) The chainlock's BLS signature.\n" - " \"known_block\" : true|false (boolean) True if the block is known by our node\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("getbestchainlock", "") - + HelpExampleRpc("getbestchainlock", "") - }, - }.ToString()); + RPCHelpMan{"getbestchainlock", + "\nReturns information about the best chainlock. Throws an error if there is no known chainlock yet.", + {}, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "The block hash hex-encoded"}, + {RPCResult::Type::NUM, "height", "The block height or index"}, + {RPCResult::Type::STR_HEX, "signature", "The chainlock's BLS signature"}, + {RPCResult::Type::BOOL, "known_block", "True if the block is known by our node"}, + }}, + RPCExamples{ + HelpExampleCli("getbestchainlock", "") + + HelpExampleRpc("getbestchainlock", "") + }, + }.Check(request); UniValue result(UniValue::VOBJ); llmq::CChainLockSig clsig = llmq::chainLocksHandler->GetBestChainLock(); @@ -275,25 +269,23 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex) static UniValue waitfornewblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( - RPCHelpMan{"waitfornewblock", - "\nWaits for a specific new block and returns useful info about it.\n" - "\nReturns the current block on timeout or exit.\n", - { - {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."}, - }, - RPCResult{ - RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::STR_HEX, "hash", "The blockhash"}, - {RPCResult::Type::NUM, "height", "Block height"}, - }}, - RPCExamples{ - HelpExampleCli("waitfornewblock", "1000") - + HelpExampleRpc("waitfornewblock", "1000") - }, - }.ToString()); + RPCHelpMan{"waitfornewblock", + "\nWaits for a specific new block and returns useful info about it.\n" + "\nReturns the current block on timeout or exit.\n", + { + {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "The blockhash"}, + {RPCResult::Type::NUM, "height", "Block height"}, + }}, + RPCExamples{ + HelpExampleCli("waitfornewblock", "1000") + + HelpExampleRpc("waitfornewblock", "1000") + }, + }.Check(request); int timeout = 0; if (!request.params[0].isNull()) timeout = request.params[0].get_int(); @@ -316,26 +308,24 @@ static UniValue waitfornewblock(const JSONRPCRequest& request) static UniValue waitforblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"waitforblock", - "\nWaits for a specific new block and returns useful info about it.\n" - "\nReturns the current block on timeout or exit.\n", - { - {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Block hash to wait for."}, - {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."}, - }, - RPCResult{ - RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::STR_HEX, "hash", "The blockhash"}, - {RPCResult::Type::NUM, "height", "Block height"}, - }}, - RPCExamples{ - HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\" 1000") - + HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000") - }, - }.ToString()); + RPCHelpMan{"waitforblock", + "\nWaits for a specific new block and returns useful info about it.\n" + "\nReturns the current block on timeout or exit.\n", + { + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Block hash to wait for."}, + {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "The blockhash"}, + {RPCResult::Type::NUM, "height", "Block height"}, + }}, + RPCExamples{ + HelpExampleCli("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\" 1000") + + HelpExampleRpc("waitforblock", "\"0000000000079f8ef3d2c688c244eb7a4570b24c9ed7b4a8c619eb02596f8862\", 1000") + }, + }.Check(request); int timeout = 0; uint256 hash = uint256S(request.params[0].get_str()); @@ -361,27 +351,25 @@ static UniValue waitforblock(const JSONRPCRequest& request) static UniValue waitforblockheight(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"waitforblockheight", - "\nWaits for (at least) block height and returns the height and hash\n" - "of the current tip.\n" - "\nReturns the current block on timeout or exit.\n", - { - {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "Block height to wait for."}, - {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."}, - }, - RPCResult{ - RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::STR_HEX, "hash", "The blockhash"}, - {RPCResult::Type::NUM, "height", "Block height"}, - }}, - RPCExamples{ - HelpExampleCli("waitforblockheight", "100 1000") - + HelpExampleRpc("waitforblockheight", "100, 1000") - }, - }.ToString()); + RPCHelpMan{"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", + { + {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "Block height to wait for."}, + {"timeout", RPCArg::Type::NUM, /* default */ "0", "Time in milliseconds to wait for a response. 0 indicates no timeout."}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "The blockhash"}, + {RPCResult::Type::NUM, "height", "Block height"}, + }}, + RPCExamples{ + HelpExampleCli("waitforblockheight", "100 1000") + + HelpExampleRpc("waitforblockheight", "100, 1000") + }, + }.Check(request); int timeout = 0; int height = request.params[0].get_int(); @@ -407,70 +395,63 @@ static UniValue waitforblockheight(const JSONRPCRequest& request) static UniValue syncwithvalidationinterfacequeue(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 0) { - throw std::runtime_error( - RPCHelpMan{"syncwithvalidationinterfacequeue", - "\nWaits for the validation interface queue to catch up on everything that was there when we entered this function.\n", - {}, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("syncwithvalidationinterfacequeue","") - + HelpExampleRpc("syncwithvalidationinterfacequeue","") - }, - }.ToString()); - } + RPCHelpMan{"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, "", ""}, + RPCExamples{ + HelpExampleCli("syncwithvalidationinterfacequeue","") + + HelpExampleRpc("syncwithvalidationinterfacequeue","") + }, + }.Check(request); SyncWithValidationInterfaceQueue(); return NullUniValue; } static UniValue getdifficulty(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"getdifficulty", - "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n", - {}, - RPCResult{ - RPCResult::Type::NUM, "", "the proof-of-work difficulty as a multiple of the minimum difficulty."}, - RPCExamples{ - HelpExampleCli("getdifficulty", "") - + HelpExampleRpc("getdifficulty", "") - }, - }.ToString()); + RPCHelpMan{"getdifficulty", + "\nReturns the proof-of-work difficulty as a multiple of the minimum difficulty.\n", + {}, + RPCResult{ + RPCResult::Type::NUM, "", "the proof-of-work difficulty as a multiple of the minimum difficulty."}, + RPCExamples{ + HelpExampleCli("getdifficulty", "") + + HelpExampleRpc("getdifficulty", "") + }, + }.Check(request); LOCK(cs_main); return GetDifficulty(::ChainActive().Tip()); } -static std::string EntryDescriptionString() -{ - return " \"vsize\" : n, (numeric) virtual transaction size. This can be different from actual serialized size for high-sigop transactions.\n" - " \"size\" : n, (numeric) (DEPRECATED) same as vsize. Only returned if dashd is started with -deprecatedrpc=size\n" - " size will be completely removed in v0.20.\n" - " \"fee\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)\n" - " \"modifiedfee\" : n, (numeric) transaction fee with fee deltas used for mining priority (DEPRECATED)\n" - " \"time\" : n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT\n" - " \"height\" : n, (numeric) block height when transaction entered pool\n" - " \"descendantcount\" : n, (numeric) number of in-mempool descendant transactions (including this one)\n" - " \"descendantsize\" : n, (numeric) size of in-mempool descendants (including this one)\n" - " \"descendantfees\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) (DEPRECATED)\n" - " \"ancestorcount\" : n, (numeric) number of in-mempool ancestor transactions (including this one)\n" - " \"ancestorsize\" : n, (numeric) size of in-mempool ancestors (including this one)\n" - " \"ancestorfees\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) (DEPRECATED)\n" - " \"fees\" : {\n" - " \"base\" : n, (numeric) transaction fee in " + CURRENCY_UNIT + "\n" - " \"modified\" : n, (numeric) transaction fee with fee deltas used for mining priority in " + CURRENCY_UNIT + "\n" - " \"ancestor\" : n, (numeric) modified fees (see above) of in-mempool ancestors (including this one) in " + CURRENCY_UNIT + "\n" - " \"descendant\" : n, (numeric) modified fees (see above) of in-mempool descendants (including this one) in " + CURRENCY_UNIT + "\n" - " }\n" - " \"depends\" : [ (json array) unconfirmed transactions used as inputs for this transaction\n" - " \"transactionid\", (string) parent transaction id\n" - " ... ],\n" - " \"spentby\" : [ (json array) unconfirmed transactions spending outputs from this transaction\n" - " \"transactionid\", (string) child transaction id\n" - " ... ]\n" - " \"instantlock\" : true|false (boolean) True if this transaction was locked via InstantSend\n"; -} +static std::vector MempoolEntryDescription() { return { + RPCResult{RPCResult::Type::NUM, "vsize", "virtual transaction size. This can be different from actual serialized size for high-sigop transactions."}, + RPCResult{RPCResult::Type::NUM, "size", "(DEPRECATED) same as vsize. Only returned if dashd is started with -deprecatedrpc=size. " + "size will be completely removed in v0.20."}, + RPCResult{RPCResult::Type::STR_AMOUNT, "fee", "transaction fee in " + CURRENCY_UNIT + " (DEPRECATED)"}, + RPCResult{RPCResult::Type::STR_AMOUNT, "modifiedfee", "transaction fee with fee deltas used for mining priority (DEPRECATED)"}, + RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in seconds since 1 Jan 1970 GMT"}, + RPCResult{RPCResult::Type::NUM, "height", "block height when transaction entered pool"}, + RPCResult{RPCResult::Type::NUM, "descendantcount", "number of in-mempool descendant transactions (including this one)"}, + RPCResult{RPCResult::Type::NUM, "descendantsize", "size of in-mempool descendants (including this one)"}, + RPCResult{RPCResult::Type::STR_AMOUNT, "descendantfees", "modified fees (see above) of in-mempool descendants (including this one) (DEPRECATED)"}, + RPCResult{RPCResult::Type::NUM, "ancestorcount", "number of in-mempool ancestor transactions (including this one)"}, + RPCResult{RPCResult::Type::NUM, "ancestorsize", "size of in-mempool ancestors (including this one)"}, + RPCResult{RPCResult::Type::STR_AMOUNT, "ancestorfees", "modified fees (see above) of in-mempool ancestors (including this one) (DEPRECATED)"}, + RPCResult{RPCResult::Type::OBJ, "fees", "", + { + RPCResult{RPCResult::Type::STR_AMOUNT, "base", "transaction fee in " + CURRENCY_UNIT}, + RPCResult{RPCResult::Type::STR_AMOUNT, "modified", "transaction fee with fee deltas used for mining priority in " + CURRENCY_UNIT}, + RPCResult{RPCResult::Type::STR_AMOUNT, "ancestor", "transaction fees of in-mempool ancestors (including this one) in " + CURRENCY_UNIT}, + RPCResult{RPCResult::Type::STR_AMOUNT, "descendant", "transaction fees of in-mempool descendants (including this one) in " + CURRENCY_UNIT}, + }}, + RPCResult{RPCResult::Type::ARR, "depends", "unconfirmed transactions used as inputs for this transaction", + {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}}, + RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction", + {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}}, + RPCResult{RPCResult::Type::BOOL, "time", "True if this transaction was locked via InstantSend"} +};} static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPoolEntry& e) EXCLUSIVE_LOCKS_REQUIRED(pool.cs) { @@ -551,31 +532,29 @@ UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose) static UniValue getrawmempool(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( - RPCHelpMan{"getrawmempool", - "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" - "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n", + RPCHelpMan{"getrawmempool", + "\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n" + "\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n", + { + {"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"}, + }, + { + RPCResult{"for verbose = false", + RPCResult::Type::ARR, "", "", { - {"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"}, - }, - RPCResult{"for verbose = false", - "[ (json array of string)\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - "]\n" - "\nResult: (for verbose = true):\n" - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - + EntryDescriptionString() - + " }, ...\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("getrawmempool", "true") - + HelpExampleRpc("getrawmempool", "true") - }, - }.ToString()); + {RPCResult::Type::STR_HEX, "", "The transaction id"}, + }}, + RPCResult{"for verbose = true", + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ_DYN, "transactionid", "", MempoolEntryDescription()}, + }}, + }, + RPCExamples{ + HelpExampleCli("getrawmempool", "true") + + HelpExampleRpc("getrawmempool", "true") + }, + }.Check(request); bool fVerbose = false; if (!request.params[0].isNull()) @@ -586,35 +565,25 @@ static UniValue getrawmempool(const JSONRPCRequest& request) static UniValue getmempoolancestors(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( - RPCHelpMan{"getmempoolancestors", - "\nIf txid is in the mempool, returns all in-mempool ancestors.\n", - { - {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"}, - {"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"}, - }, - { - RPCResult{"for verbose = false", - "[ (json array of strings)\n" - " \"transactionid\" (string) The transaction id of an in-mempool ancestor transaction\n" - " ,...\n" - "]\n" - }, - RPCResult{"for verbose = true", - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - + EntryDescriptionString() - + " }, ...\n" - "}\n" - }, - }, - RPCExamples{ - HelpExampleCli("getmempoolancestors", "\"mytxid\"") - + HelpExampleRpc("getmempoolancestors", "\"mytxid\"") - }, - }.ToString()); - } + RPCHelpMan{"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)"}, + {"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"}, + }, + { + RPCResult{"for verbose = false", + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool ancestor transaction"}}}, + RPCResult{"for verbose = true", + RPCResult::Type::OBJ_DYN, "transactionid", "", MempoolEntryDescription() + }, + }, + RPCExamples{ + HelpExampleCli("getmempoolancestors", "\"mytxid\"") + + HelpExampleRpc("getmempoolancestors", "\"mytxid\"") + }, + }.Check(request); bool fVerbose = false; if (!request.params[1].isNull()) @@ -656,35 +625,27 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request) static UniValue getmempooldescendants(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( - RPCHelpMan{"getmempooldescendants", - "\nIf txid is in the mempool, returns all in-mempool descendants.\n", - { - {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"}, - {"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"}, - }, + RPCHelpMan{"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)"}, + {"verbose", RPCArg::Type::BOOL, /* default */ "false", "True for a json object, false for array of transaction ids"}, + }, + { + RPCResult{"for verbose = false", + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::STR_HEX, "", "The transaction id of an in-mempool descendant transaction"}}}, + RPCResult{"for verbose = true", + RPCResult::Type::OBJ, "", "", { - RPCResult{"for verbose = false", - "[ (json array of strings)\n" - " \"transactionid\" (string) The transaction id of an in-mempool descendant transaction\n" - " ,...\n" - "]\n" - }, - RPCResult{"for verbose = true", - "{ (json object)\n" - " \"transactionid\" : { (json object)\n" - + EntryDescriptionString() - + " }, ...\n" - "}\n" - }, - }, - RPCExamples{ - HelpExampleCli("getmempooldescendants", "\"mytxid\"") - + HelpExampleRpc("getmempooldescendants", "\"mytxid\"") - }, - }.ToString()); - } + {RPCResult::Type::OBJ_DYN, "transactionid", "", MempoolEntryDescription()}, + }}, + }, + RPCExamples{ + HelpExampleCli("getmempooldescendants", "\"mytxid\"") + + HelpExampleRpc("getmempooldescendants", "\"mytxid\"") + }, + }.Check(request); bool fVerbose = false; if (!request.params[1].isNull()) @@ -726,24 +687,18 @@ static UniValue getmempooldescendants(const JSONRPCRequest& request) static UniValue getmempoolentry(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( - RPCHelpMan{"getmempoolentry", - "\nReturns mempool data for given transaction\n", - { - {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"}, - }, - RPCResult{ - "{ (json object)\n" - + EntryDescriptionString() - + "}\n" - }, - RPCExamples{ - HelpExampleCli("getmempoolentry", "\"mytxid\"") - + HelpExampleRpc("getmempoolentry", "\"mytxid\"") - }, - }.ToString()); - } + RPCHelpMan{"getmempoolentry", + "\nReturns mempool data for given transaction\n", + { + {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id (must be in mempool)"}, + }, + RPCResult{ + RPCResult::Type::OBJ_DYN, "", "", MempoolEntryDescription()}, + RPCExamples{ + HelpExampleCli("getmempoolentry", "\"mytxid\"") + + HelpExampleRpc("getmempoolentry", "\"mytxid\"") + }, + }.Check(request); uint256 hash = ParseHashV(request.params[0], "parameter 1"); @@ -762,24 +717,20 @@ static UniValue getmempoolentry(const JSONRPCRequest& request) static UniValue getblockhashes(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 2) - throw std::runtime_error( - RPCHelpMan{"getblockhashes", - "\nReturns array of hashes of blocks within the timestamp range provided.\n", - { - {"high", RPCArg::Type::NUM, RPCArg::Optional::NO, "The newer block timestamp"}, - {"low", RPCArg::Type::NUM, RPCArg::Optional::NO, "The older block timestamp"}, - }, - RPCResult{ - "[\n" - " \"hash\" (string) The block hash\n" - "]\n" - }, - RPCExamples{ - HelpExampleCli("getblockhashes", "1231614698 1231024505") - + HelpExampleRpc("getblockhashes", "1231614698, 1231024505") - }, - }.ToString()); + RPCHelpMan{"getblockhashes", + "\nReturns array of hashes of blocks within the timestamp range provided.\n", + { + {"high", RPCArg::Type::NUM, RPCArg::Optional::NO, "The newer block timestamp"}, + {"low", RPCArg::Type::NUM, RPCArg::Optional::NO, "The older block timestamp"}, + }, + RPCResult{ + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::STR_HEX, "", "The block hash"}}}, + RPCExamples{ + HelpExampleCli("getblockhashes", "1231614698 1231024505") + + HelpExampleRpc("getblockhashes", "1231614698, 1231024505") + }, + }.Check(request); unsigned int high = request.params[0].get_int(); unsigned int low = request.params[1].get_int(); @@ -799,20 +750,18 @@ static UniValue getblockhashes(const JSONRPCRequest& request) static UniValue getblockhash(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"getblockhash", - "\nReturns hash of block in best-block-chain at height provided.\n", - { - {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The height index"}, - }, - RPCResult{ - RPCResult::Type::STR_HEX, "", "The block hash"}, - RPCExamples{ - HelpExampleCli("getblockhash", "1000") - + HelpExampleRpc("getblockhash", "1000") - }, - }.ToString()); + RPCHelpMan{"getblockhash", + "\nReturns hash of block in best-block-chain at height provided.\n", + { + {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The height index"}, + }, + RPCResult{ + RPCResult::Type::STR_HEX, "", "The block hash"}, + RPCExamples{ + HelpExampleCli("getblockhash", "1000") + + HelpExampleRpc("getblockhash", "1000") + }, + }.Check(request); LOCK(cs_main); @@ -826,44 +775,41 @@ static UniValue getblockhash(const JSONRPCRequest& request) static UniValue getblockheader(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"getblockheader", - "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" - "If verbose is true, returns an Object with information about blockheader .\n", - { - {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"}, - {"verbose", RPCArg::Type::BOOL, /* default */ "true", "true for a json object, false for the hex-encoded data"}, - }, + RPCHelpMan{"getblockheader", + "\nIf verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'.\n" + "If verbose is true, returns an Object with information about blockheader .\n", + { + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"}, + {"verbose", RPCArg::Type::BOOL, /* default */ "true", "true for a json object, false for the hex-encoded data"}, + }, + { + RPCResult{"for verbose = true", + RPCResult::Type::OBJ, "", "", { - RPCResult{"for verbose = true", - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n" - " \"nTx\" : n, (numeric) The number of transactions in the block.\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\", (string) The hash of the next block\n" - "}\n" - }, - RPCResult{"for verbose=false", - "\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n" - }, - }, - RPCExamples{ - HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") - }, - }.ToString()); + {RPCResult::Type::STR_HEX, "hash", "the block hash (same as provided)"}, + {RPCResult::Type::NUM, "confirmations", "The number of confirmations, or -1 if the block is not on the main chain"}, + {RPCResult::Type::NUM, "height", "The block height or index"}, + {RPCResult::Type::NUM, "version", "The block version"}, + {RPCResult::Type::STR_HEX, "versionHex", "The block version formatted in hexadecimal"}, + {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"}, + {RPCResult::Type::NUM_TIME, "time", "The block time expressed in seconds since epoch (Jan 1 1970 GMT)"}, + {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in seconds since epoch (Jan 1 1970 GMT)"}, + {RPCResult::Type::NUM, "nonce", "The nonce"}, + {RPCResult::Type::STR_HEX, "bits", "The bits"}, + {RPCResult::Type::NUM, "difficulty", "The difficulty"}, + {RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the current chain"}, + {RPCResult::Type::NUM, "nTx", "The number of transactions in the block"}, + {RPCResult::Type::STR_HEX, "previousblockhash", "The hash of the previous block"}, + {RPCResult::Type::STR_HEX, "nextblockhash", "The hash of the next block"}, + }}, + RPCResult{"for verbose=false", + RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"}, + }, + RPCExamples{ + HelpExampleCli("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + + HelpExampleRpc("getblockheader", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\"") + }, + }.Check(request); std::string strHash = request.params[0].get_str(); uint256 hash(uint256S(strHash)); @@ -897,49 +843,46 @@ static UniValue getblockheader(const JSONRPCRequest& request) static UniValue getblockheaders(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) - throw std::runtime_error( - RPCHelpMan{"getblockheaders", - "\nReturns an array of items with information about blockheaders starting from .\n" - "\nIf verbose is false, each item is a string that is serialized, hex-encoded data for a single blockheader.\n" - "If verbose is true, each item is an Object with information about a single blockheader.\n", - { - {"hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"}, - {"count", RPCArg::Type::NUM, /* default */ strprintf("%s", MAX_HEADERS_RESULTS), ""}, - {"verbose", RPCArg::Type::BOOL, /* default */ "true", "true for a json object, false for the hex-encoded data"}, - }, - RPCResults{ - {"for verbose = true", - "[ {\n" - " \"hash\" : \"hash\", (string) The block hash\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\", (string) The hash of the next block\n" - "}, {\n" - " ...\n" - " },\n" - "...\n" - "]\n" - },{"for verbose=false", - "[\n" - " \"data\", (string) A string that is serialized, hex-encoded data for block header.\n" - " ...\n" - "]\n" + RPCHelpMan{"getblockheaders", + "\nReturns an array of items with information about blockheaders starting from .\n" + "\nIf verbose is false, each item is a string that is serialized, hex-encoded data for a single blockheader.\n" + "If verbose is true, each item is an Object with information about a single blockheader.\n", + { + {"hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"}, + {"count", RPCArg::Type::NUM, /* default */ strprintf("%s", MAX_HEADERS_RESULTS), ""}, + {"verbose", RPCArg::Type::BOOL, /* default */ "true", "true for a json object, false for the hex-encoded data"}, + }, + { + RPCResult{"for verbose = true", + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "the block hash (same as provided)"}, + {RPCResult::Type::NUM, "confirmations", "The number of confirmations, or -1 if the block is not on the main chain"}, + {RPCResult::Type::NUM, "height", "The block height or index"}, + {RPCResult::Type::NUM, "version", "The block version"}, + {RPCResult::Type::STR_HEX, "versionHex", "The block version formatted in hexadecimal"}, + {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"}, + {RPCResult::Type::NUM_TIME, "time", "The block time expressed in seconds since epoch (Jan 1 1970 GMT)"}, + {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in seconds since epoch (Jan 1 1970 GMT)"}, + {RPCResult::Type::NUM, "nonce", "The nonce"}, + {RPCResult::Type::STR_HEX, "bits", "The bits"}, + {RPCResult::Type::NUM, "difficulty", "The difficulty"}, + {RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the current chain"}, + {RPCResult::Type::NUM, "nTx", "The number of transactions in the block"}, + {RPCResult::Type::STR_HEX, "previousblockhash", "The hash of the previous block"}, + {RPCResult::Type::STR_HEX, "nextblockhash", "The hash of the next block"}, + }}, }}, - RPCExamples{ - HelpExampleCli("getblockheaders", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 2000") - + HelpExampleRpc("getblockheaders", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 2000") - }, - }.ToString()); + RPCResult{"for verbose=false", + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"}}}, + }, + RPCExamples{ + HelpExampleCli("getblockheaders", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 2000") + + HelpExampleRpc("getblockheaders", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 2000") + }, + }.Check(request); LOCK(cs_main); @@ -1010,26 +953,21 @@ static CBlock GetBlockChecked(const CBlockIndex* pblockindex) static UniValue getmerkleblocks(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) - throw std::runtime_error( - RPCHelpMan{"getmerkleblocks", - "\nReturns an array of hex-encoded merkleblocks for blocks starting from which match .\n", - { - {"filter", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded bloom filter"}, - {"hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"}, - {"count", RPCArg::Type::NUM, /* default */ strprintf("%s", MAX_HEADERS_RESULTS), ""}, - }, - RPCResult{ - "[\n" - " \"data\", (string) A string that is serialized, hex-encoded data for a merkleblock.\n" - " ...\n" - "]\n" - }, - RPCExamples{ - HelpExampleCli("getmerkleblocks", "\"2303028005802040100040000008008400048141010000f8400420800080025004000004130000000000000001\" \"00000000007e1432d2af52e8463278bf556b55cf5049262f25634557e2e91202\" 2000") - + HelpExampleRpc("getmerkleblocks", "\"2303028005802040100040000008008400048141010000f8400420800080025004000004130000000000000001\" \"00000000007e1432d2af52e8463278bf556b55cf5049262f25634557e2e91202\" 2000") - }, - }.ToString()); + RPCHelpMan{"getmerkleblocks", + "\nReturns an array of hex-encoded merkleblocks for blocks starting from which match .\n", + { + {"filter", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded bloom filter"}, + {"hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"}, + {"count", RPCArg::Type::NUM, /* default */ strprintf("%s", MAX_HEADERS_RESULTS), ""}, + }, + RPCResult{ + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for a merkleblock"}}}, + RPCExamples{ + HelpExampleCli("getmerkleblocks", "\"2303028005802040100040000008008400048141010000f8400420800080025004000004130000000000000001\" \"00000000007e1432d2af52e8463278bf556b55cf5049262f25634557e2e91202\" 2000") + + HelpExampleRpc("getmerkleblocks", "\"2303028005802040100040000008008400048141010000f8400420800080025004000004130000000000000001\" \"00000000007e1432d2af52e8463278bf556b55cf5049262f25634557e2e91202\" 2000") + }, + }.Check(request); LOCK(cs_main); @@ -1089,9 +1027,7 @@ static UniValue getmerkleblocks(const JSONRPCRequest& request) static UniValue getblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"getblock", + RPCHelpMan{"getblock", "\nIf verbosity is 0, returns a string that is serialized, hex-encoded data for block 'hash'.\n" "If verbosity is 1, returns an Object with information about block .\n" "If verbosity is 2, returns an Object with information about block and information about each transaction. \n", @@ -1101,52 +1037,55 @@ static UniValue getblock(const JSONRPCRequest& request) }, { RPCResult{"for verbosity = 0", - RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"}, + RPCResult::Type::STR_HEX, "", "A string that is serialized, hex-encoded data for block 'hash'"}, RPCResult{"for verbosity = 1", - "{\n" - " \"hash\" : \"hash\", (string) the block hash (same as provided)\n" - " \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n" - " \"size\" : n, (numeric) The block size\n" - " \"height\" : n, (numeric) The block height or index\n" - " \"version\" : n, (numeric) The block version\n" - " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n" - " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" - " \"tx\" : [ (array of string) The transaction ids\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - " ],\n" - " \"cbTx\" : { (json object) The coinbase special transaction \n" - " \"version\" (numeric) The coinbase special transaction version\n" - " \"height\" (numeric) The block height\n" - " \"merkleRootMNList\" : \"xxxx\", (string) The merkle root of the masternode list\n" - " \"merkleRootQuorums\" : \"xxxx\", (string) The merkle root of the quorum list\n" - " },\n" - " \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"nonce\" : n, (numeric) The nonce\n" - " \"bits\" : \"1d00ffff\", (string) The bits\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"chainwork\" : \"xxxx\", (string) Expected number of hashes required to produce the chain up to this block (in hex)\n" - " \"nTx\" : n, (numeric) The number of transactions in the block.\n" - " \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n" - " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hash", "the block hash (same as provided)"}, + {RPCResult::Type::NUM, "confirmations", "The number of confirmations, or -1 if the block is not on the main chain"}, + {RPCResult::Type::NUM, "size", "The block size"}, + {RPCResult::Type::NUM, "height", "The block height or index"}, + {RPCResult::Type::NUM, "version", "The block version"}, + {RPCResult::Type::STR_HEX, "versionHex", "The block version formatted in hexadecimal"}, + {RPCResult::Type::STR_HEX, "merkleroot", "The merkle root"}, + {RPCResult::Type::ARR, "tx", "The transaction ids", + {{RPCResult::Type::STR_HEX, "", "The transaction id"}}}, + {RPCResult::Type::OBJ, "cbTx", "The coinbase special transaction", + { + {RPCResult::Type::NUM, "version", "The coinbase special transaction version"}, + {RPCResult::Type::STR_HEX, "height", "The block height"}, + {RPCResult::Type::STR_HEX, "merkleRootMNList", "The merkle root of the masternode list"}, + {RPCResult::Type::STR_HEX, "merkleRootQuorums", "The merkle root of the quorum list"}, + }}, + {RPCResult::Type::NUM_TIME, "time", "The block time expressed in seconds since epoch (Jan 1 1970 GMT)"}, + {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in seconds since epoch (Jan 1 1970 GMT)"}, + {RPCResult::Type::NUM, "nonce", "The nonce"}, + {RPCResult::Type::STR_HEX, "bits", "The bits"}, + {RPCResult::Type::NUM, "difficulty", "The difficulty"}, + {RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the chain up to this block (in hex)"}, + {RPCResult::Type::NUM, "nTx", "The number of transactions in the block"}, + {RPCResult::Type::STR_HEX, "previousblockhash", "The hash of the previous block"}, + {RPCResult::Type::STR_HEX, "nextblockhash", "The hash of the next block"}, + }}, RPCResult{"for verbosity = 2", - "{\n" - " ..., Same output as verbosity = 1.\n" - " \"tx\" : [ (array of Objects) The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result.\n" - " ,...\n" - " ],\n" - " ,... Same output as verbosity = 1.\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ELISION, "", "Same output as verbosity = 1"}, + {RPCResult::Type::ARR, "tx", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ELISION, "", "The transactions in the format of the getrawtransaction RPC. Different from verbosity = 1 \"tx\" result"}, + }}, + }}, + {RPCResult::Type::ELISION, "", "Same output as verbosity = 1"}, + }}, }, RPCExamples{ HelpExampleCli("getblock", "\"00000000000fd08c2fb661d2fcb0d49abb3a91e5f27082ce64feed3b4dede2e2\"") + HelpExampleRpc("getblock", "\"00000000000fd08c2fb661d2fcb0d49abb3a91e5f27082ce64feed3b4dede2e2\"") }, - }.ToString()); + }.Check(request); LOCK(cs_main); @@ -1181,20 +1120,18 @@ static UniValue getblock(const JSONRPCRequest& request) static UniValue pruneblockchain(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"pruneblockchain", "", - { - {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block height to prune up to. May be set to a discrete height, or a unix timestamp\n" - " to prune blocks whose block time is at least 2 hours older than the provided timestamp."}, - }, - RPCResult{ - RPCResult::Type::NUM, "", "Height of the last block pruned"}, - RPCExamples{ - HelpExampleCli("pruneblockchain", "1000") - + HelpExampleRpc("pruneblockchain", "1000") - }, - }.ToString()); + RPCHelpMan{"pruneblockchain", "", + { + {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block height to prune up to. May be set to a discrete height, or a unix timestamp\n" + " to prune blocks whose block time is at least 2 hours older than the provided timestamp."}, + }, + RPCResult{ + RPCResult::Type::NUM, "", "Height of the last block pruned"}, + RPCExamples{ + HelpExampleCli("pruneblockchain", "1000") + + HelpExampleRpc("pruneblockchain", "1000") + }, + }.Check(request); if (!fPruneMode) throw JSONRPCError(RPC_MISC_ERROR, "Cannot prune blocks because node is not in prune mode."); @@ -1251,32 +1188,30 @@ CoinStatsHashType ParseHashType(const std::string& hash_type_input) static UniValue gettxoutsetinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( - RPCHelpMan{"gettxoutsetinfo", - "\nReturns statistics about the unspent transaction output set.\n" - "Note this call may take some time.\n", - { - {"hash_type", RPCArg::Type::STR, /* default */ "hash_serialized_2", "Which UTXO set hash should be calculated. Options: 'hash_serialized_2' (the legacy algorithm), 'muhash', 'none'."}, - }, - RPCResult{ - RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::NUM, "height", "The current block height (index)"}, - {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"}, - {RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs"}, - {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"}, - {RPCResult::Type::NUM, "bogosize", "A meaningless metric for UTXO set size"}, - {RPCResult::Type::STR_HEX, "hash_serialized_2", "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"}, - {RPCResult::Type::STR_HEX, "muhash", "The serialized hash (only present if 'muhash' hash_type is chosen)"}, - {RPCResult::Type::NUM, "disk_size", "The estimated size of the chainstate on disk"}, - {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount"}, - }}, - RPCExamples{ - HelpExampleCli("gettxoutsetinfo", "") - + HelpExampleRpc("gettxoutsetinfo", "") - }, - }.ToString()); + RPCHelpMan{"gettxoutsetinfo", + "\nReturns statistics about the unspent transaction output set.\n" + "Note this call may take some time.\n", + { + {"hash_type", RPCArg::Type::STR, /* default */ "hash_serialized_2", "Which UTXO set hash should be calculated. Options: 'hash_serialized_2' (the legacy algorithm), 'muhash', 'none'."}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "height", "The current block height (index)"}, + {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"}, + {RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs"}, + {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs"}, + {RPCResult::Type::NUM, "bogosize", "A meaningless metric for UTXO set size"}, + {RPCResult::Type::STR_HEX, "hash_serialized_2", /* optional */ true, "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"}, + {RPCResult::Type::STR_HEX, "muhash", /* optional */ true, "The serialized hash (only present if 'muhash' hash_type is chosen)"}, + {RPCResult::Type::NUM, "disk_size", "The estimated size of the chainstate on disk"}, + {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount"}, + }}, + RPCExamples{ + HelpExampleCli("gettxoutsetinfo", "") + + HelpExampleRpc("gettxoutsetinfo", "") + }, + }.Check(request); UniValue ret(UniValue::VOBJ); @@ -1308,42 +1243,39 @@ static UniValue gettxoutsetinfo(const JSONRPCRequest& request) static UniValue gettxout(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) - throw std::runtime_error( - RPCHelpMan{"gettxout", - "\nReturns details about an unspent transaction output.\n", - { - {"txid", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction id"}, - {"n", RPCArg::Type::NUM, RPCArg::Optional::NO, "vout number"}, - {"include_mempool", RPCArg::Type::BOOL, /* default */ "true", "Whether to include the mempool. Note that an unspent output that is spent in the mempool won't appear."}, - }, - RPCResult{ - "{\n" - " \"bestblock\" : \"hash\", (string) The hash of the block at the tip of the chain\n" - " \"confirmations\" : n, (numeric) The number of confirmations\n" - " \"value\" : x.xxx, (numeric) The transaction value in " + CURRENCY_UNIT + "\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"code\", (string) \n" - " \"hex\" : \"hex\", (string) \n" - " \"reqSigs\" : n, (numeric) Number of required signatures\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" - " \"addresses\" : [ (array of string) array of dash addresses\n" - " \"address\" (string) dash address\n" - " ,...\n" - " ]\n" - " },\n" - " \"coinbase\" : true|false (boolean) Coinbase or not\n" - "}\n" - }, - RPCExamples{ - "\nGet unspent transactions\n" - + HelpExampleCli("listunspent", "") + - "\nView the details\n" - + HelpExampleCli("gettxout", "\"txid\" 1") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("gettxout", "\"txid\", 1") - }, - }.ToString()); + RPCHelpMan{"gettxout", + "\nReturns details about an unspent transaction output.\n", + { + {"txid", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction id"}, + {"n", RPCArg::Type::NUM, RPCArg::Optional::NO, "vout number"}, + {"include_mempool", RPCArg::Type::BOOL, /* default */ "true", "Whether to include the mempool. Note that an unspent output that is spent in the mempool won't appear."}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"}, + {RPCResult::Type::NUM, "confirmations", "The number of confirmations"}, + {RPCResult::Type::STR_AMOUNT, "value", "The transaction value in " + CURRENCY_UNIT}, + {RPCResult::Type::OBJ, "scriptPubKey", "", + { + {RPCResult::Type::STR_HEX, "asm", ""}, + {RPCResult::Type::STR_HEX, "hex", ""}, + {RPCResult::Type::NUM, "reqSigs", "Number of required signatures"}, + {RPCResult::Type::STR_HEX, "type", "The type, eg pubkeyhash"}, + {RPCResult::Type::ARR, "addresses", "array of dash addresses", + {{RPCResult::Type::STR, "address", "dash address"}}}, + }}, + {RPCResult::Type::BOOL, "coinbase", "Coinbase or not"}, + }}, + RPCExamples{ + "\nGet unspent transactions\n" + + HelpExampleCli("listunspent", "") + + "\nView the details\n" + + HelpExampleCli("gettxout", "\"txid\" 1") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("gettxout", "\"txid\", 1") + }, + }.Check(request); LOCK(cs_main); @@ -1392,21 +1324,19 @@ static UniValue verifychain(const JSONRPCRequest& request) { int nCheckLevel = gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL); int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); - if (request.fHelp || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"verifychain", - "\nVerifies blockchain database.\n", - { - {"checklevel", RPCArg::Type::NUM, /* default */ strprintf("%d, range=0-4", nCheckLevel), "How thorough the block verification is."}, - {"nblocks", RPCArg::Type::NUM, /* default */ strprintf("%d, 0=all", nCheckDepth), "The number of blocks to check."}, - }, - RPCResult{ - RPCResult::Type::BOOL, "", "Verified or not"}, - RPCExamples{ - HelpExampleCli("verifychain", "") - + HelpExampleRpc("verifychain", "") - }, - }.ToString()); + RPCHelpMan{"verifychain", + "\nVerifies blockchain database.\n", + { + {"checklevel", RPCArg::Type::NUM, /* default */ strprintf("%d, range=0-4", nCheckLevel), "How thorough the block verification is."}, + {"nblocks", RPCArg::Type::NUM, /* default */ strprintf("%d, 0=all", nCheckDepth), "The number of blocks to check."}, + }, + RPCResult{ + RPCResult::Type::BOOL, "", "Verified or not"}, + RPCExamples{ + HelpExampleCli("verifychain", "") + + HelpExampleRpc("verifychain", "") + }, + }.Check(request); LOCK(cs_main); @@ -1492,61 +1422,65 @@ static void BIP9SoftForkDescPushBack(UniValue& bip9_softforks, const Consensus:: UniValue getblockchaininfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"getblockchaininfo", - "Returns an object containing various state info regarding blockchain processing.\n", - {}, - RPCResult{ - "{\n" - " \"chain\" : \"xxxx\", (string) current network name (main, test, regtest) and\n" - " devnet or devnet- for \"-devnet\" and \"-devnet=\" respectively\n" - " \"blocks\" : xxxxxx, (numeric) the height of the most-work fully-validated chain. The genesis block has height 0\n" - " \"headers\" : xxxxxx, (numeric) the current number of headers we have validated\n" - " \"bestblockhash\" : \"...\", (string) the hash of the currently best block\n" - " \"difficulty\" : xxxxxx, (numeric) the current difficulty\n" - " \"mediantime\" : xxxxxx, (numeric) median time for the current best block\n" - " \"verificationprogress\" : xxxx, (numeric) estimate of verification progress [0..1]\n" - " \"initialblockdownload\" : xxxx, (boolean) (debug information) estimate of whether this node is in Initial Block Download mode.\n" - " \"chainwork\" : \"xxxx\" (string) total amount of work in active chain, in hexadecimal\n" - " \"size_on_disk\" : xxxxxx, (numeric) the estimated size of the block and undo files on disk\n" - " \"pruned\" : xx, (boolean) if the blocks are subject to pruning\n" - " \"pruneheight\" : xxxxxx, (numeric) lowest-height complete block stored (only present if pruning is enabled)\n" - " \"automatic_pruning\" : xx, (boolean) whether automatic pruning is enabled (only present if pruning is enabled)\n" - " \"prune_target_size\" : xxxxxx, (numeric) the target size used by pruning (only present if automatic pruning is enabled)\n" - " \"softforks\" : [ (json array) status of softforks in progress\n" - " {\n" - " \"id\" : \"xxxx\", (string) name of softfork\n" - " \"version\" : xx, (numeric) block version\n" - " \"reject\" : { (json object) progress toward rejecting pre-softfork blocks\n" - " \"status\" : xx, (boolean) true if threshold reached\n" - " },\n" - " }, ...\n" - " ],\n" - " \"bip9_softforks\": { (json object) status of BIP9 softforks in progress\n" - " \"xxxx\" : { (string) name of the softfork\n" - " \"status\" : \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" - " \"bit\" : xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" - " \"start_time\" : xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" - " \"timeout\" : xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" - " \"since\" : xx, (numeric) height of the first block to which the status applies\n" - " \"statistics\" : { (json object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n" - " \"period\" : xx, (numeric) the length in blocks of the BIP9 signalling period \n" - " \"threshold\" : xx, (numeric) the number of blocks with the version bit set required to activate the feature \n" - " \"elapsed\" : xx, (numeric) the number of blocks elapsed since the beginning of the current period \n" - " \"count\" : xx, (numeric) the number of blocks with the version bit set in the current period \n" - " \"possible\" : xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n" - " }\n" - " }\n" - " }\n" - " \"warnings\" : \"...\", (string) any network and blockchain warnings.\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("getblockchaininfo", "") - + HelpExampleRpc("getblockchaininfo", "") - }, - }.ToString()); + RPCHelpMan{"getblockchaininfo", + "Returns an object containing various state info regarding blockchain processing.\n", + {}, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "chain", "current network name (main, test, regtest) and " + "devnet or devnet- for \"-devnet\" and \"-devnet=\" respectively\n"}, + {RPCResult::Type::NUM, "blocks", "the height of the most-work fully-validated chain. The genesis block has height 0"}, + {RPCResult::Type::NUM, "headers", "the current number of headers we have validated"}, + {RPCResult::Type::STR, "bestblockhash", "the hash of the currently best block"}, + {RPCResult::Type::NUM, "difficulty", "the current difficulty"}, + {RPCResult::Type::NUM, "mediantime", "median time for the current best block"}, + {RPCResult::Type::NUM, "verificationprogress", "estimate of verification progress [0..1]"}, + {RPCResult::Type::BOOL, "initialblockdownload", "(debug information) estimate of whether this node is in Initial Block Download mode"}, + {RPCResult::Type::STR_HEX, "chainwork", "total amount of work in active chain, in hexadecimal"}, + {RPCResult::Type::NUM, "size_on_disk", "the estimated size of the block and undo files on disk"}, + {RPCResult::Type::BOOL, "pruned", "if the blocks are subject to pruning"}, + {RPCResult::Type::NUM, "pruneheight", "lowest-height complete block stored (only present if pruning is enabled)"}, + {RPCResult::Type::BOOL, "automatic_pruning", "whether automatic pruning is enabled (only present if pruning is enabled)"}, + {RPCResult::Type::NUM, "prune_target_size", "the target size used by pruning (only present if automatic pruning is enabled)"}, + {RPCResult::Type::ARR, "softforks", "status of softforks in progress", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "xxxx", "name of the softfork"}, + {RPCResult::Type::STR, "version", "block version"}, + {RPCResult::Type::OBJ, "reject", "progress toward rejecting pre-softfork blocks", + { + {RPCResult::Type::BOOL, "status", "true if threshold reached"}, + }}, + }}, + }}, + {RPCResult::Type::OBJ_DYN, "bip9_softforks", "status of BIP9 softforks in progress", + { + {RPCResult::Type::OBJ, "xxxx", "name of the softfork", + { + {RPCResult::Type::STR, "status", "one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\""}, + {RPCResult::Type::NUM, "bit", "the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)"}, + {RPCResult::Type::NUM_TIME, "start_time", "the minimum median time past of a block at which the bit gains its meaning"}, + {RPCResult::Type::NUM_TIME, "timeout", "the median time past of a block at which the deployment is considered failed if not yet locked in"}, + {RPCResult::Type::NUM, "since", "height of the first block to which the status applies"}, + {RPCResult::Type::OBJ, "statistics", "numeric statistics about BIP9 signalling for a softfork", + { + {RPCResult::Type::NUM, "period", "the length in blocks of the BIP9 signalling period"}, + {RPCResult::Type::NUM, "threshold", "the number of blocks with the version bit set required to activate the feature"}, + {RPCResult::Type::NUM, "elapsed", "the number of blocks elapsed since the beginning of the current period"}, + {RPCResult::Type::NUM, "count", "the number of blocks with the version bit set in the current period"}, + {RPCResult::Type::BOOL, "possible", "returns false if there are not enough blocks left in this period to pass activation threshold"}, + }}, + }}, + }}, + {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"}, + }}, + RPCExamples{ + HelpExampleCli("getblockchaininfo", "") + + HelpExampleRpc("getblockchaininfo", "") + }, + }.Check(request); LOCK(cs_main); @@ -1616,48 +1550,36 @@ struct CompareBlocksByHeight static UniValue getchaintips(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"getchaintips", - "Return information about all known tips in the block tree," - " including the main chain as well as orphaned branches.\n", + RPCHelpMan{"getchaintips", + "Return information about all known tips in the block tree," + " including the main chain as well as orphaned branches.\n", + { + {"count", RPCArg::Type::NUM, /* default */ "", "only show this much of latest tips"}, + {"branchlen", RPCArg::Type::NUM, /* default */ "", "only show tips that have equal or greater length of branch"}, + }, + RPCResult{ + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::OBJ, "", "", { - {"count", RPCArg::Type::NUM, /* default */ "", "only show this much of latest tips"}, - {"branchlen", RPCArg::Type::NUM, /* default */ "", "only show tips that have equal or greater length of branch"}, - }, - RPCResult{ - "[\n" - " {\n" - " \"height\" : xxxx, (numeric) height of the chain tip\n" - " \"hash\" : \"xxxx\", (string) block hash of the tip\n" - " \"difficulty\" : x.xxx, (numeric) The difficulty\n" - " \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n" - " \"branchlen\" : 0 (numeric) zero for main chain\n" - " \"forkpoint\" : \"xxxx\", (string) same as \"hash\" for the main chain\n" - " \"status\" : \"active\" (string) \"active\" for the main chain\n" - " },\n" - " {\n" - " \"height\" : xxxx,\n" - " \"hash\" : \"xxxx\",\n" - " \"difficulty\" : x.xxx,\n" - " \"chainwork\" : \"0000...1f3\"\n" - " \"branchlen\" : 1 (numeric) length of branch connecting the tip to the main chain\n" - " \"forkpoint\" : \"xxxx\", (string) block hash of the last common block between this tip and the main chain\n" - " \"status\" : \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" - " }\n" - "]\n" - "Possible values for status:\n" - "1. \"invalid\" This branch contains at least one invalid block\n" - "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" - "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" - "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" - "5. \"active\" This is the tip of the active main chain, which is certainly valid\n" - }, - RPCExamples{ - HelpExampleCli("getchaintips", "") - + HelpExampleRpc("getchaintips", "") - }, - }.ToString()); + {RPCResult::Type::NUM, "height", "height of the chain tip"}, + {RPCResult::Type::STR_HEX, "hash", "block hash of the tip"}, + {RPCResult::Type::NUM, "difficulty", "The difficulty"}, + {RPCResult::Type::STR_HEX, "chainwork", "Expected number of hashes required to produce the current chain (in hex)"}, + {RPCResult::Type::NUM, "branchlen", "zero for main chain, otherwise length of branch connecting the tip to the main chain"}, + {RPCResult::Type::STR_HEX, "forkpoint", "same as \"hash\" for the main chain"}, + {RPCResult::Type::STR, "status", "status of the chain, \"active\" for the main chain\n" + "Possible values for status:\n" + "1. \"invalid\" This branch contains at least one invalid block\n" + "2. \"headers-only\" Not all blocks for this branch are available, but the headers are valid\n" + "3. \"valid-headers\" All blocks are available for this branch, but they were never fully validated\n" + "4. \"valid-fork\" This branch is not part of the active chain, but is fully validated\n" + "5. \"active\" This is the tip of the active main chain, which is certainly valid"}, + }}}}, + RPCExamples{ + HelpExampleCli("getchaintips", "") + + HelpExampleRpc("getchaintips", "") + }, + }.Check(request); LOCK(cs_main); @@ -1768,49 +1690,45 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool) static UniValue getmempoolinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"getmempoolinfo", - "\nReturns details on the active state of the TX memory pool.\n", - {}, - RPCResult{ - "{\n" - " \"loaded\" : true|false (boolean) True if the mempool is fully loaded\n" - " \"size\" : xxxxx, (numeric) Current tx count\n" - " \"bytes\" : xxxxx, (numeric) Sum of all tx sizes\n" - " \"usage\" : xxxxx, (numeric) Total memory usage for the mempool\n" - " \"maxmempool\" : xxxxx, (numeric) Maximum memory usage for the mempool\n" - " \"mempoolminfee\" : xxxxx (numeric) Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee\n" - " \"minrelaytxfee\" : xxxxx (numeric) Current minimum relay fee for transactions\n" - " \"instantsendlocks\" : xxxxx, (numeric) Number of unconfirmed instant send locks\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("getmempoolinfo", "") - + HelpExampleRpc("getmempoolinfo", "") - }, - }.ToString()); + RPCHelpMan{"getmempoolinfo", + "\nReturns details on the active state of the TX memory pool.\n", + {}, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "loaded", "True if the mempool is fully loaded"}, + {RPCResult::Type::NUM, "size", "Current tx count"}, + {RPCResult::Type::NUM, "bytes", "Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted"}, + {RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"}, + {RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"}, + {RPCResult::Type::STR_AMOUNT, "mempoolminfee", "Minimum fee rate in " + CURRENCY_UNIT + "/kB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee"}, + {RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"}, + {RPCResult::Type::NUM, "instantsendlocks", "Number of unconfirmed InstantSend locks"}, + }}, + RPCExamples{ + HelpExampleCli("getmempoolinfo", "") + + HelpExampleRpc("getmempoolinfo", "") + }, + }.Check(request); return MempoolInfoToJSON(::mempool); } static UniValue preciousblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"preciousblock", - "\nTreats a block as if it were received before others with the same work.\n" - "\nA later preciousblock call can override the effect of an earlier one.\n" - "\nThe effects of preciousblock are not retained across restarts.\n", - { - {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as precious"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("preciousblock", "\"blockhash\"") - + HelpExampleRpc("preciousblock", "\"blockhash\"") - }, - }.ToString()); + RPCHelpMan{"preciousblock", + "\nTreats a block as if it were received before others with the same work.\n" + "\nA later preciousblock call can override the effect of an earlier one.\n" + "\nThe effects of preciousblock are not retained across restarts.\n", + { + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as precious"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("preciousblock", "\"blockhash\"") + + HelpExampleRpc("preciousblock", "\"blockhash\"") + }, + }.Check(request); std::string strHash = request.params[0].get_str(); uint256 hash(uint256S(strHash)); @@ -1836,19 +1754,17 @@ static UniValue preciousblock(const JSONRPCRequest& request) static UniValue invalidateblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"invalidateblock", - "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n", - { - {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to mark as invalid"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("invalidateblock", "\"blockhash\"") - + HelpExampleRpc("invalidateblock", "\"blockhash\"") - }, - }.ToString()); + RPCHelpMan{"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"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("invalidateblock", "\"blockhash\"") + + HelpExampleRpc("invalidateblock", "\"blockhash\"") + }, + }.Check(request); std::string strHash = request.params[0].get_str(); uint256 hash(uint256S(strHash)); @@ -1877,20 +1793,18 @@ static UniValue invalidateblock(const JSONRPCRequest& request) static UniValue reconsiderblock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"reconsiderblock", - "\nRemoves invalidity status of a block, its ancestors and its descendants, reconsider them for activation.\n" - "This can be used to undo the effects of invalidateblock.\n", - { - {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to reconsider"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("reconsiderblock", "\"blockhash\"") - + HelpExampleRpc("reconsiderblock", "\"blockhash\"") - }, - }.ToString()); + RPCHelpMan{"reconsiderblock", + "\nRemoves invalidity status of a block, its ancestors and its descendants, reconsider them for activation.\n" + "This can be used to undo the effects of invalidateblock.\n", + { + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to reconsider"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("reconsiderblock", "\"blockhash\"") + + HelpExampleRpc("reconsiderblock", "\"blockhash\"") + }, + }.Check(request); std::string strHash = request.params[0].get_str(); uint256 hash(uint256S(strHash)); @@ -1917,8 +1831,6 @@ static UniValue reconsiderblock(const JSONRPCRequest& request) static UniValue getchaintxstats(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"getchaintxstats", "\nCompute statistics about the total number and rate of transactions in the chain.\n", { @@ -1926,22 +1838,22 @@ static UniValue getchaintxstats(const JSONRPCRequest& request) {"blockhash", RPCArg::Type::STR_HEX, /* default */ "chain tip", "The hash of the block that ends the window."}, }, RPCResult{ - "{\n" - " \"time\" : xxxxx, (numeric) The timestamp for the final block in the window in UNIX format.\n" - " \"txcount\" : xxxxx, (numeric) The total number of transactions in the chain up to that point.\n" - " \"window_final_block_hash\" : \"...\", (string) The hash of the final block in the window.\n" - " \"window_final_block_height\" : xxxxx, (numeric) The height of the final block in the window.\n" - " \"window_block_count\" : xxxxx, (numeric) Size of the window in number of blocks.\n" - " \"window_tx_count\" : xxxxx, (numeric) The number of transactions in the window. Only returned if \"window_block_count\" is > 0.\n" - " \"window_interval\" : xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n" - " \"txrate\" : x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM_TIME, "time", "The timestamp for the final block in the window in UNIX format."}, + {RPCResult::Type::NUM, "txcount", "The total number of transactions in the chain up to that point"}, + {RPCResult::Type::STR_HEX, "window_final_block_hash", "The hash of the final block in the window"}, + {RPCResult::Type::NUM, "window_final_block_height", "The height of the final block in the window."}, + {RPCResult::Type::NUM, "window_block_count", "Size of the window in number of blocks"}, + {RPCResult::Type::NUM, "window_tx_count", "The number of transactions in the window. Only returned if \"window_block_count\" is > 0"}, + {RPCResult::Type::NUM, "window_interval", "The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0"}, + {RPCResult::Type::NUM, "txrate", "The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0"}, + }}, RPCExamples{ HelpExampleCli("getchaintxstats", "") + HelpExampleRpc("getchaintxstats", "2016") }, - }.ToString()); + }.Check(request); const CBlockIndex* pindex; int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month @@ -2052,7 +1964,7 @@ static constexpr size_t PER_UTXO_OVERHEAD = sizeof(COutPoint) + sizeof(uint32_t) static UniValue getblockstats(const JSONRPCRequest& request) { - const RPCHelpMan help{"getblockstats", + RPCHelpMan{"getblockstats", "\nCompute per block statistics for a given window. All amounts are in duffs.\n" "It won't work for some heights with pruning.\n" "It won't work without -txindex for utxo_size_inc, *fee or *feerate stats.\n", @@ -2066,50 +1978,48 @@ static UniValue getblockstats(const JSONRPCRequest& request) "stats"}, }, RPCResult{ - "{ (json object)\n" - " \"avgfee\" : xxxxx, (numeric) Average fee in the block\n" - " \"avgfeerate\" : xxxxx, (numeric) Average feerate (in duffs per byte)\n" - " \"avgtxsize\" : xxxxx, (numeric) Average transaction size\n" - " \"blockhash\" : xxxxx, (string) The block hash (to check for potential reorgs)\n" - " \"feerate_percentiles\" : [ (array of numeric) Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in duffs per byte)\n" - " \"10th_percentile_feerate\", (numeric) The 10th percentile feerate\n" - " \"25th_percentile_feerate\", (numeric) The 25th percentile feerate\n" - " \"50th_percentile_feerate\", (numeric) The 50th percentile feerate\n" - " \"75th_percentile_feerate\", (numeric) The 75th percentile feerate\n" - " \"90th_percentile_feerate\", (numeric) The 90th percentile feerate\n" - " ],\n" - " \"height\" : xxxxx, (numeric) The height of the block\n" - " \"ins\" : xxxxx, (numeric) The number of inputs (excluding coinbase)\n" - " \"maxfee\" : xxxxx, (numeric) Maximum fee in the block\n" - " \"maxfeerate\" : xxxxx, (numeric) Maximum feerate (in duffs per byte)\n" - " \"maxtxsize\" : xxxxx, (numeric) Maximum transaction size\n" - " \"medianfee\" : xxxxx, (numeric) Truncated median fee in the block\n" - " \"mediantime\" : xxxxx, (numeric) The block median time past\n" - " \"mediantxsize\" : xxxxx, (numeric) Truncated median transaction size\n" - " \"minfee\" : xxxxx, (numeric) Minimum fee in the block\n" - " \"minfeerate\" : xxxxx, (numeric) Minimum feerate (in duffs per byte)\n" - " \"mintxsize\" : xxxxx, (numeric) Minimum transaction size\n" - " \"outs\" : xxxxx, (numeric) The number of outputs\n" - " \"subsidy\" : xxxxx, (numeric) The block subsidy\n" - " \"time\" : xxxxx, (numeric) The block time\n" - " \"total_out\" : xxxxx, (numeric) Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])\n" - " \"total_size\" : xxxxx, (numeric) Total size of all non-coinbase transactions\n" - " \"totalfee\" : xxxxx, (numeric) The fee total\n" - " \"txs\" : xxxxx, (numeric) The number of transactions (excluding coinbase)\n" - " \"utxo_increase\" : xxxxx, (numeric) The increase/decrease in the number of unspent outputs\n" - " \"utxo_size_inc\" : xxxxx, (numeric) The increase/decrease in size for the utxo index (not discounting op_return and similar)\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "avgfee", "Average fee in the block"}, + {RPCResult::Type::NUM, "avgfeerate", "Average feerate (in satoshis per virtual byte)"}, + {RPCResult::Type::NUM, "avgtxsize", "Average transaction size"}, + {RPCResult::Type::STR_HEX, "blockhash", "The block hash (to check for potential reorgs)"}, + {RPCResult::Type::ARR_FIXED, "feerate_percentiles", "Feerates at the 10th, 25th, 50th, 75th, and 90th percentile weight unit (in duffs per byte)", + { + {RPCResult::Type::NUM, "10th_percentile_feerate", "The 10th percentile feerate"}, + {RPCResult::Type::NUM, "25th_percentile_feerate", "The 25th percentile feerate"}, + {RPCResult::Type::NUM, "50th_percentile_feerate", "The 50th percentile feerate"}, + {RPCResult::Type::NUM, "75th_percentile_feerate", "The 75th percentile feerate"}, + {RPCResult::Type::NUM, "90th_percentile_feerate", "The 90th percentile feerate"}, + }}, + {RPCResult::Type::NUM, "height", "The height of the block"}, + {RPCResult::Type::NUM, "ins", "The number of inputs (excluding coinbase)"}, + {RPCResult::Type::NUM, "maxfee", "Maximum fee in the block"}, + {RPCResult::Type::NUM, "maxfeerate", "Maximum feerate (in satoshis per virtual byte)"}, + {RPCResult::Type::NUM, "maxtxsize", "Maximum transaction size"}, + {RPCResult::Type::NUM, "medianfee", "Truncated median fee in the block"}, + {RPCResult::Type::NUM, "mediantime", "The block median time past"}, + {RPCResult::Type::NUM, "mediantxsize", "Truncated median transaction size"}, + {RPCResult::Type::NUM, "minfee", "Minimum fee in the block"}, + {RPCResult::Type::NUM, "minfeerate", "Minimum feerate (in satoshis per virtual byte)"}, + {RPCResult::Type::NUM, "mintxsize", "Minimum transaction size"}, + {RPCResult::Type::NUM, "outs", "The number of outputs"}, + {RPCResult::Type::NUM, "subsidy", "The block subsidy"}, + {RPCResult::Type::NUM, "time", "The block time"}, + {RPCResult::Type::NUM, "total_out", "Total amount in all outputs (excluding coinbase and thus reward [ie subsidy + totalfee])"}, + {RPCResult::Type::NUM, "total_size", "Total size of all non-coinbase transactions"}, + {RPCResult::Type::NUM, "totalfee", "The fee total"}, + {RPCResult::Type::NUM, "txs", "The number of transactions (excluding coinbase)"}, + {RPCResult::Type::NUM, "utxo_increase", "The increase/decrease in the number of unspent outputs"}, + {RPCResult::Type::NUM, "utxo_size_inc", "The increase/decrease in size for the utxo index (not discounting op_return and similar)"}, + }}, RPCExamples{ HelpExampleCli("getblockstats", R"('"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"' '["minfeerate","avgfeerate"]')") + HelpExampleCli("getblockstats", R"(1000 '["minfeerate","avgfeerate"]')") + HelpExampleRpc("getblockstats", R"("00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09", ["minfeerate","avgfeerate"])") + HelpExampleRpc("getblockstats", R"(1000, ["minfeerate","avgfeerate"])") }, - }; - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); if (g_txindex) { g_txindex->BlockUntilSyncedToCurrentChain(); @@ -2301,39 +2211,34 @@ static UniValue getblockstats(const JSONRPCRequest& request) static UniValue getspecialtxes(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 5) - throw std::runtime_error( - RPCHelpMan{"getspecialtxes", - "Returns an array of special transactions found in the specified block\n" - "\nIf verbosity is 0, returns tx hash for each transaction.\n" - "If verbosity is 1, returns hex-encoded data for each transaction.\n" - "If verbosity is 2, returns an Object with information for each transaction.\n", - { - {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"}, - {"type", RPCArg::Type::NUM, /* default */ "-1", "Filter special txes by type, -1 means all types"}, - {"count", RPCArg::Type::NUM, /* default */ "10", "The number of transactions to return"}, - {"skip", RPCArg::Type::NUM, /* default */ "0", "The number of transactions to skip"}, - {"verbosity", RPCArg::Type::NUM, /* default */ "0", "0 for hashes, 1 for hex-encoded data, and 2 for json object"}, - }, - RPCResults{ - {"for verbosity = 0", - "[\n" - " \"txid\" : \"xxxx\", (string) The transaction id\n" - "]\n" - }, {"for verbosity = 1", - "[\n" - " \"data\", (string) A string that is serialized, hex-encoded data for the transaction\n" - "]\n" - }, {"for verbosity = 2", - "[ (array of Objects) The transactions in the format of the getrawtransaction RPC.\n" - " ...,\n" - "]\n" - }}, - RPCExamples{ - HelpExampleCli("getspecialtxes", "\"00000000000fd08c2fb661d2fcb0d49abb3a91e5f27082ce64feed3b4dede2e2\"") - + HelpExampleRpc("getspecialtxes", "\"00000000000fd08c2fb661d2fcb0d49abb3a91e5f27082ce64feed3b4dede2e2\"") - }, - }.ToString()); + RPCHelpMan{"getspecialtxes", + "Returns an array of special transactions found in the specified block\n" + "\nIf verbosity is 0, returns tx hash for each transaction.\n" + "If verbosity is 1, returns hex-encoded data for each transaction.\n" + "If verbosity is 2, returns an Object with information for each transaction.\n", + { + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"}, + {"type", RPCArg::Type::NUM, /* default */ "-1", "Filter special txes by type, -1 means all types"}, + {"count", RPCArg::Type::NUM, /* default */ "10", "The number of transactions to return"}, + {"skip", RPCArg::Type::NUM, /* default */ "0", "The number of transactions to skip"}, + {"verbosity", RPCArg::Type::NUM, /* default */ "0", "0 for hashes, 1 for hex-encoded data, and 2 for json object"}, + }, + { + RPCResult{"for verbosity = 0", + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::STR_HEX, "", "The transaction id"}}}, + RPCResult{"for verbosity = 1", + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::STR_HEX, "data", "A string that is serialized, hex-encoded data for the transaction"}}}, + RPCResult{"for verbosity = 2", + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::ELISION, "", "The transactions in the format of the getrawtransaction RPC"}}}, + }, + RPCExamples{ + HelpExampleCli("getspecialtxes", "\"00000000000fd08c2fb661d2fcb0d49abb3a91e5f27082ce64feed3b4dede2e2\"") + + HelpExampleRpc("getspecialtxes", "\"00000000000fd08c2fb661d2fcb0d49abb3a91e5f27082ce64feed3b4dede2e2\"") + }, + }.Check(request); LOCK(cs_main); @@ -2406,18 +2311,15 @@ static UniValue getspecialtxes(const JSONRPCRequest& request) static UniValue savemempool(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) { - throw std::runtime_error( - RPCHelpMan{"savemempool", - "\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n", - {}, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("savemempool", "") - + HelpExampleRpc("savemempool", "") - }, - }.ToString()); - } + RPCHelpMan{"savemempool", + "\nDumps the mempool to disk. It will fail until the previous dump is fully loaded.\n", + {}, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("savemempool", "") + + HelpExampleRpc("savemempool", "") + }, + }.Check(request); if (!::mempool.IsLoaded()) { throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet"); @@ -2492,64 +2394,61 @@ class CoinsViewScanReserver UniValue scantxoutset(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"scantxoutset", - "\nEXPERIMENTAL warning: this call may be removed or changed in future releases.\n" - "\nScans the unspent transaction output set for entries that match certain output descriptors.\n" - "Examples of output descriptors are:\n" - " addr(
) Outputs whose scriptPubKey corresponds to the specified address (does not include P2PK)\n" - " raw() Outputs whose scriptPubKey equals the specified hex scripts\n" - " combo() P2PK and P2PKH outputs for the given pubkey\n" - " pkh() P2PKH outputs for the given pubkey\n" - " sh(multi(,,,...)) P2SH-multisig outputs for the given threshold and pubkeys\n" - "\nIn the above, either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n" - "or more path elements separated by \"/\", and optionally ending in \"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n" - "unhardened or hardened child keys.\n" - "In the latter case, a range needs to be specified by below if different from 1000.\n" - "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n", + RPCHelpMan{"scantxoutset", + "\nEXPERIMENTAL warning: this call may be removed or changed in future releases.\n" + "\nScans the unspent transaction output set for entries that match certain output descriptors.\n" + "Examples of output descriptors are:\n" + " addr(
) Outputs whose scriptPubKey corresponds to the specified address (does not include P2PK)\n" + " raw() Outputs whose scriptPubKey equals the specified hex scripts\n" + " combo() P2PK and P2PKH outputs for the given pubkey\n" + " pkh() P2PKH outputs for the given pubkey\n" + " sh(multi(,,,...)) P2SH-multisig outputs for the given threshold and pubkeys\n" + "\nIn the above, either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n" + "or more path elements separated by \"/\", and optionally ending in \"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n" + "unhardened or hardened child keys.\n" + "In the latter case, a range needs to be specified by below if different from 1000.\n" + "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n", + { + {"action", RPCArg::Type::STR, RPCArg::Optional::NO, "The action to execute\n" + " \"start\" for starting a scan\n" + " \"abort\" for aborting the current scan (returns true when abort was successful)\n" + " \"status\" for progress report (in %) of the current scan"}, + {"scanobjects", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "Array of scan objects. Required for \"start\" action\n" + " Every scan object is either a string descriptor or an object:", { - {"action", RPCArg::Type::STR, RPCArg::Optional::NO, "The action to execute\n" - " \"start\" for starting a scan\n" - " \"abort\" for aborting the current scan (returns true when abort was successful)\n" - " \"status\" for progress report (in %) of the current scan"}, - {"scanobjects", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "Array of scan objects. Required for \"start\" action\n" - " Every scan object is either a string descriptor or an object:", + {"descriptor", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "An output descriptor"}, + {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "An object with output descriptor and metadata", { - {"descriptor", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "An output descriptor"}, - {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "An object with output descriptor and metadata", - { - {"desc", RPCArg::Type::STR, RPCArg::Optional::NO, "An output descriptor"}, - {"range", RPCArg::Type::RANGE, /* default */ "1000", "The range of HD chain indexes to explore (either end or [begin,end])"}, - }, - }, + {"desc", RPCArg::Type::STR, RPCArg::Optional::NO, "An output descriptor"}, + {"range", RPCArg::Type::RANGE, /* default */ "1000", "The range of HD chain indexes to explore (either end or [begin,end])"}, }, - "[scanobjects,...]"}, + }, }, - RPCResult{ - RPCResult::Type::OBJ, "", "", + "[scanobjects,...]"}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "success", "Whether the scan was completed"}, + {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs scanned"}, + {RPCResult::Type::NUM, "height", "The current block height (index)"}, + {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"}, + {RPCResult::Type::ARR, "unspents", "", { - {RPCResult::Type::BOOL, "success", "Whether the scan was completed"}, - {RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs scanned"}, - {RPCResult::Type::NUM, "height", "The current block height (index)"}, - {RPCResult::Type::STR_HEX, "bestblock", "The hash of the block at the tip of the chain"}, - {RPCResult::Type::ARR, "unspents", "", + {RPCResult::Type::OBJ, "", "", { - {RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, - {RPCResult::Type::NUM, "vout", "The vout value"}, - {RPCResult::Type::STR_HEX, "scriptPubKey", "The script key"}, - {RPCResult::Type::STR, "desc", "A specialized descriptor for the matched scriptPubKey"}, - {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the unspent output"}, - {RPCResult::Type::NUM, "height", "Height of the unspent transaction output"}, - }}, + {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + {RPCResult::Type::NUM, "vout", "The vout value"}, + {RPCResult::Type::STR_HEX, "scriptPubKey", "The script key"}, + {RPCResult::Type::STR, "desc", "A specialized descriptor for the matched scriptPubKey"}, + {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the unspent output"}, + {RPCResult::Type::NUM, "height", "Height of the unspent transaction output"}, }}, - {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of all found unspent outputs in " + CURRENCY_UNIT}, }}, - RPCExamples{""}, - }.ToString() - ); + {RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of all found unspent outputs in " + CURRENCY_UNIT}, + }}, + RPCExamples{""}, + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}); @@ -2676,25 +2575,22 @@ UniValue scantxoutset(const JSONRPCRequest& request) static UniValue getblockfilter(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( - RPCHelpMan{"getblockfilter", - "\nRetrieve a BIP 157 content filter for a particular block.\n", - { - {"blockhash", RPCArg::Type::STR, RPCArg::Optional::NO, "The hash of the block"}, - {"filtertype", RPCArg::Type::STR, /* default */ "basic", "The type name of the filter"}, - }, - RPCResult{ - "{\n" - " \"filter\" : (string) the hex-encoded filter data\n" - " \"header\" : (string) the hex-encoded filter header\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"") - }, - }.ToString()); - } + RPCHelpMan{"getblockfilter", + "\nRetrieve a BIP 157 content filter for a particular block.\n", + { + {"blockhash", RPCArg::Type::STR, RPCArg::Optional::NO, "The hash of the block"}, + {"filtertype", RPCArg::Type::STR, /* default */ "basic", "The type name of the filter"}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "filter", "the hex-encoded filter data"}, + {RPCResult::Type::STR_HEX, "header", "the hex-encoded filter header"}, + }}, + RPCExamples{ + HelpExampleCli("getblockfilter", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" \"basic\"") + }, + }.Check(request); uint256 block_hash = ParseHashV(request.params[0], "blockhash"); std::string filtertype_name = "basic"; diff --git a/src/rpc/coinjoin.cpp b/src/rpc/coinjoin.cpp index 933afa8df1ed..47340b7ffe9e 100644 --- a/src/rpc/coinjoin.cpp +++ b/src/rpc/coinjoin.cpp @@ -20,8 +20,6 @@ #ifdef ENABLE_WALLET static UniValue coinjoin(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"coinjoin", "\nAvailable commands:\n" " start - Start mixing\n" @@ -32,7 +30,7 @@ static UniValue coinjoin(const JSONRPCRequest& request) }, RPCResults{}, RPCExamples{""}, - }.ToString()); + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -96,52 +94,51 @@ static UniValue getpoolinfo(const JSONRPCRequest& request) static UniValue getcoinjoininfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) { - throw std::runtime_error( RPCHelpMan{"getcoinjoininfo", "Returns an object containing an information about CoinJoin settings and state.\n", {}, - RPCResults{ - {"for regular nodes", - "{\n" - " \"enabled\" : true|false, (boolean) Whether mixing functionality is enabled\n" - " \"multisession\" : true|false, (boolean) Whether CoinJoin Multisession option is enabled\n" - " \"max_sessions\" : xxx, (numeric) How many parallel mixing sessions can there be at once\n" - " \"max_rounds\" : xxx, (numeric) How many rounds to mix\n" - " \"max_amount\" : xxx, (numeric) Target CoinJoin balance in " + CURRENCY_UNIT + "\n" - " \"denoms_goal\" : xxx, (numeric) How many inputs of each denominated amount to target\n" - " \"denoms_hardcap\" : xxx, (numeric) Maximum limit of how many inputs of each denominated amount to create\n" - " \"queue_size\" : xxx, (numeric) How many queues there are currently on the network\n" - " \"running\" : true|false, (boolean) Whether mixing is currently running\n" - " \"sessions\" : (array of json objects)\n" - " [\n" - " {\n" - " \"protxhash\" : \"...\", (string) The ProTxHash of the masternode\n" - " \"outpoint\" : \"txid-index\", (string) The outpoint of the masternode\n" - " \"service\" : \"host:port\", (string) The IP address and port of the masternode\n" - " \"denomination\" : xxx, (numeric) The denomination of the mixing session in " + CURRENCY_UNIT + "\n" - " \"state\" : \"...\", (string) Current state of the mixing session\n" - " \"entries_count\" : xxx, (numeric) The number of entries in the mixing session\n" - " }\n" - " ,...\n" - " ],\n" - " \"keys_left\" : xxx, (numeric) How many new keys are left since last automatic backup\n" - " \"warnings\" : \"...\" (string) Warnings if any\n" - "}\n" - }, {"for masternodes", - "{\n" - " \"queue_size\" : xxx, (numeric) How many queues there are currently on the network\n" - " \"denomination\" : xxx, (numeric) The denomination of the mixing session in " + CURRENCY_UNIT + "\n" - " \"state\" : \"...\", (string) Current state of the mixing session\n" - " \"entries_count\" : xxx, (numeric) The number of entries in the mixing session\n" - "}\n" - }}, + { + RPCResult{"for regular nodes", + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "enabled", "Whether mixing functionality is enabled"}, + {RPCResult::Type::BOOL, "multisession", "Whether CoinJoin Multisession option is enabled"}, + {RPCResult::Type::NUM, "max_sessions", "How many parallel mixing sessions can there be at once"}, + {RPCResult::Type::NUM, "max_rounds", "How many rounds to mix"}, + {RPCResult::Type::NUM, "max_amount", "Target CoinJoin balance in " + CURRENCY_UNIT + ""}, + {RPCResult::Type::NUM, "denoms_goal", "How many inputs of each denominated amount to target"}, + {RPCResult::Type::NUM, "denoms_hardcap", "Maximum limit of how many inputs of each denominated amount to create"}, + {RPCResult::Type::NUM, "queue_size", "How many queues there are currently on the network"}, + {RPCResult::Type::BOOL, "running", "Whether mixing is currently running"}, + {RPCResult::Type::ARR, "sessions", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "protxhash", "The ProTxHash of the masternode"}, + {RPCResult::Type::STR_HEX, "outpoint", "The outpoint of the masternode"}, + {RPCResult::Type::STR, "service", "The IP address and port of the masternode"}, + {RPCResult::Type::NUM, "denomination", "The denomination of the mixing session in " + CURRENCY_UNIT + ""}, + {RPCResult::Type::STR_HEX, "state", "Current state of the mixing session"}, + {RPCResult::Type::NUM, "entries_count", "The number of entries in the mixing session"}, + }}, + }}, + {RPCResult::Type::NUM, "keys_left", "How many new keys are left since last automatic backup"}, + {RPCResult::Type::STR, "warnings", "Warnings if any"}, + }}, + RPCResult{"for masternodes", + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "queue_size", "How many queues there are currently on the network"}, + {RPCResult::Type::NUM, "denomination", "The denomination of the mixing session in " + CURRENCY_UNIT + ""}, + {RPCResult::Type::STR_HEX, "state", "Current state of the mixing session"}, + {RPCResult::Type::NUM, "entries_count", "The number of entries in the mixing session"}, + }}, + }, RPCExamples{ HelpExampleCli("getcoinjoininfo", "") + HelpExampleRpc("getcoinjoininfo", "") }, - }.ToString()); - } + }.Check(request); UniValue obj(UniValue::VOBJ); diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index 12c27cc83c39..e5661bc919c1 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -39,13 +39,12 @@ static void gobject_count_help(const JSONRPCRequest& request) static UniValue gobject_count(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 2) - gobject_count_help(request); + gobject_count_help(request); std::string strMode{"json"}; - if (!request.params[1].isNull()) { - strMode = request.params[1].get_str(); + if (!request.params[0].isNull()) { + strMode = request.params[0].get_str(); } if (strMode != "json" && strMode != "all") @@ -56,7 +55,7 @@ static UniValue gobject_count(const JSONRPCRequest& request) static void gobject_deserialize_help(const JSONRPCRequest& request) { - RPCHelpMan {"gobject deserialize", + RPCHelpMan{"gobject deserialize", "Deserialize governance object from hex string to JSON\n", { {"hex_data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "data in hex string form"}, @@ -68,10 +67,9 @@ static void gobject_deserialize_help(const JSONRPCRequest& request) static UniValue gobject_deserialize(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 2) - gobject_deserialize_help(request); + gobject_deserialize_help(request); - std::string strHex = request.params[1].get_str(); + std::string strHex = request.params[0].get_str(); std::vector v = ParseHex(strHex); std::string s(v.begin(), v.end()); @@ -96,8 +94,7 @@ static void gobject_check_help(const JSONRPCRequest& request) static UniValue gobject_check(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 2) - gobject_check_help(request); + gobject_check_help(request); // ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS @@ -106,7 +103,7 @@ static UniValue gobject_check(const JSONRPCRequest& request) int nRevision = 1; int64_t nTime = GetAdjustedTime(); - std::string strDataHex = request.params[1].get_str(); + std::string strDataHex = request.params[0].get_str(); CGovernanceObject govobj(hashParent, nRevision, nTime, uint256(), strDataHex); @@ -155,8 +152,7 @@ static UniValue gobject_prepare(const JSONRPCRequest& request) if (!wallet) return NullUniValue; CWallet* const pwallet = wallet.get(); - if (request.fHelp || (request.params.size() != 5 && request.params.size() != 6 && request.params.size() != 8)) - gobject_prepare_help(request); + gobject_prepare_help(request); EnsureWalletIsUnlocked(pwallet); @@ -165,15 +161,15 @@ static UniValue gobject_prepare(const JSONRPCRequest& request) uint256 hashParent; // -- attach to root node (root node doesn't really exist, but has a hash of zero) - if (request.params[1].get_str() == "0") { + if (request.params[0].get_str() == "0") { hashParent = uint256(); } else { - hashParent = ParseHashV(request.params[1], "parent-hash"); + hashParent = ParseHashV(request.params[0], "parent-hash"); } - int nRevision = ParseInt32V(request.params[2], "revision"); - int64_t nTime = ParseInt64V(request.params[3], "time"); - std::string strDataHex = request.params[4].get_str(); + int nRevision = ParseInt32V(request.params[1], "revision"); + int64_t nTime = ParseInt64V(request.params[2], "time"); + std::string strDataHex = request.params[3].get_str(); // CREATE A NEW COLLATERAL TRANSACTION FOR THIS SPECIFIC OBJECT @@ -184,8 +180,8 @@ static UniValue gobject_prepare(const JSONRPCRequest& request) // users ignore all instructions on dashcentral etc. and do not save them... // Let's log them here and hope users do not mess with debug.log LogPrintf("gobject_prepare -- params: %s %s %s %s, data: %s, hash: %s\n", - request.params[1].getValStr(), request.params[2].getValStr(), - request.params[3].getValStr(), request.params[4].getValStr(), + request.params[0].getValStr(), request.params[1].getValStr(), + request.params[2].getValStr(), request.params[3].getValStr(), govobj.GetDataAsPlainString(), govobj.GetHash().ToString()); if (govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL) { @@ -219,9 +215,9 @@ static UniValue gobject_prepare(const JSONRPCRequest& request) // If specified, spend this outpoint as the proposal fee COutPoint outpoint; outpoint.SetNull(); - if (!request.params[6].isNull() && !request.params[7].isNull()) { - uint256 collateralHash = ParseHashV(request.params[6], "outputHash"); - int32_t collateralIndex = ParseInt32V(request.params[7], "outputIndex"); + if (!request.params[5].isNull() && !request.params[6].isNull()) { + uint256 collateralHash = ParseHashV(request.params[5], "outputHash"); + int32_t collateralIndex = ParseInt32V(request.params[6], "outputIndex"); if (collateralHash.IsNull() || collateralIndex < 0) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid hash or index: %s-%d", collateralHash.ToString(), collateralIndex)); } @@ -234,7 +230,7 @@ static UniValue gobject_prepare(const JSONRPCRequest& request) if (!pwallet->GetBudgetSystemCollateralTX(*locked_chain, tx, govobj.GetHash(), govobj.GetMinCollateralFee(fork_active), outpoint)) { std::string err = "Error making collateral transaction for governance object. Please check your wallet balance and make sure your wallet is unlocked."; - if (!request.params[6].isNull() && !request.params[7].isNull()) { + if (!request.params[5].isNull() && !request.params[6].isNull()) { err += "Please verify your specified output is valid and is enough for the combined proposal fee and transaction fee."; } throw JSONRPCError(RPC_INTERNAL_ERROR, err); @@ -268,9 +264,7 @@ static void gobject_list_prepared_help(const JSONRPCRequest& request) static UniValue gobject_list_prepared(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() > 2)) { - gobject_list_prepared_help(request); - } + gobject_list_prepared_help(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -278,7 +272,7 @@ static UniValue gobject_list_prepared(const JSONRPCRequest& request) EnsureWalletIsUnlocked(pwallet); - int64_t nCount = request.params.size() > 1 ? ParseInt64V(request.params[1], "count") : 10; + int64_t nCount = request.params.empty() ? 10 : ParseInt64V(request.params[0], "count"); if (nCount < 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count"); } @@ -321,8 +315,7 @@ static void gobject_submit_help(const JSONRPCRequest& request) static UniValue gobject_submit(const JSONRPCRequest& request) { - if (request.fHelp || ((request.params.size() < 5) || (request.params.size() > 6))) - gobject_submit_help(request); + gobject_submit_help(request); if(!masternodeSync.IsBlockchainSynced()) { throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Must wait for client to sync with masternode network. Try again in a minute or so."); @@ -339,21 +332,21 @@ static UniValue gobject_submit(const JSONRPCRequest& request) uint256 txidFee; - if (!request.params[5].isNull()) { - txidFee = ParseHashV(request.params[5], "fee-txid"); + if (!request.params[4].isNull()) { + txidFee = ParseHashV(request.params[4], "fee-txid"); } uint256 hashParent; - if (request.params[1].get_str() == "0") { // attach to root node (root node doesn't really exist, but has a hash of zero) + if (request.params[0].get_str() == "0") { // attach to root node (root node doesn't really exist, but has a hash of zero) hashParent = uint256(); } else { - hashParent = ParseHashV(request.params[1], "parent-hash"); + hashParent = ParseHashV(request.params[0], "parent-hash"); } // GET THE PARAMETERS FROM USER - int nRevision = ParseInt32V(request.params[2], "revision"); - int64_t nTime = ParseInt64V(request.params[3], "time"); - std::string strDataHex = request.params[4].get_str(); + int nRevision = ParseInt32V(request.params[1], "revision"); + int64_t nTime = ParseInt64V(request.params[2], "time"); + std::string strDataHex = request.params[3].get_str(); CGovernanceObject govobj(hashParent, nRevision, nTime, txidFee, strDataHex); @@ -380,7 +373,7 @@ static UniValue gobject_submit(const JSONRPCRequest& request) LogPrintf("gobject(submit) -- Object submission rejected because node is not a masternode\n"); throw JSONRPCError(RPC_INVALID_PARAMETER, "Only valid masternodes can submit this type of object"); } - } else if (request.params.size() != 6) { + } else if (request.params.size() != 5) { LogPrintf("gobject(submit) -- Object submission rejected because fee tx not provided\n"); throw JSONRPCError(RPC_INVALID_PARAMETER, "The fee-txid parameter must be included to submit this type of object"); } @@ -436,14 +429,13 @@ static void gobject_vote_conf_help(const JSONRPCRequest& request) static UniValue gobject_vote_conf(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 4) - gobject_vote_conf_help(request); + gobject_vote_conf_help(request); uint256 hash; - hash = ParseHashV(request.params[1], "Object hash"); - std::string strVoteSignal = request.params[2].get_str(); - std::string strVoteOutcome = request.params[3].get_str(); + hash = ParseHashV(request.params[0], "Object hash"); + std::string strVoteSignal = request.params[1].get_str(); + std::string strVoteOutcome = request.params[2].get_str(); vote_signal_enum_t eVoteSignal = CGovernanceVoting::ConvertVoteSignal(strVoteSignal); if (eVoteSignal == VOTE_SIGNAL_NONE) { @@ -610,16 +602,15 @@ static void gobject_vote_many_help(const JSONRPCRequest& request) static UniValue gobject_vote_many(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 4) - gobject_vote_many_help(request); + gobject_vote_many_help(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; CWallet* const pwallet = wallet.get(); - uint256 hash = ParseHashV(request.params[1], "Object hash"); - std::string strVoteSignal = request.params[2].get_str(); - std::string strVoteOutcome = request.params[3].get_str(); + uint256 hash = ParseHashV(request.params[0], "Object hash"); + std::string strVoteSignal = request.params[1].get_str(); + std::string strVoteOutcome = request.params[2].get_str(); vote_signal_enum_t eVoteSignal = CGovernanceVoting::ConvertVoteSignal(strVoteSignal); if (eVoteSignal == VOTE_SIGNAL_NONE) { @@ -666,16 +657,15 @@ static void gobject_vote_alias_help(const JSONRPCRequest& request) static UniValue gobject_vote_alias(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 5) - gobject_vote_alias_help(request); + gobject_vote_alias_help(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; CWallet* const pwallet = wallet.get(); - uint256 hash = ParseHashV(request.params[1], "Object hash"); - std::string strVoteSignal = request.params[2].get_str(); - std::string strVoteOutcome = request.params[3].get_str(); + uint256 hash = ParseHashV(request.params[0], "Object hash"); + std::string strVoteSignal = request.params[1].get_str(); + std::string strVoteOutcome = request.params[2].get_str(); vote_signal_enum_t eVoteSignal = CGovernanceVoting::ConvertVoteSignal(strVoteSignal); if (eVoteSignal == VOTE_SIGNAL_NONE) { @@ -691,7 +681,7 @@ static UniValue gobject_vote_alias(const JSONRPCRequest& request) EnsureWalletIsUnlocked(pwallet); - uint256 proTxHash = ParseHashV(request.params[4], "protx-hash"); + uint256 proTxHash = ParseHashV(request.params[3], "protx-hash"); auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(proTxHash); if (!dmn) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid or unknown proTxHash"); @@ -782,19 +772,18 @@ static void gobject_list_help(const JSONRPCRequest& request) static UniValue gobject_list(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 3) - gobject_list_help(request); + gobject_list_help(request); std::string strCachedSignal = "valid"; - if (!request.params[1].isNull()) { - strCachedSignal = request.params[1].get_str(); + if (!request.params[0].isNull()) { + strCachedSignal = request.params[0].get_str(); } if (strCachedSignal != "valid" && strCachedSignal != "funding" && strCachedSignal != "delete" && strCachedSignal != "endorsed" && strCachedSignal != "all") return "Invalid signal, should be 'valid', 'funding', 'delete', 'endorsed' or 'all'"; std::string strType = "all"; - if (!request.params[2].isNull()) { - strType = request.params[2].get_str(); + if (!request.params[1].isNull()) { + strType = request.params[1].get_str(); } if (strType != "proposals" && strType != "triggers" && strType != "all") return "Invalid type, should be 'proposals', 'triggers' or 'all'"; @@ -817,19 +806,18 @@ static void gobject_diff_help(const JSONRPCRequest& request) static UniValue gobject_diff(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 3) - gobject_diff_help(request); + gobject_diff_help(request); std::string strCachedSignal = "valid"; - if (!request.params[1].isNull()) { - strCachedSignal = request.params[1].get_str(); + if (!request.params[0].isNull()) { + strCachedSignal = request.params[0].get_str(); } if (strCachedSignal != "valid" && strCachedSignal != "funding" && strCachedSignal != "delete" && strCachedSignal != "endorsed" && strCachedSignal != "all") return "Invalid signal, should be 'valid', 'funding', 'delete', 'endorsed' or 'all'"; std::string strType = "all"; - if (!request.params[2].isNull()) { - strType = request.params[2].get_str(); + if (!request.params[1].isNull()) { + strType = request.params[1].get_str(); } if (strType != "proposals" && strType != "triggers" && strType != "all") return "Invalid type, should be 'proposals', 'triggers' or 'all'"; @@ -851,11 +839,10 @@ static void gobject_get_help(const JSONRPCRequest& request) static UniValue gobject_get(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 2) - gobject_get_help(request); + gobject_get_help(request); // COLLECT VARIABLES FROM OUR USER - uint256 hash = ParseHashV(request.params[1], "GovObj hash"); + uint256 hash = ParseHashV(request.params[0], "GovObj hash"); if (g_txindex) { g_txindex->BlockUntilSyncedToCurrentChain(); @@ -944,17 +931,16 @@ static void gobject_getcurrentvotes_help(const JSONRPCRequest& request) static UniValue gobject_getcurrentvotes(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() != 2 && request.params.size() != 4)) - gobject_getcurrentvotes_help(request); + gobject_getcurrentvotes_help(request); // COLLECT PARAMETERS FROM USER - uint256 hash = ParseHashV(request.params[1], "Governance hash"); + uint256 hash = ParseHashV(request.params[0], "Governance hash"); COutPoint mnCollateralOutpoint; - if (!request.params[2].isNull() && !request.params[3].isNull()) { - uint256 txid = ParseHashV(request.params[2], "Masternode Collateral hash"); - std::string strVout = request.params[3].get_str(); + if (!request.params[1].isNull() && !request.params[2].isNull()) { + uint256 txid = ParseHashV(request.params[1], "Masternode Collateral hash"); + std::string strVout = request.params[2].get_str(); mnCollateralOutpoint = COutPoint(txid, (uint32_t)atoi(strVout)); } @@ -984,7 +970,7 @@ static UniValue gobject_getcurrentvotes(const JSONRPCRequest& request) [[ noreturn ]] static void gobject_help() { - RPCHelpMan {"gobject", + RPCHelpMan{"gobject", "Set of commands to manage governance objects.\n" "\nAvailable commands:\n" " check - Validate governance object data (proposal only)\n" @@ -1015,56 +1001,51 @@ static UniValue gobject_getcurrentvotes(const JSONRPCRequest& request) static UniValue gobject(const JSONRPCRequest& request) { - std::string strCommand; - if (!request.params[0].isNull()) - strCommand = request.params[0].get_str(); + const JSONRPCRequest new_request{request.strMethod == "gobject" ? request.squashed() : request}; + const std::string command{new_request.strMethod}; - if (request.fHelp && strCommand.empty()) { - gobject_help(); - } - - if (strCommand == "count") { - return gobject_count(request); - } else if (strCommand == "deserialize") { + if (command == "gobjectcount") { + return gobject_count(new_request); + } else if (command == "gobjectdeserialize") { // DEBUG : TEST DESERIALIZATION OF GOVERNANCE META DATA - return gobject_deserialize(request); - } else if (strCommand == "check") { + return gobject_deserialize(new_request); + } else if (command == "gobjectcheck") { // VALIDATE A GOVERNANCE OBJECT PRIOR TO SUBMISSION - return gobject_check(request); + return gobject_check(new_request); #ifdef ENABLE_WALLET - } else if (strCommand == "prepare") { + } else if (command == "gobjectprepare") { // PREPARE THE GOVERNANCE OBJECT BY CREATING A COLLATERAL TRANSACTION - return gobject_prepare(request); - } else if (strCommand == "list-prepared") { - return gobject_list_prepared(request); + return gobject_prepare(new_request); + } else if (command == "gobjectlist-prepared") { + return gobject_list_prepared(new_request); #endif // ENABLE_WALLET - } else if (strCommand == "submit") { + } else if (command == "gobjectsubmit") { // AFTER COLLATERAL TRANSACTION HAS MATURED USER CAN SUBMIT GOVERNANCE OBJECT TO PROPAGATE NETWORK /* ------ Example Governance Item ------ gobject submit 6e622bb41bad1fb18e7f23ae96770aeb33129e18bd9efe790522488e580a0a03 0 1 1464292854 "beer-reimbursement" 5b5b22636f6e7472616374222c207b2270726f6a6563745f6e616d65223a20225c22626565722d7265696d62757273656d656e745c22222c20227061796d656e745f61646472657373223a20225c225879324c4b4a4a64655178657948726e34744744514238626a6876464564615576375c22222c2022656e645f64617465223a202231343936333030343030222c20226465736372697074696f6e5f75726c223a20225c227777772e646173687768616c652e6f72672f702f626565722d7265696d62757273656d656e745c22222c2022636f6e74726163745f75726c223a20225c22626565722d7265696d62757273656d656e742e636f6d2f3030312e7064665c22222c20227061796d656e745f616d6f756e74223a20223233342e323334323232222c2022676f7665726e616e63655f6f626a6563745f6964223a2037342c202273746172745f64617465223a202231343833323534303030227d5d5d1 */ - return gobject_submit(request); - } else if (strCommand == "vote-conf") { - return gobject_vote_conf(request); + return gobject_submit(new_request); + } else if (command == "gobjectvote-conf") { + return gobject_vote_conf(new_request); #ifdef ENABLE_WALLET - } else if (strCommand == "vote-many") { - return gobject_vote_many(request); - } else if (strCommand == "vote-alias") { - return gobject_vote_alias(request); + } else if (command == "gobjectvote-many") { + return gobject_vote_many(new_request); + } else if (command == "gobjectvote-alias") { + return gobject_vote_alias(new_request); #endif - } else if (strCommand == "list") { + } else if (command == "gobjectlist") { // USERS CAN QUERY THE SYSTEM FOR A LIST OF VARIOUS GOVERNANCE ITEMS - return gobject_list(request); - } else if (strCommand == "diff") { - return gobject_diff(request); - } else if (strCommand == "get") { + return gobject_list(new_request); + } else if (command == "gobjectdiff") { + return gobject_diff(new_request); + } else if (command == "gobjectget") { // GET SPECIFIC GOVERNANCE ENTRY - return gobject_get(request); - } else if (strCommand == "getcurrentvotes") { + return gobject_get(new_request); + } else if (command == "gobjectgetcurrentvotes") { // GET VOTES FOR SPECIFIC GOVERNANCE OBJECT - return gobject_getcurrentvotes(request); + return gobject_getcurrentvotes(new_request); } else { gobject_help(); } @@ -1072,22 +1053,20 @@ static UniValue gobject(const JSONRPCRequest& request) static UniValue voteraw(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 7) - throw std::runtime_error( - RPCHelpMan{"voteraw", - "Compile and relay a governance vote with provided external signature instead of signing vote internally\n", - { - {"mn-collateral-tx-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, ""}, - {"mn-collateral-tx-index", RPCArg::Type::NUM, RPCArg::Optional::NO, ""}, - {"governance-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, ""}, - {"vote-signal", RPCArg::Type::STR, RPCArg::Optional::NO, ""}, - {"vote-outcome", RPCArg::Type::STR, RPCArg::Optional::NO, "yes|no|abstain"}, - {"time", RPCArg::Type::NUM, RPCArg::Optional::NO, ""}, - {"vote-sig", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, ""}, - }, - RPCResults{}, - RPCExamples{""} - }.ToString()); + RPCHelpMan{"voteraw", + "Compile and relay a governance vote with provided external signature instead of signing vote internally\n", + { + {"mn-collateral-tx-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, ""}, + {"mn-collateral-tx-index", RPCArg::Type::NUM, RPCArg::Optional::NO, ""}, + {"governance-hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, ""}, + {"vote-signal", RPCArg::Type::STR, RPCArg::Optional::NO, ""}, + {"vote-outcome", RPCArg::Type::STR, RPCArg::Optional::NO, "yes|no|abstain"}, + {"time", RPCArg::Type::NUM, RPCArg::Optional::NO, ""}, + {"vote-sig", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, ""}, + }, + RPCResults{}, + RPCExamples{""} + }.Check(request); uint256 hashMnCollateralTx = ParseHashV(request.params[0], "mn collateral tx hash"); int nMnCollateralTxIndex = request.params[1].get_int(); @@ -1154,26 +1133,24 @@ static UniValue voteraw(const JSONRPCRequest& request) static UniValue getgovernanceinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) { - throw std::runtime_error( - RPCHelpMan{"getgovernanceinfo", - "Returns an object containing governance parameters.\n", - {}, - RPCResult{ - "{\n" - " \"governanceminquorum\" : xxxxx, (numeric) the absolute minimum number of votes needed to trigger a governance action\n" - " \"proposalfee\" : xxx.xx, (numeric) the collateral transaction fee which must be paid to create a proposal in " + CURRENCY_UNIT + "\n" - " \"superblockcycle\" : xxxxx, (numeric) the number of blocks between superblocks\n" - " \"lastsuperblock\" : xxxxx, (numeric) the block number of the last superblock\n" - " \"nextsuperblock\" : xxxxx, (numeric) the block number of the next superblock\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("getgovernanceinfo", "") - + HelpExampleRpc("getgovernanceinfo", "") - }, - }.ToString()); - } + RPCHelpMan{"getgovernanceinfo", + "Returns an object containing governance parameters.\n", + {}, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "governanceminquorum", "the absolute minimum number of votes needed to trigger a governance action"}, + {RPCResult::Type::NUM, "proposalfee", "the collateral transaction fee which must be paid to create a proposal in " + CURRENCY_UNIT + ""}, + {RPCResult::Type::NUM, "superblockcycle", "the number of blocks between superblocks"}, + {RPCResult::Type::NUM, "lastsuperblock", "the block number of the last superblock"}, + {RPCResult::Type::NUM, "nextsuperblock", "the block number of the next superblock"}, + }}, + RPCExamples{ + HelpExampleCli("getgovernanceinfo", "") + + HelpExampleRpc("getgovernanceinfo", "") + }, + }.Check(request); + int nLastSuperblock = 0, nNextSuperblock = 0; const auto* pindex = WITH_LOCK(cs_main, return ::ChainActive().Tip()); @@ -1194,22 +1171,19 @@ static UniValue getgovernanceinfo(const JSONRPCRequest& request) static UniValue getsuperblockbudget(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( - RPCHelpMan{"getsuperblockbudget", - "\nReturns the absolute maximum sum of superblock payments allowed.\n", - { - {"index", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block index"}, - }, - RPCResult{ - "n (numeric) The absolute maximum sum of superblock payments allowed, in " + CURRENCY_UNIT + "\n" - }, - RPCExamples{ - HelpExampleCli("getsuperblockbudget", "1000") - + HelpExampleRpc("getsuperblockbudget", "1000") - }, - }.ToString()); - } + RPCHelpMan{"getsuperblockbudget", + "\nReturns the absolute maximum sum of superblock payments allowed.\n", + { + {"index", RPCArg::Type::NUM, RPCArg::Optional::NO, "The block index"}, + }, + RPCResult{ + RPCResult::Type::NUM, "n", "The absolute maximum sum of superblock payments allowed, in " + CURRENCY_UNIT + }, + RPCExamples{ + HelpExampleCli("getsuperblockbudget", "1000") + + HelpExampleRpc("getsuperblockbudget", "1000") + }, + }.Check(request); int nBlockHeight = request.params[0].get_int(); if (nBlockHeight < 0) { diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 1c9f7272403e..cd18937d075c 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -56,19 +56,6 @@ static void masternode_list_help(const JSONRPCRequest& request) }.Check(request); } -static UniValue masternode_list(const JSONRPCRequest& request) -{ - if (request.fHelp) - masternode_list_help(request); - JSONRPCRequest newRequest = request; - newRequest.params.setArray(); - // forward params but skip "list" - for (unsigned int i = 1; i < request.params.size(); i++) { - newRequest.params.push_back(request.params[i]); - } - return masternodelist(newRequest); -} - static void masternode_connect_help(const JSONRPCRequest& request) { RPCHelpMan{"masternode connect", @@ -83,10 +70,9 @@ static void masternode_connect_help(const JSONRPCRequest& request) static UniValue masternode_connect(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2) - masternode_connect_help(request); + masternode_connect_help(request); - std::string strAddress = request.params[1].get_str(); + std::string strAddress = request.params[0].get_str(); CService addr; if (!Lookup(strAddress.c_str(), addr, 0, false)) @@ -112,8 +98,7 @@ static void masternode_count_help(const JSONRPCRequest& request) static UniValue masternode_count(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) - masternode_count_help(request); + masternode_count_help(request); auto mnList = deterministicMNManager->GetListAtChainTip(); int total = mnList.GetAllMNsCount(); @@ -163,9 +148,7 @@ static void masternode_winner_help(const JSONRPCRequest& request) static UniValue masternode_winner(const JSONRPCRequest& request) { - if (request.fHelp || !IsDeprecatedRPCEnabled("masternode_winner")) - masternode_winner_help(request); - + masternode_winner_help(request); return GetNextMasternodeForPayment(10); } @@ -185,9 +168,7 @@ static void masternode_current_help(const JSONRPCRequest& request) static UniValue masternode_current(const JSONRPCRequest& request) { - if (request.fHelp || !IsDeprecatedRPCEnabled("masternode_current")) - masternode_current_help(request); - + masternode_current_help(request); return GetNextMasternodeForPayment(1); } @@ -204,8 +185,7 @@ static void masternode_outputs_help(const JSONRPCRequest& request) static UniValue masternode_outputs(const JSONRPCRequest& request) { - if (request.fHelp) - masternode_outputs_help(request); + masternode_outputs_help(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -242,8 +222,7 @@ static void masternode_status_help(const JSONRPCRequest& request) static UniValue masternode_status(const JSONRPCRequest& request) { - if (request.fHelp) - masternode_status_help(request); + masternode_status_help(request); if (!fMasternodeMode) throw JSONRPCError(RPC_INTERNAL_ERROR, "This is not a masternode"); @@ -324,8 +303,7 @@ static void masternode_winners_help(const JSONRPCRequest& request) static UniValue masternode_winners(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 3) - masternode_winners_help(request); + masternode_winners_help(request); const CBlockIndex* pindexTip{nullptr}; { @@ -337,12 +315,12 @@ static UniValue masternode_winners(const JSONRPCRequest& request) int nCount = 10; std::string strFilter = ""; - if (!request.params[1].isNull()) { - nCount = atoi(request.params[1].get_str()); + if (!request.params[0].isNull()) { + nCount = atoi(request.params[0].get_str()); } - if (!request.params[2].isNull()) { - strFilter = request.params[2].get_str(); + if (!request.params[1].isNull()) { + strFilter = request.params[1].get_str(); } UniValue obj(UniValue::VOBJ); @@ -376,26 +354,26 @@ static void masternode_payments_help(const JSONRPCRequest& request) {"count", RPCArg::Type::NUM, /* default */ "1", "The number of blocks to return. Will return previous blocks if is negative. Both 1 and -1 correspond to the chain tip."}, }, RPCResult { - " [ (json array) Blocks\n" - " {\n" - " \"height\" : n, (numeric) The height of the block\n" - " \"blockhash\" : \"hash\", (string) The hash of the block\n" - " \"amount\" : n (numeric) Amount received in this block by all masternodes\n" - " \"masternodes\" : [ (json array) Masternodes that received payments in this block\n" - " {\n" - " \"proTxHash\" : \"xxxx\", (string) The hash of the corresponding ProRegTx\n" - " \"amount\" : n (numeric) Amount received by this masternode\n" - " \"payees\" : [ (json array) Payees who received a share of this payment\n" - " {\n" - " \"address\" : \"xxx\", (string) Payee address\n" - " \"script\" : \"xxx\", (string) Payee scriptPubKey\n" - " \"amount\" : n (numeric) Amount received by this payee\n" - " },...\n" - " ]\n" - " },...\n" - " ]\n" - " },...\n" - " ]" + RPCResult::Type::ARR, "", "Blocks", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "height", "The height of the block"}, + {RPCResult::Type::STR_HEX, "blockhash", "The hash of the block"}, + {RPCResult::Type::NUM, "amount", "Amount received in this block by all masternodes"}, + {RPCResult::Type::ARR, "masternodes", "Masternodes that received payments in this block", + { + {RPCResult::Type::STR_HEX, "proTxHash", "The hash of the corresponding ProRegTx"}, + {RPCResult::Type::NUM, "amount", "Amount received by this masternode"}, + {RPCResult::Type::ARR, "payees", "Payees who received a share of this payment", + { + {RPCResult::Type::STR, "address", "Payee address"}, + {RPCResult::Type::STR_HEX, "script", "Payee scriptPubKey"}, + {RPCResult::Type::NUM, "amount", "Amount received by this payee"}, + }}, + }}, + }}, + }, }, RPCExamples{""} }.Check(request); @@ -403,9 +381,7 @@ static void masternode_payments_help(const JSONRPCRequest& request) static UniValue masternode_payments(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 3) { - masternode_payments_help(request); - } + masternode_payments_help(request); CBlockIndex* pindex{nullptr}; @@ -413,19 +389,19 @@ static UniValue masternode_payments(const JSONRPCRequest& request) g_txindex->BlockUntilSyncedToCurrentChain(); } - if (request.params[1].isNull()) { + if (request.params[0].isNull()) { LOCK(cs_main); pindex = ::ChainActive().Tip(); } else { LOCK(cs_main); - uint256 blockHash = ParseHashV(request.params[1], "blockhash"); + uint256 blockHash = ParseHashV(request.params[0], "blockhash"); pindex = LookupBlockIndex(blockHash); if (pindex == nullptr) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } } - int64_t nCount = request.params.size() > 2 ? ParseInt64V(request.params[2], "count") : 1; + int64_t nCount = request.params.size() > 1 ? ParseInt64V(request.params[1], "count") : 1; // A temporary vector which is used to sort results properly (there is no "reverse" in/for UniValue) std::vector vecPayments; @@ -536,35 +512,29 @@ static UniValue masternode_payments(const JSONRPCRequest& request) static UniValue masternode(const JSONRPCRequest& request) { - std::string strCommand; - if (!request.params[0].isNull()) { - strCommand = request.params[0].get_str(); - } - - if (request.fHelp && strCommand.empty()) { - masternode_help(); - } - - if (strCommand == "list") { - return masternode_list(request); - } else if (strCommand == "connect") { - return masternode_connect(request); - } else if (strCommand == "count") { - return masternode_count(request); - } else if (strCommand == "current") { - return masternode_current(request); - } else if (strCommand == "winner") { - return masternode_winner(request); + const JSONRPCRequest new_request{request.strMethod == "masternode" ? request.squashed() : request}; + const std::string command{new_request.strMethod}; + + if (command == "masternodeconnect") { + return masternode_connect(new_request); + } else if (command == "masternodecount") { + return masternode_count(new_request); + } else if (command == "masternodecurrent") { + return masternode_current(new_request); + } else if (command == "masternodewinner") { + return masternode_winner(new_request); #ifdef ENABLE_WALLET - } else if (strCommand == "outputs") { - return masternode_outputs(request); + } else if (command == "masternodeoutputs") { + return masternode_outputs(new_request); #endif // ENABLE_WALLET - } else if (strCommand == "status") { - return masternode_status(request); - } else if (strCommand == "payments") { - return masternode_payments(request); - } else if (strCommand == "winners") { - return masternode_winners(request); + } else if (command == "masternodestatus") { + return masternode_status(new_request); + } else if (command == "masternodepayments") { + return masternode_payments(new_request); + } else if (command == "masternodewinners") { + return masternode_winners(new_request); + } else if (command == "masternodelist") { + return masternodelist(new_request); } else { masternode_help(); } @@ -722,7 +692,7 @@ static const CRPCCommand commands[] = { // category name actor (function) argNames // --------------------- ------------------------ ----------------------- ---------- { "dash", "masternode", &masternode, {} }, - { "dash", "masternodelist", &masternodelist, {} }, + { "dash", "masternodelist", &masternode, {} }, }; // clang-format on void RegisterMasternodeRPCCommands(CRPCTable &t) diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index d22adeb0d123..abfa450d45ad 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -85,23 +85,21 @@ static UniValue GetNetworkHashPS(int lookup, int height) { static UniValue getnetworkhashps(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"getnetworkhashps", - "\nReturns the estimated network hashes per second based on the last n blocks.\n" - "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n" - "Pass in [height] to estimate the network speed at the time when a certain block was found.\n", - { - {"nblocks", RPCArg::Type::NUM, /* default */ "120", "The number of blocks, or -1 for blocks since last difficulty change."}, - {"height", RPCArg::Type::NUM, /* default */ "-1", "To estimate at the time of the given height."}, - }, - RPCResult{ - RPCResult::Type::NUM, "", "Hashes per second estimated"}, - RPCExamples{ - HelpExampleCli("getnetworkhashps", "") - + HelpExampleRpc("getnetworkhashps", "") - }, - }.ToString()); + RPCHelpMan{"getnetworkhashps", + "\nReturns the estimated network hashes per second based on the last n blocks.\n" + "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n" + "Pass in [height] to estimate the network speed at the time when a certain block was found.\n", + { + {"nblocks", RPCArg::Type::NUM, /* default */ "120", "The number of blocks, or -1 for blocks since last difficulty change."}, + {"height", RPCArg::Type::NUM, /* default */ "-1", "To estimate at the time of the given height."}, + }, + RPCResult{ + RPCResult::Type::NUM, "", "Hashes per second estimated"}, + RPCExamples{ + HelpExampleCli("getnetworkhashps", "") + + HelpExampleRpc("getnetworkhashps", "") + }, + }.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); @@ -221,7 +219,11 @@ static UniValue generatetodescriptor(const JSONRPCRequest& request) {"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."}, }, RPCResult{ - "[ blockhashes ] (array) hashes of blocks generated\n"}, + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::STR_HEX, "blockhashes", "hashes of blocks generated"}, + } + }, RPCExamples{ "\nGenerate 11 blocks to mydesc\n" + HelpExampleCli("generatetodescriptor", "11 \"mydesc\"")}, } @@ -246,27 +248,24 @@ static UniValue generatetodescriptor(const JSONRPCRequest& request) static UniValue generatetoaddress(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) - throw std::runtime_error( - RPCHelpMan{"generatetoaddress", - "\nMine blocks immediately to a specified address (before the RPC call returns)\n", - { - {"nblocks", RPCArg::Type::NUM, RPCArg::Optional::NO, "How many blocks are generated immediately."}, - {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The address to send the newly generated Dash to."}, - {"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."}, - }, - RPCResult{ - RPCResult::Type::ARR, "", "hashes of blocks generated", - { - {RPCResult::Type::STR_HEX, "", "blockhash"}, - }}, - RPCExamples{ - "\nGenerate 11 blocks to myaddress\n" - + HelpExampleCli("generatetoaddress", "11 \"myaddress\"") - + "If you are running the Dash Core wallet, you can get a new address to send the newly generated coins to with:\n" - + HelpExampleCli("getnewaddress", "") - }, - }.ToString()); + RPCHelpMan{"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."}, + {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The address to send the newly generated Dash to."}, + {"maxtries", RPCArg::Type::NUM, /* default */ "1000000", "How many iterations to try."}, + }, + RPCResult{ + RPCResult::Type::ARR, "", "hashes of blocks generated", + { + {RPCResult::Type::STR_HEX, "", "blockhash"}, + }}, + RPCExamples{ + "\nGenerate 11 blocks to myaddress\n" + + HelpExampleCli("generatetoaddress", "11 \"myaddress\"") + + "If you are running the Dash Core wallet, you can get a new address to send the newly generated coins to with:\n" + + HelpExampleCli("getnewaddress", "")}, + }.Check(request); int nGenerate = request.params[0].get_int(); uint64_t nMaxTries = 1000000; @@ -409,29 +408,26 @@ static UniValue generateblock(const JSONRPCRequest& request) static UniValue getmininginfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) { - throw std::runtime_error( RPCHelpMan{"getmininginfo", "\nReturns a json object containing mining-related information.", {}, RPCResult{ - "{\n" - " \"blocks\" : nnn, (numeric) The current block\n" - " \"currentblocksize\" : nnn, (numeric, optional) The block size of the last assembled block (only present if a block was ever assembled)\n" - " \"currentblocktx\" : nnn, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)\n" - " \"difficulty\" : xxx.xxxxx (numeric) The current difficulty\n" - " \"networkhashps\" : nnn, (numeric) The network hashes per second\n" - " \"pooledtx\" : n (numeric) The size of the mempool\n" - " \"chain\" : \"xxxx\", (string) current network name (main, test, regtest)\n" - " \"warnings\" : \"...\" (string) any network and blockchain warnings\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "blocks", "The current block"}, + {RPCResult::Type::NUM, "currentblocksize", /* optional */ true, "The block size of the last assembled block (only present if a block was ever assembled)"}, + {RPCResult::Type::NUM, "currentblocktx", /* optional */ true, "The number of block transactions of the last assembled block (only present if a block was ever assembled)"}, + {RPCResult::Type::NUM, "difficulty", "The current difficulty"}, + {RPCResult::Type::NUM, "networkhashps", "The network hashes per second"}, + {RPCResult::Type::NUM, "pooledtx", "The size of the mempool"}, + {RPCResult::Type::STR, "chain", "current network name (main, test, regtest)"}, + {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"}, + }}, RPCExamples{ HelpExampleCli("getmininginfo", "") + HelpExampleRpc("getmininginfo", "") }, - }.ToString()); - } + }.Check(request); LOCK(cs_main); @@ -451,24 +447,22 @@ static UniValue getmininginfo(const JSONRPCRequest& request) // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts static UniValue prioritisetransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 2) - throw std::runtime_error( - RPCHelpMan{"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."}, - {"fee_delta", RPCArg::Type::NUM, RPCArg::Optional::NO, "The fee value (in duffs) to add (or subtract, if negative).\n" - " Note, that this value is not a fee rate. It is a value to modify absolute fee of the TX.\n" - " The fee is not actually paid, only the algorithm for selecting transactions into a block\n" - " considers the transaction as it would have paid a higher (or lower) fee."}, - }, - RPCResult{ - RPCResult::Type::BOOL, "", "Returns true"}, - RPCExamples{ - HelpExampleCli("prioritisetransaction", "\"txid\" 10000") - + HelpExampleRpc("prioritisetransaction", "\"txid\", 10000") - }, - }.ToString()); + RPCHelpMan{"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."}, + {"fee_delta", RPCArg::Type::NUM, RPCArg::Optional::NO, "The fee value (in duffs) to add (or subtract, if negative).\n" + " Note, that this value is not a fee rate. It is a value to modify absolute fee of the TX.\n" + " The fee is not actually paid, only the algorithm for selecting transactions into a block\n" + " considers the transaction as it would have paid a higher (or lower) fee."}, + }, + RPCResult{ + RPCResult::Type::BOOL, "", "Returns true"}, + RPCExamples{ + HelpExampleCli("prioritisetransaction", "\"txid\" 10000") + + HelpExampleRpc("prioritisetransaction", "\"txid\", 10000") + }, + }.Check(request); LOCK(cs_main); @@ -510,99 +504,115 @@ static std::string gbt_vb_name(const Consensus::DeploymentPos pos) { static UniValue getblocktemplate(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( - RPCHelpMan{"getblocktemplate", - "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n" - "It returns data needed to construct a block to work on.\n" - "For full specification, see BIPs 22, 23, and 9:\n" - " https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n" - " https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n" - " https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n", + RPCHelpMan{"getblocktemplate", + "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n" + "It returns data needed to construct a block to work on.\n" + "For full specification, see BIPs 22, 23, and 9:\n" + " https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n" + " https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki\n" + " https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n", + { + {"template_request", RPCArg::Type::OBJ, /* default_val */ "", "A json object in the following spec", { - {"template_request", RPCArg::Type::OBJ, /* default_val */ "", "A json object in the following spec", + {"mode", RPCArg::Type::STR, /* treat as named arg */ RPCArg::Optional::OMITTED_NAMED_ARG, "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"}, + {"capabilities", RPCArg::Type::ARR, /* treat as named arg */ RPCArg::Optional::OMITTED_NAMED_ARG, "A list of strings", { - {"mode", RPCArg::Type::STR, /* treat as named arg */ RPCArg::Optional::OMITTED_NAMED_ARG, "This must be set to \"template\", \"proposal\" (see BIP 23), or omitted"}, - {"capabilities", RPCArg::Type::ARR, /* treat as named arg */ RPCArg::Optional::OMITTED_NAMED_ARG, "A list of strings", - { - {"support", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'"}, - }, - }, - {"rules", RPCArg::Type::ARR, /* default_val */ "", "A list of strings", - { - {"support", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported softfork deployment"}, - }, - }, + {"support", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'"}, + }, + }, + {"rules", RPCArg::Type::ARR, /* default_val */ "", "A list of strings", + { + {"support", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported softfork deployment"}, + }, }, - "\"template_request\""}, - }, - RPCResult{ - "{\n" - " \"capabilities\" : [ \"capability\", ... ], (array of strings) specific client side supported features\n" - " \"version\" : n, (numeric) The preferred block version\n" - " \"rules\" : [ \"rulename\", ... ], (array of strings) specific block rules that are to be enforced\n" - " \"vbavailable\" : { (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n" - " \"rulename\" : bitnumber (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n" - " ,...\n" - " },\n" - " \"vbrequired\" : n, (numeric) bit mask of versionbits the server requires set in submissions\n" - " \"previousblockhash\" : \"xxxx\", (string) The hash of current highest block\n" - " \"transactions\" : [ (json array) contents of non-coinbase transactions that should be included in the next block\n" - " {\n" - " \"data\" : \"xxxx\", (string) transaction data encoded in hexadecimal (byte-for-byte)\n" - " \"hash\" : \"xxxx\", (string) hash/id encoded in little-endian hexadecimal\n" - " \"depends\" : [ (json array) array of numbers \n" - " n (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n" - " ,...\n" - " ],\n" - " \"fee\" : n, (numeric) difference in value between transaction inputs and outputs (in duffs); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n" - " \"sigops\" : n, (numeric) total number of SigOps, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients MUST NOT assume there aren't any\n" - " }\n" - " ,...\n" - " ],\n" - " \"coinbaseaux\" : { ... }, (json object) data that should be included in the coinbase's scriptSig content\n" - " \"coinbasevalue\" : n, (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in duffs)\n" - " \"coinbasetxn\" : { ... }, (json object) information for coinbase transaction\n" - " \"target\" : \"xxxx\", (string) The hash target\n" - " \"mintime\" : xxx, (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"mutable\" : [ (array of string) list of ways the block template may be changed \n" - " \"value\" (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n" - " ,...\n" - " ],\n" - " \"noncerange\" : \"00000000ffffffff\",(string) A range of valid nonces\n" - " \"sigoplimit\" : n, (numeric) limit of sigops in blocks\n" - " \"sizelimit\" : n, (numeric) limit of block size\n" - " \"curtime\" : ttt, (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n" - " \"bits\" : \"xxxxxxxx\", (string) compressed target of next block\n" - " \"previousbits\" : \"xxxxxxxx\", (string) compressed target of current highest block\n" - " \"height\" : n (numeric) The height of the next block\n" - " \"masternode\" : [ (json array) required masternode payments that must be included in the next block\n" - " {\n" - " \"payee\" : \"xxxx\", (string) payee address\n" - " \"script\" : \"xxxx\", (string) payee scriptPubKey\n" - " \"amount\" : n (numeric) required amount to pay\n" - " }\n" - " },\n" - " \"masternode_payments_started\" : true|false, (boolean) true, if masternode payments started\n" - " \"masternode_payments_enforced\" : true|false, (boolean) true, if masternode payments are enforced\n" - " \"superblock\" : [ (json array) required superblock payees that must be included in the next block\n" - " {\n" - " \"payee\" : \"xxxx\", (string) payee address\n" - " \"script\" : \"xxxx\", (string) payee scriptPubKey\n" - " \"amount\" : n (numeric) required amount to pay\n" - " }\n" - " ,...\n" - " ],\n" - " \"superblocks_started\" : true|false, (boolean) true, if superblock payments started\n" - " \"superblocks_enabled\" : true|false, (boolean) true, if superblock payments are enabled\n" - " \"coinbase_payload\" : \"xxxxxxxx\" (string) coinbase transaction payload data encoded in hexadecimal\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("getblocktemplate", "") - + HelpExampleRpc("getblocktemplate", "") }, - }.ToString()); + "\"template_request\""}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ARR, "capabilities", "specific client side supported features", + { + {RPCResult::Type::STR, "", "capability"}, + }}, + {RPCResult::Type::NUM, "version", "The preferred block version"}, + {RPCResult::Type::ARR, "rules", "specific block rules that are to be enforced", + { + {RPCResult::Type::STR, "", "rulename"}, + }}, + {RPCResult::Type::OBJ_DYN, "vbavailable", "set of pending, supported versionbit (BIP 9) softfork deployments", + { + {RPCResult::Type::NUM, "rulename", "identifies the bit number as indicating acceptance and readiness for the named softfork rule"}, + }}, + {RPCResult::Type::NUM, "vbrequired", "bit mask of versionbits the server requires set in submissions"}, + {RPCResult::Type::STR, "previousblockhash", "The hash of current highest block"}, + // {RPCResult::Type::ARR, transactions", "contents of non-coinbase transactions that should be included in the next block", + {RPCResult::Type::ARR, "?????", "contents of non-coinbase transactions that should be included in the next block", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "data", "transaction data encoded in hexadecimal (byte-for-byte)"}, + {RPCResult::Type::STR_HEX, "txid", "transaction id encoded in little-endian hexadecimal"}, + {RPCResult::Type::STR_HEX, "hash", "hash encoded in little-endian hexadecimal (including witness data)"}, + {RPCResult::Type::ARR, "depends", "array of numbers", + { + {RPCResult::Type::NUM, "", "transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is"}, + }}, + {RPCResult::Type::NUM, "fee", "difference in value between transaction inputs and outputs (in satoshis); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one"}, + {RPCResult::Type::NUM, "sigops", "total number of SigOps, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients MUST NOT assume there aren't any"}, + }}, + }}, + {RPCResult::Type::OBJ, "coinbaseaux", "data that should be included in the coinbase's scriptSig content", + { + {RPCResult::Type::ELISION, "", ""}, + }}, + {RPCResult::Type::NUM, "coinbasevalue", "maximum allowable input to coinbase transaction, including the generation award and transaction fees (in satoshis)"}, + {RPCResult::Type::OBJ, "coinbasetxn", "information for coinbase transaction", + { + {RPCResult::Type::ELISION, "", ""}, + }}, + {RPCResult::Type::STR, "target", "The hash target"}, + {RPCResult::Type::NUM_TIME, "mintime", "The minimum timestamp appropriate for the next block time, expressed in seconds since epoch (Jan 1 1970 GMT)"}, + {RPCResult::Type::ARR, "mutable", "list of ways the block template may be changed", + { + {RPCResult::Type::STR, "value", "A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'"}, + }}, + {RPCResult::Type::STR_HEX, "noncerange", "A range of valid nonces"}, + {RPCResult::Type::NUM, "sigoplimit", "limit of sigops in blocks"}, + {RPCResult::Type::NUM, "sizelimit", "limit of block size"}, + {RPCResult::Type::NUM_TIME, "curtime", "current timestamp in seconds since epoch (Jan 1 1970 GMT)"}, + {RPCResult::Type::STR, "bits", "compressed target of next block"}, + {RPCResult::Type::STR, "previousbits", "compressed target of current highest block"}, + {RPCResult::Type::NUM, "height", "The height of the next block"}, + {RPCResult::Type::ARR, "masternode", "required masternode payments that must be included in the next block", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "payee", "payee address"}, + {RPCResult::Type::STR_HEX, "script", "payee scriptPubKey"}, + {RPCResult::Type::NUM, "amount", "required amount to pay"}, + }}, + }}, + {RPCResult::Type::BOOL, "masternode_payments_started", "true, if masternode payments started"}, + {RPCResult::Type::BOOL, "masternode_payments_enforced", "true, if masternode payments are enforced"}, + {RPCResult::Type::ARR, "superblock", "required superblock payees that must be included in the next block", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "payee", "payee address"}, + {RPCResult::Type::STR_HEX, "script", "payee scriptPubKey"}, + {RPCResult::Type::NUM, "amount", "required amount to pay"}, + }}, + }}, + {RPCResult::Type::BOOL, "superblocks_started", "true, if superblock payments started"}, + {RPCResult::Type::BOOL, "superblocks_enabled", "true, if superblock payments are enabled"}, + {RPCResult::Type::STR_HEX, "coinbase_payload", "coinbase transaction payload data encoded in hexadecimal"}, + }}, + RPCExamples{ + HelpExampleCli("getblocktemplate", "") + + HelpExampleRpc("getblocktemplate", "") + }, + }.Check(request); LOCK(cs_main); @@ -941,22 +951,19 @@ class submitblock_StateCatcher : public CValidationInterface static UniValue submitblock(const JSONRPCRequest& request) { // We allow 2 arguments for compliance with BIP22. Argument 2 is ignored. - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) { - throw std::runtime_error( - RPCHelpMan{"submitblock", - "\nAttempts to submit new block to network.\n" - "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n", - { - {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block data to submit"}, - {"dummy", RPCArg::Type::STR, /* default */ "ignored", "dummy value, for compatibility with BIP22. This value is ignored."}, - }, - RPCResult{RPCResult::Type::NONE, "", "Returns JSON Null when valid, a string according to BIP22 otherwise"}, - RPCExamples{ - HelpExampleCli("submitblock", "\"mydata\"") - + HelpExampleRpc("submitblock", "\"mydata\"") - }, - }.ToString()); - } + RPCHelpMan{"submitblock", + "\nAttempts to submit new block to network.\n" + "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n", + { + {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block data to submit"}, + {"dummy", RPCArg::Type::STR, /* default */ "ignored", "dummy value, for compatibility with BIP22. This value is ignored."}, + }, + RPCResult{RPCResult::Type::NONE, "", "Returns JSON Null when valid, a string according to BIP22 otherwise"}, + RPCExamples{ + HelpExampleCli("submitblock", "\"mydata\"") + + HelpExampleRpc("submitblock", "\"mydata\"") + }, + }.Check(request); std::shared_ptr blockptr = std::make_shared(); CBlock& block = *blockptr; @@ -998,22 +1005,19 @@ static UniValue submitblock(const JSONRPCRequest& request) static UniValue submitheader(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( - RPCHelpMan{"submitheader", - "\nDecode the given hexdata as a header and submit it as a candidate chain tip if valid." - "\nThrows when the header is invalid.\n", - { - {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block header data"}, - }, - RPCResult{ - RPCResult::Type::NONE, "", "None"}, - RPCExamples{ - HelpExampleCli("submitheader", "\"aabbcc\"") + - HelpExampleRpc("submitheader", "\"aabbcc\"") - }, - }.ToString()); - } + RPCHelpMan{"submitheader", + "\nDecode the given hexdata as a header and submit it as a candidate chain tip if valid." + "\nThrows when the header is invalid.\n", + { + {"hexdata", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded block header data"}, + }, + RPCResult{ + RPCResult::Type::NONE, "", "None"}, + RPCExamples{ + HelpExampleCli("submitheader", "\"aabbcc\"") + + HelpExampleRpc("submitheader", "\"aabbcc\"") + }, + }.Check(request); CBlockHeader h; if (!DecodeHexBlockHeader(h, request.params[0].get_str())) { @@ -1037,42 +1041,40 @@ static UniValue submitheader(const JSONRPCRequest& request) static UniValue estimatesmartfee(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"estimatesmartfee", - "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" - "confirmation within conf_target blocks if possible and return the number of blocks\n" - "for which the estimate is valid.\n", - { - {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"}, - {"estimate_mode", RPCArg::Type::STR, /* default */ "CONSERVATIVE", "The fee estimate mode.\n" - " Whether to return a more conservative estimate which also satisfies\n" - " a longer history. A conservative estimate potentially returns a\n" - " higher feerate and is more likely to be sufficient for the desired\n" - " target, but is not as responsive to short term drops in the\n" - " prevailing fee market. Must be one of:\n" - " \"UNSET\"\n" - " \"ECONOMICAL\"\n" - " \"CONSERVATIVE\""}, - }, - RPCResult{ - RPCResult::Type::OBJ, "", "", + RPCHelpMan{"estimatesmartfee", + "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" + "confirmation within conf_target blocks if possible and return the number of blocks\n" + "for which the estimate is valid.\n", + { + {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"}, + {"estimate_mode", RPCArg::Type::STR, /* default */ "CONSERVATIVE", "The fee estimate mode.\n" + " Whether to return a more conservative estimate which also satisfies\n" + " a longer history. A conservative estimate potentially returns a\n" + " higher feerate and is more likely to be sufficient for the desired\n" + " target, but is not as responsive to short term drops in the\n" + " prevailing fee market. Must be one of:\n" + " \"UNSET\"\n" + " \"ECONOMICAL\"\n" + " \"CONSERVATIVE\""}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "feerate", /* optional */ true, "estimate fee rate in " + CURRENCY_UNIT + "/kB (only present if no errors were encountered)"}, + {RPCResult::Type::ARR, "errors", "Errors encountered during processing", { - {RPCResult::Type::NUM, "feerate", /* optional */ true, "estimate fee rate in " + CURRENCY_UNIT + "/kB (only present if no errors were encountered)"}, - {RPCResult::Type::ARR, "errors", "Errors encountered during processing", - { - {RPCResult::Type::STR, "", "error"}, - }}, - {RPCResult::Type::NUM, "blocks", "block number where estimate was found\n" - "The request target will be clamped between 2 and the highest target\n" - "fee estimation is able to return based on how long it has been running.\n" - "An error is returned if not enough transactions and blocks\n" - "have been observed to make an estimate for any number of blocks."}, + {RPCResult::Type::STR, "", "error"}, }}, - RPCExamples{ - HelpExampleCli("estimatesmartfee", "6") - }, - }.ToString()); + {RPCResult::Type::NUM, "blocks", "block number where estimate was found\n" + "The request target will be clamped between 2 and the highest target\n" + "fee estimation is able to return based on how long it has been running.\n" + "An error is returned if not enough transactions and blocks\n" + "have been observed to make an estimate for any number of blocks."}, + }}, + RPCExamples{ + HelpExampleCli("estimatesmartfee", "6") + }, + }.Check(request); RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VSTR}); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); @@ -1103,48 +1105,58 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request) static UniValue estimaterawfee(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"estimaterawfee", - "\nWARNING: This interface is unstable and may disappear or change!\n" - "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n" - " implementation of fee estimation. The parameters it can be called with\n" - " and the results it returns will change if the internal implementation changes.\n" - "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" - "confirmation within conf_target blocks if possible.\n", + RPCHelpMan{"estimaterawfee", + "\nWARNING: This interface is unstable and may disappear or change!\n" + "\nWARNING: This is an advanced API call that is tightly coupled to the specific\n" + " implementation of fee estimation. The parameters it can be called with\n" + " and the results it returns will change if the internal implementation changes.\n" + "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n" + "confirmation within conf_target blocks if possible.\n", + { + {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"}, + {"threshold", RPCArg::Type::NUM, /* default */ "0.95", "The proportion of transactions in a given feerate range that must have been\n" + " confirmed within conf_target in order to consider those feerates as high enough and proceed to check\n" + " lower buckets."}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "Results are returned for any horizon which tracks blocks up to the confirmation target", + { + {RPCResult::Type::OBJ, "short", /* optional */ true, "estimate for short time horizon", + { + {RPCResult::Type::NUM, "feerate", /* optional */ true, "estimate fee rate in " + CURRENCY_UNIT + "/kB"}, + {RPCResult::Type::NUM, "decay", "exponential decay (per block) for historical moving average of confirmation data"}, + {RPCResult::Type::NUM, "scale", "The resolution of confirmation targets at this time horizon"}, + {RPCResult::Type::OBJ, "pass", /* optional */ true, "information about the lowest range of feerates to succeed in meeting the threshold", + { + {RPCResult::Type::NUM, "startrange", "start of feerate range"}, + {RPCResult::Type::NUM, "endrange", "end of feerate range"}, + {RPCResult::Type::NUM, "withintarget", "number of txs over history horizon in the feerate range that were confirmed within target"}, + {RPCResult::Type::NUM, "totalconfirmed", "number of txs over history horizon in the feerate range that were confirmed at any point"}, + {RPCResult::Type::NUM, "inmempool", "current number of txs in mempool in the feerate range unconfirmed for at least target blocks"}, + {RPCResult::Type::NUM, "leftmempool", "number of txs over history horizon in the feerate range that left mempool unconfirmed after target"}, + }}, + {RPCResult::Type::OBJ, "fail", /* optional */ true, "information about the highest range of feerates to fail to meet the threshold", + { + {RPCResult::Type::ELISION, "", ""}, + }}, + {RPCResult::Type::ARR, "errors", /* optional */ true, "Errors encountered during processing", + { + {RPCResult::Type::STR, "error", ""}, + }}, + }}, + {RPCResult::Type::OBJ, "medium", /* optional */ true, "estimate for medium time horizon", { - {"conf_target", RPCArg::Type::NUM, RPCArg::Optional::NO, "Confirmation target in blocks (1 - 1008)"}, - {"threshold", RPCArg::Type::NUM, /* default */ "0.95", "The proportion of transactions in a given feerate range that must have been\n" - " confirmed within conf_target in order to consider those feerates as high enough and proceed to check\n" - " lower buckets."}, - }, - RPCResult{ - "{\n" - " \"short\" : { (json object, optional) estimate for short time horizon\n" - " \"feerate\" : x.x, (numeric, optional) estimate fee rate in " + CURRENCY_UNIT + "/kB\n" - " \"decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n" - " \"scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n" - " \"pass\" : { (json object, optional) information about the lowest range of feerates to succeed in meeting the threshold\n" - " \"startrange\" : x.x, (numeric) start of feerate range\n" - " \"endrange\" : x.x, (numeric) end of feerate range\n" - " \"withintarget\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed within target\n" - " \"totalconfirmed\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed at any point\n" - " \"inmempool\" : x.x, (numeric) current number of txs in mempool in the feerate range unconfirmed for at least target blocks\n" - " \"leftmempool\" : x.x, (numeric) number of txs over history horizon in the feerate range that left mempool unconfirmed after target\n" - " },\n" - " \"fail\" : { ... }, (json object, optional) information about the highest range of feerates to fail to meet the threshold\n" - " \"errors\" : [ str... ] (json array of strings, optional) Errors encountered during processing\n" - " },\n" - " \"medium\" : { ... }, (json object, optional) estimate for medium time horizon\n" - " \"long\" : { ... } (json object) estimate for long time horizon\n" - "}\n" - "\n" - "Results are returned for any horizon which tracks blocks up to the confirmation target.\n" - }, - RPCExamples{ - HelpExampleCli("estimaterawfee", "6 0.9") - }, - }.ToString()); + {RPCResult::Type::ELISION, "", ""}, + }}, + {RPCResult::Type::OBJ, "long", /* optional */ true, "estimate for long time horizon", + { + {RPCResult::Type::ELISION, "", ""}, + }}, + }}, + RPCExamples{ + HelpExampleCli("estimaterawfee", "6 0.9") + }, + }.Check(request); RPCTypeCheck(request.params, {UniValue::VNUM, UniValue::VNUM}, true); RPCTypeCheckArgument(request.params[0], UniValue::VNUM); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 28a6a38ad7cd..b190927c8719 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -38,27 +38,25 @@ static UniValue debug(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"debug", - "Change debug category on the fly. Specify single category or use '+' to specify many.\n" - "The valid debug categories are: " + ListLogCategories() + ".\n" - "libevent logging is configured on startup and cannot be modified by this RPC during runtime.\n" - "There are also a few meta-categories:\n" - " - \"all\", \"1\" and \"\" activate all categories at once;\n" - " - \"dash\" activates all Dash-specific categories at once;\n" - " - \"none\" (or \"0\") deactivates all categories at once.\n" - "Note: If specified category doesn't match any of the above, no error is thrown.\n", - { - {"category", RPCArg::Type::STR, RPCArg::Optional::NO, "The name of the debug category to turn on."}, - }, - RPCResult { - " result (string) \"Debug mode: \" followed by the specified category.\n" - }, - RPCExamples { - HelpExampleCli("debug", "dash") - + HelpExampleRpc("debug", "dash+net") - }}.ToString()); + RPCHelpMan{"debug", + "Change debug category on the fly. Specify single category or use '+' to specify many.\n" + "The valid debug categories are: " + ListLogCategories() + ".\n" + "libevent logging is configured on startup and cannot be modified by this RPC during runtime.\n" + "There are also a few meta-categories:\n" + " - \"all\", \"1\" and \"\" activate all categories at once;\n" + " - \"dash\" activates all Dash-specific categories at once;\n" + " - \"none\" (or \"0\") deactivates all categories at once.\n" + "Note: If specified category doesn't match any of the above, no error is thrown.\n", + { + {"category", RPCArg::Type::STR, RPCArg::Optional::NO, "The name of the debug category to turn on."}, + }, + RPCResult{ + RPCResult::Type::STR, "result", "\"Debug mode: \" followed by the specified category", + }, + RPCExamples { + HelpExampleCli("debug", "dash") + + HelpExampleRpc("debug", "dash+net") + }}.Check(request); std::string strMode = request.params[0].get_str(); LogInstance().DisableCategory(BCLog::ALL); @@ -77,16 +75,14 @@ static UniValue debug(const JSONRPCRequest& request) static UniValue mnsync(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"mnsync", - "Returns the sync status, updates to the next step or resets it entirely.\n", - { - {"mode", RPCArg::Type::STR, RPCArg::Optional::NO, "[status|next|reset]"}, - }, - RPCResults{}, - RPCExamples{""} - }.ToString()); + RPCHelpMan{"mnsync", + "Returns the sync status, updates to the next step or resets it entirely.\n", + { + {"mode", RPCArg::Type::STR, RPCArg::Optional::NO, "[status|next|reset]"}, + }, + RPCResults{},/*TODO*/ + RPCExamples{""} + }.Check(request); std::string strMode = request.params[0].get_str(); @@ -140,28 +136,27 @@ static UniValue spork(const JSONRPCRequest& request) if (request.fHelp || request.params.size() != 2) { // default help, for basic mode - throw std::runtime_error( RPCHelpMan{"spork", "\nShows information about current state of sporks\n", { {"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'show' to show all current spork values, 'active' to show which sporks are active"}, }, - RPCResults { - {"For 'show'", - "{\n" - " \"SPORK_NAME\" : spork_value, (number) The value of the specific spork with the name SPORK_NAME\n" - " ...\n" - "}\n" - }, {"For 'active'", - "{\n" - " \"SPORK_NAME\" : true|false, (boolean) 'true' for time-based sporks if spork is active and 'false' otherwise\n" - " ...\n" - "}\n" - }}, + { + RPCResult{"For 'show'", + RPCResult::Type::OBJ_DYN, "", "keys are the sporks, and values indicates its value", + { + {RPCResult::Type::NUM, "SPORK_NAME", "The value of the specific spork with the name SPORK_NAME"}, + }}, + RPCResult{"For 'active'", + RPCResult::Type::OBJ_DYN, "", "keys are the sporks, and values indicates its status", + { + {RPCResult::Type::BOOL, "SPORK_NAME", "'true' for time-based sporks if spork is active and 'false' otherwise"}, + }}, + }, RPCExamples { HelpExampleCli("spork", "show") + HelpExampleRpc("spork", "\"show\"") - }}.ToString()); + }}.Check(request); } else { // advanced mode, update spork values SporkId nSporkID = CSporkManager::GetSporkIDByName(request.params[0].get_str()); @@ -178,7 +173,6 @@ static UniValue spork(const JSONRPCRequest& request) if(sporkManager.UpdateSpork(nSporkID, nValue, *g_rpc_node->connman)){ return "success"; } else { - throw std::runtime_error( RPCHelpMan{"spork", "\nUpdate the value of the specific spork. Requires \"-sporkkey\" to be set to sign the message.\n", { @@ -186,40 +180,39 @@ static UniValue spork(const JSONRPCRequest& request) {"value", RPCArg::Type::NUM, RPCArg::Optional::NO, "The new desired value of the spork"}, }, RPCResult{ - " result (string) \"success\" if spork value was updated or this help otherwise\n" + RPCResult::Type::STR, "result", "\"success\" if spork value was updated or this help otherwise" }, RPCExamples{ HelpExampleCli("spork", "SPORK_2_INSTANTSEND_ENABLED 4070908800") + HelpExampleRpc("spork", "\"SPORK_2_INSTANTSEND_ENABLED\", 4070908800") }, - }.ToString()); + }.Check(request); } } - + return NullUniValue; } static UniValue validateaddress(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( RPCHelpMan{"validateaddress", "\nReturn information about the given dash address.\n", { {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The dash address to validate"}, }, RPCResult{ - "{\n" - " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" - " \"address\" : \"address\", (string) The dash address validated\n" - " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n" - " \"isscript\" : true|false, (boolean) If the key is a script\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "isvalid", "If the address is valid or not. If not, this is the only property returned."}, + {RPCResult::Type::STR, "address", "The dash address validated"}, + {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded scriptPubKey generated by the address"}, + {RPCResult::Type::BOOL, "isscript", "If the key is a script"}, + } }, RPCExamples{ - HelpExampleCli("validateaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"") - + HelpExampleRpc("validateaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"") + HelpExampleCli("validateaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"") + + HelpExampleRpc("validateaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"") }, - }.ToString()); + }.Check(request); CTxDestination dest = DecodeDestination(request.params[0].get_str()); bool isValid = IsValidDestination(dest); @@ -242,9 +235,6 @@ static UniValue validateaddress(const JSONRPCRequest& request) static UniValue createmultisig(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 2) - { - std::string msg = RPCHelpMan{"createmultisig", "\nCreates a multi-signature address with n signature of m keys required.\n" "It returns a json object with the address and redeemScript.\n", @@ -256,10 +246,11 @@ static UniValue createmultisig(const JSONRPCRequest& request) }}, }, RPCResult{ - "{\n" - " \"address\" : \"multisigaddress\", (string) The value of the new multisig address.\n" - " \"redeemScript\" : \"script\" (string) The string value of the hex-encoded redemption script.\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "address", "The value of the new multisig address."}, + {RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script."}, + } }, RPCExamples{ "\nCreate a multisig address from 2 public keys\n" @@ -267,9 +258,7 @@ static UniValue createmultisig(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") }, - }.ToString(); - throw std::runtime_error(msg); - } + }.Check(request); int required = request.params[0].get_int(); @@ -297,29 +286,26 @@ static UniValue createmultisig(const JSONRPCRequest& request) UniValue getdescriptorinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( - RPCHelpMan{"getdescriptorinfo", - {"\nAnalyses a descriptor.\n"}, - { - {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor"}, - }, - RPCResult{ - RPCResult::Type::OBJ, "", "", + RPCHelpMan{"getdescriptorinfo", + {"\nAnalyses a descriptor.\n"}, + { + {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor"}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", { - {RPCResult::Type::STR, "descriptor", "The descriptor in canonical form, without private keys"}, - {RPCResult::Type::STR, "checksum", "The checksum for the input descriptor"}, - {RPCResult::Type::BOOL, "isrange", "Whether the descriptor is ranged"}, - {RPCResult::Type::BOOL, "issolvable", "Whether the descriptor is solvable"}, - {RPCResult::Type::BOOL, "hasprivatekeys", "Whether the input descriptor contained at least one private key"}, + {RPCResult::Type::STR, "descriptor", "The descriptor in canonical form, without private keys"}, + {RPCResult::Type::STR, "checksum", "The checksum for the input descriptor"}, + {RPCResult::Type::BOOL, "isrange", "Whether the descriptor is ranged"}, + {RPCResult::Type::BOOL, "issolvable", "Whether the descriptor is solvable"}, + {RPCResult::Type::BOOL, "hasprivatekeys", "Whether the input descriptor contained at least one private key"}, } - }, - RPCExamples{ - "\nAnalyse a descriptor\n" - + HelpExampleCli("getdescriptorinfo", "\"pkh([d34db33f/84h/0h/0h]0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2dce28d959f2815b16f81798)\"") - } - }.ToString()); - } + }, + RPCExamples{ + "\nAnalyse a descriptor\n" + + HelpExampleCli("getdescriptorinfo", "\"pkh([d34db33f/84h/0h/0h]0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2dce28d959f2815b16f81798)\"") + } + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -341,33 +327,30 @@ UniValue getdescriptorinfo(const JSONRPCRequest& request) UniValue deriveaddresses(const JSONRPCRequest& request) { - if (request.fHelp || request.params.empty() || request.params.size() > 2) { - throw std::runtime_error( - RPCHelpMan{"deriveaddresses", - "\nDerives one or more addresses corresponding to an output descriptor.\n" - "Examples of output descriptors are:\n" - " pkh() P2PKH outputs for the given pubkey\n" - " sh(multi(,,,...)) P2SH-multisig outputs for the given threshold and pubkeys\n" - " raw() Outputs whose scriptPubKey equals the specified hex scripts\n" - "\nIn the above, either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n" - "or more path elements separated by \"/\", where \"h\" represents a hardened child key.\n" - "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n", + RPCHelpMan{"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" + " sh(multi(,,,...)) P2SH-multisig outputs for the given threshold and pubkeys\n" + " raw() Outputs whose scriptPubKey equals the specified hex scripts\n" + "\nIn the above, either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n" + "or more path elements separated by \"/\", where \"h\" represents a hardened child key.\n" + "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n", + { + {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor"}, + {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."}, + }, + RPCResult{ + RPCResult::Type::ARR, "", "", { - {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor"}, - {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."}, - }, - RPCResult{ - "\"address\" (json array) A json array of the derived addresses\n" - " [\n" - " ...\n" - " ]\n" - }, - RPCExamples{ - "\nFirst three receive addresses\n" - + HelpExampleCli("deriveaddresses", "\"pkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#cjjspncu\" \"[0,2]\"") + {RPCResult::Type::STR, "address", "the derived addresses"}, } - }.ToString()); - } + }, + RPCExamples{ + "\nFirst three receive addresses\n" + + HelpExampleCli("deriveaddresses", "\"pkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#cjjspncu\" \"[0,2]\"") + } + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType()}); // Range argument is checked later const std::string desc_str = request.params[0].get_str(); @@ -423,29 +406,27 @@ UniValue deriveaddresses(const JSONRPCRequest& request) static UniValue verifymessage(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 3) - throw std::runtime_error( - RPCHelpMan{"verifymessage", - "\nVerify a signed message\n", - { - {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The dash address to use for the signature."}, - {"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."}, - {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."}, - }, - RPCResult{ - RPCResult::Type::BOOL, "", "If the signature is verified or not." - }, - RPCExamples{ - "\nUnlock the wallet for 30 seconds\n" - + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") + - "\nCreate the signature\n" - + HelpExampleCli("signmessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"my message\"") + - "\nVerify the signature\n" - + HelpExampleCli("verifymessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"signature\" \"my message\"") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("verifymessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\", \"signature\", \"my message\"") - }, - }.ToString()); + RPCHelpMan{"verifymessage", + "\nVerify a signed message\n", + { + {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The dash address to use for the signature."}, + {"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."}, + {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."}, + }, + RPCResult{ + RPCResult::Type::BOOL, "", "If the signature is verified or not." + }, + RPCExamples{ + "\nUnlock the wallet for 30 seconds\n" + + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") + + "\nCreate the signature\n" + + HelpExampleCli("signmessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"my message\"") + + "\nVerify the signature\n" + + HelpExampleCli("verifymessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"signature\" \"my message\"") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("verifymessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\", \"signature\", \"my message\"") + }, + }.Check(request); LOCK(cs_main); @@ -482,26 +463,24 @@ static UniValue verifymessage(const JSONRPCRequest& request) static UniValue signmessagewithprivkey(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 2) - throw std::runtime_error( - RPCHelpMan{"signmessagewithprivkey", - "\nSign a message with the private key of an address\n", - { - {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."}, - {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."}, - }, - RPCResult{ - RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64" - }, - RPCExamples{ - "\nCreate the signature\n" - + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") + - "\nVerify the signature\n" - + HelpExampleCli("verifymessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"signature\" \"my message\"") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") - }, - }.ToString()); + RPCHelpMan{"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."}, + {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."}, + }, + RPCResult{ + RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64" + }, + RPCExamples{ + "\nCreate the signature\n" + + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") + + "\nVerify the signature\n" + + HelpExampleCli("verifymessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"signature\" \"my message\"") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") + }, + }.Check(request); std::string strPrivkey = request.params[0].get_str(); std::string strMessage = request.params[1].get_str(); @@ -524,18 +503,15 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request) static UniValue setmocktime(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"setmocktime", - "\nSet the local time to given timestamp (-regtest only)\n", - { - {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Unix seconds-since-epoch timestamp\n" - " Pass 0 to go back to using the system time."}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{""}, - }.ToString() - ); + RPCHelpMan{"setmocktime", + "\nSet the local time to given timestamp (-regtest only)\n", + { + {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, "Unix seconds-since-epoch timestamp\n" + " Pass 0 to go back to using the system time."}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{""}, + }.Check(request); if (!Params().MineBlocksOnDemand()) throw std::runtime_error("setmocktime for regression testing (-regtest mode) only"); @@ -555,18 +531,18 @@ static UniValue setmocktime(const JSONRPCRequest& request) static UniValue mnauth(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() != 3)) - throw std::runtime_error( - RPCHelpMan{"mnauth", - "\nOverride MNAUTH processing results for the specified node with a user provided data (-regtest only).\n", - { - {"nodeId", RPCArg::Type::NUM, RPCArg::Optional::NO, "Internal peer id of the node the mock data gets added to."}, - {"proTxHash", RPCArg::Type::STR, RPCArg::Optional::NO, "The authenticated proTxHash as hex string."}, - {"publicKey", RPCArg::Type::STR, RPCArg::Optional::NO, "The authenticated public key as hex string."}, - }, - RPCResults{}, - RPCExamples{""}, - }.ToString()); + RPCHelpMan{"mnauth", + "\nOverride MNAUTH processing results for the specified node with a user provided data (-regtest only).\n", + { + {"nodeId", RPCArg::Type::NUM, RPCArg::Optional::NO, "Internal peer id of the node the mock data gets added to."}, + {"proTxHash", RPCArg::Type::STR, RPCArg::Optional::NO, "The authenticated proTxHash as hex string."}, + {"publicKey", RPCArg::Type::STR, RPCArg::Optional::NO, "The authenticated public key as hex string."}, + }, + RPCResult{ + RPCResult::Type::BOOL, "result", "true, if the node was updated" + }, + RPCExamples{""}, + }.Check(request); if (!Params().MineBlocksOnDemand()) throw std::runtime_error("mnauth for regression testing (-regtest mode) only"); @@ -663,35 +639,34 @@ static bool timestampSort(std::pair > addresses; @@ -735,34 +710,33 @@ static UniValue getaddressmempool(const JSONRPCRequest& request) static UniValue getaddressutxos(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"getaddressutxos", - "\nReturns all unspent outputs for an address (requires addressindex to be enabled).\n", + RPCHelpMan{"getaddressutxos", + "\nReturns all unspent outputs for an address (requires addressindex to be enabled).\n", + { + {"addresses", RPCArg::Type::ARR, /* default */ "", "", { - {"addresses", RPCArg::Type::ARR, /* default */ "", "", - { - {"address", RPCArg::Type::STR, /* default */ "", "The base58check encoded address"}, - }, - }, - }, - RPCResult{ - "[\n" - " {\n" - " \"address\" (string) The address base58check encoded\n" - " \"txid\" (string) The output txid\n" - " \"outputIndex\" (number) The output index\n" - " \"script\" (string) The script hex-encoded\n" - " \"satoshis\" (number) The number of duffs of the output\n" - " \"height\" (number) The block height\n" - " }\n" - "]\n" + {"address", RPCArg::Type::STR, /* default */ "", "The base58check encoded address"}, }, - RPCExamples{ - HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") - + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") - }, - }.ToString()); + }, + }, + RPCResult{ + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "address", "The address base58check encoded"}, + {RPCResult::Type::STR_HEX, "txid", "The output txid"}, + {RPCResult::Type::NUM, "index", "The output index"}, + {RPCResult::Type::STR_HEX, "script", "The script hex-encoded"}, + {RPCResult::Type::NUM, "satoshis", "The number of duffs of the output"}, + {RPCResult::Type::NUM, "height", "The block height"}, + }}, + }}, + RPCExamples{ + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") + + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + }, + }.Check(request); std::vector > addresses; @@ -803,34 +777,33 @@ static UniValue getaddressutxos(const JSONRPCRequest& request) static UniValue getaddressdeltas(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1 || !request.params[0].isObject()) - throw std::runtime_error( - RPCHelpMan{"getaddressdeltas", - "\nReturns all changes for an address (requires addressindex to be enabled).\n", + RPCHelpMan{"getaddressdeltas", + "\nReturns all changes for an address (requires addressindex to be enabled).\n", + { + {"addresses", RPCArg::Type::ARR, /* default */ "", "", { - {"addresses", RPCArg::Type::ARR, /* default */ "", "", - { - {"address", RPCArg::Type::STR, /* default */ "", "The base58check encoded address"}, - }, - }, - }, - RPCResult{ - "[\n" - " {\n" - " \"satoshis\" (number) The difference of duffs\n" - " \"txid\" (string) The related txid\n" - " \"index\" (number) The related input or output index\n" - " \"blockindex\" (number) The related block index\n" - " \"height\" (number) The block height\n" - " \"address\" (string) The base58check encoded address\n" - " }\n" - "]\n" + {"address", RPCArg::Type::STR, /* default */ "", "The base58check encoded address"}, }, - RPCExamples{ - HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") - + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") - }, - }.ToString()); + }, + }, + RPCResult{ + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "satoshis", "The difference of duffs"}, + {RPCResult::Type::STR_HEX, "txid", "The related txid"}, + {RPCResult::Type::NUM, "index", "The related input or output index"}, + {RPCResult::Type::NUM, "blockindex", "The related block index"}, + {RPCResult::Type::NUM, "height", "The block height"}, + {RPCResult::Type::STR, "address", "The base58check encoded address"}, + }}, + }}, + RPCExamples{ + HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") + + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + }, + }.Check(request); UniValue startValue = find_value(request.params[0].get_obj(), "start"); @@ -890,30 +863,28 @@ static UniValue getaddressdeltas(const JSONRPCRequest& request) static UniValue getaddressbalance(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"getaddressbalance", - "\nReturns the balance for an address(es) (requires addressindex to be enabled).\n", + RPCHelpMan{"getaddressbalance", + "\nReturns the balance for an address(es) (requires addressindex to be enabled).\n", + { + {"addresses", RPCArg::Type::ARR, /* default */ "", "", { - {"addresses", RPCArg::Type::ARR, /* default */ "", "", - { - {"address", RPCArg::Type::STR, /* default */ "", "The base58check encoded address"}, - }, - }, - }, - RPCResult{ - "{\n" - " \"balance\" : xxxxx, (numeric) The current total balance in duffs\n" - " \"balance_immature\" : xxxxx, (numeric) The current immature balance in duffs\n" - " \"balance_spendable\" : xxxxx, (numeric) The current spendable balance in duffs\n" - " \"received\" : xxxxx (numeric) The total number of duffs received (including change)\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") - + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + {"address", RPCArg::Type::STR, /* default */ "", "The base58check encoded address"}, }, - }.ToString()); + }, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "balance", "The current total balance in duffs"}, + {RPCResult::Type::NUM, "balance_immature", "The current immature balance in duffs"}, + {RPCResult::Type::NUM, "balance_spendable", "The current spendable balance in duffs"}, + {RPCResult::Type::NUM, "received", "The total number of duffs received (including change)"}, + }}, + RPCExamples{ + HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") + + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + }, + }.Check(request); std::vector > addresses; @@ -960,28 +931,24 @@ static UniValue getaddressbalance(const JSONRPCRequest& request) static UniValue getaddresstxids(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"getaddresstxids", - "\nReturns the txids for an address(es) (requires addressindex to be enabled).\n", + RPCHelpMan{"getaddresstxids", + "\nReturns the txids for an address(es) (requires addressindex to be enabled).\n", + { + {"addresses", RPCArg::Type::ARR, /* default */ "", "", { - {"addresses", RPCArg::Type::ARR, /* default */ "", "", - { - {"address", RPCArg::Type::STR, /* default */ "", "The base58check encoded address"}, - }, - }, - }, - RPCResult{ - "[\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - "]\n" - }, - RPCExamples{ - HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") - + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + {"address", RPCArg::Type::STR, /* default */ "", "The base58check encoded address"}, }, - }.ToString()); + }, + }, + RPCResult{ + RPCResult::Type::ARR, "", "", + {{RPCResult::Type::STR_HEX, "transactionid", "The transaction id"}} + }, + RPCExamples{ + HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") + + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + }, + }.Check(request); std::vector > addresses; @@ -1042,30 +1009,27 @@ static UniValue getaddresstxids(const JSONRPCRequest& request) static UniValue getspentinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1 || !request.params[0].isObject()) - throw std::runtime_error( - RPCHelpMan{"getspentinfo", - "\nReturns the txid and index where an output is spent.\n", + RPCHelpMan{"getspentinfo", + "\nReturns the txid and index where an output is spent.\n", + { + {"request", RPCArg::Type::OBJ, /* default */ "", "", { - {"request", RPCArg::Type::OBJ, /* default */ "", "", - { - {"txid", RPCArg::Type::STR_HEX, /* default */ "", "The hex string of the txid"}, - {"index", RPCArg::Type::NUM, /* default */ "", "The start block height"}, - }, - }, - }, - RPCResult{ - "{\n" - " \"txid\" (string) The transaction id\n" - " \"index\" (number) The spending input index\n" - " ,...\n" - "}\n" + {"txid", RPCArg::Type::STR_HEX, /* default */ "", "The hex string of the txid"}, + {"index", RPCArg::Type::NUM, /* default */ "", "The start block height"}, }, - RPCExamples{ - HelpExampleCli("getspentinfo", "'{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}'") - + HelpExampleRpc("getspentinfo", "{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}") - }, - }.ToString()); + }, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + {RPCResult::Type::NUM, "index", "The spending input index"}, + }}, + RPCExamples{ + HelpExampleCli("getspentinfo", "'{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}'") + + HelpExampleRpc("getspentinfo", "{\"txid\": \"0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9\", \"index\": 0}") + }, + }.Check(request); UniValue txidValue = find_value(request.params[0].get_obj(), "txid"); UniValue indexValue = find_value(request.params[0].get_obj(), "index"); @@ -1161,39 +1125,37 @@ static UniValue getmemoryinfo(const JSONRPCRequest& request) /* Please, avoid using the word "pool" here in the RPC interface or help, * as users will undoubtedly confuse it with the other "memory pool" */ - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( - RPCHelpMan{"getmemoryinfo", - "Returns an object containing information about memory usage.\n", - { - {"mode", RPCArg::Type::STR, /* default */ "\"stats\"", "determines what kind of information is returned.\n" - " - \"stats\" returns general statistics about memory usage in the daemon.\n" - " - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+)."}, - }, + RPCHelpMan{"getmemoryinfo", + "Returns an object containing information about memory usage.\n", + { + {"mode", RPCArg::Type::STR, /* default */ "\"stats\"", "determines what kind of information is returned.\n" + " - \"stats\" returns general statistics about memory usage in the daemon.\n" + " - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+)."}, + }, + { + RPCResult{"mode \"stats\"", + RPCResult::Type::OBJ, "", "", { - RPCResult{"mode \"stats\"", - RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::OBJ, "locked", "Information about locked memory manager", - { - {RPCResult::Type::NUM, "used", "Number of bytes used"}, - {RPCResult::Type::NUM, "free", "Number of bytes available in current arenas"}, - {RPCResult::Type::NUM, "total", "Total number of bytes managed"}, - {RPCResult::Type::NUM, "locked", "Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk."}, - {RPCResult::Type::NUM, "chunks_used", "Number allocated chunks"}, - {RPCResult::Type::NUM, "chunks_free", "Number unused chunks"}, - }}, - } - }, - RPCResult{"mode \"mallocinfo\"", - RPCResult::Type::STR, "", "\"...\"" - }, - }, - RPCExamples{ - HelpExampleCli("getmemoryinfo", "") - + HelpExampleRpc("getmemoryinfo", "") - }, - }.ToString()); + {RPCResult::Type::OBJ, "locked", "Information about locked memory manager", + { + {RPCResult::Type::NUM, "used", "Number of bytes used"}, + {RPCResult::Type::NUM, "free", "Number of bytes available in current arenas"}, + {RPCResult::Type::NUM, "total", "Total number of bytes managed"}, + {RPCResult::Type::NUM, "locked", "Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk."}, + {RPCResult::Type::NUM, "chunks_used", "Number allocated chunks"}, + {RPCResult::Type::NUM, "chunks_free", "Number unused chunks"}, + }}, + } + }, + RPCResult{"mode \"mallocinfo\"", + RPCResult::Type::STR, "", "\"...\"" + }, + }, + RPCExamples{ + HelpExampleCli("getmemoryinfo", "") + + HelpExampleRpc("getmemoryinfo", "") + }, + }.Check(request); std::string mode = request.params[0].isNull() ? "stats" : request.params[0].get_str(); if (mode == "stats") { @@ -1231,43 +1193,40 @@ static void EnableOrDisableLogCategories(UniValue cats, bool enable) { static UniValue logging(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 2) { - throw std::runtime_error( - RPCHelpMan{"logging", - "Gets and sets the logging configuration.\n" - "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n" - "When called with arguments, adds or removes categories from debug logging and return the lists above.\n" - "The arguments are evaluated in order \"include\", \"exclude\".\n" - "If an item is both included and excluded, it will thus end up being excluded.\n" - "The valid logging categories are: " + ListLogCategories() + "\n" - "In addition, the following are available as category names with special meanings:\n" - " - \"all\", \"1\" : represent all logging categories.\n" - " - \"dash\" activates all Dash-specific categories at once.\n" - "To deactivate all categories at once you can specify \"all\" in .\n" - " - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n" - , + RPCHelpMan{"logging", + "Gets and sets the logging configuration.\n" + "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n" + "When called with arguments, adds or removes categories from debug logging and return the lists above.\n" + "The arguments are evaluated in order \"include\", \"exclude\".\n" + "If an item is both included and excluded, it will thus end up being excluded.\n" + "The valid logging categories are: " + ListLogCategories() + "\n" + "In addition, the following are available as category names with special meanings:\n" + " - \"all\", \"1\" : represent all logging categories.\n" + " - \"dash\" activates all Dash-specific categories at once.\n" + "To deactivate all categories at once you can specify \"all\" in .\n" + " - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n" + , + { + {"include", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of categories to add debug logging", { - {"include", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of categories to add debug logging", - { - {"include_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"}, - }}, - {"exclude", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of categories to remove debug logging", - { - {"exclude_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"}, - }}, - }, - RPCResult{ - RPCResult::Type::OBJ_DYN, "", "keys are the logging categories, and values indicates its status", - { - {RPCResult::Type::BOOL, "category", "if being debug logged or not. false:inactive, true:active"}, + {"include_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"}, + }}, + {"exclude", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of categories to remove debug logging", + { + {"exclude_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"}, + }}, + }, + RPCResult{ + RPCResult::Type::OBJ_DYN, "", "keys are the logging categories, and values indicates its status", + { + {RPCResult::Type::BOOL, "category", "if being debug logged or not. false:inactive, true:active"}, } - }, - RPCExamples{ - HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") - + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"") - }, - }.ToString()); - } + }, + RPCExamples{ + HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") + + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"") + }, + }.Check(request); uint64_t original_log_categories = LogInstance().GetCategoryMask(); if (request.params[0].isArray()) { @@ -1316,7 +1275,6 @@ static UniValue echo(const JSONRPCRequest& request) RPCExamples{""}, }.ToString() ); - CHECK_NONFATAL(request.params.size() != 100); return request.params; diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index f6ecaa4c9cf3..a14fe5b34861 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -30,19 +30,17 @@ static UniValue getconnectioncount(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"getconnectioncount", - "\nReturns the number of connections to other nodes.\n", - {}, - RPCResult{ - RPCResult::Type::NUM, "", "The connection count" - }, - RPCExamples{ - HelpExampleCli("getconnectioncount", "") - + HelpExampleRpc("getconnectioncount", "") - }, - }.ToString()); + RPCHelpMan{"getconnectioncount", + "\nReturns the number of connections to other nodes.\n", + {}, + RPCResult{ + RPCResult::Type::NUM, "", "The connection count" + }, + RPCExamples{ + HelpExampleCli("getconnectioncount", "") + + HelpExampleRpc("getconnectioncount", "") + }, + }.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -52,19 +50,17 @@ static UniValue getconnectioncount(const JSONRPCRequest& request) static UniValue ping(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"ping", - "\nRequests that a ping be sent to all other nodes, to measure ping time.\n" - "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" - "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n", - {}, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("ping", "") - + HelpExampleRpc("ping", "") - }, - }.ToString()); + RPCHelpMan{"ping", + "\nRequests that a ping be sent to all other nodes, to measure ping time.\n" + "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" + "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping.\n", + {}, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("ping", "") + + HelpExampleRpc("ping", "") + }, + }.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -78,75 +74,74 @@ static UniValue ping(const JSONRPCRequest& request) static UniValue getpeerinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"getpeerinfo", - "\nReturns data about each connected network node as a json array of objects.\n", - {}, - RPCResult{ - "[\n" - " {\n" - " \"id\" : n, (numeric) Peer index\n" - " \"addr\" : \"host:port\", (string) The IP address and port of the peer\n" - " \"addrbind\" : \"ip:port\", (string) Bind address of the connection to the peer\n" - " \"addrlocal\" : \"ip:port\", (string) Local address as reported by the peer\n" - " \"mapped_as\" : \"mapped_as\", (string) The AS in the BGP route to the peer used for diversifying peer selection\n" - " \"services\" : \"xxxxxxxxxxxxxxxx\", (string) The services offered\n" - " \"verified_proregtx_hash\" : h, (hex) Only present when the peer is a masternode and successfully\n" - " authenticated via MNAUTH. In this case, this field contains the\n" - " protx hash of the masternode\n" - " \"verified_pubkey_hash\" : h, (hex) Only present when the peer is a masternode and successfully\n" - " authenticated via MNAUTH. In this case, this field contains the\n" - " hash of the masternode's operator public key\n" - " \"servicesnames\" : [ (json array) the services offered, in human-readable form\n" - " \"SERVICE_NAME\", (string) the service name if it is recognised\n" - " ...\n" - " ],\n" - " \"relaytxes\" : true|false, (boolean) Whether peer has asked us to relay transactions to it\n" - " \"lastsend\" : ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n" - " \"lastrecv\" : ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last receive\n" - " \"bytessent\" : n, (numeric) The total bytes sent\n" - " \"bytesrecv\" : n, (numeric) The total bytes received\n" - " \"conntime\" : ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"timeoffset\" : ttt, (numeric) The time offset in seconds\n" - " \"pingtime\" : n, (numeric) ping time (if available)\n" - " \"minping\" : n, (numeric) minimum observed ping time (if any at all)\n" - " \"pingwait\" : n, (numeric) ping wait (if non-zero)\n" - " \"version\" : v, (numeric) The peer version, such as 70001\n" - " \"subver\" : \"/Dash Core:x.x.x/\", (string) The string version\n" - " \"inbound\" : true|false, (boolean) Inbound (true) or Outbound (false)\n" - " \"addnode\" : true|false, (boolean) Whether connection was due to addnode/-connect or if it was an automatic/inbound connection\n" - " \"masternode\" : true|false, (boolean) Whether connection was due to masternode connection attempt\n" - " \"startingheight\" : n, (numeric) The starting height (block) of the peer\n" - " \"banscore\" : n, (numeric) The ban score\n" - " \"synced_headers\" : n, (numeric) The last header we have in common with this peer\n" - " \"synced_blocks\" : n, (numeric) The last block we have in common with this peer\n" - " \"inflight\" : [\n" - " n, (numeric) The heights of blocks we're currently asking from this peer\n" - " ...\n" - " ],\n" - " \"whitelisted\" : true|false, (boolean) Whether the peer is whitelisted\n" - " \"bytessent_per_msg\" : {\n" - " \"msg\" : n, (numeric) The total bytes sent aggregated by message type\n" - " When a message type is not listed in this json object, the bytes sent are 0.\n" - " Only known message types can appear as keys in the object.\n" - " ...\n" - " },\n" - " \"bytesrecv_per_msg\" : {\n" - " \"msg\" : n, (numeric) The total bytes received aggregated by message type\n" - " When a message type is not listed in this json object, the bytes received are 0.\n" - " Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'.\n" - " ...\n" - " }\n" - " }\n" - " ,...\n" - "]\n" - }, - RPCExamples{ - HelpExampleCli("getpeerinfo", "") - + HelpExampleRpc("getpeerinfo", "") - }, - }.ToString()); + RPCHelpMan{"getpeerinfo", + "\nReturns data about each connected network node as a json array of objects.\n", + {}, + RPCResult{ + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + { + {RPCResult::Type::NUM, "id", "Peer index"}, + {RPCResult::Type::STR, "addr", "(host:port) The IP address and port of the peer"}, + {RPCResult::Type::STR, "addrbind", "(ip:port) Bind address of the connection to the peer"}, + {RPCResult::Type::STR, "addrlocal", "(ip:port) Local address as reported by the peer"}, + {RPCResult::Type::STR, "mapped_as", "The AS in the BGP route to the peer used for diversifying peer selection"}, + {RPCResult::Type::STR_HEX, "services", "The services offered"}, + {RPCResult::Type::STR_HEX, "verified_proregtx_hash", true /*optional*/, "Only present when the peer is a masternode and successfully " + "authenticated via MNAUTH. In this case, this field contains the " + "protx hash of the masternode"}, + {RPCResult::Type::STR_HEX, "verified_pubkey_hash", true /*optional*/, "Only present when the peer is a masternode and successfully " + "authenticated via MNAUTH. In this case, this field contains the " + "hash of the masternode's operator public key"}, + {RPCResult::Type::ARR, "servicesnames", "the services offered, in human-readable form", + { + {RPCResult::Type::STR, "SERVICE_NAME", "the service name if it is recognised"} + }}, + {RPCResult::Type::BOOL, "relaytxes", "Whether peer has asked us to relay transactions to it"}, + {RPCResult::Type::NUM_TIME, "lastsend", "The time in seconds since epoch (Jan 1 1970 GMT) of the last send"}, + {RPCResult::Type::NUM_TIME, "lastrecv", "The time in seconds since epoch (Jan 1 1970 GMT) of the last receive"}, + {RPCResult::Type::NUM, "bytessent", "The total bytes sent"}, + {RPCResult::Type::NUM, "bytesrecv", "The total bytes received"}, + {RPCResult::Type::NUM_TIME, "conntime", "The time in seconds since epoch (Jan 1 1970 GMT) of the connection"}, + {RPCResult::Type::NUM, "timeoffset", "The time offset in seconds"}, + {RPCResult::Type::NUM, "pingtime", "ping time (if available)"}, + {RPCResult::Type::NUM, "minping", "minimum observed ping time (if any at all)"}, + {RPCResult::Type::NUM, "pingwait", "ping wait (if non-zero)"}, + {RPCResult::Type::NUM, "version", "The peer version, such as 70001"}, + {RPCResult::Type::STR, "subver", "The string version"}, + {RPCResult::Type::BOOL, "inbound", "Inbound (true) or Outbound (false)"}, + {RPCResult::Type::BOOL, "addnode", "Whether connection was due to addnode/-connect or if it was an automatic/inbound connection"}, + {RPCResult::Type::BOOL, "masternode", "Whether connection was due to masternode connection attempt"}, + {RPCResult::Type::NUM, "startingheight", "The starting height (block) of the peer"}, + {RPCResult::Type::NUM, "banscore", "The ban score"}, + {RPCResult::Type::NUM, "synced_headers", "The last header we have in common with this peer"}, + {RPCResult::Type::NUM, "synced_blocks", "The last block we have in common with this peer"}, + {RPCResult::Type::ARR, "inflight", "", + { + {RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"}, + }}, + {RPCResult::Type::BOOL, "whitelisted", "Whether the peer is whitelisted"}, + {RPCResult::Type::OBJ_DYN, "bytessent_per_msg", "", + { + {RPCResult::Type::NUM, "msg", "The total bytes sent aggregated by message type\n" + "When a message type is not listed in this json object, the bytes sent are 0.\n" + "Only known message types can appear as keys in the object."} + }}, + {RPCResult::Type::OBJ, "bytesrecv_per_msg", "", + { + {RPCResult::Type::NUM, "msg", "The total bytes received aggregated by message type\n" + "When a message type is not listed in this json object, the bytes received are 0.\n" + "Only known message types can appear as keys in the object and all bytes received of unknown message types are listed under '"+NET_MESSAGE_COMMAND_OTHER+"'."} + }}, + }}, + }}}, + RPCExamples{ + HelpExampleCli("getpeerinfo", "") + + HelpExampleRpc("getpeerinfo", "") + }, + }.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -244,24 +239,21 @@ static UniValue addnode(const JSONRPCRequest& request) 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", - "\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" - "full nodes as other outbound peers are (though such peers will not be synced from).\n", - { - {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"}, - {"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("addnode", "\"192.168.0.6:9999\" \"onetry\"") - + HelpExampleRpc("addnode", "\"192.168.0.6:9999\", \"onetry\"") - }, - }.ToString()); + RPCHelpMan{"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" + "full nodes as other outbound peers are (though such peers will not be synced from).\n", + { + {"node", RPCArg::Type::STR, RPCArg::Optional::NO, "The node (see getpeerinfo for nodes)"}, + {"command", RPCArg::Type::STR, RPCArg::Optional::NO, "'add' to add a node to the list, 'remove' to remove a node from the list, 'onetry' to try a connection to the node once"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("addnode", "\"192.168.0.6:9999\" \"onetry\"") + + HelpExampleRpc("addnode", "\"192.168.0.6:9999\", \"onetry\"") + }, + }.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -291,24 +283,22 @@ static UniValue addnode(const JSONRPCRequest& request) static UniValue disconnectnode(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() == 0 || request.params.size() >= 3) - throw std::runtime_error( - RPCHelpMan{"disconnectnode", - "\nImmediately disconnects from the specified peer node.\n" - "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n" - "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n", - { - {"address", RPCArg::Type::STR, /* default */ "fallback to nodeid", "The IP address/port of the node"}, - {"nodeid", RPCArg::Type::NUM, /* default */ "fallback to address", "The node ID (see getpeerinfo for node IDs)"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("disconnectnode", "\"192.168.0.6:9999\"") - + HelpExampleCli("disconnectnode", "\"\" 1") - + HelpExampleRpc("disconnectnode", "\"192.168.0.6:9999\"") - + HelpExampleRpc("disconnectnode", "\"\", 1") - }, - }.ToString()); + RPCHelpMan{"disconnectnode", + "\nImmediately disconnects from the specified peer node.\n" + "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n" + "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n", + { + {"address", RPCArg::Type::STR, /* default */ "fallback to nodeid", "The IP address/port of the node"}, + {"nodeid", RPCArg::Type::NUM, /* default */ "fallback to address", "The node ID (see getpeerinfo for node IDs)"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("disconnectnode", "\"192.168.0.6:9999\"") + + HelpExampleCli("disconnectnode", "\"\" 1") + + HelpExampleRpc("disconnectnode", "\"192.168.0.6:9999\"") + + HelpExampleRpc("disconnectnode", "\"\", 1") + }, + }.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -337,8 +327,6 @@ static UniValue disconnectnode(const JSONRPCRequest& request) static UniValue getaddednodeinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) - throw std::runtime_error( RPCHelpMan{"getaddednodeinfo", "\nReturns information about the given added node, or all added nodes\n" "(note that onetry addnodes are not listed here)\n", @@ -346,26 +334,28 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request) {"node", RPCArg::Type::STR, /* default */ "all nodes", "If provided, return information about this specific node, otherwise all nodes are returned."}, }, RPCResult{ - "[\n" - " {\n" - " \"addednode\" : \"192.168.0.201\", (string) The node IP address or name (as provided to addnode)\n" - " \"connected\" : true|false, (boolean) If connected\n" - " \"addresses\" : [ (list of objects) Only when connected = true\n" - " {\n" - " \"address\" : \"192.168.0.201:9999\", (string) The dash server IP and port we're connected to\n" - " \"connected\" : \"outbound\" (string) connection, inbound or outbound\n" - " }\n" - " ]\n" - " }\n" - " ,...\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "addednode", "The node IP address or name (as provided to addnode)"}, + {RPCResult::Type::BOOL, "connected", "If connected"}, + {RPCResult::Type::ARR, "addresses", "Only when connected = true", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "address", "The dash server IP and port we're connected to"}, + {RPCResult::Type::STR, "connected", "connection, inbound or outbound"}, + }}, + }}, + }}, + } }, RPCExamples{ - HelpExampleCli("getaddednodeinfo", "") - + HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"") + HelpExampleCli("getaddednodeinfo", "\"192.168.0.201\"") + HelpExampleRpc("getaddednodeinfo", "\"192.168.0.201\"") }, - }.ToString()); + }.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -408,34 +398,32 @@ static UniValue getaddednodeinfo(const JSONRPCRequest& request) static UniValue getnettotals(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 0) - throw std::runtime_error( - RPCHelpMan{"getnettotals", - "\nReturns information about network traffic, including bytes in, bytes out,\n" - "and current time.\n", - {}, - RPCResult{ - RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"}, - {RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"}, - {RPCResult::Type::NUM_TIME, "timemillis", "Current UNIX time in milliseconds"}, - {RPCResult::Type::OBJ, "uploadtarget", "", - { - {RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"}, - {RPCResult::Type::NUM, "target", "Target in bytes"}, - {RPCResult::Type::BOOL, "target_reached", "True if target is reached"}, - {RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"}, - {RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"}, - {RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"}, - }}, + RPCHelpMan{"getnettotals", + "\nReturns information about network traffic, including bytes in, bytes out,\n" + "and current time.\n", + {}, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "totalbytesrecv", "Total bytes received"}, + {RPCResult::Type::NUM, "totalbytessent", "Total bytes sent"}, + {RPCResult::Type::NUM_TIME, "timemillis", "Current UNIX time in milliseconds"}, + {RPCResult::Type::OBJ, "uploadtarget", "", + { + {RPCResult::Type::NUM, "timeframe", "Length of the measuring timeframe in seconds"}, + {RPCResult::Type::NUM, "target", "Target in bytes"}, + {RPCResult::Type::BOOL, "target_reached", "True if target is reached"}, + {RPCResult::Type::BOOL, "serve_historical_blocks", "True if serving historical blocks"}, + {RPCResult::Type::NUM, "bytes_left_in_cycle", "Bytes left in current time cycle"}, + {RPCResult::Type::NUM, "time_left_in_cycle", "Seconds left in current time cycle"}, + }}, } - }, - RPCExamples{ - HelpExampleCli("getnettotals", "") - + HelpExampleRpc("getnettotals", "") - }, - }.ToString()); + }, + RPCExamples{ + HelpExampleCli("getnettotals", "") + + HelpExampleRpc("getnettotals", "") + }, + }.Check(request); if(!g_rpc_node->connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -478,55 +466,56 @@ static UniValue GetNetworksInfo() static UniValue getnetworkinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( RPCHelpMan{"getnetworkinfo", "Returns an object containing various state info regarding P2P networking.\n", {}, RPCResult{ - "{\n" - " \"version\" : xxxxx, (numeric) the server version\n" - " \"buildversion\" : \"x.x.x.x-xxx\", (string) the server build version including RC info or commit as relevant\n" - " \"subversion\" : \"/Dash Core:x.x.x.x/\", (string) the server subversion string\n" - " \"protocolversion\" : xxxxx, (numeric) the protocol version\n" - " \"localservices\" : \"xxxxxxxxxxxxxxxx\", (string) the services we offer to the network\n" - " \"localservicesnames\" : [ (json array) the services we offer to the network, in human-readable form\n" - " \"SERVICE_NAME\", (string) the service name\n" - " ...\n" - " ],\n" - " \"localrelay\" : true|false, (boolean) true if transaction relay is requested from peers\n" - " \"timeoffset\" : xxxxx, (numeric) the time offset\n" - " \"connections\" : xxxxx, (numeric) the number of connections\n" - " \"networkactive\" : true|false, (boolean) whether p2p networking is enabled\n" - " \"socketevents\" : \"xxx/\", (string) the socket events mode, either kqueue, epoll, poll or select\n" - " \"networks\" : [ (json array) information per network\n" - " {\n" - " \"name\" : \"xxx\", (string) network (ipv4, ipv6 or onion)\n" - " \"limited\" : true|false, (boolean) is the network limited using -onlynet?\n" - " \"reachable\" : true|false, (boolean) is the network reachable?\n" - " \"proxy\" : \"host:port\" (string) the proxy that is used for this network, or empty if none\n" - " \"proxy_randomize_credentials\" : true|false, (string) Whether randomized credentials are used\n" - " }\n" - " ,...\n" - " ],\n" - " \"relayfee\" : x.xxxxxxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n" - " \"incrementalfee\" : x.xxxxxxxx, (numeric) minimum fee increment for mempool limiting in " + CURRENCY_UNIT + "/kB\n" - " \"localaddresses\" : [ (json array) list of local addresses\n" - " {\n" - " \"address\" : \"xxxx\", (string) network address\n" - " \"port\" : xxx, (numeric) network port\n" - " \"score\" : xxx (numeric) relative score\n" - " }\n" - " ,...\n" - " ]\n" - " \"warnings\" : \"...\" (string) any network and blockchain warnings\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "version", "the server version"}, + {RPCResult::Type::STR, "buildversion", "the server build version including RC info or commit as relevant"}, + {RPCResult::Type::STR, "subversion", "the server subversion string"}, + {RPCResult::Type::NUM, "protocolversion", "the protocol version"}, + {RPCResult::Type::STR_HEX, "localservices", "the services we offer to the network"}, + {RPCResult::Type::ARR, "localservicesnames", "the services we offer to the network, in human-readable form", + { + {RPCResult::Type::STR, "SERVICE_NAME", "the service name"}, + }}, + {RPCResult::Type::BOOL, "localrelay", "true if transaction relay is requested from peers"}, + {RPCResult::Type::NUM, "timeoffset", "the time offset"}, + {RPCResult::Type::NUM, "connections", "the number of connections"}, + {RPCResult::Type::BOOL, "networkactive", "whether p2p networking is enabled"}, + {RPCResult::Type::STR, "socketevents", "the socket events mode, either kqueue, epoll, poll or select"}, + {RPCResult::Type::ARR, "networks", "information per network", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "name", "network (ipv4, ipv6 or onion)"}, + {RPCResult::Type::BOOL, "limited", "is the network limited using -onlynet?"}, + {RPCResult::Type::BOOL, "reachable", "is the network reachable?"}, + {RPCResult::Type::STR, "proxy", "(\"host:port\") the proxy that is used for this network, or empty if none"}, + {RPCResult::Type::BOOL, "proxy_randomize_credentials", "Whether randomized credentials are used"}, + }}, + }}, + {RPCResult::Type::NUM, "relayfee", "minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB"}, + {RPCResult::Type::NUM, "incrementalfee", "minimum fee increment for mempool limiting in " + CURRENCY_UNIT + "/kB"}, + {RPCResult::Type::ARR, "localaddresses", "list of local addresses", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "address", "network address"}, + {RPCResult::Type::NUM, "port", "network port"}, + {RPCResult::Type::NUM, "score", "relative score"}, + }}, + }}, + {RPCResult::Type::STR, "warnings", "any network and blockchain warnings"}, + } }, RPCExamples{ HelpExampleCli("getnetworkinfo", "") + HelpExampleRpc("getnetworkinfo", "") }, - }.ToString()); + }.Check(request); LOCK(cs_main); UniValue obj(UniValue::VOBJ); @@ -665,11 +654,9 @@ static UniValue setban(const JSONRPCRequest& request) static UniValue listbanned(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"listbanned", - "\nList all banned IPs/Subnets.\n", - {}, + RPCHelpMan{"listbanned", + "\nList all banned IPs/Subnets.\n", + {}, RPCResult{RPCResult::Type::ARR, "", "", { {RPCResult::Type::OBJ, "", "", @@ -680,11 +667,11 @@ static UniValue listbanned(const JSONRPCRequest& request) {RPCResult::Type::STR, "ban_reason", ""}, }}, }}, - RPCExamples{ - HelpExampleCli("listbanned", "") - + HelpExampleRpc("listbanned", "") - }, - }.ToString()); + RPCExamples{ + HelpExampleCli("listbanned", "") + + HelpExampleRpc("listbanned", "") + }, + }.Check(request); if(!g_rpc_node->banman) { throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); @@ -711,17 +698,15 @@ static UniValue listbanned(const JSONRPCRequest& request) static UniValue clearbanned(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"clearbanned", - "\nClear all banned IPs.\n", - {}, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("clearbanned", "") - + HelpExampleRpc("clearbanned", "") - }, - }.ToString()); + RPCHelpMan{"clearbanned", + "\nClear all banned IPs.\n", + {}, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("clearbanned", "") + + HelpExampleRpc("clearbanned", "") + }, + }.Check(request); if (!g_rpc_node->banman) { throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded"); } @@ -733,18 +718,14 @@ static UniValue clearbanned(const JSONRPCRequest& request) static UniValue setnetworkactive(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( - RPCHelpMan{"setnetworkactive", - "\nDisable/enable all p2p network activity.\n", - { - {"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{""}, - }.ToString() - ); - } + RPCHelpMan{"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); if (!g_rpc_node->connman) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); @@ -757,30 +738,28 @@ static UniValue setnetworkactive(const JSONRPCRequest& request) static UniValue getnodeaddresses(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 1) { - throw std::runtime_error( RPCHelpMan{"getnodeaddresses", "\nReturn known addresses which can potentially be used to find new nodes in the network\n", { {"count", RPCArg::Type::NUM, /* default */ "1", "How many addresses to return. Limited to the smaller of " + std::to_string(ADDRMAN_GETADDR_MAX) + " or " + std::to_string(ADDRMAN_GETADDR_MAX_PCT) + "% of all known addresses."}, }, RPCResult{ - "[\n" - " {\n" - " \"time\" : ttt, (numeric) Timestamp in seconds since epoch (Jan 1 1970 GMT) keeping track of when the node was last seen\n" - " \"services\" : n, (numeric) The services offered\n" - " \"address\" : \"host\", (string) The address of the node\n" - " \"port\" : n (numeric) The port of the node\n" - " }\n" - " ,....\n" - "]\n" + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM_TIME, "time", "Timestamp in seconds since epoch (Jan 1 1970 GMT) keeping track of when the node was last seen"}, + {RPCResult::Type::NUM, "services", "The services offered"}, + {RPCResult::Type::STR, "address", "The address of the node"}, + {RPCResult::Type::NUM, "port", "The port of the node"}, + }}, + } }, RPCExamples{ HelpExampleCli("getnodeaddresses", "8") + HelpExampleRpc("getnodeaddresses", "8") }, - }.ToString()); - } + }.Check(request); if (!g_rpc_node->connman) { throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index a1285a81802a..335d644b1b0f 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -114,9 +114,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) static UniValue getrawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) - throw std::runtime_error( - RPCHelpMan{ + RPCHelpMan{ "getrawtransaction", "\nReturn the raw transaction data.\n" @@ -137,55 +135,61 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) { RPCResult{"if verbose is not set or set to false", RPCResult::Type::STR, "data", "The serialized, hex-encoded data for 'txid'" - }, - RPCResult{"if verbose is set to true", - "{\n" - " \"in_active_chain\" : b, (boolean) Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)\n" - " \"txid\" : \"id\", (string) The transaction id (same as provided)\n" - " \"size\" : n, (numeric) The transaction size\n" - " \"version\" : n, (numeric) The version\n" - " \"locktime\" : ttt, (numeric) The lock time\n" - " \"vin\" : [ (array of json objects)\n" - " {\n" - " \"txid\" : \"id\", (string) The transaction id\n" - " \"vout\" : n, (numeric) \n" - " \"scriptSig\" : { (json object) The script\n" - " \"asm\" : \"asm\", (string) asm\n" - " \"hex\" : \"hex\" (string) hex\n" - " },\n" - " \"sequence\" : n (numeric) The script sequence number\n" - " }\n" - " ,...\n" - " ],\n" - " \"vout\" : [ (array of json objects)\n" - " {\n" - " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n" - " \"n\" : n, (numeric) index\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"asm\", (string) the asm\n" - " \"hex\" : \"hex\", (string) the hex\n" - " \"reqSigs\" : n, (numeric) The required sigs\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " \"addresses\" : [ (json array of string)\n" - " \"address\" (string) dash address\n" - " ,...\n" - " ]\n" - " }\n" - " }\n" - " ,...\n" - " ],\n" - " \"extraPayloadSize\" : n (numeric) Size of DIP2 extra payload. Only present if it's a special TX\n" - " \"extraPayload\" : \"hex\" (string) Hex-encoded DIP2 extra payload data. Only present if it's a special TX\n" - " \"hex\" : \"data\", (string) The serialized, hex-encoded data for 'txid'\n" - " \"blockhash\" : \"hash\", (string) the block hash\n" - " \"height\" : n, (numeric) The block height\n" - " \"confirmations\" : n, (numeric) The confirmations\n" - " \"blocktime\" : ttt (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n" - " \"time\" : ttt, (numeric) Same as \"blocktime\"\n" - " \"instantlock\" : true|false, (boolean) Current transaction lock state\n" - " \"instantlock_internal\" : true|false, (boolean) Current internal transaction lock state\n" - " \"chainlock\" : true|false, (boolean) The state of the corresponding block chainlock\n" - "}\n" + }, + RPCResult{"if verbose is set to true", + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::BOOL, "in_active_chain", "Whether specified block is in the active chain or not (only present with explicit \"blockhash\" argument)"}, + {RPCResult::Type::STR_HEX, "txid", "The transaction id (same as provided)"}, + {RPCResult::Type::NUM, "size", "The serialized transaction size"}, + {RPCResult::Type::NUM, "version", "The version"}, + {RPCResult::Type::NUM, "version", "The type"}, + {RPCResult::Type::NUM_TIME, "locktime", "The lock time"}, + {RPCResult::Type::ARR, "vin", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + {RPCResult::Type::STR, "vout", ""}, + {RPCResult::Type::OBJ, "scriptSig", "The script", + { + {RPCResult::Type::STR, "asm", "asm"}, + {RPCResult::Type::STR_HEX, "hex", "hex"}, + }}, + {RPCResult::Type::NUM, "sequence", "The script sequence number"}, + }}, + }}, + {RPCResult::Type::ARR, "vout", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "value", "The value in " + CURRENCY_UNIT}, + {RPCResult::Type::NUM, "n", "index"}, + {RPCResult::Type::OBJ, "scriptPubKey", "", + { + {RPCResult::Type::STR, "asm", "the asm"}, + {RPCResult::Type::STR, "hex", "the hex"}, + {RPCResult::Type::NUM, "reqSigs", "The required sigs"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + {RPCResult::Type::ARR, "addresses", "", + { + {RPCResult::Type::STR, "address", "dash address"}, + }}, + }}, + }}, + }}, + {RPCResult::Type::NUM, "extraPayloadSize", true /*optional*/, "Size of DIP2 extra payload. Only present if it's a special TX"}, + {RPCResult::Type::STR_HEX, "extraPayload", true /*optional*/, "Hex-encoded DIP2 extra payload data. Only present if it's a special TX"}, + {RPCResult::Type::STR_HEX, "hex", "The serialized, hex-encoded data for 'txid'"}, + {RPCResult::Type::STR_HEX, "blockhash", "the block hash"}, + {RPCResult::Type::NUM, "height", "The block height"}, + {RPCResult::Type::NUM, "confirmations", "The confirmations"}, + {RPCResult::Type::NUM_TIME, "blocktime", "The block time expressed in seconds since epoch (Jan 1 1970 GMT)"}, + {RPCResult::Type::NUM, "time", "Same as \"blocktime\""}, + {RPCResult::Type::BOOL, "instantlock", "Current transaction lock state"}, + {RPCResult::Type::BOOL, "instantlock_internal", "Current internal transaction lock state"}, + {RPCResult::Type::BOOL, "chainlock", "he state of the corresponding block chainlock"}, + } }, }, RPCExamples{ @@ -195,7 +199,7 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) + HelpExampleCli("getrawtransaction", "\"mytxid\" false \"myblockhash\"") + HelpExampleCli("getrawtransaction", "\"mytxid\" true \"myblockhash\"") }, - }.ToString()); + }.Check(request); bool in_active_chain = true; uint256 hash = ParseHashV(request.params[0], "parameter 1"); @@ -259,32 +263,29 @@ static UniValue getrawtransaction(const JSONRPCRequest& request) static UniValue gettxoutproof(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2)) - throw std::runtime_error( - RPCHelpMan{"gettxoutproof", - "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n" - "\nNOTE: By default this function only works sometimes. This is when there is an\n" - "unspent output in the utxo for this transaction. To make it always work,\n" - "you need to maintain a transaction index, using the -txindex command line option or\n" - "specify the block in which the transaction is included manually (by blockhash).\n", + RPCHelpMan{"gettxoutproof", + "\nReturns a hex-encoded proof that \"txid\" was included in a block.\n" + "\nNOTE: By default this function only works sometimes. This is when there is an\n" + "unspent output in the utxo for this transaction. To make it always work,\n" + "you need to maintain a transaction index, using the -txindex command line option or\n" + "specify the block in which the transaction is included manually (by blockhash).\n", + { + {"txids", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of txids to filter", { - {"txids", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of txids to filter", - { - {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A transaction hash"}, - }, - }, - {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "If specified, looks for txid in the block with this hash"}, + {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A transaction hash"}, }, - RPCResult{ - RPCResult::Type::STR, "data", "A string that is a serialized, hex-encoded data for the proof." - }, - RPCExamples{ - HelpExampleCli("gettxoutproof", "'[\"mytxid\",...]'") - + HelpExampleCli("gettxoutproof", "'[\"mytxid\",...]' \"blockhash\"") - + HelpExampleRpc("gettxoutproof", "[\"mytxid\",...], \"blockhash\"") }, - }.ToString() - ); + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "If specified, looks for txid in the block with this hash"}, + }, + RPCResult{ + RPCResult::Type::STR, "data", "A string that is a serialized, hex-encoded data for the proof." + }, + RPCExamples{ + HelpExampleCli("gettxoutproof", "'[\"mytxid\",...]'") + + HelpExampleCli("gettxoutproof", "'[\"mytxid\",...]' \"blockhash\"") + + HelpExampleRpc("gettxoutproof", "[\"mytxid\",...], \"blockhash\"") + }, + }.Check(request); std::set setTxids; uint256 oneTxid; @@ -361,26 +362,23 @@ static UniValue gettxoutproof(const JSONRPCRequest& request) static UniValue verifytxoutproof(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"verifytxoutproof", - "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n" - "and throwing an RPC error if the block is not in our best chain\n", - { - {"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded proof generated by gettxoutproof"}, - }, - RPCResult{ - RPCResult::Type::ARR, "", "", - { - {RPCResult::Type::STR_HEX, "txid", "The txid(s) which the proof commits to, or empty array if the proof can not be validated."}, - } - }, - RPCExamples{ - HelpExampleCli("verifytxoutproof", "\"proof\"") - + HelpExampleRpc("gettxoutproof", "\"proof\"") - }, - }.ToString() - ); + RPCHelpMan{"verifytxoutproof", + "\nVerifies that a proof points to a transaction in a block, returning the transaction it commits to\n" + "and throwing an RPC error if the block is not in our best chain\n", + { + {"proof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded proof generated by gettxoutproof"}, + }, + RPCResult{ + RPCResult::Type::ARR, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The txid(s) which the proof commits to, or empty array if the proof can not be validated."}, + } + }, + RPCExamples{ + HelpExampleCli("verifytxoutproof", "\"proof\"") + + HelpExampleRpc("gettxoutproof", "\"proof\"") + }, + }.Check(request); CDataStream ssMB(ParseHexV(request.params[0], "proof"), SER_NETWORK, PROTOCOL_VERSION); CMerkleBlock merkleBlock; @@ -412,56 +410,53 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request) static UniValue createrawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) { - throw std::runtime_error( - RPCHelpMan{"createrawtransaction", - "\nCreate a transaction spending the given inputs and creating new outputs.\n" - "Outputs can be addresses or data.\n" - "Returns hex-encoded raw transaction.\n" - "Note that the transaction's inputs are not signed, and\n" - "it is not stored in the wallet or transmitted to the network.\n", + RPCHelpMan{"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" + "Note that the transaction's inputs are not signed, and\n" + "it is not stored in the wallet or transmitted to the network.\n", + { + {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of json objects", { - {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of json objects", + {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", { - {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", - { - {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"}, - {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"}, - {"sequence", RPCArg::Type::NUM, /* default */ "", "The sequence number"}, - }, - }, + {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"}, + {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"}, + {"sequence", RPCArg::Type::NUM, /* default */ "", "The sequence number"}, }, }, - {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n" - "That is, each address can only appear once and there can only be one 'data' object.\n" - "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n" - " accepted as second parameter.", + }, + }, + {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n" + "That is, each address can only appear once and there can only be one 'data' object.\n" + "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n" + " accepted as second parameter.", + { + {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", { - {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", - { - {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the dash address, the value (float or string) is the amount in " + CURRENCY_UNIT}, - }, - }, - {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", - { - {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"}, - }, - }, + {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the dash address, the value (float or string) is the amount in " + CURRENCY_UNIT}, + }, + }, + {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", + { + {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"}, }, }, - {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"}, - }, - RPCResult{ - RPCResult::Type::STR_HEX, "transaction", "hex string of the transaction" }, - RPCExamples{ - HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"") - + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") - + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"address\\\":0.01}]\"") - + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"data\\\":\\\"00010203\\\"}]\"") }, - }.ToString()); - } + {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"}, + }, + RPCResult{ + RPCResult::Type::STR_HEX, "transaction", "hex string of the transaction" + }, + RPCExamples{ + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"address\\\":0.01}]\"") + + HelpExampleCli("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") + + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"address\\\":0.01}]\"") + + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"[{\\\"data\\\":\\\"00010203\\\"}]\"") + }, + }.Check(request); RPCTypeCheck(request.params, { UniValue::VARR, @@ -477,58 +472,61 @@ static UniValue createrawtransaction(const JSONRPCRequest& request) static UniValue decoderawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"decoderawtransaction", + RPCHelpMan{"decoderawtransaction", "\nReturn a JSON object representing the serialized, hex-encoded transaction.\n", { {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction hex string"}, }, RPCResult{ - "{\n" - " \"txid\" : \"id\", (string) The transaction id\n" - " \"size\" : n, (numeric) The transaction size\n" - " \"version\" : n, (numeric) The version\n" - " \"type\" : n, (numeric) The type\n" - " \"locktime\" : ttt, (numeric) The lock time\n" - " \"vin\" : [ (array of json objects)\n" - " {\n" - " \"txid\" : \"id\", (string) The transaction id\n" - " \"vout\" : n, (numeric) The output number\n" - " \"scriptSig\" : { (json object) The script\n" - " \"asm\" : \"asm\", (string) asm\n" - " \"hex\" : \"hex\" (string) hex\n" - " },\n" - " \"sequence\" : n (numeric) The script sequence number\n" - " }\n" - " ,...\n" - " ],\n" - " \"vout\" : [ (array of json objects)\n" - " {\n" - " \"value\" : x.xxx, (numeric) The value in " + CURRENCY_UNIT + "\n" - " \"n\" : n, (numeric) index\n" - " \"scriptPubKey\" : { (json object)\n" - " \"asm\" : \"asm\", (string) the asm\n" - " \"hex\" : \"hex\", (string) the hex\n" - " \"reqSigs\" : n, (numeric) The required sigs\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " \"addresses\" : [ (json array of string)\n" - " \"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" (string) Dash address\n" - " ,...\n" - " ]\n" - " }\n" - " }\n" - " ,...\n" - " ],\n" - " \"extraPayloadSize\" : n (numeric) Size of DIP2 extra payload. Only present if it's a special TX\n" - " \"extraPayload\" : \"hex\" (string) Hex-encoded DIP2 extra payload data. Only present if it's a special TX\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + {RPCResult::Type::NUM, "size", "The transaction size"}, + {RPCResult::Type::NUM, "version", "The version"}, + {RPCResult::Type::NUM, "version", "The type"}, + {RPCResult::Type::NUM_TIME, "locktime", "The lock time"}, + {RPCResult::Type::ARR, "vin", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + {RPCResult::Type::NUM, "vout", "The output number"}, + {RPCResult::Type::OBJ, "scriptSig", "The script", + { + {RPCResult::Type::STR, "asm", "asm"}, + {RPCResult::Type::STR_HEX, "hex", "hex"}, + }}, + {RPCResult::Type::NUM, "sequence", "The script sequence number"}, + }}, + }}, + {RPCResult::Type::ARR, "vout", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::NUM, "value", "The value in " + CURRENCY_UNIT}, + {RPCResult::Type::NUM, "n", "index"}, + {RPCResult::Type::OBJ, "scriptPubKey", "", + { + {RPCResult::Type::STR, "asm", "the asm"}, + {RPCResult::Type::STR_HEX, "hex", "the hex"}, + {RPCResult::Type::NUM, "reqSigs", "The required sigs"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + {RPCResult::Type::ARR, "addresses", "", + { + {RPCResult::Type::STR, "address", "dash address"}, + }}, + }}, + }}, + }}, + {RPCResult::Type::NUM, "extraPayloadSize", true /*optional*/, "Size of DIP2 extra payload. Only present if it's a special TX"}, + {RPCResult::Type::STR_HEX, "extraPayload", true /*optional*/, "Hex-encoded DIP2 extra payload data. Only present if it's a special TX"}, + } }, RPCExamples{ HelpExampleCli("decoderawtransaction", "\"hexstring\"") + HelpExampleRpc("decoderawtransaction", "\"hexstring\"") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -555,32 +553,29 @@ static std::string GetAllOutputTypes() static UniValue decodescript(const JSONRPCRequest& request) { - const RPCHelpMan help{"decodescript", + RPCHelpMan{"decodescript", "\nDecode a hex-encoded script.\n", { {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hex-encoded script"}, }, RPCResult{ - "{\n" - " \"asm\" : \"asm\", (string) Script public key\n" - " \"type\" : \"type\", (string) The output type (e.g. "+GetAllOutputTypes()+")\n" - " \"reqSigs\" : n, (numeric) The required signatures\n" - " \"addresses\" : [ (json array of string)\n" - " \"address\" (string) dash address\n" - " ,...\n" - " ],\n" - " \"p2sh\":\"str\" (string) address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "asm", "Script public key"}, + {RPCResult::Type::STR, "type", "The output type (e.g. "+GetAllOutputTypes()+")"}, + {RPCResult::Type::NUM, "reqSigs", "The required signatures"}, + {RPCResult::Type::ARR, "addresses", "", + { + {RPCResult::Type::STR, "address", "dash address"}, + }}, + {RPCResult::Type::STR, "p2sh", "address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH)"}, + } }, RPCExamples{ HelpExampleCli("decodescript", "\"hexstring\"") + HelpExampleRpc("decodescript", "\"hexstring\"") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -609,26 +604,24 @@ static UniValue decodescript(const JSONRPCRequest& request) static UniValue combinerawtransaction(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"combinerawtransaction", - "\nCombine multiple partially signed transactions into one transaction.\n" - "The combined transaction may be another partially signed transaction or a \n" - "fully signed transaction.", + RPCHelpMan{"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.", + { + {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of hex strings of partially signed transactions", { - {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of hex strings of partially signed transactions", - { - {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A hex-encoded raw transaction"}, - }, - }, + {"hexstring", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A hex-encoded raw transaction"}, }, - RPCResult{ - RPCResult::Type::STR, "", "The hex-encoded raw transaction with signature(s)" }, - RPCExamples{ - HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')") - }, - }.ToString()); + }, + RPCResult{ + RPCResult::Type::STR, "", "The hex-encoded raw transaction with signature(s)" + }, + RPCExamples{ + HelpExampleCli("combinerawtransaction", R"('["myhex1", "myhex2", "myhex3"]')") + }, + }.Check(request); UniValue txs = request.params[0].get_array(); @@ -693,66 +686,64 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request) static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) - throw std::runtime_error( - RPCHelpMan{"signrawtransactionwithkey", - "\nSign inputs for raw transaction (serialized, hex-encoded).\n" - "The second argument is an array of base58-encoded private\n" - "keys that will be the only keys used to sign the transaction.\n" - "The third optional argument (may be null) is an array of previous transaction outputs that\n" - "this transaction depends on but may not yet be in the block chain.\n", + RPCHelpMan{"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" + "The third optional argument (may be null) is an array of previous transaction outputs that\n" + "this transaction depends on but may not yet be in the block chain.\n", + { + {"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"}, + {"privkeys", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base58-encoded private keys for signing", { - {"hexstring", RPCArg::Type::STR, RPCArg::Optional::NO, "The transaction hex string"}, - {"privkeys", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base58-encoded private keys for signing", - { - {"privatekey", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "private key in base58-encoding"}, - }, - }, - {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of previous dependent transaction outputs", + {"privatekey", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "private key in base58-encoding"}, + }, + }, + {"prevtxs", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "A json array of previous dependent transaction outputs", + { + {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", { - {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", - { - {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"}, - {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"}, - {"scriptPubKey", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "script key"}, - {"redeemScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2SH or P2WSH) redeem script"}, - {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The amount spent"}, - }, - }, + {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"}, + {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"}, + {"scriptPubKey", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "script key"}, + {"redeemScript", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "(required for P2SH or P2WSH) redeem script"}, + {"amount", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "The amount spent"}, }, }, - {"sighashtype", RPCArg::Type::STR, /* default */ "ALL", "The signature hash type. Must be one of:\n" - " \"ALL\"\n" - " \"NONE\"\n" - " \"SINGLE\"\n" - " \"ALL|ANYONECANPAY\"\n" - " \"NONE|ANYONECANPAY\"\n" - " \"SINGLE|ANYONECANPAY\"\n" - }, }, - RPCResult{ - RPCResult::Type::OBJ, "", "", + }, + {"sighashtype", RPCArg::Type::STR, /* default */ "ALL", "The signature hash type. Must be one of:\n" + " \"ALL\"\n" + " \"NONE\"\n" + " \"SINGLE\"\n" + " \"ALL|ANYONECANPAY\"\n" + " \"NONE|ANYONECANPAY\"\n" + " \"SINGLE|ANYONECANPAY\"\n" + }, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"}, + {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"}, + {RPCResult::Type::ARR, "errors", "Script verification errors (if there are any)", + { + {RPCResult::Type::OBJ, "", "", { - {RPCResult::Type::STR_HEX, "hex", "The hex-encoded raw transaction with signature(s)"}, - {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"}, - {RPCResult::Type::ARR, "errors", "Script verification errors (if there are any)", - { - {RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"}, - {RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"}, - {RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"}, - {RPCResult::Type::NUM, "sequence", "Script sequence number"}, - {RPCResult::Type::STR, "error", "Verification or signing error related to the input"}, - }}, - }}, - } - }, - RPCExamples{ - HelpExampleCli("signrawtransactionwithkey", "\"myhex\" \"[\\\"key1\\\",\\\"key2\\\"]\"") - + HelpExampleRpc("signrawtransactionwithkey", "\"myhex\", \"[\\\"key1\\\",\\\"key2\\\"]\"") - }, - }.ToString()); + {RPCResult::Type::STR_HEX, "txid", "The hash of the referenced, previous transaction"}, + {RPCResult::Type::NUM, "vout", "The index of the output to spent and used as input"}, + {RPCResult::Type::STR_HEX, "scriptSig", "The hex-encoded signature script"}, + {RPCResult::Type::NUM, "sequence", "Script sequence number"}, + {RPCResult::Type::STR, "error", "Verification or signing error related to the input"}, + }}, + }}, + } + }, + RPCExamples{ + HelpExampleCli("signrawtransactionwithkey", "\"myhex\" \"[\\\"key1\\\",\\\"key2\\\"]\"") + + HelpExampleRpc("signrawtransactionwithkey", "\"myhex\", \"[\\\"key1\\\",\\\"key2\\\"]\"") + }, + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true); @@ -784,7 +775,7 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request) UniValue sendrawtransaction(const JSONRPCRequest& request) { - const RPCHelpMan help{"sendrawtransaction", "\nSubmit a raw transaction (serialized, hex-encoded) to local node and network.\n" + RPCHelpMan{"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" "nodes will normally not rebroadcast non-wallet transactions already in their mempool.\n" @@ -808,11 +799,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("sendrawtransaction", "\"signedhex\"") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, { UniValue::VSTR, @@ -851,7 +838,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) static UniValue testmempoolaccept(const JSONRPCRequest& request) { - const RPCHelpMan help{"testmempoolaccept", + RPCHelpMan{"testmempoolaccept", "\nReturns result of mempool acceptance tests indicating if raw transaction (serialized, hex-encoded) would be accepted by mempool.\n" "\nThis checks if the transaction violates the consensus or policy rules.\n" "\nSee sendrawtransaction call.\n", @@ -885,11 +872,7 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("testmempoolaccept", "[\"signedhex\"]") }, - }; - - if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { - throw std::runtime_error(help.ToString()); - } + }.Check(request); RPCTypeCheck(request.params, { UniValue::VARR, @@ -966,85 +949,92 @@ static std::string WriteHDKeypath(std::vector& keypath) UniValue decodepsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"decodepsbt", - "\nReturn a JSON object representing the serialized, base64-encoded partially signed Dash transaction.\n", + RPCHelpMan{"decodepsbt", + "\nReturn a JSON object representing the serialized, base64-encoded partially signed Dash transaction.\n", + { + {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The PSBT base64 string"}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ, "tx", "The decoded network-serialized unsigned transaction.", { - {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "The PSBT base64 string"}, - }, - RPCResult{ - "{\n" - " \"tx\" : { (json object) The decoded network-serialized unsigned transaction.\n" - " ... The layout is the same as the output of decoderawtransaction.\n" - " },\n" - " \"unknown\" : { (json object) The unknown global fields\n" - " \"key\" : \"value\" (key-value pair) An unknown key-value pair\n" - " ...\n" - " },\n" - " \"inputs\" : [ (array of json objects)\n" - " {\n" - " \"non_witness_utxo\" : { (json object, optional) Decoded network transaction for non-witness UTXOs\n" - " ...\n" - " },\n" - " \"partial_signatures\" : { (json object, optional)\n" - " \"pubkey\" : \"signature\", (string) The public key and signature that corresponds to it.\n" - " ,...\n" - " }\n" - " \"sighash\" : \"type\", (string, optional) The sighash type to be used\n" - " \"redeem_script\" : { (json object, optional)\n" - " \"asm\" : \"asm\", (string) The asm\n" - " \"hex\" : \"hex\", (string) The hex\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " }\n" - " \"bip32_derivs\" : { (json object, optional)\n" - " \"pubkey\" : { (json object, optional) The public key with the derivation path as the value.\n" - " \"master_fingerprint\" : \"fingerprint\" (string) The fingerprint of the master key\n" - " \"path\" : \"path\", (string) The path\n" - " }\n" - " ,...\n" - " }\n" - " \"final_scriptsig\" : { (json object, optional)\n" - " \"asm\" : \"asm\", (string) The asm\n" - " \"hex\" : \"hex\", (string) The hex\n" - " }\n" - " \"unknown\" : { (json object) The unknown global fields\n" - " \"key\" : \"value\" (key-value pair) An unknown key-value pair\n" - " ...\n" - " },\n" - " }\n" - " ,...\n" - " ]\n" - " \"outputs\" : [ (array of json objects)\n" - " {\n" - " \"redeem_script\" : { (json object, optional)\n" - " \"asm\" : \"asm\", (string) The asm\n" - " \"hex\" : \"hex\", (string) The hex\n" - " \"type\" : \"pubkeyhash\", (string) The type, eg 'pubkeyhash'\n" - " }\n" - " \"bip32_derivs\" : [ (array of json objects, optional)\n" - " {\n" - " \"pubkey\" : \"pubkey\", (string) The public key this path corresponds to\n" - " \"master_fingerprint\" : \"fingerprint\" (string) The fingerprint of the master key\n" - " \"path\" : \"path\", (string) The path\n" - " }\n" - " }\n" - " ,...\n" - " ],\n" - " \"unknown\" : { (json object) The unknown global fields\n" - " \"key\" : \"value\" (key-value pair) An unknown key-value pair\n" - " ...\n" - " },\n" - " }\n" - " ,...\n" - " ]\n" - " \"fee\" : fee (numeric, optional) The transaction fee paid if all UTXOs slots in the PSBT have been filled.\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("decodepsbt", "\"psbt\"") - }, - }.ToString()); + {RPCResult::Type::ELISION, "", "The layout is the same as the output of decoderawtransaction."}, + }}, + {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields", + { + {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"}, + }}, + {RPCResult::Type::ARR, "inputs", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ, "non_witness_utxo", /* optional */ true, "Decoded network transaction for non-witness UTXOs", + { + {RPCResult::Type::ELISION, "",""}, + }}, + {RPCResult::Type::OBJ_DYN, "partial_signatures", /* optional */ true, "", + { + {RPCResult::Type::STR, "pubkey", "The public key and signature that corresponds to it."}, + }}, + {RPCResult::Type::STR, "sighash", /* optional */ true, "The sighash type to be used"}, + {RPCResult::Type::OBJ, "redeem_script", /* optional */ true, "", + { + {RPCResult::Type::STR, "asm", "The asm"}, + {RPCResult::Type::STR_HEX, "hex", "The hex"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + }}, + {RPCResult::Type::ARR, "bip32_derivs", /* optional */ true, "", + { + {RPCResult::Type::OBJ, "pubkey", /* optional */ true, "The public key with the derivation path as the value.", + { + {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"}, + {RPCResult::Type::STR, "path", "The path"}, + }}, + }}, + {RPCResult::Type::OBJ, "final_scriptsig", /* optional */ true, "", + { + {RPCResult::Type::STR, "asm", "The asm"}, + {RPCResult::Type::STR, "hex", "The hex"}, + }}, + {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields", + { + {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"}, + }}, + }}, + }}, + {RPCResult::Type::ARR, "outputs", "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::OBJ, "redeem_script", /* optional */ true, "", + { + {RPCResult::Type::STR, "asm", "The asm"}, + {RPCResult::Type::STR_HEX, "hex", "The hex"}, + {RPCResult::Type::STR, "type", "The type, eg 'pubkeyhash'"}, + }}, + {RPCResult::Type::ARR, "bip32_derivs", /* optional */ true, "", + { + {RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "pubkey", "The public key this path corresponds to"}, + {RPCResult::Type::STR, "master_fingerprint", "The fingerprint of the master key"}, + {RPCResult::Type::STR, "path", "The path"}, + }}, + }}, + {RPCResult::Type::OBJ_DYN, "unknown", "The unknown global fields", + { + {RPCResult::Type::STR_HEX, "key", "(key-value pair) An unknown key-value pair"}, + }}, + }}, + }}, + {RPCResult::Type::STR_AMOUNT, "fee", /* optional */ true, "The transaction fee paid if all UTXOs slots in the PSBT have been filled."}, + } + }, + RPCExamples{ + HelpExampleCli("decodepsbt", "\"psbt\"") + }, + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}); @@ -1192,25 +1182,23 @@ UniValue decodepsbt(const JSONRPCRequest& request) UniValue combinepsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"combinepsbt", - "\nCombine multiple partially signed Dash transactions into one transaction.\n" - "Implements the Combiner role.\n", + RPCHelpMan{"combinepsbt", + "\nCombine multiple partially signed Dash transactions into one transaction.\n" + "Implements the Combiner role.\n", + { + {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base64 strings of partially signed transactions", { - {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base64 strings of partially signed transactions", - { - {"psbt", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A base64 string of a PSBT"}, - }, - }, + {"psbt", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "A base64 string of a PSBT"}, }, - RPCResult{ - RPCResult::Type::STR, "", "The base64-encoded partially signed transaction" - }, - RPCExamples{ - HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')") }, - }.ToString()); + }, + RPCResult{ + RPCResult::Type::STR, "", "The base64-encoded partially signed transaction" + }, + RPCExamples{ + HelpExampleCli("combinepsbt", R"('["mybase64_1", "mybase64_2", "mybase64_3"]')") + }, + }.Check(request); RPCTypeCheck(request.params, {UniValue::VARR}, true); @@ -1242,8 +1230,6 @@ UniValue combinepsbt(const JSONRPCRequest& request) UniValue finalizepsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( RPCHelpMan{"finalizepsbt", "Finalize the inputs of a PSBT. If the transaction is fully signed, it will produce a\n" "network serialized transaction which can be broadcast with sendrawtransaction. Otherwise a PSBT will be\n" @@ -1255,17 +1241,17 @@ UniValue finalizepsbt(const JSONRPCRequest& request) " extract and return the complete transaction in normal network serialization instead of the PSBT."}, }, RPCResult{ - "{\n" - " \"psbt\" : \"value\", (string) The base64-encoded partially signed transaction if not extracted\n" - " \"hex\" : \"value\", (string) The hex-encoded network transaction if extracted\n" - " \"complete\" : true|false, (boolean) If the transaction has a complete set of signatures\n" - " ]\n" - "}\n" + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "psbt", "The base64-encoded partially signed transaction if not extracted"}, + {RPCResult::Type::STR_HEX, "hex", "The hex-encoded network transaction if extracted"}, + {RPCResult::Type::BOOL, "complete", "If the transaction has a complete set of signatures"}, + } }, RPCExamples{ HelpExampleCli("finalizepsbt", "\"psbt\"") }, - }.ToString()); + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL}, true); @@ -1301,49 +1287,47 @@ UniValue finalizepsbt(const JSONRPCRequest& request) UniValue createpsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) - throw std::runtime_error( - RPCHelpMan{"createpsbt", - "\nCreates a transaction in the Partially Signed Transaction format.\n" - "Implements the Creator role.\n", + RPCHelpMan{"createpsbt", + "\nCreates a transaction in the Partially Signed Transaction format.\n" + "Implements the Creator role.\n", + { + {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of json objects", { - {"inputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of json objects", + {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", { - {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", - { - {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"}, - {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"}, - {"sequence", RPCArg::Type::NUM, /* default */ "depends on the value of 'locktime' argument", "The sequence number"}, - }, - }, + {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The transaction id"}, + {"vout", RPCArg::Type::NUM, RPCArg::Optional::NO, "The output number"}, + {"sequence", RPCArg::Type::NUM, /* default */ "depends on the value of 'locktime' argument", "The sequence number"}, }, }, - {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n" - "That is, each address can only appear once and there can only be one 'data' object.\n" - "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n" - " accepted as second parameter.", + }, + }, + {"outputs", RPCArg::Type::ARR, RPCArg::Optional::NO, "a json array with outputs (key-value pairs), where none of the keys are duplicated.\n" + "That is, each address can only appear once and there can only be one 'data' object.\n" + "For compatibility reasons, a dictionary, which holds the key-value pairs directly, is also\n" + " accepted as second parameter.", + { + {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", { - {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", - { - {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the Dash address, the value (float or string) is the amount in " + CURRENCY_UNIT}, - }, - }, - {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", - { - {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"}, - }, - }, + {"address", RPCArg::Type::AMOUNT, RPCArg::Optional::NO, "A key-value pair. The key (string) is the Dash address, the value (float or string) is the amount in " + CURRENCY_UNIT}, + }, + }, + {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", + { + {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A key-value pair. The key must be \"data\", the value is hex-encoded data"}, }, }, - {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"}, - }, - RPCResult{ - RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)" }, - RPCExamples{ - HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") }, - }.ToString()); + {"locktime", RPCArg::Type::NUM, /* default */ "0", "Raw locktime. Non-0 value also locktime-activates inputs"}, + }, + RPCResult{ + RPCResult::Type::STR, "", "The resulting raw transaction (base64-encoded string)" + }, + RPCExamples{ + HelpExampleCli("createpsbt", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\" \"[{\\\"data\\\":\\\"00010203\\\"}]\"") + }, + }.Check(request); RPCTypeCheck(request.params, { @@ -1374,9 +1358,7 @@ UniValue createpsbt(const JSONRPCRequest& request) UniValue converttopsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) - throw std::runtime_error( - RPCHelpMan{"converttopsbt", + RPCHelpMan{"converttopsbt", "\nConverts a network serialized transaction to a PSBT. This should be used only with createrawtransaction and fundrawtransaction\n" "createpsbt and walletcreatefundedpsbt should be used for new applications.\n", { @@ -1393,8 +1375,7 @@ UniValue converttopsbt(const JSONRPCRequest& request) "\nConvert the transaction to a PSBT\n" + HelpExampleCli("converttopsbt", "\"rawtransaction\"") }, - }.ToString()); - + }.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VBOOL}, true); @@ -1432,20 +1413,17 @@ UniValue converttopsbt(const JSONRPCRequest& request) UniValue utxoupdatepsbt(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( - RPCHelpMan{"utxoupdatepsbt", - "\nUpdates a PSBT with UTXOs retrieved from the UTXO set or the mempool.\n", - { - {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"} - }, - RPCResult { - RPCResult::Type::STR, "", "The base64-encoded partially signed transaction with inputs updated" - }, - RPCExamples { - HelpExampleCli("utxoupdatepsbt", "\"psbt\"") - }}.ToString()); - } + RPCHelpMan{"utxoupdatepsbt", + "\nUpdates a PSBT with UTXOs retrieved from the UTXO set or the mempool.\n", + { + {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"} + }, + RPCResult { + RPCResult::Type::STR, "", "The base64-encoded partially signed transaction with inputs updated" + }, + RPCExamples { + HelpExampleCli("utxoupdatepsbt", "\"psbt\"") + }}.Check(request); RPCTypeCheck(request.params, {UniValue::VSTR}, true); @@ -1493,24 +1471,21 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request) UniValue joinpsbts(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - throw std::runtime_error( - RPCHelpMan{"joinpsbts", - "\nJoins multiple distinct PSBTs with different inputs and outputs into one PSBT with inputs and outputs from all of the PSBTs\n" - "No input in any of the PSBTs can be in more than one of the PSBTs.\n", + RPCHelpMan{"joinpsbts", + "\nJoins multiple distinct PSBTs with different inputs and outputs into one PSBT with inputs and outputs from all of the PSBTs\n" + "No input in any of the PSBTs can be in more than one of the PSBTs.\n", + { + {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base64 strings of partially signed transactions", { - {"txs", RPCArg::Type::ARR, RPCArg::Optional::NO, "A json array of base64 strings of partially signed transactions", - { - {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"} - }} - }, - RPCResult { - RPCResult::Type::STR, "", "The base64-encoded partially signed transaction" - }, - RPCExamples { - HelpExampleCli("joinpsbts", "\"psbt\"") - }}.ToString()); - } + {"psbt", RPCArg::Type::STR, RPCArg::Optional::NO, "A base64 string of a PSBT"} + }} + }, + RPCResult { + RPCResult::Type::STR, "", "The base64-encoded partially signed transaction" + }, + RPCExamples { + HelpExampleCli("joinpsbts", "\"psbt\"") + }}.Check(request); RPCTypeCheck(request.params, {UniValue::VARR}, true); diff --git a/src/rpc/request.cpp b/src/rpc/request.cpp index 7c96b09152a0..948aa968ae6c 100644 --- a/src/rpc/request.cpp +++ b/src/rpc/request.cpp @@ -184,3 +184,17 @@ void JSONRPCRequest::parse(const UniValue& valRequest) else throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object"); } + +const JSONRPCRequest JSONRPCRequest::squashed() const +{ + if (params.empty()) { + return *this; + } + JSONRPCRequest new_request{*this}; + new_request.strMethod = strMethod + params[0].get_str(); + new_request.params.setArray(); + for (unsigned int i = 1; i < params.size(); ++i) { + new_request.params.push_back(params[i]); + } + return new_request; +} diff --git a/src/rpc/request.h b/src/rpc/request.h index 99eb4f9354ab..b9cdb6ad0372 100644 --- a/src/rpc/request.h +++ b/src/rpc/request.h @@ -37,6 +37,8 @@ class JSONRPCRequest JSONRPCRequest() : id(NullUniValue), params(NullUniValue), fHelp(false) {} void parse(const UniValue& valRequest); + // Returns new JSONRPCRequest with the first param "squashed' into strMethod + const JSONRPCRequest squashed() const; }; #endif // BITCOIN_RPC_REQUEST_H diff --git a/src/rpc/rpcevo.cpp b/src/rpc/rpcevo.cpp index b77532bfa63e..10d19497a989 100644 --- a/src/rpc/rpcevo.cpp +++ b/src/rpc/rpcevo.cpp @@ -336,12 +336,12 @@ static void protx_register_fund_help(const JSONRPCRequest& request) GetRpcArg("fundAddress"), GetRpcArg("submit"), }, - RPCResults{ - {"if \"submit\" is not set or set to true", - "\"txid\" (string) The transaction id.\n" - }, {"if \"submit\" is set to false", - "\"hex\" (string) The serialized signed ProTx in hex format.\n" - }}, + { + RPCResult{"if \"submit\" is not set or set to true", + RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + RPCResult{"if \"submit\" is set to false", + RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"}, + }, RPCExamples{ HelpExampleCli("protx", "register_fund \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"") }, @@ -367,12 +367,12 @@ static void protx_register_help(const JSONRPCRequest& request) GetRpcArg("feeSourceAddress"), GetRpcArg("submit"), }, - RPCResults{ - {"if \"submit\" is not set or set to true", - "\"txid\" (string) The transaction id.\n" - }, {"if \"submit\" is set to false", - "\"hex\" (string) The serialized signed ProTx in hex format.\n" - }}, + { + RPCResult{"if \"submit\" is not set or set to true", + RPCResult::Type::STR_HEX, "txid", "The transaction id"}, + RPCResult{"if \"submit\" is set to false", + RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"}, + }, RPCExamples{ HelpExampleCli("protx", "register \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"") }, @@ -397,13 +397,12 @@ static void protx_register_prepare_help(const JSONRPCRequest& request) GetRpcArg("feeSourceAddress"), }, RPCResult{ - "{ (json object)\n" - " \"tx\" : (string) The serialized unsigned ProTx in hex format.\n" - " \"collateralAddress\" : (string) The collateral address.\n" - " \"signMessage\" : (string) The string message that needs to be signed with\n" - " the collateral key.\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "tx", "The serialized unsigned ProTx in hex format"}, + {RPCResult::Type::STR_HEX, "collateralAddress", "The collateral address"}, + {RPCResult::Type::STR_HEX, "signMessage", "The string message that needs to be signed with the collateral key"}, + }}, RPCExamples{ HelpExampleCli("protx", "register_prepare \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\"") }, @@ -422,7 +421,7 @@ static void protx_register_submit_help(const JSONRPCRequest& request) {"sig", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature signed with the collateral key. Must be in base64 format."}, }, RPCResult{ - "\"txid\" (string) The transaction id.\n" + RPCResult::Type::STR_HEX, "txid", "The transaction id" }, RPCExamples{ HelpExampleCli("protx", "register_submit \"tx\" \"sig\"") @@ -433,15 +432,15 @@ static void protx_register_submit_help(const JSONRPCRequest& request) // handles register, register_prepare and register_fund in one method static UniValue protx_register(const JSONRPCRequest& request) { - bool isExternalRegister = request.params[0].get_str() == "register"; - bool isFundRegister = request.params[0].get_str() == "register_fund"; - bool isPrepareRegister = request.params[0].get_str() == "register_prepare"; + bool isExternalRegister = request.strMethod == "protxregister"; + bool isFundRegister = request.strMethod == "protxregister_fund"; + bool isPrepareRegister = request.strMethod == "protxregister_prepare"; - if (isFundRegister && (request.fHelp || (request.params.size() < 8 || request.params.size() > 10))) { + if (isFundRegister && (request.fHelp || (request.params.size() < 7 || request.params.size() > 9))) { protx_register_fund_help(request); - } else if (isExternalRegister && (request.fHelp || (request.params.size() < 9 || request.params.size() > 11))) { + } else if (isExternalRegister && (request.fHelp || (request.params.size() < 8 || request.params.size() > 10))) { protx_register_help(request); - } else if (isPrepareRegister && (request.fHelp || (request.params.size() != 9 && request.params.size() != 10))) { + } else if (isPrepareRegister && (request.fHelp || (request.params.size() != 8 && request.params.size() != 9))) { protx_register_prepare_help(request); } @@ -453,7 +452,7 @@ static UniValue protx_register(const JSONRPCRequest& request) EnsureWalletIsUnlocked(pwallet); } - size_t paramIdx = 1; + size_t paramIdx = 0; CAmount collateralAmount = 1000 * COIN; @@ -594,9 +593,7 @@ static UniValue protx_register(const JSONRPCRequest& request) static UniValue protx_register_submit(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 3) { - protx_register_submit_help(request); - } + protx_register_submit_help(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -605,7 +602,7 @@ static UniValue protx_register_submit(const JSONRPCRequest& request) EnsureWalletIsUnlocked(pwallet); CMutableTransaction tx; - if (!DecodeHexTx(tx, request.params[1].get_str())) { + if (!DecodeHexTx(tx, request.params[0].get_str())) { throw JSONRPCError(RPC_INVALID_PARAMETER, "transaction not deserializable"); } if (tx.nType != TRANSACTION_PROVIDER_REGISTER) { @@ -619,7 +616,7 @@ static UniValue protx_register_submit(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "payload signature not empty"); } - ptx.vchSig = DecodeBase64(request.params[2].get_str().c_str()); + ptx.vchSig = DecodeBase64(request.params[1].get_str().c_str()); SetTxPayload(tx, ptx); return SignAndSendSpecialTx(tx); @@ -640,7 +637,7 @@ static void protx_update_service_help(const JSONRPCRequest& request) GetRpcArg("feeSourceAddress"), }, RPCResult{ - "\"txid\" (string) The transaction id.\n" + RPCResult::Type::STR_HEX, "txid", "The transaction id" }, RPCExamples{ HelpExampleCli("protx", "update_service \"0123456701234567012345670123456701234567012345670123456701234567\" \"1.2.3.4:1234\" 5a2e15982e62f1e0b7cf9783c64cf7e3af3f90a52d6c40f6f95d624c0b1621cd") @@ -650,8 +647,7 @@ static void protx_update_service_help(const JSONRPCRequest& request) static UniValue protx_update_service(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() < 4 || request.params.size() > 6)) - protx_update_service_help(request); + protx_update_service_help(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -661,13 +657,13 @@ static UniValue protx_update_service(const JSONRPCRequest& request) CProUpServTx ptx; ptx.nVersion = CProUpServTx::CURRENT_VERSION; - ptx.proTxHash = ParseHashV(request.params[1], "proTxHash"); + ptx.proTxHash = ParseHashV(request.params[0], "proTxHash"); - if (!Lookup(request.params[2].get_str().c_str(), ptx.addr, Params().GetDefaultPort(), false)) { - throw std::runtime_error(strprintf("invalid network address %s", request.params[2].get_str())); + if (!Lookup(request.params[1].get_str().c_str(), ptx.addr, Params().GetDefaultPort(), false)) { + throw std::runtime_error(strprintf("invalid network address %s", request.params[1].get_str())); } - CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[3].get_str(), "operatorKey"); + CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[2].get_str(), "operatorKey"); auto dmn = deterministicMNManager->GetListAtChainTip().GetMN(ptx.proTxHash); if (!dmn) { @@ -683,13 +679,13 @@ static UniValue protx_update_service(const JSONRPCRequest& request) tx.nType = TRANSACTION_PROVIDER_UPDATE_SERVICE; // param operatorPayoutAddress - if (!request.params[4].isNull()) { - if (request.params[4].get_str().empty()) { + if (!request.params[3].isNull()) { + if (request.params[3].get_str().empty()) { ptx.scriptOperatorPayout = dmn->pdmnState->scriptOperatorPayout; } else { - CTxDestination payoutDest = DecodeDestination(request.params[4].get_str()); + CTxDestination payoutDest = DecodeDestination(request.params[3].get_str()); if (!IsValidDestination(payoutDest)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid operator payout address: %s", request.params[4].get_str())); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid operator payout address: %s", request.params[3].get_str())); } ptx.scriptOperatorPayout = GetScriptForDestination(payoutDest); } @@ -700,10 +696,10 @@ static UniValue protx_update_service(const JSONRPCRequest& request) CTxDestination feeSource; // param feeSourceAddress - if (!request.params[5].isNull()) { - feeSource = DecodeDestination(request.params[5].get_str()); + if (!request.params[4].isNull()) { + feeSource = DecodeDestination(request.params[4].get_str()); if (!IsValidDestination(feeSource)) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[5].get_str()); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[4].get_str()); } else { if (ptx.scriptOperatorPayout != CScript()) { // use operator reward address as default source for fees @@ -737,7 +733,7 @@ static void protx_update_registrar_help(const JSONRPCRequest& request) GetRpcArg("feeSourceAddress"), }, RPCResult{ - "\"txid\" (string) The transaction id.\n" + RPCResult::Type::STR_HEX, "txid", "The transaction id" }, RPCExamples{ HelpExampleCli("protx", "update_registrar \"0123456701234567012345670123456701234567012345670123456701234567\" \"982eb34b7c7f614f29e5c665bc3605f1beeef85e3395ca12d3be49d2868ecfea5566f11cedfad30c51b2403f2ad95b67\" \"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\"") @@ -747,9 +743,7 @@ static void protx_update_registrar_help(const JSONRPCRequest& request) static UniValue protx_update_registrar(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() != 5 && request.params.size() != 6)) { - protx_update_registrar_help(request); - } + protx_update_registrar_help(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -759,7 +753,7 @@ static UniValue protx_update_registrar(const JSONRPCRequest& request) CProUpRegTx ptx; ptx.nVersion = CProUpRegTx::CURRENT_VERSION; - ptx.proTxHash = ParseHashV(request.params[1], "proTxHash"); + ptx.proTxHash = ParseHashV(request.params[0], "proTxHash"); auto dmn = deterministicMNManager->GetListAtChainTip().GetMN(ptx.proTxHash); if (!dmn) { @@ -769,19 +763,19 @@ static UniValue protx_update_registrar(const JSONRPCRequest& request) ptx.keyIDVoting = dmn->pdmnState->keyIDVoting; ptx.scriptPayout = dmn->pdmnState->scriptPayout; - if (request.params[2].get_str() != "") { - ptx.pubKeyOperator = ParseBLSPubKey(request.params[2].get_str(), "operator BLS address"); + if (request.params[1].get_str() != "") { + ptx.pubKeyOperator = ParseBLSPubKey(request.params[1].get_str(), "operator BLS address"); } - if (request.params[3].get_str() != "") { - ptx.keyIDVoting = ParsePubKeyIDFromAddress(request.params[3].get_str(), "voting address"); + if (request.params[2].get_str() != "") { + ptx.keyIDVoting = ParsePubKeyIDFromAddress(request.params[2].get_str(), "voting address"); } CTxDestination payoutDest; ExtractDestination(ptx.scriptPayout, payoutDest); - if (request.params[4].get_str() != "") { - payoutDest = DecodeDestination(request.params[4].get_str()); + if (request.params[3].get_str() != "") { + payoutDest = DecodeDestination(request.params[3].get_str()); if (!IsValidDestination(payoutDest)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid payout address: %s", request.params[4].get_str())); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("invalid payout address: %s", request.params[3].get_str())); } ptx.scriptPayout = GetScriptForDestination(payoutDest); } @@ -799,10 +793,10 @@ static UniValue protx_update_registrar(const JSONRPCRequest& request) ptx.vchSig.resize(65); CTxDestination feeSourceDest = payoutDest; - if (!request.params[5].isNull()) { - feeSourceDest = DecodeDestination(request.params[5].get_str()); + if (!request.params[4].isNull()) { + feeSourceDest = DecodeDestination(request.params[4].get_str()); if (!IsValidDestination(feeSourceDest)) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[5].get_str()); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[4].get_str()); } FundSpecialTx(pwallet, tx, ptx, feeSourceDest); @@ -827,7 +821,7 @@ static void protx_revoke_help(const JSONRPCRequest& request) GetRpcArg("feeSourceAddress"), }, RPCResult{ - "\"txid\" (string) The transaction id.\n" + RPCResult::Type::STR_HEX, "txid", "The transaction id" }, RPCExamples{ HelpExampleCli("protx", "revoke \"0123456701234567012345670123456701234567012345670123456701234567\" \"072f36a77261cdd5d64c32d97bac417540eddca1d5612f416feb07ff75a8e240\"") @@ -837,9 +831,7 @@ static void protx_revoke_help(const JSONRPCRequest& request) static UniValue protx_revoke(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() < 3 || request.params.size() > 5)) { - protx_revoke_help(request); - } + protx_revoke_help(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -849,12 +841,12 @@ static UniValue protx_revoke(const JSONRPCRequest& request) CProUpRevTx ptx; ptx.nVersion = CProUpRevTx::CURRENT_VERSION; - ptx.proTxHash = ParseHashV(request.params[1], "proTxHash"); + ptx.proTxHash = ParseHashV(request.params[0], "proTxHash"); - CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[2].get_str(), "operatorKey"); + CBLSSecretKey keyOperator = ParseBLSSecretKey(request.params[1].get_str(), "operatorKey"); - if (!request.params[3].isNull()) { - int32_t nReason = ParseInt32V(request.params[3], "reason"); + if (!request.params[2].isNull()) { + int32_t nReason = ParseInt32V(request.params[2], "reason"); if (nReason < 0 || nReason > CProUpRevTx::REASON_LAST) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("invalid reason %d, must be between 0 and %d", nReason, CProUpRevTx::REASON_LAST)); } @@ -874,10 +866,10 @@ static UniValue protx_revoke(const JSONRPCRequest& request) tx.nVersion = 3; tx.nType = TRANSACTION_PROVIDER_UPDATE_REVOKE; - if (!request.params[4].isNull()) { - CTxDestination feeSourceDest = DecodeDestination(request.params[4].get_str()); + if (!request.params[3].isNull()) { + CTxDestination feeSourceDest = DecodeDestination(request.params[3].get_str()); if (!IsValidDestination(feeSourceDest)) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[4].get_str()); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + request.params[3].get_str()); FundSpecialTx(pwallet, tx, ptx, feeSourceDest); } else if (dmn->pdmnState->scriptOperatorPayout != CScript()) { // Using funds from previousely specified operator payout address @@ -906,13 +898,13 @@ static void protx_list_help(const JSONRPCRequest& request) "\nLists all ProTxs in your wallet or on-chain, depending on the given type.\n", { {"type", RPCArg::Type::STR, /* default */ "registered", - "\nAvailable types:\n" - " registered - List all ProTx which are registered at the given chain height.\n" - " This will also include ProTx which failed PoSe verification.\n" - " valid - List only ProTx which are active/valid at the given chain height.\n" + "\nAvailable types:\n" + " registered - List all ProTx which are registered at the given chain height.\n" + " This will also include ProTx which failed PoSe verification.\n" + " valid - List only ProTx which are active/valid at the given chain height.\n" #ifdef ENABLE_WALLET - " wallet - List only ProTx which are found in your wallet at the given chain height.\n" - " This will also include ProTx which failed PoSe verification.\n" + " wallet - List only ProTx which are found in your wallet at the given chain height.\n" + " This will also include ProTx which failed PoSe verification.\n" #endif }, {"detailed", RPCArg::Type::BOOL, /* default */ "false", "If not specified, only the hashes of the ProTx will be returned."}, @@ -990,9 +982,7 @@ static UniValue BuildDMNListEntry(CWallet* pwallet, const CDeterministicMN& dmn, static UniValue protx_list(const JSONRPCRequest& request) { - if (request.fHelp) { - protx_list_help(request); - } + protx_list_help(request); CWallet* pwallet; #ifdef ENABLE_WALLET @@ -1007,8 +997,8 @@ static UniValue protx_list(const JSONRPCRequest& request) #endif std::string type = "registered"; - if (!request.params[1].isNull()) { - type = request.params[1].get_str(); + if (!request.params[0].isNull()) { + type = request.params[0].get_str(); } UniValue ret(UniValue::VARR); @@ -1028,9 +1018,9 @@ static UniValue protx_list(const JSONRPCRequest& request) protx_list_help(request); } - bool detailed = !request.params[2].isNull() ? ParseBoolV(request.params[2], "detailed") : false; + bool detailed = !request.params[1].isNull() ? ParseBoolV(request.params[1], "detailed") : false; - int height = !request.params[3].isNull() ? ParseInt32V(request.params[3], "height") : ::ChainActive().Height(); + int height = !request.params[2].isNull() ? ParseInt32V(request.params[2], "height") : ::ChainActive().Height(); if (height < 1 || height > ::ChainActive().Height()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid height specified"); } @@ -1054,15 +1044,15 @@ static UniValue protx_list(const JSONRPCRequest& request) }); #endif } else if (type == "valid" || type == "registered") { - if (request.params.size() > 4) { + if (request.params.size() > 3) { protx_list_help(request); } LOCK(cs_main); - bool detailed = !request.params[2].isNull() ? ParseBoolV(request.params[2], "detailed") : false; + bool detailed = !request.params[1].isNull() ? ParseBoolV(request.params[1], "detailed") : false; - int height = !request.params[3].isNull() ? ParseInt32V(request.params[3], "height") : ::ChainActive().Height(); + int height = !request.params[2].isNull() ? ParseInt32V(request.params[2], "height") : ::ChainActive().Height(); if (height < 1 || height > ::ChainActive().Height()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid height specified"); } @@ -1087,8 +1077,10 @@ static void protx_info_help(const JSONRPCRequest& request) GetRpcArg("proTxHash"), }, RPCResult{ - "{ (json object) Details about a specific deterministic masternode\n" - "}\n" + RPCResult::Type::OBJ, "", "Details about a specific deterministic masternode", + { + {RPCResult::Type::ELISION, "", ""} + } }, RPCExamples{ HelpExampleCli("protx", "info \"0123456701234567012345670123456701234567012345670123456701234567\"") @@ -1098,9 +1090,7 @@ static void protx_info_help(const JSONRPCRequest& request) static UniValue protx_info(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 2) { - protx_info_help(request); - } + protx_info_help(request); CWallet* pwallet; #ifdef ENABLE_WALLET @@ -1118,7 +1108,7 @@ static UniValue protx_info(const JSONRPCRequest& request) g_txindex->BlockUntilSyncedToCurrentChain(); } - uint256 proTxHash = ParseHashV(request.params[1], "proTxHash"); + uint256 proTxHash = ParseHashV(request.params[0], "proTxHash"); auto mnList = deterministicMNManager->GetListAtChainTip(); auto dmn = mnList.GetMN(proTxHash); if (!dmn) { @@ -1156,13 +1146,11 @@ static uint256 ParseBlock(const UniValue& v, std::string strName) EXCLUSIVE_LOCK static UniValue protx_diff(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 3) { - protx_diff_help(request); - } + protx_diff_help(request); LOCK(cs_main); - uint256 baseBlockHash = ParseBlock(request.params[1], "baseBlock"); - uint256 blockHash = ParseBlock(request.params[2], "block"); + uint256 baseBlockHash = ParseBlock(request.params[0], "baseBlock"); + uint256 blockHash = ParseBlock(request.params[1], "block"); CSimplifiedMNListDiff mnListDiff; std::string strError; @@ -1205,34 +1193,28 @@ static UniValue protx_diff(const JSONRPCRequest& request) static UniValue protx(const JSONRPCRequest& request) { - if (request.fHelp && request.params.empty()) { - protx_help(); - } - - std::string command; - if (!request.params[0].isNull()) { - command = request.params[0].get_str(); - } + const JSONRPCRequest new_request{request.strMethod == "protx" ? request.squashed() : request}; + const std::string command{new_request.strMethod}; #ifdef ENABLE_WALLET - if (command == "register" || command == "register_fund" || command == "register_prepare") { - return protx_register(request); - } else if (command == "register_submit") { - return protx_register_submit(request); - } else if (command == "update_service") { - return protx_update_service(request); - } else if (command == "update_registrar") { - return protx_update_registrar(request); - } else if (command == "revoke") { - return protx_revoke(request); + if (command == "protxregister" || command == "protxregister_fund" || command == "protxregister_prepare") { + return protx_register(new_request); + } else if (command == "protxregister_submit") { + return protx_register_submit(new_request); + } else if (command == "protxupdate_service") { + return protx_update_service(new_request); + } else if (command == "protxupdate_registrar") { + return protx_update_registrar(new_request); + } else if (command == "protxrevoke") { + return protx_revoke(new_request); } else #endif - if (command == "list") { - return protx_list(request); - } else if (command == "info") { - return protx_info(request); - } else if (command == "diff") { - return protx_diff(request); + if (command == "protxlist") { + return protx_list(new_request); + } else if (command == "protxinfo") { + return protx_info(new_request); + } else if (command == "protxdiff") { + return protx_diff(new_request); } else { protx_help(); } @@ -1244,11 +1226,11 @@ static void bls_generate_help(const JSONRPCRequest& request) "\nReturns a BLS secret/public key pair.\n", {}, RPCResult{ - "{\n" - " \"secret\" : \"xxxx\", (string) BLS secret key\n" - " \"public\" : \"xxxx\", (string) BLS public key\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "secret", "BLS secret key"}, + {RPCResult::Type::STR_HEX, "public", "BLS public key"}, + }}, RPCExamples{ HelpExampleCli("bls generate", "") }, @@ -1257,9 +1239,7 @@ static void bls_generate_help(const JSONRPCRequest& request) static UniValue bls_generate(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) { - bls_generate_help(request); - } + bls_generate_help(request); CBLSSecretKey sk; sk.MakeNewKey(); @@ -1278,11 +1258,11 @@ static void bls_fromsecret_help(const JSONRPCRequest& request) {"secret", RPCArg::Type::STR, RPCArg::Optional::NO, "The BLS secret key"}, }, RPCResult{ - "{\n" - " \"secret\" : \"xxxx\", (string) BLS secret key\n" - " \"public\" : \"xxxx\", (string) BLS public key\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "secret", "BLS secret key"}, + {RPCResult::Type::STR_HEX, "public", "BLS public key"}, + }}, RPCExamples{ HelpExampleCli("bls fromsecret", "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") }, @@ -1291,12 +1271,10 @@ static void bls_fromsecret_help(const JSONRPCRequest& request) static UniValue bls_fromsecret(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 2) { - bls_fromsecret_help(request); - } + bls_fromsecret_help(request); CBLSSecretKey sk; - if (!sk.SetHexStr(request.params[1].get_str())) { + if (!sk.SetHexStr(request.params[0].get_str())) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Secret key must be a valid hex string of length %d", sk.SerSize*2)); } @@ -1324,19 +1302,13 @@ static UniValue bls_fromsecret(const JSONRPCRequest& request) static UniValue _bls(const JSONRPCRequest& request) { - if (request.fHelp && request.params.empty()) { - bls_help(); - } - - std::string command; - if (!request.params[0].isNull()) { - command = request.params[0].get_str(); - } + const JSONRPCRequest new_request{request.strMethod == "bls" ? request.squashed() : request}; + const std::string command{new_request.strMethod}; - if (command == "generate") { - return bls_generate(request); - } else if (command == "fromsecret") { - return bls_fromsecret(request); + if (command == "blsgenerate") { + return bls_generate(new_request); + } else if (command == "blsfromsecret") { + return bls_fromsecret(new_request); } else { bls_help(); } diff --git a/src/rpc/rpcquorums.cpp b/src/rpc/rpcquorums.cpp index a0cef9bfa78e..2c09d734f895 100644 --- a/src/rpc/rpcquorums.cpp +++ b/src/rpc/rpcquorums.cpp @@ -34,13 +34,13 @@ static void quorum_list_help(const JSONRPCRequest& request) {"count", RPCArg::Type::NUM, /* default */ "", "Number of quorums to list. Will list active quorums if \"count\" is not specified."}, }, RPCResult{ - "{\n" - " \"quorumName\" : [ (array of strings) List of quorum hashes per some quorum type.\n" - " \"quorumHash\" (string) Quorum hash. Note: most recent quorums come first.\n" - " ,...\n" - " ],\n" - "}\n" - }, + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ARR, "quorumName", "List of quorum hashes per some quorum type", + { + {RPCResult::Type::STR_HEX, "quorumHash", "Quorum hash. Note: most recent quorums come first."}, + }}, + }}, RPCExamples{ HelpExampleCli("quorum", "list") + HelpExampleCli("quorum", "list 10") @@ -51,12 +51,11 @@ static void quorum_list_help(const JSONRPCRequest& request) static UniValue quorum_list(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() != 1 && request.params.size() != 2)) - quorum_list_help(request); + quorum_list_help(request); int count = -1; - if (!request.params[1].isNull()) { - count = ParseInt32V(request.params[1], "count"); + if (!request.params[0].isNull()) { + count = ParseInt32V(request.params[0], "count"); if (count < 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "count can't be negative"); } @@ -135,18 +134,17 @@ static UniValue BuildQuorumInfo(const llmq::CQuorumCPtr& quorum, bool includeMem static UniValue quorum_info(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() != 3 && request.params.size() != 4)) - quorum_info_help(request); + quorum_info_help(request); - Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[1], "llmqType"); + Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType"); if (!Params().HasLLMQ(llmqType)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type"); } - uint256 quorumHash = ParseHashV(request.params[2], "quorumHash"); + uint256 quorumHash = ParseHashV(request.params[1], "quorumHash"); bool includeSkShare = false; - if (!request.params[3].isNull()) { - includeSkShare = ParseBoolV(request.params[3], "includeSkShare"); + if (!request.params[2].isNull()) { + includeSkShare = ParseBoolV(request.params[2], "includeSkShare"); } auto quorum = llmq::quorumManager->GetQuorum(llmqType, quorumHash); @@ -174,13 +172,11 @@ static void quorum_dkgstatus_help(const JSONRPCRequest& request) static UniValue quorum_dkgstatus(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() < 1 || request.params.size() > 2)) { - quorum_dkgstatus_help(request); - } + quorum_dkgstatus_help(request); int detailLevel = 0; - if (!request.params[1].isNull()) { - detailLevel = ParseInt32V(request.params[1], "detail_level"); + if (!request.params[0].isNull()) { + detailLevel = ParseInt32V(request.params[0], "detail_level"); if (detailLevel < 0 || detailLevel > 2) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid detail_level"); } @@ -280,14 +276,12 @@ static void quorum_memberof_help(const JSONRPCRequest& request) static UniValue quorum_memberof(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() < 2 || request.params.size() > 3)) { - quorum_memberof_help(request); - } + quorum_memberof_help(request); - uint256 protxHash = ParseHashV(request.params[1], "proTxHash"); + uint256 protxHash = ParseHashV(request.params[0], "proTxHash"); int scanQuorumsCount = -1; - if (!request.params[2].isNull()) { - scanQuorumsCount = ParseInt32V(request.params[2], "scanQuorumsCount"); + if (!request.params[1].isNull()) { + scanQuorumsCount = ParseInt32V(request.params[1], "scanQuorumsCount"); if (scanQuorumsCount <= 0) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid scanQuorumsCount parameter"); } @@ -332,11 +326,10 @@ static void quorum_sign_help(const JSONRPCRequest& request) {"id", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Request id."}, {"msgHash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "Message hash."}, {"quorumHash", RPCArg::Type::STR_HEX, /* default */ "", "The quorum identifier."}, - {"submit", RPCArg::Type::BOOL, /* default */ "true", "Submits the signature share to the network if this is true."}, - }, - RPCResult{ - "\nReturns an object containing the signature share if this is false.\n" + {"submit", RPCArg::Type::BOOL, /* default */ "true", "Submits the signature share to the network if this is true. " + "Returns an object containing the signature share if this is false."}, }, + RPCResults{}, RPCExamples{""}, }.Check(request); } @@ -406,21 +399,17 @@ static void quorum_isconflicting_help(const JSONRPCRequest& request) static UniValue quorum_sigs_cmd(const JSONRPCRequest& request) { - auto cmd = request.params[0].get_str(); - if (request.fHelp || (request.params.size() != 4)) { - if (cmd == "sign") { - if ((request.params.size() < 4) || (request.params.size() > 6)) { - quorum_sign_help(request); - } - } else if (cmd == "verify") { - if (request.params.size() < 5 || request.params.size() > 7) { - quorum_verify_help(request); - } - } else if (cmd == "hasrecsig") { + auto cmd = request.strMethod; + if (request.fHelp || (request.params.size() != 3)) { + if (cmd == "quorumsign") { + quorum_sign_help(request); + } else if (cmd == "quorumverify") { + quorum_verify_help(request); + } else if (cmd == "quorumhasrecsig") { quorum_hasrecsig_help(request); - } else if (cmd == "getrecsig") { + } else if (cmd == "quorumgetrecsig") { quorum_getrecsig_help(request); - } else if (cmd == "isconflicting") { + } else if (cmd == "quorumisconflicting") { quorum_isconflicting_help(request); } else { // shouldn't happen as it's already handled by the caller @@ -428,22 +417,22 @@ static UniValue quorum_sigs_cmd(const JSONRPCRequest& request) } } - Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[1], "llmqType"); + Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType"); if (!Params().HasLLMQ(llmqType)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type"); } - uint256 id = ParseHashV(request.params[2], "id"); - uint256 msgHash = ParseHashV(request.params[3], "msgHash"); + uint256 id = ParseHashV(request.params[1], "id"); + uint256 msgHash = ParseHashV(request.params[2], "msgHash"); - if (cmd == "sign") { + if (cmd == "quorumsign") { uint256 quorumHash; - if (!request.params[4].isNull() && !request.params[4].get_str().empty()) { - quorumHash = ParseHashV(request.params[4], "quorumHash"); + if (!request.params[3].isNull() && !request.params[3].get_str().empty()) { + quorumHash = ParseHashV(request.params[3], "quorumHash"); } bool fSubmit{true}; - if (!request.params[5].isNull()) { - fSubmit = ParseBoolV(request.params[5], "submit"); + if (!request.params[4].isNull()) { + fSubmit = ParseBoolV(request.params[4], "submit"); } if (fSubmit) { return llmq::quorumSigningManager->AsyncSignIfMember(llmqType, id, msgHash, quorumHash); @@ -478,23 +467,23 @@ static UniValue quorum_sigs_cmd(const JSONRPCRequest& request) return obj; } - } else if (cmd == "verify") { + } else if (cmd == "quorumverify") { CBLSSignature sig; - if (!sig.SetHexStr(request.params[4].get_str())) { + if (!sig.SetHexStr(request.params[3].get_str())) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid signature format"); } - if (request.params[5].isNull() || (request.params[5].get_str().empty() && !request.params[6].isNull())) { + if (request.params[4].isNull() || (request.params[4].get_str().empty() && !request.params[5].isNull())) { int signHeight{-1}; - if (!request.params[6].isNull()) { - signHeight = ParseInt32V(request.params[6], "signHeight"); + if (!request.params[5].isNull()) { + signHeight = ParseInt32V(request.params[5], "signHeight"); } // First check against the current active set, if it fails check against the last active set int signOffset{llmq::GetLLMQParams(llmqType).dkgInterval}; return llmq::quorumSigningManager->VerifyRecoveredSig(llmqType, signHeight, id, msgHash, sig, 0) || llmq::quorumSigningManager->VerifyRecoveredSig(llmqType, signHeight, id, msgHash, sig, signOffset); } else { - uint256 quorumHash = ParseHashV(request.params[5], "quorumHash"); + uint256 quorumHash = ParseHashV(request.params[4], "quorumHash"); llmq::CQuorumCPtr quorum = llmq::quorumManager->GetQuorum(llmqType, quorumHash); if (!quorum) { @@ -504,9 +493,9 @@ static UniValue quorum_sigs_cmd(const JSONRPCRequest& request) uint256 signHash = llmq::CLLMQUtils::BuildSignHash(llmqType, quorum->qc->quorumHash, id, msgHash); return sig.VerifyInsecure(quorum->qc->quorumPublicKey, signHash); } - } else if (cmd == "hasrecsig") { + } else if (cmd == "quorumhasrecsig") { return llmq::quorumSigningManager->HasRecoveredSig(llmqType, id, msgHash); - } else if (cmd == "getrecsig") { + } else if (cmd == "quorumgetrecsig") { llmq::CRecoveredSig recSig; if (!llmq::quorumSigningManager->GetRecoveredSigForId(llmqType, id, recSig)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "recovered signature not found"); @@ -515,7 +504,7 @@ static UniValue quorum_sigs_cmd(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "recovered signature not found"); } return recSig.ToJson(); - } else if (cmd == "isconflicting") { + } else if (cmd == "quorumisconflicting") { return llmq::quorumSigningManager->IsConflicting(llmqType, id, msgHash); } else { // shouldn't happen as it's already handled by the caller @@ -538,16 +527,14 @@ static void quorum_selectquorum_help(const JSONRPCRequest& request) static UniValue quorum_selectquorum(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 3) { - quorum_selectquorum_help(request); - } + quorum_selectquorum_help(request); - Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[1], "llmqType"); + Consensus::LLMQType llmqType = (Consensus::LLMQType)ParseInt32V(request.params[0], "llmqType"); if (!Params().HasLLMQ(llmqType)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid LLMQ type"); } - uint256 id = ParseHashV(request.params[2], "id"); + uint256 id = ParseHashV(request.params[1], "id"); UniValue ret(UniValue::VOBJ); @@ -583,12 +570,10 @@ static void quorum_dkgsimerror_help(const JSONRPCRequest& request) static UniValue quorum_dkgsimerror(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() != 3)) { - quorum_dkgsimerror_help(request); - } + quorum_dkgsimerror_help(request); - std::string type = request.params[1].get_str(); - double rate = ParseDoubleV(request.params[2], "rate"); + std::string type = request.params[0].get_str(); + double rate = ParseDoubleV(request.params[1], "rate"); if (rate < 0 || rate > 1) { throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid rate. Must be between 0 and 1"); @@ -621,20 +606,18 @@ static void quorum_getdata_help(const JSONRPCRequest& request) static UniValue quorum_getdata(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() < 5 || request.params.size() > 6)) { - quorum_getdata_help(request); - } + quorum_getdata_help(request); - NodeId nodeId = ParseInt64V(request.params[1], "nodeId"); - Consensus::LLMQType llmqType = static_cast(ParseInt32V(request.params[2], "llmqType")); - uint256 quorumHash = ParseHashV(request.params[3], "quorumHash"); - uint16_t nDataMask = static_cast(ParseInt32V(request.params[4], "dataMask")); + NodeId nodeId = ParseInt64V(request.params[0], "nodeId"); + Consensus::LLMQType llmqType = static_cast(ParseInt32V(request.params[1], "llmqType")); + uint256 quorumHash = ParseHashV(request.params[2], "quorumHash"); + uint16_t nDataMask = static_cast(ParseInt32V(request.params[3], "dataMask")); uint256 proTxHash; // Check if request wants ENCRYPTED_CONTRIBUTIONS data if (nDataMask & llmq::CQuorumDataRequest::ENCRYPTED_CONTRIBUTIONS) { - if (!request.params[5].isNull()) { - proTxHash = ParseHashV(request.params[5], "proTxHash"); + if (!request.params[4].isNull()) { + proTxHash = ParseHashV(request.params[4], "proTxHash"); if (proTxHash.IsNull()) { throw JSONRPCError(RPC_INVALID_PARAMETER, "proTxHash invalid"); } @@ -649,37 +632,33 @@ static UniValue quorum_getdata(const JSONRPCRequest& request) }); } -static void quorum_rotationinfo_help() +static void quorum_rotationinfo_help(const JSONRPCRequest& request) { - throw std::runtime_error( - RPCHelpMan{ - "quorum rotationinfo", - "Get quorum rotation information\n", - { - {"blockRequestHash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The blockHash of the request"}, - {"extraShare", RPCArg::Type::BOOL, /* default */ "false", "Extra share"}, - {"baseBlockHash...", RPCArg::Type::STR_HEX, /* default*/ "", "baseBlockHashes"}, - }, - RPCResults{}, - RPCExamples{""}, - } - .ToString()); + RPCHelpMan{ + "quorum rotationinfo", + "Get quorum rotation information\n", + { + {"blockRequestHash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The blockHash of the request."}, + {"extraShare", RPCArg::Type::BOOL, /* default */ "false", "Extra share"}, + {"baseBlockHash...", RPCArg::Type::STR_HEX, /* default*/ "", "baseBlockHashes"}, + }, + RPCResults{}, + RPCExamples{""}, + }.Check(request); } static UniValue quorum_rotationinfo(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() < 2)) { - quorum_rotationinfo_help(); - } + quorum_rotationinfo_help(request); llmq::CGetQuorumRotationInfo cmd; llmq::CQuorumRotationInfo quorumRotationInfoRet; std::string strError; - cmd.blockRequestHash = ParseHashV(request.params[1], "blockRequestHash"); - cmd.extraShare = request.params[2].isNull() ? false : ParseBoolV(request.params[2], "extraShare"); + cmd.blockRequestHash = ParseHashV(request.params[0], "blockRequestHash"); + cmd.extraShare = request.params[1].isNull() ? false : ParseBoolV(request.params[1], "extraShare"); - size_t idx = 3; + size_t idx = 2; while (!request.params[idx].isNull()) { cmd.baseBlockHashes.emplace_back(ParseHashV(request.params[idx], "baseBlockHash")); ++idx; @@ -727,33 +706,27 @@ static UniValue quorum_rotationinfo(const JSONRPCRequest& request) static UniValue _quorum(const JSONRPCRequest& request) { - if (request.fHelp && request.params.empty()) { - quorum_help(); - } - - std::string command; - if (!request.params[0].isNull()) { - command = request.params[0].get_str(); - } - - if (command == "list") { - return quorum_list(request); - } else if (command == "info") { - return quorum_info(request); - } else if (command == "dkgstatus") { - return quorum_dkgstatus(request); - } else if (command == "memberof") { - return quorum_memberof(request); - } else if (command == "sign" || command == "verify" || command == "hasrecsig" || command == "getrecsig" || command == "isconflicting") { - return quorum_sigs_cmd(request); - } else if (command == "selectquorum") { - return quorum_selectquorum(request); - } else if (command == "dkgsimerror") { - return quorum_dkgsimerror(request); - } else if (command == "getdata") { - return quorum_getdata(request); - } else if (command == "rotationinfo") { - return quorum_rotationinfo(request); + const JSONRPCRequest new_request{request.strMethod == "quorum" ? request.squashed() : request}; + const std::string command{new_request.strMethod}; + + if (command == "quorumlist") { + return quorum_list(new_request); + } else if (command == "quoruminfo") { + return quorum_info(new_request); + } else if (command == "quorumdkgstatus") { + return quorum_dkgstatus(new_request); + } else if (command == "quorummemberof") { + return quorum_memberof(new_request); + } else if (command == "quorumsign" || command == "quorumverify" || command == "quorumhasrecsig" || command == "quorumgetrecsig" || command == "quorumisconflicting") { + return quorum_sigs_cmd(new_request); + } else if (command == "quorumselectquorum") { + return quorum_selectquorum(new_request); + } else if (command == "quorumdkgsimerror") { + return quorum_dkgsimerror(new_request); + } else if (command == "quorumgetdata") { + return quorum_getdata(new_request); + } else if (command == "quorumrotationinfo") { + return quorum_rotationinfo(new_request); } else { quorum_help(); } @@ -775,9 +748,7 @@ static void verifychainlock_help(const JSONRPCRequest& request) static UniValue verifychainlock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) { - verifychainlock_help(request); - } + verifychainlock_help(request); const uint256 nBlockHash = ParseHashV(request.params[0], "blockHash"); @@ -819,9 +790,7 @@ static void verifyislock_help(const JSONRPCRequest& request) static UniValue verifyislock(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 3 || request.params.size() > 4) { - verifyislock_help(request); - } + verifyislock_help(request); uint256 id = ParseHashV(request.params[0], "id"); uint256 txid = ParseHashV(request.params[1], "txid"); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 16349d578c27..96003b735ded 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -150,23 +150,20 @@ void CRPCTable::InitPlatformRestrictions() }; } -UniValue help(const JSONRPCRequest& jsonRequest) +static RPCHelpMan help() +{ + return RPCHelpMan{"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"}, + {"subcommand", RPCArg::Type::STR, /* default */ "all subcommands", "The subcommand to get help on. Please note that not all subcommands support this at the moment"}, + }, + RPCResult{ + RPCResult::Type::STR, "", "The help text" + }, + RPCExamples{""}, + [&](const RPCHelpMan& self, const JSONRPCRequest& jsonRequest) -> UniValue { - if (jsonRequest.fHelp || jsonRequest.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"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"}, - {"subcommand", RPCArg::Type::STR, /* default */ "all subcommands", "The subcommand to get help on. Please note that not all subcommands support this at the moment"}, - }, - RPCResult{ - RPCResult::Type::STR, "", "The help text" - }, - RPCExamples{""}, - }.ToString() - ); - std::string strCommand, strSubCommand; if (jsonRequest.params.size() > 0) strCommand = jsonRequest.params[0].get_str(); @@ -174,24 +171,26 @@ UniValue help(const JSONRPCRequest& jsonRequest) strSubCommand = jsonRequest.params[1].get_str(); return tableRPC.help(strCommand, strSubCommand, jsonRequest); +}, + }; } -UniValue stop(const JSONRPCRequest& jsonRequest) +static RPCHelpMan stop() { static const std::string RESULT{PACKAGE_NAME " stopping"}; - // Accept the deprecated and ignored 'detach' boolean argument + return RPCHelpMan{"stop", // 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", - "\nStop Dash Core server.", - {}, - RPCResult{RPCResult::Type::STR, "", "A string with the content '" + RESULT + "'"}, - RPCExamples{""}, - }.ToString()); + "\nStop Dash Core server.", + { + {"wait", RPCArg::Type::NUM, RPCArg::Optional::OMITTED_NAMED_ARG, "how long to wait in ms", "", {}, /* hidden */ true}, + }, + RPCResult{RPCResult::Type::STR, "", "A string with the content '" + RESULT + "'"}, + RPCExamples{""}, + [&](const RPCHelpMan& self, const JSONRPCRequest& jsonRequest) -> UniValue +{ // Event loop will exit after current HTTP requests have been handled, so // this reply will get back to the client. StartShutdown(); @@ -199,52 +198,54 @@ UniValue stop(const JSONRPCRequest& jsonRequest) UninterruptibleSleep(std::chrono::milliseconds{jsonRequest.params[0].get_int()}); } return RESULT; +}, + }; } -static UniValue uptime(const JSONRPCRequest& jsonRequest) +static RPCHelpMan uptime() +{ + return RPCHelpMan{"uptime", + "\nReturns the total uptime of the server.\n", + {}, + RPCResult{ + RPCResult::Type::NUM, "", "The number of seconds that the server has been running" + }, + RPCExamples{ + HelpExampleCli("uptime", "") + + HelpExampleRpc("uptime", "") + }, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - if (jsonRequest.fHelp || jsonRequest.params.size() > 0) - throw std::runtime_error( - RPCHelpMan{"uptime", - "\nReturns the total uptime of the server.\n", - {}, - RPCResult{ - RPCResult::Type::NUM, "", "The number of seconds that the server has been running" - }, - RPCExamples{ - HelpExampleCli("uptime", "") - + HelpExampleRpc("uptime", "") - }, - }.ToString()); return GetTime() - GetStartupTime(); } + }; +} -static UniValue getrpcinfo(const JSONRPCRequest& request) -{ - if (request.fHelp || request.params.size() > 0) { - throw std::runtime_error( - RPCHelpMan{"getrpcinfo", - "\nReturns details of the RPC server.\n", - {}, - RPCResult{ - "{\n" - " \"active_commands\" (array) All active commands\n" - " [\n" - " { (object) Information about an active command\n" - " \"method\" (string) The name of the RPC command \n" - " \"duration\" (numeric) The running time in microseconds\n" - " },...\n" - " ],\n" - " \"logpath\": \"xxx\" (string) The complete file path to the debug log\n" - "}\n" +static RPCHelpMan getrpcinfo() +{ + return RPCHelpMan{"getrpcinfo", + "\nReturns details of the RPC server.\n", + {}, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::ARR, "active_commands", "All active commands", + { + {RPCResult::Type::OBJ, "", "Information about an active command", + { + {RPCResult::Type::STR, "method", "The name of the RPC command"}, + {RPCResult::Type::NUM, "duration", "The running time in microseconds"}, + }}, + }}, + {RPCResult::Type::STR, "logpath", "The complete file path to the debug log"}, + } }, RPCExamples{ HelpExampleCli("getrpcinfo", "") + HelpExampleRpc("getrpcinfo", "")}, - }.ToString() - ); - } + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue +{ LOCK(g_rpc_server_info.mutex); UniValue active_commands(UniValue::VARR); @@ -264,7 +265,8 @@ static UniValue getrpcinfo(const JSONRPCRequest& request) return result; } - + }; +} // clang-format off static const CRPCCommand vRPCCommands[] = { // category name actor (function) argNames diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index 9e77526578a7..17b3e4f44417 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -170,7 +170,7 @@ std::string HelpExampleRpc(const std::string& methodname, const std::string& arg { return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", " "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;'" - " http://127.0.0.1:" + strprintf("%d", gArgs.GetArg("-rpcport", BaseParams().RPCPort())) + "/\n"; + " http://127.0.0.1:9998/\n"; } // Converts a hex string to a public key if possible @@ -421,13 +421,9 @@ std::string RPCResults::ToDescriptionString() const } else { result += "\nResult (" + r.m_cond + "):\n"; } - if (r.m_legacy) { - result += r.m_result; - } else { - Sections sections; - r.ToSections(sections); - result += sections.ToString(); - } + Sections sections; + r.ToSections(sections); + result += sections.ToString(); } return result; } diff --git a/src/rpc/util.h b/src/rpc/util.h index c3c725bbdf40..f6ed1711bda9 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -223,8 +223,6 @@ struct RPCResult { const bool m_optional; const std::string m_description; const std::string m_cond; - const bool m_legacy; //!< Used for legacy support - const std::string m_result; //!< Used for legacy support RPCResult( const std::string cond, @@ -238,44 +236,13 @@ struct RPCResult { m_inner{std::move(inner)}, m_optional{optional}, m_description{std::move(description)}, - m_cond{std::move(cond)}, - m_result{}, - m_legacy{false} + m_cond{std::move(cond)} { CHECK_NONFATAL(!m_cond.empty()); const bool inner_needed{type == Type::ARR || type == Type::ARR_FIXED || type == Type::OBJ || type == Type::OBJ_DYN}; CHECK_NONFATAL(inner_needed != inner.empty()); } - // start legacy support logic - RPCResult(std::string cond, std::string result) - : m_type{Type::NONE}, - m_key_name{}, - m_inner{}, - m_optional{false}, - m_description{}, - m_cond{std::move(cond)}, - m_result{std::move(result)}, - m_legacy{true} - { - CHECK_NONFATAL(!m_cond.empty()); - CHECK_NONFATAL(!m_result.empty()); - } - - RPCResult(std::string result) - : m_type{Type::NONE}, - m_key_name{}, - m_inner{}, - m_optional{false}, - m_description{}, - m_cond{}, - m_result{std::move(result)}, - m_legacy{true} - { - CHECK_NONFATAL(!m_result.empty()); - } - // end legacy support logic - RPCResult( const std::string cond, const Type type, @@ -295,9 +262,7 @@ struct RPCResult { m_inner{std::move(inner)}, m_optional{optional}, m_description{std::move(description)}, - m_cond{}, - m_result{}, - m_legacy{false} + m_cond{} { const bool inner_needed{type == Type::ARR || type == Type::ARR_FIXED || type == Type::OBJ || type == Type::OBJ_DYN}; CHECK_NONFATAL(inner_needed != inner.empty()); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 3e7c1cad5915..1fc7db249e2b 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -70,32 +70,30 @@ static void RescanWallet(CWallet& wallet, const WalletRescanReserver& reserver, UniValue importprivkey(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) - throw std::runtime_error( - RPCHelpMan{"importprivkey", - "\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n" - "Hint: use importmulti to import more than one private key.\n" - "\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 key exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n", - { - {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key (see dumpprivkey)"}, - {"label", RPCArg::Type::STR, /* default */ "current label if address exists, otherwise \"\"", "An optional label"}, - {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - "\nDump a private key\n" - + HelpExampleCli("dumpprivkey", "\"myaddress\"") + - "\nImport the private key with rescan\n" - + HelpExampleCli("importprivkey", "\"mykey\"") + - "\nImport using a label and without rescan\n" - + HelpExampleCli("importprivkey", "\"mykey\" \"testing\" false") + - "\nImport using default blank label and without rescan\n" - + HelpExampleCli("importprivkey", "\"mykey\" \"\" false") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false") - }, - }.ToString()); + RPCHelpMan{"importprivkey", + "\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n" + "Hint: use importmulti to import more than one private key.\n" + "\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 key exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n", + { + {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key (see dumpprivkey)"}, + {"label", RPCArg::Type::STR, /* default */ "current label if address exists, otherwise \"\"", "An optional label"}, + {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + "\nDump a private key\n" + + HelpExampleCli("dumpprivkey", "\"myaddress\"") + + "\nImport the private key with rescan\n" + + HelpExampleCli("importprivkey", "\"mykey\"") + + "\nImport using a label and without rescan\n" + + HelpExampleCli("importprivkey", "\"mykey\" \"testing\" false") + + "\nImport using default blank label and without rescan\n" + + HelpExampleCli("importprivkey", "\"mykey\" \"\" false") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("importprivkey", "\"mykey\", \"testing\", false") + }, + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -169,9 +167,7 @@ UniValue importprivkey(const JSONRPCRequest& request) UniValue abortrescan(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() > 0) - throw std::runtime_error( - RPCHelpMan{"abortrescan", + RPCHelpMan{"abortrescan", "\nStops current wallet rescan triggered by an RPC call, e.g. by an importprivkey call.\n", {}, RPCResult{RPCResult::Type::BOOL, "", "Whether the abort was successful"}, @@ -183,7 +179,7 @@ UniValue abortrescan(const JSONRPCRequest& request) "\nAs a JSON-RPC call\n" + HelpExampleRpc("abortrescan", "") }, - }.ToString()); + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -234,32 +230,30 @@ static void ImportAddress(CWallet * const pwallet, const CTxDestination& dest, c UniValue importaddress(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) - throw std::runtime_error( - RPCHelpMan{"importaddress", - "\nAdds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n" - "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n" - "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" - "If you have the full public key, you should call importpubkey instead of this.\n" - "Hint: use importmulti to import more than one address.\n" - "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n" - "as change, and not show up in many RPCs.\n", - { - {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The Dash address (or hex-encoded script)"}, - {"label", RPCArg::Type::STR, /* default */ "\"\"", "An optional label"}, - {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"}, - {"p2sh", RPCArg::Type::BOOL, /* default */ "false", "Add the P2SH version of the script as well"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - "\nImport an address with rescan\n" - + HelpExampleCli("importaddress", "\"myaddress\"") + - "\nImport using a label without rescan\n" - + HelpExampleCli("importaddress", "\"myaddress\" \"testing\" false") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false") - }, - }.ToString()); + RPCHelpMan{"importaddress", + "\nAdds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n" + "\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n" + "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" + "If you have the full public key, you should call importpubkey instead of this.\n" + "Hint: use importmulti to import more than one address.\n" + "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n" + "as change, and not show up in many RPCs.\n", + { + {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The Dash address (or hex-encoded script)"}, + {"label", RPCArg::Type::STR, /* default */ "\"\"", "An optional label"}, + {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"}, + {"p2sh", RPCArg::Type::BOOL, /* default */ "false", "Add the P2SH version of the script as well"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + "\nImport an address with rescan\n" + + HelpExampleCli("importaddress", "\"myaddress\"") + + "\nImport using a label without rescan\n" + + HelpExampleCli("importaddress", "\"myaddress\" \"testing\" false") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("importaddress", "\"myaddress\", \"testing\", false") + }, + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -323,18 +317,15 @@ UniValue importaddress(const JSONRPCRequest& request) UniValue importprunedfunds(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 2) - throw std::runtime_error( - RPCHelpMan{"importprunedfunds", - "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n", - { - {"rawtransaction", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A raw transaction in hex funding an already-existing address in wallet"}, - {"txoutproof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex output from gettxoutproof that contains the transaction"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{""}, - }.ToString() - ); + RPCHelpMan{"importprunedfunds", + "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n", + { + {"rawtransaction", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "A raw transaction in hex funding an already-existing address in wallet"}, + {"txoutproof", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex output from gettxoutproof that contains the transaction"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{""}, + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -385,20 +376,18 @@ UniValue importprunedfunds(const JSONRPCRequest& request) UniValue removeprunedfunds(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"removeprunedfunds", - "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will affect wallet balances.\n", - { - {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded id of the transaction you are deleting"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") - }, - }.ToString()); + RPCHelpMan{"removeprunedfunds", + "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will affect wallet balances.\n", + { + {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The hex-encoded id of the transaction you are deleting"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") + }, + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -426,28 +415,26 @@ UniValue removeprunedfunds(const JSONRPCRequest& request) UniValue importpubkey(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) - throw std::runtime_error( - RPCHelpMan{"importpubkey", - "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n" - "Hint: use importmulti to import more than one public key.\n" - "\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 pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n", - { - {"pubkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The hex-encoded public key"}, - {"label", RPCArg::Type::STR, /* default */ "\"\"", "An optional label"}, - {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - "\nImport a public key with rescan\n" - + HelpExampleCli("importpubkey", "\"mypubkey\"") + - "\nImport using a label without rescan\n" - + HelpExampleCli("importpubkey", "\"mypubkey\" \"testing\" false") + - "\nAs a JSON-RPC call\n" - + HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false") - }, - }.ToString()); + RPCHelpMan{"importpubkey", + "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n" + "Hint: use importmulti to import more than one public key.\n" + "\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 pubkey exists but related transactions are still missing, leading to temporarily incorrect/bogus balances and unspent outputs until rescan completes.\n", + { + {"pubkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The hex-encoded public key"}, + {"label", RPCArg::Type::STR, /* default */ "\"\"", "An optional label"}, + {"rescan", RPCArg::Type::BOOL, /* default */ "true", "Rescan the wallet for transactions"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + "\nImport a public key with rescan\n" + + HelpExampleCli("importpubkey", "\"mypubkey\"") + + "\nImport using a label without rescan\n" + + HelpExampleCli("importpubkey", "\"mypubkey\" \"testing\" false") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("importpubkey", "\"mypubkey\", \"testing\", false") + }, + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -504,24 +491,22 @@ UniValue importpubkey(const JSONRPCRequest& request) UniValue importwallet(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"importwallet", - "\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n" - "Note: Use \"getwalletinfo\" to query the scanning progress.\n", - { - {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet file"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - "\nDump the wallet\n" - + HelpExampleCli("dumpwallet", "\"test\"") + - "\nImport the wallet\n" - + HelpExampleCli("importwallet", "\"test\"") + - "\nImport using the json rpc call\n" - + HelpExampleRpc("importwallet", "\"test\"") - }, - }.ToString()); + RPCHelpMan{"importwallet", + "\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n" + "Note: Use \"getwalletinfo\" to query the scanning progress.\n", + { + {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet file"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + "\nDump the wallet\n" + + HelpExampleCli("dumpwallet", "\"test\"") + + "\nImport the wallet\n" + + HelpExampleCli("importwallet", "\"test\"") + + "\nImport using the json rpc call\n" + + HelpExampleRpc("importwallet", "\"test\"") + }, + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -668,24 +653,22 @@ UniValue importwallet(const JSONRPCRequest& request) UniValue importelectrumwallet(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"importselectrumwallet", - "\nImports keys from an Electrum wallet export file (.csv or .json)\n", - { - {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The Electrum wallet export file, should be in csv or json format"}, - {"index", RPCArg::Type::NUM, /* default */ "0", "Rescan the wallet for transactions starting from this block index"}, - }, - RPCResults{}, - RPCExamples{ - "\nImport the wallet\n" - + HelpExampleCli("importelectrumwallet", "\"test.csv\"") - + HelpExampleCli("importelectrumwallet", "\"test.json\"") + - "\nImport using the json rpc call\n" - + HelpExampleRpc("importelectrumwallet", "\"test.csv\"") - + HelpExampleRpc("importelectrumwallet", "\"test.json\"") - }, - }.ToString()); + RPCHelpMan{"importselectrumwallet", + "\nImports keys from an Electrum wallet export file (.csv or .json)\n", + { + {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The Electrum wallet export file, should be in csv or json format"}, + {"index", RPCArg::Type::NUM, /* default */ "0", "Rescan the wallet for transactions starting from this block index"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + "\nImport the wallet\n" + + HelpExampleCli("importelectrumwallet", "\"test.csv\"") + + HelpExampleCli("importelectrumwallet", "\"test.json\"") + + "\nImport using the json rpc call\n" + + HelpExampleRpc("importelectrumwallet", "\"test.csv\"") + + HelpExampleRpc("importelectrumwallet", "\"test.json\"") + }, + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -818,23 +801,21 @@ UniValue importelectrumwallet(const JSONRPCRequest& request) UniValue dumpprivkey(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"dumpprivkey", - "\nReveals the private key corresponding to 'address'.\n" - "Then the importprivkey can be used with this output\n", - { - {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The dash address for the private key"}, - }, - RPCResult{ - RPCResult::Type::STR, "key", "The private key" - }, - RPCExamples{ - HelpExampleCli("dumpprivkey", "\"myaddress\"") - + HelpExampleCli("importprivkey", "\"mykey\"") - + HelpExampleRpc("dumpprivkey", "\"myaddress\"") - }, - }.ToString()); + RPCHelpMan{"dumpprivkey", + "\nReveals the private key corresponding to 'address'.\n" + "Then the importprivkey can be used with this output\n", + { + {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The dash address for the private key"}, + }, + RPCResult{ + RPCResult::Type::STR, "key", "The private key" + }, + RPCExamples{ + HelpExampleCli("dumpprivkey", "\"myaddress\"") + + HelpExampleCli("importprivkey", "\"mykey\"") + + HelpExampleRpc("dumpprivkey", "\"myaddress\"") + }, + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -863,23 +844,22 @@ UniValue dumpprivkey(const JSONRPCRequest& request) UniValue dumphdinfo(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 0) - throw std::runtime_error( - RPCHelpMan{"dumphdinfo", - "Returns an object containing sensitive private info about this HD wallet.\n", - {}, - RPCResult{ - "{\n" - " \"hdseed\" : \"seed\", (string) The HD seed (bip32, in hex)\n" - " \"mnemonic\" : \"words\", (string) The mnemonic for this HD wallet (bip39, english words) \n" - " \"mnemonicpassphrase\" : \"passphrase\", (string) The mnemonic passphrase for this HD wallet (bip39)\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("dumphdinfo", "") - + HelpExampleRpc("dumphdinfo", "") - }, - }.ToString()); + RPCHelpMan{"dumphdinfo", + "Returns an object containing sensitive private info about this HD wallet.\n", + {}, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR_HEX, "hdseed", "The HD seed (bip32, in hex)"}, + {RPCResult::Type::STR, "mnemonic", "The mnemonic for this HD wallet (bip39, english words)"}, + {RPCResult::Type::STR, "mnemonicpassphrase", "The mnemonic passphrase for this HD wallet (bip39)"}, + } + }, + RPCExamples{ + HelpExampleCli("dumphdinfo", "") + + HelpExampleRpc("dumphdinfo", "") + }, + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -910,28 +890,27 @@ UniValue dumphdinfo(const JSONRPCRequest& request) UniValue dumpwallet(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) - throw std::runtime_error( - RPCHelpMan{"dumpwallet", - "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n" - "Imported scripts are included in the dumpfile too, their corresponding addresses will 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" - "only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n", + RPCHelpMan{"dumpwallet", + "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n" + "Imported scripts are included in the dumpfile too, their corresponding addresses will 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" + "only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n", + { + {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The filename with path (either absolute or relative to dashd)"}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", { - {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The filename with path (either absolute or relative to dashd)"}, - }, - RPCResult{ - "{ (json object)\n" - " \"keys\" : { (numeric) The number of keys contained in the wallet dump\n" - " \"filename\" : { (string) The filename with full absolute path\n" - " \"warning\" : { (string) A warning about not sharing the wallet dump with anyone\n" - "}\n" - }, - RPCExamples{ - HelpExampleCli("dumpwallet", "\"test\"") - + HelpExampleRpc("dumpwallet", "\"test\"") - }, - }.ToString()); + {RPCResult::Type::NUM, "keys", "The number of keys contained in the wallet dump"}, + {RPCResult::Type::STR, "filename", "The filename with full absolute path"}, + {RPCResult::Type::STR, "warning", "A warning about not sharing the wallet dump with anyone"}, + } + }, + RPCExamples{ + HelpExampleCli("dumpwallet", "\"test\"") + + HelpExampleRpc("dumpwallet", "\"test\"") + }, + }.Check(request); std::shared_ptr const wallet = GetWalletForJSONRPCRequest(request); if (!wallet) return NullUniValue; @@ -1447,69 +1426,79 @@ static int64_t GetImportTimestamp(const UniValue& data, int64_t now) UniValue importmulti(const JSONRPCRequest& mainRequest) { - if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2) - throw std::runtime_error( - RPCHelpMan{"importmulti", - "\nImport addresses/scripts (with private or public keys, redeem script (P2SH)), optionally rescanning the blockchain from the earliest creation time of the imported scripts. Requires a new wallet backup.\n" - "If an address/script is imported without all of the private keys required to spend from that address, it will be watchonly. The 'watchonly' option must be set to true in this case or a warning will be returned.\n" - "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" - "\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 keys, addresses or scripts exists but related transactions are still missing.\n", + RPCHelpMan{"importmulti", + "\nImport addresses/scripts (with private or public keys, redeem script (P2SH)), optionally rescanning the blockchain from the earliest creation time of the imported scripts. Requires a new wallet backup.\n" + "If an address/script is imported without all of the private keys required to spend from that address, it will be watchonly. The 'watchonly' option must be set to true in this case or a warning will be returned.\n" + "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" + "\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 keys, addresses or scripts exists but related transactions are still missing.\n", + { + {"requests", RPCArg::Type::ARR, RPCArg::Optional::NO, "Data to be imported", { - {"requests", RPCArg::Type::ARR, RPCArg::Optional::NO, "Data to be imported", + {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", { - {"", RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, "", + {"desc", RPCArg::Type::STR, /* default */ "", "Descriptor to import. If using descriptor, do not also provide address/scriptPubKey, scripts, or pubkeys" + }, + {"scriptPubKey", RPCArg::Type::STR, RPCArg::Optional::NO, "Type of scriptPubKey (string for script, json for address). Should not be provided if using a descriptor", + /* oneline_description */ "", {"\"