diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -123,24 +123,21 @@
QMessageBox::warning(
this, tr("Wallet encrypted"),
"" +
- tr("%1 will close now to finish the encryption "
- "process. "
+ tr("Your wallet is now encrypted. "
"Remember that encrypting your wallet "
- "cannot fully protect "
- "your bitcoins from being stolen by malware "
- "infecting your computer.")
- .arg(tr(PACKAGE_NAME)) +
+ "cannot fully protect your bitcoins from "
+ "being stolen by malware infecting your "
+ "computer.") +
"
" +
tr("IMPORTANT: Any previous backups you have "
- "made of your wallet file "
- "should be replaced with the newly "
- "generated, encrypted wallet file. "
+ "made of your wallet file should be "
+ "replaced with the newly generated, "
+ "encrypted wallet file. "
"For security reasons, previous backups of "
- "the unencrypted wallet file "
- "will become useless as soon as you start "
- "using the new, encrypted wallet.") +
+ "the unencrypted wallet file will become "
+ "useless as soon as you start using the "
+ "new, encrypted wallet.") +
"");
- QApplication::quit();
} else {
QMessageBox::critical(
this, tr("Wallet encryption failed"),
diff --git a/src/wallet/db.h b/src/wallet/db.h
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -38,6 +38,7 @@
std::unique_ptr dbenv;
std::map mapFileUseCount;
std::map mapDb;
+ std::condition_variable_any m_db_in_use;
BerkeleyEnvironment(const fs::path &env_directory);
~BerkeleyEnvironment();
@@ -79,6 +80,7 @@
void CheckpointLSN(const std::string &strFile);
void CloseDb(const std::string &strFile);
+ void ReloadDbEnv();
DbTxn *TxnBegin(int flags = DB_TXN_WRITE_NOSYNC) {
DbTxn *ptxn = nullptr;
@@ -155,6 +157,8 @@
void IncrementUpdateCounter();
+ void ReloadDbEnv();
+
std::atomic nUpdateCounter;
unsigned int nLastSeen;
unsigned int nLastFlushed;
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -608,8 +608,11 @@
Flush();
}
- LOCK(cs_db);
- --env->mapFileUseCount[strFile];
+ {
+ LOCK(cs_db);
+ --env->mapFileUseCount[strFile];
+ }
+ env->m_db_in_use.notify_all();
}
void BerkeleyEnvironment::CloseDb(const std::string &strFile) {
@@ -623,6 +626,34 @@
}
}
+void BerkeleyEnvironment::ReloadDbEnv() {
+ // Make sure that no Db's are in use
+ AssertLockNotHeld(cs_db);
+ std::unique_lock lock(cs_db);
+ m_db_in_use.wait(lock, [this]() {
+ for (auto &count : mapFileUseCount) {
+ if (count.second > 0) {
+ return false;
+ }
+ }
+ return true;
+ });
+
+ std::vector filenames;
+ for (auto it : mapDb) {
+ filenames.push_back(it.first);
+ }
+ // Close the individual Db's
+ for (const std::string &filename : filenames) {
+ CloseDb(filename);
+ }
+ // Reset the environment
+ // This will flush and close the environment
+ Flush(true);
+ Reset();
+ Open(true);
+}
+
bool BerkeleyBatch::Rewrite(BerkeleyDatabase &database, const char *pszSkip) {
if (database.IsDummy()) {
return true;
@@ -779,7 +810,6 @@
if (!fMockDb) {
fs::remove_all(fs::path(strPath) / "database");
}
- g_dbenvs.erase(strPath);
}
}
}
@@ -876,7 +906,15 @@
if (!IsDummy()) {
env->Flush(shutdown);
if (shutdown) {
+ LOCK(cs_db);
+ g_dbenvs.erase(env->Directory().string());
env = nullptr;
}
}
}
+
+void BerkeleyDatabase::ReloadDbEnv() {
+ if (!IsDummy()) {
+ env->ReloadDbEnv();
+ }
+}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -3262,7 +3262,6 @@
"call.\n"
"If the wallet is already encrypted, use the "
"walletpassphrasechange call.\n"
- "Note that this will shutdown the server.\n"
"\nArguments:\n"
"1. \"passphrase\" (string) The pass phrase to encrypt the "
"wallet with. It must be at least 1 character, but should be "
@@ -3309,12 +3308,7 @@
"Error: Failed to encrypt the wallet.");
}
- // BDB seems to have a bad habit of writing old data into
- // slack space in .dat files; that is bad if the old data is
- // unencrypted private keys. So:
- StartShutdown();
- return "wallet encrypted; Bitcoin server stopping, restart to run with "
- "encrypted wallet. The keypool has been flushed and a new HD seed "
+ return "wallet encrypted; The keypool has been flushed and a new HD seed "
"was generated (if you are using HD). You need to make a new "
"backup.";
}
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -800,6 +800,11 @@
// keep bits of the unencrypted private key in slack space in the
// database file.
database->Rewrite();
+
+ // BDB seems to have a bad habit of writing old data into
+ // slack space in .dat files; that is bad if the old data is
+ // unencrypted private keys. So:
+ database->ReloadDbEnv();
}
NotifyStatusChanged(this);
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -483,10 +483,8 @@
#
# locked wallet test
- self.stop_node(0)
- self.nodes[1].node_encrypt_wallet("test")
- self.stop_node(2)
- self.stop_node(3)
+ self.nodes[1].encryptwallet("test")
+ self.stop_nodes()
self.start_nodes()
# This test is not meant to test fee estimation and we'd like
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -350,14 +350,6 @@
assert_msg = "bitcoind should have exited with expected error " + expected_msg
self._raise_assertion_error(assert_msg)
- def node_encrypt_wallet(self, passphrase):
- """"Encrypts the wallet.
-
- This causes bitcoind to shutdown, so this method takes
- care of cleaning up resources."""
- self.encryptwallet(passphrase)
- self.wait_until_stopped()
-
def relay_fee(self, cached=True):
if not self.relay_fee_cache or not cached:
self.relay_fee_cache = self.getnetworkinfo()["relayfee"]
diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py
--- a/test/functional/wallet_dump.py
+++ b/test/functional/wallet_dump.py
@@ -117,8 +117,7 @@
assert_equal(found_addr_rsv, 90 * 2)
# encrypt wallet, restart, unlock and dump
- self.nodes[0].node_encrypt_wallet('test')
- self.start_node(0)
+ self.nodes[0].encryptwallet('test')
self.nodes[0].walletpassphrase('test', 10)
# Should be a no-op:
self.nodes[0].keypoolrefill()
diff --git a/test/functional/wallet_encryption.py b/test/functional/wallet_encryption.py
--- a/test/functional/wallet_encryption.py
+++ b/test/functional/wallet_encryption.py
@@ -32,8 +32,7 @@
assert_equal(len(privkey), 52)
# Encrypt the wallet
- self.nodes[0].node_encrypt_wallet(passphrase)
- self.start_node(0)
+ self.nodes[0].encryptwallet(passphrase)
# Check the encrypted wallet is marked as locked on initialization
assert_equal(self.nodes[0].getwalletinfo()['unlocked_until'], 0)
diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py
--- a/test/functional/wallet_keypool.py
+++ b/test/functional/wallet_keypool.py
@@ -25,9 +25,7 @@
'hdseedid'] == wallet_info_old['hdseedid']
# Encrypt wallet and wait to terminate
- nodes[0].node_encrypt_wallet('test')
- # Restart node 0
- self.start_node(0)
+ nodes[0].encryptwallet('test')
# Keep creating keys
addr = nodes[0].getnewaddress()
addr_data = nodes[0].getaddressinfo(addr)