Merge #8776: Wallet refactoring leading up to multiwallet

5394b39 Wallet: Split main logic from InitLoadWallet into CreateWalletFromFile (Luke Dashjr)
fb0c934 Wallet: Let the interval-flushing thread figure out the filename (Luke Dashjr)
This commit is contained in:
Pieter Wuille 2017-01-03 14:10:41 -08:00 committed by Alexander Block
parent 1d83352dad
commit da209546df
4 changed files with 67 additions and 33 deletions

View File

@ -4665,16 +4665,8 @@ std::string CWallet::GetWalletHelpString(bool showDebug)
return strUsage; 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 // needed to restore wallet transaction meta data after -zapwallettxes
std::vector<CWalletTx> vWtx; std::vector<CWalletTx> vWtx;
@ -4684,7 +4676,8 @@ bool CWallet::InitLoadWallet()
CWallet *tempWallet = new CWallet(walletFile); CWallet *tempWallet = new CWallet(walletFile);
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
if (nZapWalletRet != DB_LOAD_OK) { 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; delete tempWallet;
@ -4699,23 +4692,29 @@ bool CWallet::InitLoadWallet()
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DB_LOAD_OK) if (nLoadWalletRet != DB_LOAD_OK)
{ {
if (nLoadWalletRet == DB_CORRUPT) if (nLoadWalletRet == DB_CORRUPT) {
return InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
return NULL;
}
else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
{ {
InitWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data" InitWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
" or address book entries might be missing or incorrect."), " or address book entries might be missing or incorrect."),
walletFile)); walletFile));
} }
else if (nLoadWalletRet == DB_TOO_NEW) else if (nLoadWalletRet == DB_TOO_NEW) {
return InitError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), InitError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, _(PACKAGE_NAME)));
walletFile, _(PACKAGE_NAME))); return NULL;
}
else if (nLoadWalletRet == DB_NEED_REWRITE) 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)) if (GetBoolArg("-upgradewallet", fFirstRun))
@ -4731,7 +4730,8 @@ bool CWallet::InitLoadWallet()
LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
if (nMaxVersion < walletInstance->GetVersion()) if (nMaxVersion < walletInstance->GetVersion())
{ {
return InitError(_("Cannot downgrade wallet")); InitError(_("Cannot downgrade wallet"));
return NULL;
} }
walletInstance->SetMaxVersion(nMaxVersion); walletInstance->SetMaxVersion(nMaxVersion);
} }
@ -4741,7 +4741,8 @@ bool CWallet::InitLoadWallet()
// Create new keyUser and set as default key // Create new keyUser and set as default key
if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsHDEnabled()) { if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsHDEnabled()) {
if (GetArg("-mnemonicpassphrase", "").size() > 256) { 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 // generate a new master key
walletInstance->GenerateNewHDChain(); walletInstance->GenerateNewHDChain();
@ -4753,8 +4754,10 @@ bool CWallet::InitLoadWallet()
CPubKey newDefaultKey; CPubKey newDefaultKey;
if (walletInstance->GetKeyFromPool(newDefaultKey, false)) { if (walletInstance->GetKeyFromPool(newDefaultKey, false)) {
walletInstance->SetDefaultKey(newDefaultKey); walletInstance->SetDefaultKey(newDefaultKey);
if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive")) if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive")) {
return InitError(_("Cannot write default address") += "\n"); InitError(_("Cannot write default address") += "\n");
return NULL;
}
} }
walletInstance->SetBestChain(chainActive.GetLocator()); walletInstance->SetBestChain(chainActive.GetLocator());
@ -4767,7 +4770,8 @@ bool CWallet::InitLoadWallet()
InitWarning(strBackupWarning); InitWarning(strBackupWarning);
} }
if (!strBackupError.empty()) { if (!strBackupError.empty()) {
return InitError(strBackupError); InitError(strBackupError);
return NULL;
} }
} }
@ -4775,12 +4779,14 @@ bool CWallet::InitLoadWallet()
else if (IsArgSet("-usehd")) { else if (IsArgSet("-usehd")) {
bool useHD = GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET); bool useHD = GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET);
if (walletInstance->IsHDEnabled() && !useHD) { if (walletInstance->IsHDEnabled() && !useHD) {
return InitError(strprintf(_("Error loading %s: You can't disable HD on a already existing HD wallet"), InitError(strprintf(_("Error loading %s: You can't disable HD on a already existing HD wallet"),
walletInstance->strWalletFile)); walletInstance->strWalletFile));
return NULL;
} }
if (!walletInstance->IsHDEnabled() && useHD) { if (!walletInstance->IsHDEnabled() && useHD) {
return InitError(strprintf(_("Error loading %s: You can't enable HD on a already existing non-HD wallet"), InitError(strprintf(_("Error loading %s: You can't enable HD on a already existing non-HD wallet"),
walletInstance->strWalletFile)); 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) while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block)
block = block->pprev; block = block->pprev;
if (pindexRescan != block) 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)")); 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...")); uiInterface.InitMessage(_("Rescanning..."));
@ -4863,11 +4871,30 @@ bool CWallet::InitLoadWallet()
LogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size()); 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; return true;
} }
std::atomic<bool> CWallet::fFlushThreadRunning(false);
void CWallet::postInitProcess(boost::thread_group& threadGroup) void CWallet::postInitProcess(boost::thread_group& threadGroup)
{ {
// Add wallet transactions that aren't already in a block to mempool // Add wallet transactions that aren't already in a block to mempool
@ -4875,7 +4902,9 @@ void CWallet::postInitProcess(boost::thread_group& threadGroup)
ReacceptWalletTransactions(); ReacceptWalletTransactions();
// Run a thread to flush wallet periodically // 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() bool CWallet::ParameterInteraction()

View File

@ -23,6 +23,7 @@
#include "privatesend.h" #include "privatesend.h"
#include <algorithm> #include <algorithm>
#include <atomic>
#include <map> #include <map>
#include <set> #include <set>
#include <stdexcept> #include <stdexcept>
@ -618,6 +619,8 @@ private:
class CWallet : public CCryptoKeyStore, public CValidationInterface class CWallet : public CCryptoKeyStore, public CValidationInterface
{ {
private: private:
static std::atomic<bool> fFlushThreadRunning;
/** /**
* Select a set of coins such that nValueRet >= nTargetValue and at least * Select a set of coins such that nValueRet >= nTargetValue and at least
* all coins from coinControl are selected; Never select unconfirmed coins * all coins from coinControl are selected; Never select unconfirmed coins
@ -1047,6 +1050,7 @@ public:
static std::string GetWalletHelpString(bool showDebug); static std::string GetWalletHelpString(bool showDebug);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ /* 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(); static bool InitLoadWallet();
/** /**

View File

@ -801,7 +801,7 @@ DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector<CWalletTx>& vWtx)
return DB_LOAD_OK; return DB_LOAD_OK;
} }
void ThreadFlushWalletDB(const string& strFile) void ThreadFlushWalletDB()
{ {
// Make this thread recognisable as the wallet flushing thread // Make this thread recognisable as the wallet flushing thread
RenameThread("dash-wallet"); RenameThread("dash-wallet");
@ -843,6 +843,7 @@ void ThreadFlushWalletDB(const string& strFile)
if (nRefCount == 0) if (nRefCount == 0)
{ {
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();
const std::string& strFile = pwalletMain->strWalletFile;
map<string, int>::iterator _mi = bitdb.mapFileUseCount.find(strFile); map<string, int>::iterator _mi = bitdb.mapFileUseCount.find(strFile);
if (_mi != bitdb.mapFileUseCount.end()) if (_mi != bitdb.mapFileUseCount.end())
{ {

View File

@ -145,6 +145,6 @@ private:
}; };
void ThreadFlushWalletDB(const std::string& strFile); void ThreadFlushWalletDB();
#endif // BITCOIN_WALLET_WALLETDB_H #endif // BITCOIN_WALLET_WALLETDB_H