Browse Source

Merge #11647: 0.15: Backports

7af2457 contrib/init: Update openrc-run filename (Luke Dashjr)
3f1db56 Wrap dumpwallet warning and note scripts aren't dumped (MeshCollider)
42ea47d Add wallet backup text to import*, add* and dumpwallet RPCs (MeshCollider)
3a6cdd4 Add test for multiwallet batch RPC calls (Russell Yanofsky)
1c8c7f8 Add missing batch rpc calls to python coverage logs (Russell Yanofsky)
1036c43 Add missing multiwallet rpc calls to python coverage logs (Russell Yanofsky)
2eea279 Make AuthServiceProxy._batch method usable (Russell Yanofsky)
305f768 Limit AuthServiceProxyWrapper.__getattr__ wrapping (Russell Yanofsky)
7026845 Fix uninitialized URI in batch RPC requests (Russell Yanofsky)
6372a75 [Wallet] always show help-line of wallet encryption calls (Jonas Schnelli)

Pull request description:

  This fixes some multiwallet issues on the 0.15 branch...

Tree-SHA512: 304a6c6acbce22c8b7338d1e618451978ab2cd04938c71a3daf40fe9996ef14e324645d642fbc21950a5481fb993254082d54da1cb953a739ebaeaab34c080d4
tags/v0.15.1
Wladimir J. van der Laan 2 years ago
parent
commit
2559a19e6f
No account linked to committer's email address

+ 1
- 1
contrib/init/bitcoind.openrc View File

@@ -1,4 +1,4 @@
#!/sbin/runscript
#!/sbin/openrc-run

# backward compatibility for existing gentoo layout
#

+ 1
- 1
src/httprpc.cpp View File

@@ -192,7 +192,7 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &)

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


+ 3
- 4
src/rpc/server.cpp View File

@@ -387,11 +387,10 @@ void JSONRPCRequest::parse(const UniValue& valRequest)
throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object");
}

static UniValue JSONRPCExecOne(const UniValue& req)
static UniValue JSONRPCExecOne(JSONRPCRequest jreq, const UniValue& req)
{
UniValue rpc_result(UniValue::VOBJ);

JSONRPCRequest jreq;
try {
jreq.parse(req);

@@ -411,11 +410,11 @@ static UniValue JSONRPCExecOne(const UniValue& req)
return rpc_result;
}

std::string JSONRPCExecBatch(const UniValue& vReq)
std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq)
{
UniValue ret(UniValue::VARR);
for (unsigned int reqIdx = 0; reqIdx < vReq.size(); reqIdx++)
ret.push_back(JSONRPCExecOne(vReq[reqIdx]));
ret.push_back(JSONRPCExecOne(jreq, vReq[reqIdx]));

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

+ 1
- 1
src/rpc/server.h View File

@@ -191,7 +191,7 @@ extern std::string HelpExampleRpc(const std::string& methodname, const std::stri
bool StartRPC();
void InterruptRPC();
void StopRPC();
std::string JSONRPCExecBatch(const UniValue& vReq);
std::string JSONRPCExecBatch(const JSONRPCRequest& jreq, const UniValue& vReq);

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

+ 8
- 5
src/wallet/rpcdump.cpp View File

@@ -80,7 +80,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
"importprivkey \"privkey\" ( \"label\" ) ( rescan )\n"
"\nAdds a private key (as returned by dumpprivkey) to your wallet.\n"
"\nAdds a private key (as returned by dumpprivkey) to your wallet. Requires a new wallet backup.\n"
"\nArguments:\n"
"1. \"privkey\" (string, required) The private key (see dumpprivkey)\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n"
@@ -224,7 +224,7 @@ UniValue importaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw std::runtime_error(
"importaddress \"address\" ( \"label\" rescan p2sh )\n"
"\nAdds a script (in hex) or address that can be watched as if it were in your wallet but cannot be used to spend.\n"
"\nAdds a script (in hex) or address that can be watched as if it were in your wallet but cannot be used to spend. Requires a new wallet backup.\n"
"\nArguments:\n"
"1. \"script\" (string, required) The hex-encoded script (or address)\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n"
@@ -393,7 +393,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4)
throw std::runtime_error(
"importpubkey \"pubkey\" ( \"label\" rescan )\n"
"\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend.\n"
"\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"
"\nArguments:\n"
"1. \"pubkey\" (string, required) The hex-encoded public key\n"
"2. \"label\" (string, optional, default=\"\") An optional label\n"
@@ -453,7 +453,7 @@ UniValue importwallet(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() != 1)
throw std::runtime_error(
"importwallet \"filename\"\n"
"\nImports keys from a wallet dump file (see dumpwallet).\n"
"\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n"
"\nArguments:\n"
"1. \"filename\" (string, required) The wallet file\n"
"\nExamples:\n"
@@ -596,6 +596,9 @@ UniValue dumpwallet(const JSONRPCRequest& request)
throw std::runtime_error(
"dumpwallet \"filename\"\n"
"\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 not currently included in wallet dumps, these must be backed up separately.\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"
"\nArguments:\n"
"1. \"filename\" (string, required) The filename with path (either absolute or relative to bitcoind)\n"
"\nResult:\n"
@@ -1038,7 +1041,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2)
throw std::runtime_error(
"importmulti \"requests\" ( \"options\" )\n\n"
"Import addresses/scripts (with private or public keys, redeem script (P2SH)), rescanning all addresses in one-shot-only (rescan can be disabled via options).\n\n"
"Import addresses/scripts (with private or public keys, redeem script (P2SH)), rescanning all addresses in one-shot-only (rescan can be disabled via options). Requires a new wallet backup.\n\n"
"Arguments:\n"
"1. requests (array, required) Data to be imported\n"
" [ (array of json objects)\n"

+ 6
- 6
src/wallet/rpcwallet.cpp View File

@@ -1077,7 +1077,7 @@ UniValue addmultisigaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
{
std::string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
"\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
"\nAdd a nrequired-to-sign multisignature address to the wallet. Requires a new wallet backup.\n"
"Each key is a Bitcoin address or hex-encoded public key.\n"
"If 'account' is specified (DEPRECATED), assign address to that account.\n"

@@ -1182,7 +1182,7 @@ UniValue addwitnessaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
{
std::string msg = "addwitnessaddress \"address\"\n"
"\nAdd a witness address for a script (with pubkey or redeemscript known).\n"
"\nAdd a witness address for a script (with pubkey or redeemscript known). Requires a new wallet backup.\n"
"It returns the witness script.\n"

"\nArguments:\n"
@@ -2106,7 +2106,7 @@ UniValue walletpassphrase(const JSONRPCRequest& request)
return NullUniValue;
}

if (pwallet->IsCrypted() && (request.fHelp || request.params.size() != 2)) {
if (request.fHelp || request.params.size() != 2) {
throw std::runtime_error(
"walletpassphrase \"passphrase\" timeout\n"
"\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
@@ -2170,7 +2170,7 @@ UniValue walletpassphrasechange(const JSONRPCRequest& request)
return NullUniValue;
}

if (pwallet->IsCrypted() && (request.fHelp || request.params.size() != 2)) {
if (request.fHelp || request.params.size() != 2) {
throw std::runtime_error(
"walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
"\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
@@ -2221,7 +2221,7 @@ UniValue walletlock(const JSONRPCRequest& request)
return NullUniValue;
}

if (pwallet->IsCrypted() && (request.fHelp || request.params.size() != 0)) {
if (request.fHelp || request.params.size() != 0) {
throw std::runtime_error(
"walletlock\n"
"\nRemoves the wallet encryption key from memory, locking the wallet.\n"
@@ -2261,7 +2261,7 @@ UniValue encryptwallet(const JSONRPCRequest& request)
return NullUniValue;
}

if (!pwallet->IsCrypted() && (request.fHelp || request.params.size() != 1)) {
if (request.fHelp || request.params.size() != 1) {
throw std::runtime_error(
"encryptwallet \"passphrase\"\n"
"\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"

+ 4
- 0
test/functional/multiwallet.py View File

@@ -82,5 +82,9 @@ class MultiWalletTest(BitcoinTestFramework):
assert_equal(w2.getbalance(), 1)
assert_equal(w3.getbalance(), 2)

batch = w1.batch([w1.getblockchaininfo.get_request(), w1.getwalletinfo.get_request()])
assert_equal(batch[0]["result"]["chain"], "regtest")
assert_equal(batch[1]["result"]["walletname"], "w1")

if __name__ == '__main__':
MultiWalletTest().main()

+ 9
- 6
test/functional/test_framework/authproxy.py View File

@@ -138,17 +138,20 @@ class AuthServiceProxy(object):
self.__conn.request(method, path, postdata, headers)
return self._get_response()

def __call__(self, *args, **argsn):
def get_request(self, *args, **argsn):
AuthServiceProxy.__id_count += 1

log.debug("-%s-> %s %s"%(AuthServiceProxy.__id_count, self._service_name,
json.dumps(args, default=EncodeDecimal, ensure_ascii=self.ensure_ascii)))
if args and argsn:
raise ValueError('Cannot handle both named and positional arguments')
postdata = json.dumps({'version': '1.1',
'method': self._service_name,
'params': args or argsn,
'id': AuthServiceProxy.__id_count}, default=EncodeDecimal, ensure_ascii=self.ensure_ascii)
return {'version': '1.1',
'method': self._service_name,
'params': args or argsn,
'id': AuthServiceProxy.__id_count}

def __call__(self, *args, **argsn):
postdata = json.dumps(self.get_request(*args, **argsn), default=EncodeDecimal, ensure_ascii=self.ensure_ascii)
response = self._request('POST', self.__url.path, postdata.encode('utf-8'))
if response['error'] is not None:
raise JSONRPCException(response['error'])
@@ -158,7 +161,7 @@ class AuthServiceProxy(object):
else:
return response['result']

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

+ 15
- 11
test/functional/test_framework/coverage.py View File

@@ -31,10 +31,11 @@ class AuthServiceProxyWrapper(object):
self.auth_service_proxy_instance = auth_service_proxy_instance
self.coverage_logfile = coverage_logfile

def __getattr__(self, *args, **kwargs):
return_val = self.auth_service_proxy_instance.__getattr__(
*args, **kwargs)

def __getattr__(self, name):
return_val = getattr(self.auth_service_proxy_instance, name)
if not isinstance(return_val, type(self.auth_service_proxy_instance)):
# If proxy getattr returned an unwrapped value, do the same here.
return return_val
return AuthServiceProxyWrapper(return_val, self.coverage_logfile)

def __call__(self, *args, **kwargs):
@@ -44,20 +45,23 @@ class AuthServiceProxyWrapper(object):

"""
return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
self._log_call()
return return_val

def _log_call(self):
rpc_method = self.auth_service_proxy_instance._service_name

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

return return_val

@property
def url(self):
return self.auth_service_proxy_instance.url

def __truediv__(self, relative_uri):
return AuthServiceProxyWrapper(self.auth_service_proxy_instance / relative_uri)
return AuthServiceProxyWrapper(self.auth_service_proxy_instance / relative_uri,
self.coverage_logfile)

def get_request(self, *args, **kwargs):
self._log_call()
return self.auth_service_proxy_instance.get_request(*args, **kwargs)

def get_filename(dirname, n_node):
"""

Loading…
Cancel
Save