Skip to content

Commit f74459d

Browse files
committed
Merge #11277: Fix uninitialized URI in batch RPC requests
4526d21 Add test for multiwallet batch RPC calls (Russell Yanofsky) 74182f2 Add missing batch rpc calls to python coverage logs (Russell Yanofsky) 505530c Add missing multiwallet rpc calls to python coverage logs (Russell Yanofsky) 9f67646 Make AuthServiceProxy._batch method usable (Russell Yanofsky) e02007a Limit AuthServiceProxyWrapper.__getattr__ wrapping (Russell Yanofsky) edafc71 Fix uninitialized URI in batch RPC requests (Russell Yanofsky) Pull request description: This fixes "Wallet file not specified" errors when making batch wallet RPC calls with more than one wallet loaded. This issue was reported by @NicolasDorier in bitcoin/bitcoin#11257 Request URI is not used for anything except multiwallet request dispatching, so this change has no other effect. Tree-SHA512: b3907af48a6323f864bb045ee2fa56b604188b835025ef82ba3d81673244c04228d796323cec208a676e7cd578a95ec7c7ba1e84d0158b93844d5dda8f6589b9
2 parents 3bb77eb + 4526d21 commit f74459d

File tree

6 files changed

+33
-23
lines changed

6 files changed

+33
-23
lines changed

src/httprpc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &)
192192

193193
// array of requests
194194
} else if (valRequest.isArray())
195-
strReply = JSONRPCExecBatch(valRequest.get_array());
195+
strReply = JSONRPCExecBatch(jreq, valRequest.get_array());
196196
else
197197
throw JSONRPCError(RPC_PARSE_ERROR, "Top-level object parse error");
198198

src/rpc/server.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -389,11 +389,10 @@ bool IsDeprecatedRPCEnabled(const std::string& method)
389389
return find(enabled_methods.begin(), enabled_methods.end(), method) != enabled_methods.end();
390390
}
391391

392-
static UniValue JSONRPCExecOne(const UniValue& req)
392+
static UniValue JSONRPCExecOne(JSONRPCRequest jreq, const UniValue& req)
393393
{
394394
UniValue rpc_result(UniValue::VOBJ);
395395

396-
JSONRPCRequest jreq;
397396
try {
398397
jreq.parse(req);
399398

@@ -413,11 +412,11 @@ static UniValue JSONRPCExecOne(const UniValue& req)
413412
return rpc_result;
414413
}
415414

416-
std::string JSONRPCExecBatch(const UniValue& vReq)
415+
std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq)
417416
{
418417
UniValue ret(UniValue::VARR);
419418
for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++)
420-
ret.push_back(JSONRPCExecOne(vReq[reqIdx]));
419+
ret.push_back(JSONRPCExecOne(jreq, vReq[reqIdx]));
421420

422421
return ret.write() + "\n";
423422
}

src/rpc/server.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ extern std::string HelpExampleRpc(const std::string& methodname, const std::stri
191191
bool StartRPC();
192192
void InterruptRPC();
193193
void StopRPC();
194-
std::string JSONRPCExecBatch(const UniValue& vReq);
194+
std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq);
195195

196196
// Retrieves any serialization flags requested in command line argument
197197
int RPCSerializationFlags();

test/functional/multiwallet.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,9 @@ def run_test(self):
7676
assert_equal(w2.getbalance(), 1)
7777
assert_equal(w3.getbalance(), 2)
7878

79+
batch = w1.batch([w1.getblockchaininfo.get_request(), w1.getwalletinfo.get_request()])
80+
assert_equal(batch[0]["result"]["chain"], "regtest")
81+
assert_equal(batch[1]["result"]["walletname"], "w1")
82+
7983
if __name__ == '__main__':
8084
MultiWalletTest().main()

test/functional/test_framework/authproxy.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,17 +138,20 @@ 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, **argsn):
141+
def get_request(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)))
146146
if args and argsn:
147147
raise ValueError('Cannot handle both named and positional arguments')
148-
postdata = json.dumps({'version': '1.1',
149-
'method': self._service_name,
150-
'params': args or argsn,
151-
'id': AuthServiceProxy.__id_count}, default=EncodeDecimal, ensure_ascii=self.ensure_ascii)
148+
return {'version': '1.1',
149+
'method': self._service_name,
150+
'params': args or argsn,
151+
'id': AuthServiceProxy.__id_count}
152+
153+
def __call__(self, *args, **argsn):
154+
postdata = json.dumps(self.get_request(*args, **argsn), default=EncodeDecimal, ensure_ascii=self.ensure_ascii)
152155
response = self._request('POST', self.__url.path, postdata.encode('utf-8'))
153156
if response['error'] is not None:
154157
raise JSONRPCException(response['error'])
@@ -158,7 +161,7 @@ def __call__(self, *args, **argsn):
158161
else:
159162
return response['result']
160163

161-
def _batch(self, rpc_call_list):
164+
def batch(self, rpc_call_list):
162165
postdata = json.dumps(list(rpc_call_list), default=EncodeDecimal, ensure_ascii=self.ensure_ascii)
163166
log.debug("--> "+postdata)
164167
return self._request('POST', self.__url.path, postdata.encode('utf-8'))

test/functional/test_framework/coverage.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ def __init__(self, auth_service_proxy_instance, coverage_logfile=None):
3131
self.auth_service_proxy_instance = auth_service_proxy_instance
3232
self.coverage_logfile = coverage_logfile
3333

34-
def __getattr__(self, *args, **kwargs):
35-
return_val = self.auth_service_proxy_instance.__getattr__(
36-
*args, **kwargs)
37-
34+
def __getattr__(self, name):
35+
return_val = getattr(self.auth_service_proxy_instance, name)
36+
if not isinstance(return_val, type(self.auth_service_proxy_instance)):
37+
# If proxy getattr returned an unwrapped value, do the same here.
38+
return return_val
3839
return AuthServiceProxyWrapper(return_val, self.coverage_logfile)
3940

4041
def __call__(self, *args, **kwargs):
@@ -44,20 +45,23 @@ def __call__(self, *args, **kwargs):
4445
4546
"""
4647
return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
48+
self._log_call()
49+
return return_val
50+
51+
def _log_call(self):
4752
rpc_method = self.auth_service_proxy_instance._service_name
4853

4954
if self.coverage_logfile:
5055
with open(self.coverage_logfile, 'a+', encoding='utf8') as f:
5156
f.write("%s\n" % rpc_method)
5257

53-
return return_val
54-
55-
@property
56-
def url(self):
57-
return self.auth_service_proxy_instance.url
58-
5958
def __truediv__(self, relative_uri):
60-
return AuthServiceProxyWrapper(self.auth_service_proxy_instance / relative_uri)
59+
return AuthServiceProxyWrapper(self.auth_service_proxy_instance / relative_uri,
60+
self.coverage_logfile)
61+
62+
def get_request(self, *args, **kwargs):
63+
self._log_call()
64+
return self.auth_service_proxy_instance.get_request(*args, **kwargs)
6165

6266
def get_filename(dirname, n_node):
6367
"""

0 commit comments

Comments
 (0)