diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ce67943f5..74efd2c9b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4665,16 +4665,8 @@ std::string CWallet::GetWalletHelpString(bool showDebug) return strUsage; } -bool CWallet::InitLoadWallet() +CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) { - if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { - pwalletMain = NULL; - LogPrintf("Wallet disabled!\n"); - return true; - } - - std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); - // needed to restore wallet transaction meta data after -zapwallettxes std::vector vWtx; @@ -4684,7 +4676,8 @@ bool CWallet::InitLoadWallet() CWallet *tempWallet = new CWallet(walletFile); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DB_LOAD_OK) { - return InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); + InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); + return NULL; } delete tempWallet; @@ -4699,23 +4692,29 @@ bool CWallet::InitLoadWallet() DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); if (nLoadWalletRet != DB_LOAD_OK) { - if (nLoadWalletRet == DB_CORRUPT) - return InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); + if (nLoadWalletRet == DB_CORRUPT) { + InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); + return NULL; + } else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) { InitWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data" " or address book entries might be missing or incorrect."), walletFile)); } - else if (nLoadWalletRet == DB_TOO_NEW) - return InitError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), - walletFile, _(PACKAGE_NAME))); + else if (nLoadWalletRet == DB_TOO_NEW) { + InitError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, _(PACKAGE_NAME))); + return NULL; + } else if (nLoadWalletRet == DB_NEED_REWRITE) { - return InitError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME))); + InitError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME))); + return NULL; + } + else { + InitError(strprintf(_("Error loading %s"), walletFile)); + return NULL; } - else - return InitError(strprintf(_("Error loading %s"), walletFile)); } if (GetBoolArg("-upgradewallet", fFirstRun)) @@ -4731,7 +4730,8 @@ bool CWallet::InitLoadWallet() LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); if (nMaxVersion < walletInstance->GetVersion()) { - return InitError(_("Cannot downgrade wallet")); + InitError(_("Cannot downgrade wallet")); + return NULL; } walletInstance->SetMaxVersion(nMaxVersion); } @@ -4741,7 +4741,8 @@ bool CWallet::InitLoadWallet() // Create new keyUser and set as default key if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsHDEnabled()) { if (GetArg("-mnemonicpassphrase", "").size() > 256) { - return InitError(_("Mnemonic passphrase is too long, must be at most 256 characters")); + InitError(_("Mnemonic passphrase is too long, must be at most 256 characters")); + return NULL; } // generate a new master key walletInstance->GenerateNewHDChain(); @@ -4753,8 +4754,10 @@ bool CWallet::InitLoadWallet() CPubKey newDefaultKey; if (walletInstance->GetKeyFromPool(newDefaultKey, false)) { walletInstance->SetDefaultKey(newDefaultKey); - if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive")) - return InitError(_("Cannot write default address") += "\n"); + if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive")) { + InitError(_("Cannot write default address") += "\n"); + return NULL; + } } walletInstance->SetBestChain(chainActive.GetLocator()); @@ -4767,7 +4770,8 @@ bool CWallet::InitLoadWallet() InitWarning(strBackupWarning); } if (!strBackupError.empty()) { - return InitError(strBackupError); + InitError(strBackupError); + return NULL; } } @@ -4775,12 +4779,14 @@ bool CWallet::InitLoadWallet() else if (IsArgSet("-usehd")) { bool useHD = GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET); if (walletInstance->IsHDEnabled() && !useHD) { - return InitError(strprintf(_("Error loading %s: You can't disable HD on a already existing HD wallet"), - walletInstance->strWalletFile)); + InitError(strprintf(_("Error loading %s: You can't disable HD on a already existing HD wallet"), + walletInstance->strWalletFile)); + return NULL; } if (!walletInstance->IsHDEnabled() && useHD) { - return InitError(strprintf(_("Error loading %s: You can't enable HD on a already existing non-HD wallet"), - walletInstance->strWalletFile)); + InitError(strprintf(_("Error loading %s: You can't enable HD on a already existing non-HD wallet"), + walletInstance->strWalletFile)); + return NULL; } } @@ -4816,8 +4822,10 @@ bool CWallet::InitLoadWallet() while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block) block = block->pprev; - if (pindexRescan != block) - return InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); + if (pindexRescan != block) { + InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); + return NULL; + } } uiInterface.InitMessage(_("Rescanning...")); @@ -4863,11 +4871,30 @@ bool CWallet::InitLoadWallet() LogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size()); } - pwalletMain = walletInstance; + return walletInstance; +} + +bool CWallet::InitLoadWallet() +{ + if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { + pwalletMain = NULL; + LogPrintf("Wallet disabled!\n"); + return true; + } + + std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + + CWallet * const pwallet = CreateWalletFromFile(walletFile); + if (!pwallet) { + return false; + } + pwalletMain = pwallet; return true; } +std::atomic CWallet::fFlushThreadRunning(false); + void CWallet::postInitProcess(boost::thread_group& threadGroup) { // Add wallet transactions that aren't already in a block to mempool @@ -4875,7 +4902,9 @@ void CWallet::postInitProcess(boost::thread_group& threadGroup) ReacceptWalletTransactions(); // Run a thread to flush wallet periodically - threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(this->strWalletFile))); + if (!CWallet::fFlushThreadRunning.exchange(true)) { + threadGroup.create_thread(ThreadFlushWalletDB); + } } bool CWallet::ParameterInteraction() diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 1706feecb..399c6843a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -23,6 +23,7 @@ #include "privatesend.h" #include +#include #include #include #include @@ -618,6 +619,8 @@ private: class CWallet : public CCryptoKeyStore, public CValidationInterface { private: + static std::atomic fFlushThreadRunning; + /** * Select a set of coins such that nValueRet >= nTargetValue and at least * all coins from coinControl are selected; Never select unconfirmed coins @@ -1047,6 +1050,7 @@ public: static std::string GetWalletHelpString(bool showDebug); /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ + static CWallet* CreateWalletFromFile(const std::string walletFile); static bool InitLoadWallet(); /** diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 269456142..3e3be3d3b 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -801,7 +801,7 @@ DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector& vWtx) return DB_LOAD_OK; } -void ThreadFlushWalletDB(const string& strFile) +void ThreadFlushWalletDB() { // Make this thread recognisable as the wallet flushing thread RenameThread("dash-wallet"); @@ -843,6 +843,7 @@ void ThreadFlushWalletDB(const string& strFile) if (nRefCount == 0) { boost::this_thread::interruption_point(); + const std::string& strFile = pwalletMain->strWalletFile; map::iterator _mi = bitdb.mapFileUseCount.find(strFile); if (_mi != bitdb.mapFileUseCount.end()) { diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 1de44f047..4584b3586 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -145,6 +145,6 @@ private: }; -void ThreadFlushWalletDB(const std::string& strFile); +void ThreadFlushWalletDB(); #endif // BITCOIN_WALLET_WALLETDB_H