From f28eb8020e3bb341e7f16c6bf93da7e92c82ec94 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 9 Mar 2017 20:29:01 +0000 Subject: Bugfix: wallet: Increment "update counter" only after actually making the applicable db changes to avoid potential races Also does all "update counter" access via IncrementUpdateCounter --- src/wallet/walletdb.cpp | 78 ++++++++++++++++++------------------------------- src/wallet/walletdb.h | 21 +++++++++++++ 2 files changed, 50 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 342c797dd3..3015d6b963 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -32,47 +32,39 @@ static std::atomic nWalletDBUpdateCounter; bool CWalletDB::WriteName(const std::string& strAddress, const std::string& strName) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("name"), strAddress), strName); + return WriteIC(std::make_pair(std::string("name"), strAddress), strName); } bool CWalletDB::EraseName(const std::string& strAddress) { // This should only be used for sending addresses, never for receiving addresses, // receiving addresses must always have an address book entry if they're not change return. - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("name"), strAddress)); + return EraseIC(std::make_pair(std::string("name"), strAddress)); } bool CWalletDB::WritePurpose(const std::string& strAddress, const std::string& strPurpose) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("purpose"), strAddress), strPurpose); + return WriteIC(std::make_pair(std::string("purpose"), strAddress), strPurpose); } bool CWalletDB::ErasePurpose(const std::string& strPurpose) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("purpose"), strPurpose)); + return EraseIC(std::make_pair(std::string("purpose"), strPurpose)); } bool CWalletDB::WriteTx(const CWalletTx& wtx) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); + return WriteIC(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); } bool CWalletDB::EraseTx(uint256 hash) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("tx"), hash)); + return EraseIC(std::make_pair(std::string("tx"), hash)); } bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta) { - nWalletDBUpdateCounter++; - - if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey), + if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) return false; @@ -82,7 +74,7 @@ bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, c vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end()); vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end()); - return batch.Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false); + return WriteIC(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false); } bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, @@ -90,55 +82,50 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, const CKeyMetadata &keyMeta) { const bool fEraseUnencryptedKey = true; - nWalletDBUpdateCounter++; - if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey), + if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) return false; - if (!batch.Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) + if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) return false; if (fEraseUnencryptedKey) { - batch.Erase(std::make_pair(std::string("key"), vchPubKey)); - batch.Erase(std::make_pair(std::string("wkey"), vchPubKey)); + EraseIC(std::make_pair(std::string("key"), vchPubKey)); + EraseIC(std::make_pair(std::string("wkey"), vchPubKey)); } + return true; } bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true); + return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true); } bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false); + return WriteIC(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false); } bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta) { - nWalletDBUpdateCounter++; - if (!batch.Write(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) + if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) return false; - return batch.Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1'); + return WriteIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1'); } bool CWalletDB::EraseWatchOnly(const CScript &dest) { - nWalletDBUpdateCounter++; - if (!batch.Erase(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) + if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) return false; - return batch.Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest))); + return EraseIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest))); } bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) { - nWalletDBUpdateCounter++; - batch.Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan - return batch.Write(std::string("bestblock_nomerkle"), locator); + WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan + return WriteIC(std::string("bestblock_nomerkle"), locator); } bool CWalletDB::ReadBestBlock(CBlockLocator& locator) @@ -149,14 +136,12 @@ bool CWalletDB::ReadBestBlock(CBlockLocator& locator) bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext) { - nWalletDBUpdateCounter++; - return batch.Write(std::string("orderposnext"), nOrderPosNext); + return WriteIC(std::string("orderposnext"), nOrderPosNext); } bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey) { - nWalletDBUpdateCounter++; - return batch.Write(std::string("defaultkey"), vchPubKey); + return WriteIC(std::string("defaultkey"), vchPubKey); } bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool) @@ -166,19 +151,17 @@ bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool) bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("pool"), nPool), keypool); + return WriteIC(std::make_pair(std::string("pool"), nPool), keypool); } bool CWalletDB::ErasePool(int64_t nPool) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("pool"), nPool)); + return EraseIC(std::make_pair(std::string("pool"), nPool)); } bool CWalletDB::WriteMinVersion(int nVersion) { - return batch.Write(std::string("minversion"), nVersion); + return WriteIC(std::string("minversion"), nVersion); } bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account) @@ -854,21 +837,18 @@ bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value); + return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value); } bool CWalletDB::EraseDestData(const std::string &address, const std::string &key) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key))); + return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key))); } bool CWalletDB::WriteHDChain(const CHDChain& chain) { - nWalletDBUpdateCounter++; - return batch.Write(std::string("hdchain"), chain); + return WriteIC(std::string("hdchain"), chain); } void CWalletDB::IncrementUpdateCounter() diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index cd9fe279c5..0fafdb6a1b 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -140,6 +140,27 @@ public: */ class CWalletDB { +private: + template + bool WriteIC(const K& key, const T& value, bool fOverwrite = true) + { + if (!batch.Write(key, value, fOverwrite)) { + return false; + } + IncrementUpdateCounter(); + return true; + } + + template + bool EraseIC(const K& key) + { + if (!batch.Erase(key)) { + return false; + } + IncrementUpdateCounter(); + return true; + } + public: CWalletDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool _fFlushOnClose = true) : batch(dbw, pszMode, _fFlushOnClose) -- cgit v1.2.3 From 9d15d5548d375e7841e0505cdcf4ddcf11591994 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 9 Mar 2017 20:30:31 +0000 Subject: Bugfix: wallet: Increment "update counter" when modifying account stuff --- src/wallet/walletdb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 3015d6b963..f0d7f44ec0 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -172,12 +172,12 @@ bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account) bool CWalletDB::WriteAccount(const std::string& strAccount, const CAccount& account) { - return batch.Write(std::make_pair(std::string("acc"), strAccount), account); + return WriteIC(std::make_pair(std::string("acc"), strAccount), account); } bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry) { - return batch.Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); + return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); } bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry) -- cgit v1.2.3 From 23fb9adaea01c7baece6e1269e65713571088c5f Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 9 Mar 2017 20:11:36 +0000 Subject: wallet: Move nAccountingEntryNumber from static/global to CWallet --- src/wallet/wallet.cpp | 2 +- src/wallet/wallet.h | 2 ++ src/wallet/walletdb.cpp | 12 +++--------- src/wallet/walletdb.h | 1 - 4 files changed, 6 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 3e000d2a9d..547daf5c62 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2871,7 +2871,7 @@ bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry) bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwalletdb) { - if (!pwalletdb->WriteAccountingEntry_Backend(acentry)) + if (!pwalletdb->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) return false; laccentries.push_back(acentry); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index a3974bf00b..6236b5e560 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -785,6 +785,7 @@ public: nMasterKeyMaxID = 0; pwalletdbEncryption = NULL; nOrderPosNext = 0; + nAccountingEntryNumber = 0; nNextResend = 0; nLastResend = 0; nTimeFirstKey = 0; @@ -802,6 +803,7 @@ public: TxItems wtxOrdered; int64_t nOrderPosNext; + uint64_t nAccountingEntryNumber; std::map mapRequestCount; std::map mapAddressBook; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index f0d7f44ec0..75dbb2edff 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -22,8 +22,6 @@ #include #include -static uint64_t nAccountingEntryNumber = 0; - static std::atomic nWalletDBUpdateCounter; // @@ -180,11 +178,6 @@ bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccount return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); } -bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry) -{ - return WriteAccountingEntry(++nAccountingEntryNumber, acentry); -} - CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount) { std::list entries; @@ -321,8 +314,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssKey >> strAccount; uint64_t nNumber; ssKey >> nNumber; - if (nNumber > nAccountingEntryNumber) - nAccountingEntryNumber = nNumber; + if (nNumber > pwallet->nAccountingEntryNumber) { + pwallet->nAccountingEntryNumber = nNumber; + } if (!wss.fAnyUnordered) { diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 0fafdb6a1b..5f9aec9afd 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -201,7 +201,6 @@ public: /// This writes directly to the database, and will not update the CWallet's cached accounting entries! /// Use wallet.AddAccountingEntry instead, to write *and* update its caches. bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry); - bool WriteAccountingEntry_Backend(const CAccountingEntry& acentry); bool ReadAccount(const std::string& strAccount, CAccount& account); bool WriteAccount(const std::string& strAccount, const CAccount& account); -- cgit v1.2.3 From 74e87389616ce1147c65f0e49f3d84b817693ac6 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 3 Jan 2017 20:33:55 +0000 Subject: Bugfix: ForceSetArg should replace entr(ies) in mapMultiArgs, not append --- src/util.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/util.cpp b/src/util.cpp index 653a4f072a..745c3e3bc0 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -477,6 +477,7 @@ void ArgsManager::ForceSetArg(const std::string& strArg, const std::string& strV { LOCK(cs_args); mapArgs[strArg] = strValue; + mapMultiArgs[strArg].clear(); mapMultiArgs[strArg].push_back(strValue); } -- cgit v1.2.3 From 19b3648bb52d27c3a9674159d71726b73fe532d9 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 9 Mar 2017 20:56:58 +0000 Subject: CWalletDB: Store the update counter per wallet --- src/wallet/db.cpp | 10 ++++++++++ src/wallet/db.h | 4 ++++ src/wallet/wallet.cpp | 2 +- src/wallet/walletdb.cpp | 28 +++++++++------------------- src/wallet/walletdb.h | 11 +++++------ 5 files changed, 29 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 25f6bdd9d9..7e1b94ffa4 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -434,6 +434,16 @@ void CDB::Flush() env->dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0); } +void CWalletDBWrapper::IncrementUpdateCounter() +{ + ++nUpdateCounter; +} + +unsigned int CWalletDBWrapper::GetUpdateCounter() +{ + return nUpdateCounter.load(); +} + void CDB::Close() { if (!pdb) diff --git a/src/wallet/db.h b/src/wallet/db.h index 3c6870d169..1a583c3ce9 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -119,10 +119,14 @@ public: */ void Flush(bool shutdown); + void IncrementUpdateCounter(); + unsigned int GetUpdateCounter(); + private: /** BerkeleyDB specific */ CDBEnv *env; std::string strFile; + std::atomic nUpdateCounter; /** Return whether this database handle is a dummy for testing. * Only to be used at a low level, application should ideally not care diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 547daf5c62..9d49b72308 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3884,7 +3884,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) walletInstance->ScanForWalletTransactions(pindexRescan, true); LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); walletInstance->SetBestChain(chainActive.GetLocator()); - CWalletDB::IncrementUpdateCounter(); + walletInstance->dbw->IncrementUpdateCounter(); // Restore wallet transaction metadata after -zapwallettxes=1 if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 75dbb2edff..149d0e0c20 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -22,8 +22,6 @@ #include #include -static std::atomic nWalletDBUpdateCounter; - // // CWalletDB // @@ -762,20 +760,22 @@ void MaybeCompactWalletDB() return; } - static unsigned int nLastSeen = CWalletDB::GetUpdateCounter(); - static unsigned int nLastFlushed = CWalletDB::GetUpdateCounter(); + CWalletDBWrapper& dbh = pwalletMain->GetDBHandle(); + + static unsigned int nLastSeen = dbh.GetUpdateCounter(); + static unsigned int nLastFlushed = dbh.GetUpdateCounter(); static int64_t nLastWalletUpdate = GetTime(); - if (nLastSeen != CWalletDB::GetUpdateCounter()) + if (nLastSeen != dbh.GetUpdateCounter()) { - nLastSeen = CWalletDB::GetUpdateCounter(); + nLastSeen = dbh.GetUpdateCounter(); nLastWalletUpdate = GetTime(); } - if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2) + if (nLastFlushed != dbh.GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2) { - if (CDB::PeriodicFlush(pwalletMain->GetDBHandle())) { - nLastFlushed = CWalletDB::GetUpdateCounter(); + if (CDB::PeriodicFlush(dbh)) { + nLastFlushed = dbh.GetUpdateCounter(); } } fOneThread = false; @@ -845,16 +845,6 @@ bool CWalletDB::WriteHDChain(const CHDChain& chain) return WriteIC(std::string("hdchain"), chain); } -void CWalletDB::IncrementUpdateCounter() -{ - nWalletDBUpdateCounter++; -} - -unsigned int CWalletDB::GetUpdateCounter() -{ - return nWalletDBUpdateCounter; -} - bool CWalletDB::TxnBegin() { return batch.TxnBegin(); diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 5f9aec9afd..64cebd4330 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -147,7 +147,7 @@ private: if (!batch.Write(key, value, fOverwrite)) { return false; } - IncrementUpdateCounter(); + m_dbw.IncrementUpdateCounter(); return true; } @@ -157,13 +157,14 @@ private: if (!batch.Erase(key)) { return false; } - IncrementUpdateCounter(); + m_dbw.IncrementUpdateCounter(); return true; } public: CWalletDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool _fFlushOnClose = true) : - batch(dbw, pszMode, _fFlushOnClose) + batch(dbw, pszMode, _fFlushOnClose), + m_dbw(dbw) { } @@ -232,9 +233,6 @@ public: //! write the hdchain model (external chain child index counter) bool WriteHDChain(const CHDChain& chain); - static void IncrementUpdateCounter(); - static unsigned int GetUpdateCounter(); - //! Begin a new transaction bool TxnBegin(); //! Commit current transaction @@ -247,6 +245,7 @@ public: bool WriteVersion(int nVersion); private: CDB batch; + CWalletDBWrapper& m_dbw; CWalletDB(const CWalletDB&); void operator=(const CWalletDB&); -- cgit v1.2.3 From b124cf04ea47e1eda60bbc26a9690a9715c6b23f Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 9 Sep 2016 08:42:30 +0000 Subject: Wallet: Replace pwalletMain with a vector of wallet pointers --- src/init.cpp | 21 +++++++++++++-------- src/qt/bitcoin.cpp | 5 +++-- src/wallet/db.cpp | 5 ----- src/wallet/db.h | 13 ++++++++----- src/wallet/rpcwallet.cpp | 3 ++- src/wallet/test/wallet_test_fixture.cpp | 2 ++ src/wallet/test/wallet_tests.cpp | 14 +++++++------- src/wallet/wallet.cpp | 5 ++--- src/wallet/wallet.h | 3 ++- src/wallet/walletdb.cpp | 25 ++++++++++++------------- 10 files changed, 51 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/init.cpp b/src/init.cpp index 33023a1800..cc630d7337 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -198,8 +198,9 @@ void Shutdown() StopRPC(); StopHTTPServer(); #ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->Flush(false); + for (CWalletRef pwallet : vpwallets) { + pwallet->Flush(false); + } #endif MapPort(false); UnregisterValidationInterface(peerLogic.get()); @@ -239,8 +240,9 @@ void Shutdown() pblocktree = NULL; } #ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->Flush(true); + for (CWalletRef pwallet : vpwallets) { + pwallet->Flush(true); + } #endif #if ENABLE_ZMQ @@ -260,8 +262,10 @@ void Shutdown() #endif UnregisterAllValidationInterfaces(); #ifdef ENABLE_WALLET - delete pwalletMain; - pwalletMain = NULL; + for (CWalletRef pwallet : vpwallets) { + delete pwallet; + } + vpwallets.clear(); #endif globalVerifyHandle.reset(); ECC_Stop(); @@ -1673,8 +1677,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) uiInterface.InitMessage(_("Done loading")); #ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->postInitProcess(scheduler); + for (CWalletRef pwallet : vpwallets) { + pwallet->postInitProcess(scheduler); + } #endif return !fRequestShutdown; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 23ec3ab434..6d8760c071 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -474,9 +474,10 @@ void BitcoinApplication::initializeResult(bool success) window->setClientModel(clientModel); #ifdef ENABLE_WALLET - if(pwalletMain) + // TODO: Expose secondary wallets + if (!vpwallets.empty()) { - walletModel = new WalletModel(platformStyle, pwalletMain, optionsModel); + walletModel = new WalletModel(platformStyle, vpwallets[0], optionsModel); window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel); window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET); diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 7e1b94ffa4..906cc809bf 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -439,11 +439,6 @@ void CWalletDBWrapper::IncrementUpdateCounter() ++nUpdateCounter; } -unsigned int CWalletDBWrapper::GetUpdateCounter() -{ - return nUpdateCounter.load(); -} - void CDB::Close() { if (!pdb) diff --git a/src/wallet/db.h b/src/wallet/db.h index 1a583c3ce9..a2ede99d1b 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -93,13 +93,13 @@ class CWalletDBWrapper friend class CDB; public: /** Create dummy DB handle */ - CWalletDBWrapper(): env(nullptr) + CWalletDBWrapper() : nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr) { } /** Create DB handle to real database */ - CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in): - env(env_in), strFile(strFile_in) + CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) : + nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in) { } @@ -120,13 +120,16 @@ public: void Flush(bool shutdown); void IncrementUpdateCounter(); - unsigned int GetUpdateCounter(); + + std::atomic nUpdateCounter; + unsigned int nLastSeen; + unsigned int nLastFlushed; + int64_t nLastWalletUpdate; private: /** BerkeleyDB specific */ CDBEnv *env; std::string strFile; - std::atomic nUpdateCounter; /** Return whether this database handle is a dummy for testing. * Only to be used at a low level, application should ideally not care diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3b6dfd42ca..7b9ed91947 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -33,7 +33,8 @@ CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request) { - return pwalletMain; + // TODO: Some way to access secondary wallets + return vpwallets.empty() ? nullptr : vpwallets[0]; } std::string HelpRequiringPassphrase(CWallet * const pwallet) diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 1989bf8d9b..922fcc8e89 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -8,6 +8,8 @@ #include "wallet/db.h" #include "wallet/wallet.h" +CWallet *pwalletMain; + WalletTestingSetup::WalletTestingSetup(const std::string& chainName): TestingSetup(chainName) { diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index b30748d66b..7c48bc29ea 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -19,6 +19,8 @@ #include #include +extern CWallet* pwalletMain; + extern UniValue importmulti(const JSONRPCRequest& request); extern UniValue dumpwallet(const JSONRPCRequest& request); extern UniValue importwallet(const JSONRPCRequest& request); @@ -402,8 +404,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) // after. { CWallet wallet; - CWallet *backup = ::pwalletMain; - ::pwalletMain = &wallet; + vpwallets.insert(vpwallets.begin(), &wallet); UniValue keys; keys.setArray(); UniValue key; @@ -434,7 +435,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) "downloading and rescanning the relevant blocks (see -reindex and -rescan " "options).\"}},{\"success\":true}]", 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW)); - ::pwalletMain = backup; + vpwallets.erase(vpwallets.begin()); } } @@ -444,7 +445,6 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) // than or equal to key birthday. BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) { - CWallet *pwalletMainBackup = ::pwalletMain; LOCK(cs_main); // Create two blocks with same timestamp to verify that importwallet rescan @@ -470,7 +470,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); request.params.push_back("wallet.backup"); - ::pwalletMain = &wallet; + vpwallets.insert(vpwallets.begin(), &wallet); ::dumpwallet(request); } @@ -482,7 +482,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); request.params.push_back("wallet.backup"); - ::pwalletMain = &wallet; + vpwallets[0] = &wallet; ::importwallet(request); BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3); @@ -495,7 +495,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) } SetMockTime(0); - ::pwalletMain = pwalletMainBackup; + vpwallets.erase(vpwallets.begin()); } // Check that GetImmatureCredit() returns a newly calculated value instead of diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 9d49b72308..e5c9f11aa6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -35,7 +35,7 @@ #include #include -CWallet* pwalletMain = NULL; +std::vector vpwallets; /** Transaction fee set by the user */ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; @@ -3926,7 +3926,6 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) bool CWallet::InitLoadWallet() { if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { - pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); return true; } @@ -3943,7 +3942,7 @@ bool CWallet::InitLoadWallet() if (!pwallet) { return false; } - pwalletMain = pwallet; + vpwallets.push_back(pwallet); return true; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 6236b5e560..b1516c6e65 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -29,7 +29,8 @@ #include #include -extern CWallet* pwalletMain; +typedef CWallet* CWalletRef; +extern std::vector vpwallets; /** * Settings diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 149d0e0c20..6f5ddece9a 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -760,24 +760,23 @@ void MaybeCompactWalletDB() return; } - CWalletDBWrapper& dbh = pwalletMain->GetDBHandle(); + for (CWalletRef pwallet : vpwallets) { + CWalletDBWrapper& dbh = pwallet->GetDBHandle(); - static unsigned int nLastSeen = dbh.GetUpdateCounter(); - static unsigned int nLastFlushed = dbh.GetUpdateCounter(); - static int64_t nLastWalletUpdate = GetTime(); + unsigned int nUpdateCounter = dbh.nUpdateCounter; - if (nLastSeen != dbh.GetUpdateCounter()) - { - nLastSeen = dbh.GetUpdateCounter(); - nLastWalletUpdate = GetTime(); - } + if (dbh.nLastSeen != nUpdateCounter) { + dbh.nLastSeen = nUpdateCounter; + dbh.nLastWalletUpdate = GetTime(); + } - if (nLastFlushed != dbh.GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2) - { - if (CDB::PeriodicFlush(dbh)) { - nLastFlushed = dbh.GetUpdateCounter(); + if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) { + if (CDB::PeriodicFlush(dbh)) { + dbh.nLastFlushed = nUpdateCounter; + } } } + fOneThread = false; } -- cgit v1.2.3 From 0f08575be2c6016c2c920e2b5b994e467576857d Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 9 Sep 2016 08:50:09 +0000 Subject: Wallet: Support loading multiple wallets if -wallet used more than once --- src/wallet/wallet.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e5c9f11aa6..241aaffcef 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3930,19 +3930,21 @@ bool CWallet::InitLoadWallet() return true; } - std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + SoftSetArg("-wallet", DEFAULT_WALLET_DAT); - if (boost::filesystem::path(walletFile).filename() != walletFile) { - return InitError(_("-wallet parameter must only specify a filename (not a path)")); - } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { - return InitError(_("Invalid characters in -wallet filename")); - } + for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { + if (boost::filesystem::path(walletFile).filename() != walletFile) { + return InitError(_("-wallet parameter must only specify a filename (not a path)")); + } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { + return InitError(_("Invalid characters in -wallet filename")); + } - CWallet * const pwallet = CreateWalletFromFile(walletFile); - if (!pwallet) { - return false; + CWallet * const pwallet = CreateWalletFromFile(walletFile); + if (!pwallet) { + return false; + } + vpwallets.push_back(pwallet); } - vpwallets.push_back(pwallet); return true; } -- cgit v1.2.3 From 008c3600834d42a98d4f0838e9bedc873102fe73 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 9 Mar 2017 23:45:58 +0000 Subject: Wallet: Move multiwallet sanity checks to CWallet::Verify, and do other checks on all wallets --- src/wallet/wallet.cpp | 56 ++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 241aaffcef..f4ff5f8363 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -440,30 +440,40 @@ bool CWallet::Verify() if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; - uiInterface.InitMessage(_("Verifying wallet...")); - std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + SoftSetArg("-wallet", DEFAULT_WALLET_DAT); - std::string strError; - if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) - return InitError(strError); + uiInterface.InitMessage(_("Verifying wallet(s)...")); - if (GetBoolArg("-salvagewallet", false)) - { - // Recover readable keypairs: - CWallet dummyWallet; - if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter)) + for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { + if (boost::filesystem::path(walletFile).filename() != walletFile) { + return InitError(_("-wallet parameter must only specify a filename (not a path)")); + } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { + return InitError(_("Invalid characters in -wallet filename")); + } + + std::string strError; + if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) + return InitError(strError); + + if (GetBoolArg("-salvagewallet", false)) + { + // Recover readable keypairs: + CWallet dummyWallet; + if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter)) + return false; + } + + std::string strWarning; + bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); + if (!strWarning.empty()) + InitWarning(strWarning); + if (!dbV) + { + InitError(strError); return false; + } } - std::string strWarning; - bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); - if (!strWarning.empty()) - InitWarning(strWarning); - if (!dbV) - { - InitError(strError); - return false; - } return true; } @@ -3930,15 +3940,7 @@ bool CWallet::InitLoadWallet() return true; } - SoftSetArg("-wallet", DEFAULT_WALLET_DAT); - for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { - if (boost::filesystem::path(walletFile).filename() != walletFile) { - return InitError(_("-wallet parameter must only specify a filename (not a path)")); - } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { - return InitError(_("Invalid characters in -wallet filename")); - } - CWallet * const pwallet = CreateWalletFromFile(walletFile); if (!pwallet) { return false; -- cgit v1.2.3 From 84dcb45017a85e358fed274c49b342a40a1d1233 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 5 Jun 2017 21:36:02 +0000 Subject: Bugfix: wallet: Fix warningStr, errorStr argument order --- src/wallet/walletdb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 6f5ddece9a..a1fc933a37 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -825,7 +825,7 @@ bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr) { - return CDB::VerifyDatabaseFile(walletFile, dataDir, errorStr, warningStr, CWalletDB::Recover); + return CDB::VerifyDatabaseFile(walletFile, dataDir, warningStr, errorStr, CWalletDB::Recover); } bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value) -- cgit v1.2.3 From b823a4c9f6836c802803dbd265cb7451fb93b8e7 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 5 Jun 2017 22:01:48 +0000 Subject: wallet: Include actual backup filename in recovery warning message --- src/wallet/db.cpp | 15 ++++++++------- src/wallet/db.h | 7 ++++--- src/wallet/wallet.cpp | 3 ++- src/wallet/walletdb.cpp | 8 ++++---- src/wallet/walletdb.h | 4 ++-- 5 files changed, 20 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 906cc809bf..f82b59db8b 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -143,7 +143,7 @@ void CDBEnv::MakeMock() fMockDb = true; } -CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFunc)(const std::string& strFile)) +CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename) { LOCK(cs_db); assert(mapFileUseCount.count(strFile) == 0); @@ -156,11 +156,11 @@ CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFu return RECOVER_FAIL; // Try to recover: - bool fRecovered = (*recoverFunc)(strFile); + bool fRecovered = (*recoverFunc)(strFile, out_backup_filename); return (fRecovered ? RECOVER_OK : RECOVER_FAIL); } -bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)) +bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename) { // Recovery procedure: // move wallet file to wallet.timestamp.bak @@ -170,7 +170,7 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco // Set -rescan so any missing transactions will be // found. int64_t now = GetTime(); - std::string newFilename = strprintf("wallet.%d.bak", now); + newFilename = strprintf("wallet.%d.bak", now); int result = bitdb.dbenv->dbrename(NULL, filename.c_str(), NULL, newFilename.c_str(), DB_AUTO_COMMIT); @@ -261,18 +261,19 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD return true; } -bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile)) +bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc) { if (fs::exists(dataDir / walletFile)) { - CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc); + std::string backup_filename; + CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc, backup_filename); if (r == CDBEnv::RECOVER_OK) { warningStr = strprintf(_("Warning: Wallet file corrupt, data salvaged!" " Original %s saved as %s in %s; if" " your balance or transactions are incorrect you should" " restore from a backup."), - walletFile, "wallet.{timestamp}.bak", dataDir); + walletFile, backup_filename, dataDir); } if (r == CDBEnv::RECOVER_FAIL) { diff --git a/src/wallet/db.h b/src/wallet/db.h index a2ede99d1b..ba37853572 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -55,7 +55,8 @@ public: enum VerifyResult { VERIFY_OK, RECOVER_OK, RECOVER_FAIL }; - VerifyResult Verify(const std::string& strFile, bool (*recoverFunc)(const std::string& strFile)); + typedef bool (*recoverFunc_type)(const std::string& strFile, std::string& out_backup_filename); + VerifyResult Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename); /** * Salvage data from a file that Verify says is bad. * fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation). @@ -156,7 +157,7 @@ public: void Flush(); void Close(); - static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)); + static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename); /* flush the wallet passively (TRY_LOCK) ideal to be called periodically */ @@ -164,7 +165,7 @@ public: /* verifies the database environment */ static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile)); + static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc); private: CDB(const CDB&); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f4ff5f8363..065748bb9d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -459,7 +459,8 @@ bool CWallet::Verify() { // Recover readable keypairs: CWallet dummyWallet; - if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter)) + std::string backup_filename; + if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter, backup_filename)) return false; } diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index a1fc933a37..4dd1ebf677 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -783,16 +783,16 @@ void MaybeCompactWalletDB() // // Try to (very carefully!) recover wallet file if there is a problem. // -bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)) +bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename) { - return CDB::Recover(filename, callbackDataIn, recoverKVcallback); + return CDB::Recover(filename, callbackDataIn, recoverKVcallback, out_backup_filename); } -bool CWalletDB::Recover(const std::string& filename) +bool CWalletDB::Recover(const std::string& filename, std::string& out_backup_filename) { // recover without a key filter callback // results in recovering all record types - return CWalletDB::Recover(filename, NULL, NULL); + return CWalletDB::Recover(filename, NULL, NULL, out_backup_filename); } bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue) diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 64cebd4330..d78f143ebd 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -218,9 +218,9 @@ public: DBErrors ZapWalletTx(std::vector& vWtx); DBErrors ZapSelectTx(std::vector& vHashIn, std::vector& vHashOut); /* Try to (very carefully!) recover wallet database (with a possible key type filter) */ - static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)); + static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename); /* Recover convenience-function to bypass the key filter callback, called when verify fails, recovers everything */ - static bool Recover(const std::string& filename); + static bool Recover(const std::string& filename, std::string& out_backup_filename); /* Recover filter (used as callback), will only let keys (cryptographical keys) as KV/key-type pass through */ static bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue); /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */ -- cgit v1.2.3 From a2a5f3f0f06cd3e3cd6203d2ef713360dcb9afe1 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 5 Jun 2017 22:02:32 +0000 Subject: wallet: Base backup filenames on original wallet filename --- src/wallet/db.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index f82b59db8b..2047dc5f72 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -163,14 +163,14 @@ CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, recoverFunc_type bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename) { // Recovery procedure: - // move wallet file to wallet.timestamp.bak + // move wallet file to walletfilename.timestamp.bak // Call Salvage with fAggressive=true to // get as much data as possible. // Rewrite salvaged data to fresh wallet file // Set -rescan so any missing transactions will be // found. int64_t now = GetTime(); - newFilename = strprintf("wallet.%d.bak", now); + newFilename = strprintf("%s.%d.bak", filename, now); int result = bitdb.dbenv->dbrename(NULL, filename.c_str(), NULL, newFilename.c_str(), DB_AUTO_COMMIT); -- cgit v1.2.3 From 9cbe8c80bad1b55557a91db65a06b66ec4743f18 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 5 Jun 2017 22:21:20 +0000 Subject: wallet: Forbid -salvagewallet, -zapwallettxes, and -upgradewallet with multiple wallets --- src/wallet/wallet.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 065748bb9d..b3d94e42b2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -440,8 +440,6 @@ bool CWallet::Verify() if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; - SoftSetArg("-wallet", DEFAULT_WALLET_DAT); - uiInterface.InitMessage(_("Verifying wallet(s)...")); for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { @@ -3968,6 +3966,9 @@ void CWallet::postInitProcess(CScheduler& scheduler) bool CWallet::ParameterInteraction() { + SoftSetArg("-wallet", DEFAULT_WALLET_DAT); + const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1; + if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; @@ -3976,15 +3977,27 @@ bool CWallet::ParameterInteraction() } if (GetBoolArg("-salvagewallet", false) && SoftSetBoolArg("-rescan", true)) { + if (is_multiwallet) { + return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet")); + } // Rewrite just private keys: rescan to find transactions LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); } // -zapwallettx implies a rescan if (GetBoolArg("-zapwallettxes", false) && SoftSetBoolArg("-rescan", true)) { + if (is_multiwallet) { + return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes")); + } LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -rescan=1\n", __func__); } + if (is_multiwallet) { + if (GetBoolArg("-upgradewallet", false)) { + return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet")); + } + } + if (GetBoolArg("-sysperms", false)) return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); if (GetArg("-prune", 0) && GetBoolArg("-rescan", false)) -- cgit v1.2.3 From c237bd750e11472f0f9639891036b975cf7faf15 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 5 Jun 2017 22:23:20 +0000 Subject: wallet: Update formatting --- src/wallet/wallet.cpp | 18 ++++++++++-------- src/wallet/walletdb.cpp | 17 ++++++++++------- 2 files changed, 20 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b3d94e42b2..a7a47e02fd 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -450,24 +450,25 @@ bool CWallet::Verify() } std::string strError; - if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) + if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) { return InitError(strError); + } - if (GetBoolArg("-salvagewallet", false)) - { + if (GetBoolArg("-salvagewallet", false)) { // Recover readable keypairs: CWallet dummyWallet; std::string backup_filename; - if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter, backup_filename)) + if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter, backup_filename)) { return false; + } } std::string strWarning; bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); - if (!strWarning.empty()) + if (!strWarning.empty()) { InitWarning(strWarning); - if (!dbV) - { + } + if (!dbV) { InitError(strError); return false; } @@ -2880,8 +2881,9 @@ bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry) bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwalletdb) { - if (!pwalletdb->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) + if (!pwalletdb->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) { return false; + } laccentries.push_back(acentry); CAccountingEntry & entry = laccentries.back(); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 4dd1ebf677..4e2a963b71 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -60,9 +60,9 @@ bool CWalletDB::EraseTx(uint256 hash) bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta) { - if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), - keyMeta, false)) + if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) { return false; + } // hash pubkey/privkey to accelerate wallet load std::vector vchKey; @@ -79,12 +79,13 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, { const bool fEraseUnencryptedKey = true; - if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), - keyMeta)) + if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) { return false; + } - if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) + if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) { return false; + } if (fEraseUnencryptedKey) { EraseIC(std::make_pair(std::string("key"), vchPubKey)); @@ -106,15 +107,17 @@ bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta) { - if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) + if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) { return false; + } return WriteIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1'); } bool CWalletDB::EraseWatchOnly(const CScript &dest) { - if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) + if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) { return false; + } return EraseIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest))); } -- cgit v1.2.3