diff options
-rw-r--r-- | doc/bitcoin-conf.md | 15 | ||||
-rw-r--r-- | doc/release-notes-16394.md | 4 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 15 | ||||
-rw-r--r-- | src/wallet/wallet.h | 22 | ||||
-rw-r--r-- | src/wallet/walletdb.cpp | 18 | ||||
-rwxr-xr-x | test/functional/wallet_createwallet.py | 15 |
6 files changed, 49 insertions, 40 deletions
diff --git a/doc/bitcoin-conf.md b/doc/bitcoin-conf.md index 88ecb8fe65..f8146b5d75 100644 --- a/doc/bitcoin-conf.md +++ b/doc/bitcoin-conf.md @@ -30,6 +30,21 @@ Network specific options can be: - placed into sections with headers `[main]` (not `[mainnet]`), `[test]` (not `[testnet]`) or `[regtest]`; - prefixed with a chain name; e.g., `regtest.maxmempool=100`. +Network specific options take precedence over non-network specific options. +If multiple values for the same option are found with the same precedence, the +first one is generally chosen. + +This means that given the following configuration, `regtest.rpcport` is set to `3000`: + +``` +regtest=1 +rpcport=2000 +regtest.rpcport=3000 + +[regtest] +rpcport=4000 +``` + ## Configuration File Path The configuration file is not automatically created; you can create it using your favorite text editor. By default, the configuration file name is `bitcoin.conf` and it is located in the Bitcoin data directory, but both the Bitcoin data directory and the configuration file path may be changed using the `-datadir` and `-conf` command-line options. diff --git a/doc/release-notes-16394.md b/doc/release-notes-16394.md new file mode 100644 index 0000000000..f09cba4b6d --- /dev/null +++ b/doc/release-notes-16394.md @@ -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. diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index bf72ef6b16..a86e93481c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2676,11 +2676,12 @@ static UniValue createwallet(const JSONRPCRequest& request) } SecureString passphrase; passphrase.reserve(100); + std::string warning; if (!request.params[3].isNull()) { passphrase = request.params[3].get_str().c_str(); if (passphrase.empty()) { - // Empty string is invalid - throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Cannot encrypt a wallet with a blank password"); + // Empty string means unencrypted + 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 warning; + std::string create_warning; 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) { case WalletCreationStatus::CREATION_FAILED: 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 } + if (warning.empty()) { + warning = create_warning; + } else if (!warning.empty() && !create_warning.empty()){ + warning += "; " + create_warning; + } + UniValue obj(UniValue::VOBJ); obj.pushKV("name", wallet->GetName()); obj.pushKV("warning", warning); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 86c2cf851c..8b0ae8bb85 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -663,28 +663,6 @@ public: } }; -/** Private key that was serialized by an old wallet (only used for deserialization) */ -struct OldKey { - CPrivKey vchPrivKey; - ADD_SERIALIZE_METHODS; - - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action) { - // no longer used by the wallet, thus dropped after deserialization: - int64_t nTimeCreated; - int64_t nTimeExpires; - std::string strComment; - - int nVersion = s.GetVersion(); - if (!(s.GetType() & SER_GETHASH)) - READWRITE(nVersion); - READWRITE(vchPrivKey); - READWRITE(nTimeCreated); - READWRITE(nTimeExpires); - READWRITE(LIMITED_STRING(strComment, 65536)); - } -}; - struct CoinSelectionParams { bool use_bnb = true; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 9f467c0f5a..635997afc9 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -115,7 +115,6 @@ bool WalletBatch::WriteCryptedKey(const CPubKey& vchPubKey, return false; } EraseIC(std::make_pair(DBKeys::KEY, vchPubKey)); - EraseIC(std::make_pair(DBKeys::OLD_KEY, vchPubKey)); return true; } @@ -256,7 +255,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssValue >> fYes; if (fYes == '1') pwallet->LoadWatchOnly(script); - } else if (strType == DBKeys::KEY || strType == DBKeys::OLD_KEY) { + } else if (strType == DBKeys::KEY) { CPubKey vchPubKey; ssKey >> vchPubKey; if (!vchPubKey.IsValid()) @@ -268,14 +267,8 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, CPrivKey pkey; uint256 hash; - if (strType == DBKeys::KEY) { - wss.nKeys++; - ssValue >> pkey; - } else { - OldKey wkey; - ssValue >> wkey; - pkey = wkey.vchPrivKey; - } + wss.nKeys++; + ssValue >> pkey; // Old wallets store keys as DBKeys::KEY [pubkey] => [privkey] // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key @@ -407,6 +400,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, strErr = "Error reading wallet database: Unknown non-tolerable wallet flags found"; return false; } + } else if (strType == DBKeys::OLD_KEY) { + strErr = "Found unsupported 'wkey' record, try loading with version 0.18"; + return false; } else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE && strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY && strType != DBKeys::VERSION && strType != DBKeys::SETTINGS) { @@ -428,7 +424,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, bool WalletBatch::IsKeyType(const std::string& strType) { - return (strType == DBKeys::KEY || strType == DBKeys::OLD_KEY || + return (strType == DBKeys::KEY || strType == DBKeys::MASTER_KEY || strType == DBKeys::CRYPTED_KEY); } diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py index 294f90a0fa..e302e499f4 100755 --- a/test/functional/wallet_createwallet.py +++ b/test/functional/wallet_createwallet.py @@ -116,11 +116,20 @@ class CreateWalletTest(BitcoinTestFramework): walletinfo = w6.getwalletinfo() assert_equal(walletinfo['keypoolsize'], 1) assert_equal(walletinfo['keypoolsize_hd_internal'], 1) - # Empty passphrase, error - assert_raises_rpc_error(-16, 'Cannot encrypt a wallet with a blank password', self.nodes[0].createwallet, 'w7', False, False, '') + # Allow empty passphrase, but there should be a warning + 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') - 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__': CreateWalletTest().main() |