diff options
author | Jeff Garzik <jgarzik@bitpay.com> | 2014-02-14 11:33:07 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@bitpay.com> | 2014-02-14 11:33:07 -0500 |
commit | 518f3bdae3415fdb60cef984b69b36f2633c1fe1 (patch) | |
tree | 98022a0e8b5a3c2b5ab50fbb6089a8d2e29c0967 /src/walletdb.cpp | |
parent | 6056c87d25994bbceb23d6ae50df1276a51d51bd (diff) |
Add -zapwallettxes cli/config option, used for wallet recovery
This diagnostic tool removes all "tx" records from the wallet db,
then forces a full rescan, to rebuild "tx" records accurately.
Diffstat (limited to 'src/walletdb.cpp')
-rw-r--r-- | src/walletdb.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 56349fcfbd..b3cc9a2350 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -684,6 +684,86 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) return result; } +DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash) +{ + pwallet->vchDefaultKey = CPubKey(); + CWalletScanState wss; + bool fNoncriticalErrors = false; + DBErrors result = DB_LOAD_OK; + + try { + LOCK(pwallet->cs_wallet); + int nMinVersion = 0; + if (Read((string)"minversion", nMinVersion)) + { + if (nMinVersion > CLIENT_VERSION) + return DB_TOO_NEW; + pwallet->LoadMinVersion(nMinVersion); + } + + // Get cursor + Dbc* pcursor = GetCursor(); + if (!pcursor) + { + LogPrintf("Error getting wallet database cursor\n"); + return DB_CORRUPT; + } + + while (true) + { + // Read next record + CDataStream ssKey(SER_DISK, CLIENT_VERSION); + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + int ret = ReadAtCursor(pcursor, ssKey, ssValue); + if (ret == DB_NOTFOUND) + break; + else if (ret != 0) + { + LogPrintf("Error reading next record from wallet database\n"); + return DB_CORRUPT; + } + + string strType; + ssKey >> strType; + if (strType == "tx") { + uint256 hash; + ssKey >> hash; + + vTxHash.push_back(hash); + } + } + pcursor->close(); + } + catch (boost::thread_interrupted) { + throw; + } + catch (...) { + result = DB_CORRUPT; + } + + if (fNoncriticalErrors && result == DB_LOAD_OK) + result = DB_NONCRITICAL_ERROR; + + return result; +} + +DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet) +{ + // build list of wallet TXs + vector<uint256> vTxHash; + DBErrors err = FindWalletTx(pwallet, vTxHash); + if (err != DB_LOAD_OK) + return err; + + // erase each wallet TX + BOOST_FOREACH (uint256& hash, vTxHash) { + if (!EraseTx(hash)) + return DB_CORRUPT; + } + + return DB_LOAD_OK; +} + void ThreadFlushWalletDB(const string& strFile) { // Make this thread recognisable as the wallet flushing thread |