Skip to content

Commit

Permalink
Merge #2386: [RPC] Support for JSON-RPC named arguments
Browse files Browse the repository at this point in the history
9ed1bdd [RPC] Remove obsolete and ignored 'detach' argument of stop command (random-zebra)
7d9af29 [Doc] Add RPC named arguments to release notes (random-zebra)
1582bdf [QA] Add rpc_named_arguments.py functional test (random-zebra)
d87da93 rpc: Rename first named arg of createrawtransaction (random-zebra)
7ae8964 [Refactor] Sort RPC command tables alphabetically (random-zebra)
da63bb8 rpc: Named argument support for pivx-cli (random-zebra)
22ee72a rpc: Named arguments for rawtransaction calls (Wladimir J. van der Laan)
3a93690 rpc: Named arguments for wallet calls (random-zebra)
f137eca rpc: Named arguments for mining calls (Wladimir J. van der Laan)
d524cc1 RPC: Named arguments for masternode, budget, and evo calls (random-zebra)
81de632 rpc: Named arguments for net calls (Wladimir J. van der Laan)
8e5bed7 rpc: Named arguments for misc calls (random-zebra)
4b2b980 rpc: Add 'echo' call for testing (Wladimir J. van der Laan)
f8617c2 rpc: Named arguments for blockchain calls (random-zebra)
a00e323 rpc: Support named arguments (Wladimir J. van der Laan)
a0da903 authproxy: Add support for RPC named arguments (Wladimir J. van der Laan)

Pull request description:

  The [JSON-RPC specification](http://www.jsonrpc.org/specification) allows either passing parameters as an Array, for positional arguments, or as an Object, for named arguments. Currently PIVX Core only supports positional arguments.

  This pull request adds support for named arguments, but preserves full backwards compatibility. APIs using by-name arguments are easier to extend - as arguments can be left out - and easier to use - no need to guess which argument goes where.

  This is especially nice in languages such as Python, which have native support for named arguments. Examples from the test:
  ```python
  h = node.help(command='getinfo')
  h = node.getblockhash(height=0)
  h = node.getblock(hash=h)
  ```

  Backported from:
  - bitcoin#8811 : Add support for JSON-RPC named arguments _[W. J. van der Laan]_
  - bitcoin#10084 : Rename first named arg of createrawtransaction _[MarcoFalke]_

ACKs for top commit:
  furszy:
    cool feature, ACK 9ed1bdd
  Fuzzbawls:
    ACK 9ed1bdd

Tree-SHA512: 03001e5d1525e30af2126ebbabda275256df3dda170dbaf5732547af50dff90d655db78312666017840959704f6e0f268f99d91542e3a5f15484f1417a7bc904
  • Loading branch information
furszy committed Jun 2, 2021
2 parents c69d416 + 9ed1bdd commit 29650e0
Show file tree
Hide file tree
Showing 19 changed files with 712 additions and 534 deletions.
21 changes: 21 additions & 0 deletions doc/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,25 @@ Results without keys can be queried using an integer in brackets.
example: getblock(getblockhash(0),true)[tx][0]
```

Support for JSON-RPC Named Arguments
------------------------------------

Commands sent over the JSON-RPC interface and through the `pivx-cli` binary can now use named arguments. This follows the [JSON-RPC specification](http://www.jsonrpc.org/specification) for passing parameters by-name with an object.
`pivx-cli` has been updated to support this by parsing `name=value` arguments when the `-named` option is given.

Some examples:

```
src/pivx-cli -named help command="help"
src/pivx-cli -named getblockhash height=0
src/pivx-cli -named getblock blockhash=000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
src/pivx-cli -named sendtoaddress address="DMJRSsuU9zfyrvxVaAEFQqK4MxZg6vgeS6" amount="1.0" comment="donation"
```

The order of arguments doesn't matter in this case. Named arguments are also useful to leave out arguments that should stay at their default value.
The RPC server remains fully backwards compatible with positional arguments.


#### Allow to optional specify the directory for the blocks storage

A new init option flag '-blocksdir' will allow one to keep the blockfiles external from the data directory.
Expand All @@ -113,6 +132,8 @@ Low-level RPC changes
- `maximumCount` - a number specifying the minimum number of UTXOs
- `minimumSumAmount` - a number specifying the minimum sum value of all UTXOs

- the `stop` RPC no longer accepts the (already deprecated, ignored, and undocumented) optional boolean argument `detach`.


#### Show wallet's auto-combine settings in getwalletinfo

Expand Down
10 changes: 9 additions & 1 deletion src/pivx-cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <univalue.h>

static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
static const bool DEFAULT_NAMED=false;
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;

std::string HelpMessageCli()
Expand All @@ -35,6 +36,7 @@ std::string HelpMessageCli()
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), PIVX_CONF_FILENAME));
strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
AppendParamsHelpMessages(strUsage);
strUsage += HelpMessageOpt("-named", strprintf(_("Pass named instead of positional arguments (default: %s)"), DEFAULT_NAMED));
strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), DEFAULT_RPCCONNECT));
strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"), defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()));
strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
Expand Down Expand Up @@ -73,6 +75,7 @@ static bool AppInitRPC(int argc, char* argv[])
if (!gArgs.IsArgSet("-version")) {
strUsage += "\n" + _("Usage:") + "\n" +
" pivx-cli [options] <command> [params] " + _("Send command to PIVX Core") + "\n" +
" pivx-cli [options] -named <command> [name=value] ... " + _("Send command to PIVX Core (with named arguments)") + "\n" +
" pivx-cli [options] help " + _("List commands") + "\n" +
" pivx-cli [options] help <command> " + _("Get help for a command") + "\n";

Expand Down Expand Up @@ -236,7 +239,12 @@ int CommandLineRPC(int argc, char* argv[])

// Parameters default to strings
std::vector<std::string> strParams(&argv[2], &argv[argc]);
UniValue params = RPCConvertValues(strMethod, strParams);
UniValue params;
if(gArgs.GetBoolArg("-named", DEFAULT_NAMED)) {
params = RPCConvertNamedValues(strMethod, strParams);
} else {
params = RPCConvertValues(strMethod, strParams);
}

// Execute and handle connection failures with -rpcwait
const bool fWait = gArgs.GetBoolArg("-rpcwait", false);
Expand Down
96 changes: 48 additions & 48 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ UniValue getrawmempool(const JSONRPCRequest& request)
"\nReturns all transaction ids in memory pool as a json array of string transaction ids.\n"

"\nArguments:\n"
"1. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n"
"1. verbose (boolean, optional, default=false) True for a json object, false for array of transaction ids\n"

"\nResult: (for verbose = false):\n"
"[ (json array of string)\n"
Expand Down Expand Up @@ -490,11 +490,11 @@ UniValue getblockhash(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"getblockhash index\n"
"\nReturns hash of block in best-block-chain at index provided.\n"
"getblockhash height\n"
"\nReturns hash of block in best-block-chain at height provided.\n"

"\nArguments:\n"
"1. index (numeric, required) The block index\n"
"1. height (numeric, required) The height index\n"

"\nResult:\n"
"\"hash\" (string) The block hash\n"
Expand All @@ -516,13 +516,13 @@ UniValue getblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
"getblock \"hash\" ( verbose )\n"
"getblock \"blockhash\" ( verbose )\n"
"\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash'.\n"
"If verbose is true, returns an Object with information about block <hash>.\n"

"\nArguments:\n"
"1. \"hash\" (string, required) The block hash\n"
"2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
"1. \"blockhash\" (string, required) The block hash\n"
"2. verbose (boolean, optional, default=true) True for a json object, false for the hex encoded data\n"

"\nResult (for verbose = true):\n"
"{\n"
Expand Down Expand Up @@ -588,13 +588,13 @@ UniValue getblockheader(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
"getblockheader \"hash\" ( verbose )\n"
"getblockheader \"blockhash\" ( verbose )\n"
"\nIf verbose is false, returns a string that is serialized, hex-encoded data for block 'hash' header.\n"
"If verbose is true, returns an Object with information about block <hash> header.\n"

"\nArguments:\n"
"1. \"hash\" (string, required) The block hash\n"
"2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
"1. \"blockhash\" (string, required) The block hash\n"
"2. verbose (boolean, optional, default=true) True for a json object, false for the hex encoded data\n"

"\nResult (for verbose = true):\n"
"{\n"
Expand Down Expand Up @@ -646,16 +646,16 @@ UniValue getsupplyinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
"getsupplyinfo ( forceupdate )\n"
"\nIf forceupdate=false (default if no argument is given): return the last cached money supply"
"getsupplyinfo ( force_update )\n"
"\nIf force_update=false (default if no argument is given): return the last cached money supply"
"\n(sum of spendable transaction outputs) and the height of the chain when it was last updated"
"\n(it is updated periodically, whenever the chainstate is flushed)."
"\n"
"\nIf forceupdate=true: Flush the chainstate to disk and return the money supply updated to"
"\nIf force_update=true: Flush the chainstate to disk and return the money supply updated to"
"\nthe current chain height.\n"

"\nArguments:\n"
"1. forceupdate (boolean, optional, default=false) flush chainstate to disk and update cache\n"
"1. force_update (boolean, optional, default=false) flush chainstate to disk and update cache\n"

"\nResult:\n"
"{\n"
Expand Down Expand Up @@ -796,13 +796,13 @@ UniValue gettxout(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
throw std::runtime_error(
"gettxout \"txid\" n ( includemempool )\n"
"gettxout \"txid\" n ( include_mempool )\n"
"\nReturns details about an unspent transaction output.\n"

"\nArguments:\n"
"1. \"txid\" (string, required) The transaction id\n"
"2. n (numeric, required) vout value\n"
"3. includemempool (boolean, optional) Whether to included the mem pool\n"
"3. include_mempool (boolean, optional) Whether to included the mem pool\n"

"\nResult:\n"
"{\n"
Expand Down Expand Up @@ -876,11 +876,11 @@ UniValue verifychain(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 1)
throw std::runtime_error(
"verifychain ( numblocks )\n"
"verifychain ( nblocks )\n"
"\nVerifies blockchain database.\n"

"\nArguments:\n"
"1. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n"
"1. nblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n"

"\nResult:\n"
"true|false (boolean) Verified or not\n"
Expand Down Expand Up @@ -1189,11 +1189,11 @@ UniValue invalidateblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"invalidateblock \"hash\"\n"
"invalidateblock \"blockhash\"\n"
"\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"

"\nArguments:\n"
"1. hash (string, required) the hash of the block to mark as invalid\n"
"1. blockhash (string, required) the hash of the block to mark as invalid\n"

"\nExamples:\n" +
HelpExampleCli("invalidateblock", "\"blockhash\"") + HelpExampleRpc("invalidateblock", "\"blockhash\""));
Expand Down Expand Up @@ -1229,12 +1229,12 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"reconsiderblock \"hash\"\n"
"reconsiderblock \"blockhash\"\n"
"\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
"This can be used to undo the effects of invalidateblock.\n"

"\nArguments:\n"
"1. hash (string, required) the hash of the block to reconsider\n"
"1. blockhash (string, required) the hash of the block to reconsider\n"

"\nExamples:\n" +
HelpExampleCli("reconsiderblock", "\"blockhash\"") + HelpExampleRpc("reconsiderblock", "\"blockhash\""));
Expand Down Expand Up @@ -1300,7 +1300,7 @@ void validaterange(const UniValue& params, int& heightStart, int& heightEnd, int
}

UniValue getblockindexstats(const JSONRPCRequest& request) {
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
if (request.fHelp || request.params.size() != 2)
throw std::runtime_error(
"getblockindexstats height range\n"
"\nReturns aggregated BlockIndex data for blocks "
Expand Down Expand Up @@ -1441,33 +1441,33 @@ UniValue getfeeinfo(const JSONRPCRequest& request)
}

static const CRPCCommand commands[] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------
{ "blockchain", "getblockindexstats", &getblockindexstats, true },
{ "blockchain", "getblockchaininfo", &getblockchaininfo, true },
{ "blockchain", "getbestblockhash", &getbestblockhash, true },
{ "blockchain", "getbestsaplinganchor", &getbestsaplinganchor, true },
{ "blockchain", "getblockcount", &getblockcount, true },
{ "blockchain", "getblock", &getblock, true },
{ "blockchain", "getblockhash", &getblockhash, true },
{ "blockchain", "getblockheader", &getblockheader, false },
{ "blockchain", "getchaintips", &getchaintips, true },
{ "blockchain", "getdifficulty", &getdifficulty, true },
{ "blockchain", "getfeeinfo", &getfeeinfo, true },
{ "blockchain", "getmempoolinfo", &getmempoolinfo, true },
{ "blockchain", "getsupplyinfo", &getsupplyinfo, true },
{ "blockchain", "getrawmempool", &getrawmempool, true },
{ "blockchain", "gettxout", &gettxout, true },
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true },
{ "blockchain", "verifychain", &verifychain, true },
{ // category name actor (function) okSafe argNames
// --------------------- ------------------------ ----------------------- ------ --------
{ "blockchain", "getbestblockhash", &getbestblockhash, true, {} },
{ "blockchain", "getbestsaplinganchor", &getbestsaplinganchor, true, {} },
{ "blockchain", "getblock", &getblock, true, {"blockhash","verbose"} },
{ "blockchain", "getblockchaininfo", &getblockchaininfo, true, {} },
{ "blockchain", "getblockcount", &getblockcount, true, {} },
{ "blockchain", "getblockhash", &getblockhash, true, {"height"} },
{ "blockchain", "getblockheader", &getblockheader, false, {"blockhash","verbose"} },
{ "blockchain", "getblockindexstats", &getblockindexstats, true, {"height","range"} },
{ "blockchain", "getchaintips", &getchaintips, true, {} },
{ "blockchain", "getdifficulty", &getdifficulty, true, {} },
{ "blockchain", "getfeeinfo", &getfeeinfo, true, {"blocks"} },
{ "blockchain", "getmempoolinfo", &getmempoolinfo, true, {} },
{ "blockchain", "getrawmempool", &getrawmempool, true, {"verbose"} },
{ "blockchain", "getsupplyinfo", &getsupplyinfo, true, {"force_update"} },
{ "blockchain", "gettxout", &gettxout, true, {"txid","n","include_mempool"} },
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, {} },
{ "blockchain", "verifychain", &verifychain, true, {"nblocks"} },

/* Not shown in help */
{ "hidden", "invalidateblock", &invalidateblock, true },
{ "hidden", "reconsiderblock", &reconsiderblock, true },
{ "hidden", "waitfornewblock", &waitfornewblock, true },
{ "hidden", "waitforblock", &waitforblock, true },
{ "hidden", "waitforblockheight", &waitforblockheight, true },
{ "hidden", "syncwithvalidationinterfacequeue", &syncwithvalidationinterfacequeue, true },
{ "hidden", "invalidateblock", &invalidateblock, true, {"blockhash"} },
{ "hidden", "reconsiderblock", &reconsiderblock, true, {"blockhash"} },
{ "hidden", "waitforblock", &waitforblock, true, {"blockhash","timeout"} },
{ "hidden", "waitforblockheight", &waitforblockheight, true, {"height","timeout"} },
{ "hidden", "waitfornewblock", &waitfornewblock, true, {"timeout"} },
{ "hidden", "syncwithvalidationinterfacequeue", &syncwithvalidationinterfacequeue, true, {} },


};
Expand Down
Loading

0 comments on commit 29650e0

Please sign in to comment.