Allow createwallet to take empty passwords to make unencrypted wallets
Allow createwallet to take the empty string as a password and interpret that as leaving the wallet unencrypted. Also warn when that happens.
This commit is contained in:
parent
b21acab82f
commit
c5d3787367
3 changed files with 27 additions and 7 deletions
4
doc/release-notes-16394.md
Normal file
4
doc/release-notes-16394.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
RPC changes
|
||||||
|
-----------
|
||||||
|
`createwallet` now returns a warning if an empty string is used as an encryption password, and does not encrypt the wallet, instead of raising an error.
|
||||||
|
This makes it easier to disable encryption but also specify other options when using the `bitcoin-cli` tool.
|
|
@ -2676,11 +2676,12 @@ static UniValue createwallet(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
SecureString passphrase;
|
SecureString passphrase;
|
||||||
passphrase.reserve(100);
|
passphrase.reserve(100);
|
||||||
|
std::string warning;
|
||||||
if (!request.params[3].isNull()) {
|
if (!request.params[3].isNull()) {
|
||||||
passphrase = request.params[3].get_str().c_str();
|
passphrase = request.params[3].get_str().c_str();
|
||||||
if (passphrase.empty()) {
|
if (passphrase.empty()) {
|
||||||
// Empty string is invalid
|
// Empty string means unencrypted
|
||||||
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Cannot encrypt a wallet with a blank password");
|
warning = "Empty string given as passphrase, wallet will not be encrypted.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2689,9 +2690,9 @@ static UniValue createwallet(const JSONRPCRequest& request)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string error;
|
std::string error;
|
||||||
std::string warning;
|
std::string create_warning;
|
||||||
std::shared_ptr<CWallet> wallet;
|
std::shared_ptr<CWallet> wallet;
|
||||||
WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, warning, wallet);
|
WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, create_warning, wallet);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case WalletCreationStatus::CREATION_FAILED:
|
case WalletCreationStatus::CREATION_FAILED:
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, error);
|
throw JSONRPCError(RPC_WALLET_ERROR, error);
|
||||||
|
@ -2702,6 +2703,12 @@ static UniValue createwallet(const JSONRPCRequest& request)
|
||||||
// no default case, so the compiler can warn about missing cases
|
// no default case, so the compiler can warn about missing cases
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (warning.empty()) {
|
||||||
|
warning = create_warning;
|
||||||
|
} else if (!warning.empty() && !create_warning.empty()){
|
||||||
|
warning += "; " + create_warning;
|
||||||
|
}
|
||||||
|
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
obj.pushKV("name", wallet->GetName());
|
obj.pushKV("name", wallet->GetName());
|
||||||
obj.pushKV("warning", warning);
|
obj.pushKV("warning", warning);
|
||||||
|
|
|
@ -116,11 +116,20 @@ class CreateWalletTest(BitcoinTestFramework):
|
||||||
walletinfo = w6.getwalletinfo()
|
walletinfo = w6.getwalletinfo()
|
||||||
assert_equal(walletinfo['keypoolsize'], 1)
|
assert_equal(walletinfo['keypoolsize'], 1)
|
||||||
assert_equal(walletinfo['keypoolsize_hd_internal'], 1)
|
assert_equal(walletinfo['keypoolsize_hd_internal'], 1)
|
||||||
# Empty passphrase, error
|
# Allow empty passphrase, but there should be a warning
|
||||||
assert_raises_rpc_error(-16, 'Cannot encrypt a wallet with a blank password', self.nodes[0].createwallet, 'w7', False, False, '')
|
resp = self.nodes[0].createwallet(wallet_name='w7', disable_private_keys=False, blank=False, passphrase='')
|
||||||
|
assert_equal(resp['warning'], 'Empty string given as passphrase, wallet will not be encrypted.')
|
||||||
|
w7 = node.get_wallet_rpc('w7')
|
||||||
|
assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10)
|
||||||
|
|
||||||
|
self.log.info('Test making a wallet with avoid reuse flag')
|
||||||
|
self.nodes[0].createwallet('w8', False, False, '', True) # Use positional arguments to check for bug where avoid_reuse could not be set for wallets without needing them to be encrypted
|
||||||
|
w8 = node.get_wallet_rpc('w8')
|
||||||
|
assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10)
|
||||||
|
assert_equal(w8.getwalletinfo()["avoid_reuse"], True)
|
||||||
|
|
||||||
self.log.info('Using a passphrase with private keys disabled returns error')
|
self.log.info('Using a passphrase with private keys disabled returns error')
|
||||||
assert_raises_rpc_error(-4, 'Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.', self.nodes[0].createwallet, wallet_name='w8', disable_private_keys=True, passphrase='thisisapassphrase')
|
assert_raises_rpc_error(-4, 'Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.', self.nodes[0].createwallet, wallet_name='w9', disable_private_keys=True, passphrase='thisisapassphrase')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
CreateWalletTest().main()
|
CreateWalletTest().main()
|
||||||
|
|
Loading…
Reference in a new issue