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.
This commit is contained in:
Jeff Garzik
2014-02-14 11:33:07 -05:00
parent 6056c87d25
commit 518f3bdae3
5 changed files with 128 additions and 0 deletions

View File

@@ -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