Skip to content

Commit c5d3787

Browse files
committed
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.
1 parent b21acab commit c5d3787

File tree

3 files changed

+27
-7
lines changed

3 files changed

+27
-7
lines changed

doc/release-notes-16394.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
RPC changes
2+
-----------
3+
`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.
4+
This makes it easier to disable encryption but also specify other options when using the `bitcoin-cli` tool.

src/wallet/rpcwallet.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2676,11 +2676,12 @@ static UniValue createwallet(const JSONRPCRequest& request)
26762676
}
26772677
SecureString passphrase;
26782678
passphrase.reserve(100);
2679+
std::string warning;
26792680
if (!request.params[3].isNull()) {
26802681
passphrase = request.params[3].get_str().c_str();
26812682
if (passphrase.empty()) {
2682-
// Empty string is invalid
2683-
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Cannot encrypt a wallet with a blank password");
2683+
// Empty string means unencrypted
2684+
warning = "Empty string given as passphrase, wallet will not be encrypted.";
26842685
}
26852686
}
26862687

@@ -2689,9 +2690,9 @@ static UniValue createwallet(const JSONRPCRequest& request)
26892690
}
26902691

26912692
std::string error;
2692-
std::string warning;
2693+
std::string create_warning;
26932694
std::shared_ptr<CWallet> wallet;
2694-
WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, warning, wallet);
2695+
WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, create_warning, wallet);
26952696
switch (status) {
26962697
case WalletCreationStatus::CREATION_FAILED:
26972698
throw JSONRPCError(RPC_WALLET_ERROR, error);
@@ -2702,6 +2703,12 @@ static UniValue createwallet(const JSONRPCRequest& request)
27022703
// no default case, so the compiler can warn about missing cases
27032704
}
27042705

2706+
if (warning.empty()) {
2707+
warning = create_warning;
2708+
} else if (!warning.empty() && !create_warning.empty()){
2709+
warning += "; " + create_warning;
2710+
}
2711+
27052712
UniValue obj(UniValue::VOBJ);
27062713
obj.pushKV("name", wallet->GetName());
27072714
obj.pushKV("warning", warning);

test/functional/wallet_createwallet.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,20 @@ def run_test(self):
116116
walletinfo = w6.getwalletinfo()
117117
assert_equal(walletinfo['keypoolsize'], 1)
118118
assert_equal(walletinfo['keypoolsize_hd_internal'], 1)
119-
# Empty passphrase, error
120-
assert_raises_rpc_error(-16, 'Cannot encrypt a wallet with a blank password', self.nodes[0].createwallet, 'w7', False, False, '')
119+
# Allow empty passphrase, but there should be a warning
120+
resp = self.nodes[0].createwallet(wallet_name='w7', disable_private_keys=False, blank=False, passphrase='')
121+
assert_equal(resp['warning'], 'Empty string given as passphrase, wallet will not be encrypted.')
122+
w7 = node.get_wallet_rpc('w7')
123+
assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10)
124+
125+
self.log.info('Test making a wallet with avoid reuse flag')
126+
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
127+
w8 = node.get_wallet_rpc('w8')
128+
assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10)
129+
assert_equal(w8.getwalletinfo()["avoid_reuse"], True)
121130

122131
self.log.info('Using a passphrase with private keys disabled returns error')
123-
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')
132+
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')
124133

125134
if __name__ == '__main__':
126135
CreateWalletTest().main()

0 commit comments

Comments
 (0)