Skip to content

Commit 5754e03

Browse files
committed
Merge #8811: rpc: Add support for JSON-RPC named arguments
4e7e2e1 Update RPC argument names (John Newbery) 481f289 rpc: Named argument support for bitcoin-cli (Wladimir J. van der Laan) 9adb4e1 rpc: Argument name consistency (Wladimir J. van der Laan) 8d713f7 rpc: Named arguments for rawtransaction calls (Wladimir J. van der Laan) 37a166f rpc: Named arguments for wallet calls (Wladimir J. van der Laan) 78b684f rpc: Named arguments for mining calls (Wladimir J. van der Laan) b8ebc59 rpc: Named arguments for net calls (Wladimir J. van der Laan) 2ca9dcd test: Add test for RPC named arguments (Wladimir J. van der Laan) fba1a61 rpc: Named arguments for misc calls (Wladimir J. van der Laan) 286ec08 rpc: Add 'echo' call for testing (Wladimir J. van der Laan) 495eb44 rpc: Named arguments for blockchain calls (Wladimir J. van der Laan) 6f1c76a rpc: Support named arguments (Wladimir J. van der Laan) 5865d41 authproxy: Add support for RPC named arguments (Wladimir J. van der Laan)
2 parents 68eb562 + 4e7e2e1 commit 5754e03

File tree

16 files changed

+540
-348
lines changed

16 files changed

+540
-348
lines changed

qa/pull-tester/rpc-tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@
151151
'signmessages.py',
152152
'nulldummy.py',
153153
'import-rescan.py',
154+
'rpcnamedargs.py',
154155
]
155156
if ENABLE_ZMQ:
156157
testScripts.append('zmq_test.py')

qa/rpc-tests/rpcnamedargs.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2016 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
from decimal import Decimal
7+
8+
from test_framework.test_framework import BitcoinTestFramework
9+
from test_framework.authproxy import JSONRPCException
10+
from test_framework.util import (
11+
assert_equal,
12+
assert_raises_jsonrpc,
13+
assert_is_hex_string,
14+
assert_is_hash_string,
15+
start_nodes,
16+
connect_nodes_bi,
17+
)
18+
19+
20+
class NamedArgumentTest(BitcoinTestFramework):
21+
"""
22+
Test named arguments on RPC calls.
23+
"""
24+
25+
def __init__(self):
26+
super().__init__()
27+
self.setup_clean_chain = False
28+
self.num_nodes = 1
29+
30+
def setup_network(self, split=False):
31+
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
32+
self.is_network_split = False
33+
self.sync_all()
34+
35+
def run_test(self):
36+
node = self.nodes[0]
37+
h = node.help(command='getinfo')
38+
assert(h.startswith('getinfo\n'))
39+
40+
assert_raises_jsonrpc(-8, node.help, random='getinfo')
41+
42+
h = node.getblockhash(height=0)
43+
node.getblock(blockhash=h)
44+
45+
assert_equal(node.echo(), [])
46+
assert_equal(node.echo(arg0=0,arg9=9), [0] + [None]*8 + [9])
47+
assert_equal(node.echo(arg1=1), [None, 1])
48+
assert_equal(node.echo(arg9=None), [None]*10)
49+
assert_equal(node.echo(arg0=0,arg3=3,arg9=9), [0] + [None]*2 + [3] + [None]*5 + [9])
50+
51+
if __name__ == '__main__':
52+
NamedArgumentTest().main()

qa/rpc-tests/test_framework/authproxy.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,16 @@ def _request(self, method, path, postdata):
138138
self.__conn.request(method, path, postdata, headers)
139139
return self._get_response()
140140

141-
def __call__(self, *args):
141+
def __call__(self, *args, **argsn):
142142
AuthServiceProxy.__id_count += 1
143143

144144
log.debug("-%s-> %s %s"%(AuthServiceProxy.__id_count, self._service_name,
145145
json.dumps(args, default=EncodeDecimal, ensure_ascii=self.ensure_ascii)))
146+
if args and argsn:
147+
raise ValueError('Cannot handle both named and positional arguments')
146148
postdata = json.dumps({'version': '1.1',
147149
'method': self._service_name,
148-
'params': args,
150+
'params': args or argsn,
149151
'id': AuthServiceProxy.__id_count}, default=EncodeDecimal, ensure_ascii=self.ensure_ascii)
150152
response = self._request('POST', self.__url.path, postdata.encode('utf-8'))
151153
if response['error'] is not None:

qa/rpc-tests/test_framework/util.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,18 @@ def assert_raises_message(exc, message, fun, *args, **kwds):
546546
else:
547547
raise AssertionError("No exception raised")
548548

549+
def assert_raises_jsonrpc(code, fun, *args, **kwds):
550+
'''Check for specific JSONRPC exception code'''
551+
try:
552+
fun(*args, **kwds)
553+
except JSONRPCException as e:
554+
if e.error["code"] != code:
555+
raise AssertionError("Unexpected JSONRPC error code %i" % e.error["code"])
556+
except Exception as e:
557+
raise AssertionError("Unexpected exception raised: "+type(e).__name__)
558+
else:
559+
raise AssertionError("No exception raised")
560+
549561
def assert_is_hex_string(string):
550562
try:
551563
int(string, 16)

src/bitcoin-cli.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
2727
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
28+
static const bool DEFAULT_NAMED=false;
2829
static const int CONTINUE_EXECUTION=-1;
2930

3031
std::string HelpMessageCli()
@@ -35,6 +36,7 @@ std::string HelpMessageCli()
3536
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME));
3637
strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
3738
AppendParamsHelpMessages(strUsage);
39+
strUsage += HelpMessageOpt("-named", strprintf(_("Pass named instead of positional arguments (default: %s)"), DEFAULT_NAMED));
3840
strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), DEFAULT_RPCCONNECT));
3941
strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), BaseParams(CBaseChainParams::MAIN).RPCPort(), BaseParams(CBaseChainParams::TESTNET).RPCPort()));
4042
strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
@@ -80,6 +82,7 @@ static int AppInitRPC(int argc, char* argv[])
8082
if (!IsArgSet("-version")) {
8183
strUsage += "\n" + _("Usage:") + "\n" +
8284
" bitcoin-cli [options] <command> [params] " + strprintf(_("Send command to %s"), _(PACKAGE_NAME)) + "\n" +
85+
" bitcoin-cli [options] -named <command> [name=value] ... " + strprintf(_("Send command to %s (with named arguments)"), _(PACKAGE_NAME)) + "\n" +
8386
" bitcoin-cli [options] help " + _("List commands") + "\n" +
8487
" bitcoin-cli [options] help <command> " + _("Get help for a command") + "\n";
8588

@@ -278,7 +281,14 @@ int CommandLineRPC(int argc, char *argv[])
278281
if (args.size() < 1)
279282
throw std::runtime_error("too few parameters (need at least command)");
280283
std::string strMethod = args[0];
281-
UniValue params = RPCConvertValues(strMethod, std::vector<std::string>(args.begin()+1, args.end()));
284+
args.erase(args.begin()); // Remove trailing method name from arguments vector
285+
286+
UniValue params;
287+
if(GetBoolArg("-named", DEFAULT_NAMED)) {
288+
params = RPCConvertNamedValues(strMethod, args);
289+
} else {
290+
params = RPCConvertValues(strMethod, args);
291+
}
282292

283293
// Execute and handle connection failures with -rpcwait
284294
const bool fWait = GetBoolArg("-rpcwait", false);

0 commit comments

Comments
 (0)