" -enforcecanonical " + _("Enforce transaction scripts to use canonical PUSH operators (default: 1)") + "\n" +
" -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n" +
" -rescan " + _("Rescan the block chain for missing wallet transactions") + "\n" +
+ " -zapwallettxes " + _("Clear list of wallet transactions (diagnostic tool; implies -rescan)") + "\n" +
" -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + "\n" +
" -checkblocks=<n> " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" +
" -checklevel=<n> " + _("How thorough the block verification is (0-6, default: 1)") + "\n" +
SoftSetBoolArg("-rescan", true);
}
+ if (GetBoolArg("-zapwallettxes", false)) {
+ // -zapwallettx implies a rescan
+ if (SoftSetBoolArg("-rescan", true))
+ printf("AppInit2 : parameter interaction: -zapwallettxes=1 -> setting -rescan=1\n");
+ }
+
// ********************************************************* Step 3: parameter-to-internal-flags
fDebug = GetBoolArg("-debug");
// ********************************************************* Step 8: load wallet
+ if (GetBoolArg("-zapwallettxes", false)) {
+ uiInterface.InitMessage(_("Zapping all transactions from wallet..."));
+
+ pwalletMain = new CWallet(strWalletFileName);
+ DBErrors nZapWalletRet = pwalletMain->ZapWalletTx();
+ if (nZapWalletRet != DB_LOAD_OK) {
+ uiInterface.InitMessage(_("Error loading wallet.dat: Wallet corrupted"));
+ return false;
+ }
+ delete pwalletMain;
+ pwalletMain = NULL;
+ }
+
uiInterface.InitMessage(_("Loading wallet..."));
printf("Loading wallet...\n");
nStart = GetTimeMillis();
return DB_LOAD_OK;
}
+DBErrors CWallet::ZapWalletTx()
+{
+ if (!fFileBacked)
+ return DB_LOAD_OK;
+ DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this);
+ if (nZapWalletTxRet == DB_NEED_REWRITE)
+ {
+ if (CDB::Rewrite(strWalletFile, "\x04pool"))
+ {
+ LOCK(cs_wallet);
+ setKeyPool.clear();
+ // Note: can't top-up keypool here, because wallet is locked.
+ // User will be prompted to unlock wallet the next operation
+ // the requires a new key.
+ }
+ }
+
+ if (nZapWalletTxRet != DB_LOAD_OK)
+ return nZapWalletTxRet;
+
+ return DB_LOAD_OK;
+}
bool CWallet::SetAddressBookName(const CTxDestination& address, const string& strName)
{
DBErrors LoadWallet(bool& fFirstRunRet);
+ DBErrors ZapWalletTx();
+
bool SetAddressBookName(const CTxDestination& address, const std::string& strName);
bool DelAddressBookName(const CTxDestination& address);
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)
+ {
+ printf("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)
+ {
+ printf("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(void* parg)
{
// Make this thread recognisable as the wallet flushing thread
DBErrors ReorderTransactions(CWallet*);
DBErrors LoadWallet(CWallet* pwallet);
+ DBErrors FindWalletTx(CWallet* pwallet, std::vector<uint256>& vTxHash);
+ DBErrors ZapWalletTx(CWallet* pwallet);
+
static bool Recover(CDBEnv& dbenv, std::string filename, bool fOnlyKeys);
static bool Recover(CDBEnv& dbenv, std::string filename);
};