diff --git a/src/init.cpp b/src/init.cpp index 6973574cf..ba9860014 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1424,149 +1424,19 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); } else { - - // needed to restore wallet transaction meta data after -zapwallettxes - std::vector vWtx; - - if (GetBoolArg("-zapwallettxes", false)) { - uiInterface.InitMessage(_("Zapping all transactions from wallet...")); - - pwalletMain = new CWallet(strWalletFile); - DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(vWtx); - if (nZapWalletRet != DB_LOAD_OK) { - uiInterface.InitMessage(_("Error loading wallet.dat: Wallet corrupted")); - return false; - } - - delete pwalletMain; - pwalletMain = NULL; - } - - uiInterface.InitMessage(_("Loading wallet...")); - - nStart = GetTimeMillis(); - bool fFirstRun = true; - pwalletMain = new CWallet(strWalletFile); - DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun); - if (nLoadWalletRet != DB_LOAD_OK) - { - if (nLoadWalletRet == DB_CORRUPT) - strErrors << _("Error loading wallet.dat: Wallet corrupted") << "\n"; - else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) - { - InitWarning(_("Error reading wallet.dat! All keys read correctly, but transaction data" - " or address book entries might be missing or incorrect.")); - } - else if (nLoadWalletRet == DB_TOO_NEW) - strErrors << strprintf(_("Error loading wallet.dat: Wallet requires newer version of %s"), _(PACKAGE_NAME)) << "\n"; - else if (nLoadWalletRet == DB_NEED_REWRITE) - { - strErrors << strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)) << "\n"; - LogPrintf("%s", strErrors.str()); - return InitError(strErrors.str()); - } - else - strErrors << _("Error loading wallet.dat") << "\n"; - } - - if (GetBoolArg("-upgradewallet", fFirstRun)) - { - int nMaxVersion = GetArg("-upgradewallet", 0); - if (nMaxVersion == 0) // the -upgradewallet without argument case - { - LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST); - nMaxVersion = CLIENT_VERSION; - pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately - } - else - LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); - if (nMaxVersion < pwalletMain->GetVersion()) - strErrors << _("Cannot downgrade wallet") << "\n"; - pwalletMain->SetMaxVersion(nMaxVersion); - } - - if (fFirstRun) - { - // Create new keyUser and set as default key - RandAddSeedPerfmon(); - - CPubKey newDefaultKey; - if (pwalletMain->GetKeyFromPool(newDefaultKey)) { - pwalletMain->SetDefaultKey(newDefaultKey); - if (!pwalletMain->SetAddressBook(pwalletMain->vchDefaultKey.GetID(), "", "receive")) - strErrors << _("Cannot write default address") << "\n"; - } - - pwalletMain->SetBestChain(chainActive.GetLocator()); - } - - LogPrintf("%s", strErrors.str()); - LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); - - RegisterValidationInterface(pwalletMain); - - CBlockIndex *pindexRescan = chainActive.Tip(); - if (GetBoolArg("-rescan", false)) - pindexRescan = chainActive.Genesis(); - else - { - CWalletDB walletdb(strWalletFile); - CBlockLocator locator; - if (walletdb.ReadBestBlock(locator)) - pindexRescan = FindForkInGlobalIndex(chainActive, locator); - else - pindexRescan = chainActive.Genesis(); - } - if (chainActive.Tip() && chainActive.Tip() != pindexRescan) + std::string warningString; + std::string errorString; + pwalletMain = CWallet::InitLoadWallet(fDisableWallet, strWalletFile, warningString, errorString); + if (!warningString.empty()) + InitWarning(warningString); + if (!errorString.empty()) { - //We can't rescan beyond non-pruned blocks, stop and throw an error - //this might happen if a user uses a old wallet within a pruned node - // or if he ran -disablewallet for a longer time, then decided to re-enable - if (fPruneMode) - { - CBlockIndex *block = chainActive.Tip(); - while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block) - block = block->pprev; - - 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)")); - } - - uiInterface.InitMessage(_("Rescanning...")); - LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight); - nStart = GetTimeMillis(); - pwalletMain->ScanForWalletTransactions(pindexRescan, true); - LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); - pwalletMain->SetBestChain(chainActive.GetLocator()); - nWalletDBUpdated++; - - // Restore wallet transaction metadata after -zapwallettxes=1 - if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") - { - CWalletDB walletdb(strWalletFile); - - BOOST_FOREACH(const CWalletTx& wtxOld, vWtx) - { - uint256 hash = wtxOld.GetHash(); - std::map::iterator mi = pwalletMain->mapWallet.find(hash); - if (mi != pwalletMain->mapWallet.end()) - { - const CWalletTx* copyFrom = &wtxOld; - CWalletTx* copyTo = &mi->second; - copyTo->mapValue = copyFrom->mapValue; - copyTo->vOrderForm = copyFrom->vOrderForm; - copyTo->nTimeReceived = copyFrom->nTimeReceived; - copyTo->nTimeSmart = copyFrom->nTimeSmart; - copyTo->fFromMe = copyFrom->fFromMe; - copyTo->strFromAccount = copyFrom->strFromAccount; - copyTo->nOrderPos = copyFrom->nOrderPos; - copyTo->WriteToDisk(&walletdb); - } - } - } + LogPrintf("%s", errorString); + return InitError(errorString); } - pwalletMain->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); - } // (!fDisableWallet) + if (!pwalletMain) + return false; + } #else // ENABLE_WALLET LogPrintf("No wallet support compiled in!\n"); #endif // !ENABLE_WALLET diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6ce7fcbb2..d409d7480 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2991,6 +2991,164 @@ std::string CWallet::GetWalletHelpString(bool showDebug) return strUsage; } +CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString) +{ + // needed to restore wallet transaction meta data after -zapwallettxes + std::vector vWtx; + + if (GetBoolArg("-zapwallettxes", false)) { + uiInterface.InitMessage(_("Zapping all transactions from wallet...")); + + CWallet *tempWallet = new CWallet(strWalletFile); + DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); + if (nZapWalletRet != DB_LOAD_OK) { + errorString = _("Error loading wallet.dat: Wallet corrupted"); + uiInterface.InitMessage(_("Error loading wallet.dat: Wallet corrupted")); + return NULL; + } + + delete tempWallet; + tempWallet = NULL; + } + + uiInterface.InitMessage(_("Loading wallet...")); + + int64_t nStart = GetTimeMillis(); + bool fFirstRun = true; + CWallet *walletInstance = new CWallet(strWalletFile); + DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); + if (nLoadWalletRet != DB_LOAD_OK) + { + if (nLoadWalletRet == DB_CORRUPT) + errorString += _("Error loading wallet.dat: Wallet corrupted") + "\n"; + else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) + { + warningString += _("Error reading wallet.dat! All keys read correctly, but transaction data" + " or address book entries might be missing or incorrect."); + } + else if (nLoadWalletRet == DB_TOO_NEW) + errorString += strprintf(_("Error loading wallet.dat: Wallet requires newer version of %s"), _(PACKAGE_NAME)) + "\n"; + else if (nLoadWalletRet == DB_NEED_REWRITE) + { + errorString += strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)) + "\n"; + LogPrintf("%s", errorString); + } + else + errorString += _("Error loading wallet.dat") + "\n"; + + if (!errorString.empty()) + return NULL; + } + + if (GetBoolArg("-upgradewallet", fFirstRun)) + { + int nMaxVersion = GetArg("-upgradewallet", 0); + if (nMaxVersion == 0) // the -upgradewallet without argument case + { + LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST); + nMaxVersion = CLIENT_VERSION; + walletInstance->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately + } + else + LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); + if (nMaxVersion < walletInstance->GetVersion()) + { + errorString += _("Cannot downgrade wallet") + "\n"; + return NULL; + } + walletInstance->SetMaxVersion(nMaxVersion); + } + + if (fFirstRun) + { + // Create new keyUser and set as default key + RandAddSeedPerfmon(); + + CPubKey newDefaultKey; + if (walletInstance->GetKeyFromPool(newDefaultKey)) { + walletInstance->SetDefaultKey(newDefaultKey); + if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive")) + { + errorString += _("Cannot write default address") += "\n"; + return NULL; + } + } + + walletInstance->SetBestChain(chainActive.GetLocator()); + } + + LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); + + RegisterValidationInterface(walletInstance); + + CBlockIndex *pindexRescan = chainActive.Tip(); + if (GetBoolArg("-rescan", false)) + pindexRescan = chainActive.Genesis(); + else + { + CWalletDB walletdb(strWalletFile); + CBlockLocator locator; + if (walletdb.ReadBestBlock(locator)) + pindexRescan = FindForkInGlobalIndex(chainActive, locator); + else + pindexRescan = chainActive.Genesis(); + } + if (chainActive.Tip() && chainActive.Tip() != pindexRescan) + { + //We can't rescan beyond non-pruned blocks, stop and throw an error + //this might happen if a user uses a old wallet within a pruned node + // or if he ran -disablewallet for a longer time, then decided to re-enable + if (fPruneMode) + { + CBlockIndex *block = chainActive.Tip(); + while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block) + block = block->pprev; + + if (pindexRescan != block) + { + errorString = _("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...")); + LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight); + nStart = GetTimeMillis(); + walletInstance->ScanForWalletTransactions(pindexRescan, true); + LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); + walletInstance->SetBestChain(chainActive.GetLocator()); + nWalletDBUpdated++; + + // Restore wallet transaction metadata after -zapwallettxes=1 + if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") + { + CWalletDB walletdb(strWalletFile); + + BOOST_FOREACH(const CWalletTx& wtxOld, vWtx) + { + uint256 hash = wtxOld.GetHash(); + std::map::iterator mi = walletInstance->mapWallet.find(hash); + if (mi != walletInstance->mapWallet.end()) + { + const CWalletTx* copyFrom = &wtxOld; + CWalletTx* copyTo = &mi->second; + copyTo->mapValue = copyFrom->mapValue; + copyTo->vOrderForm = copyFrom->vOrderForm; + copyTo->nTimeReceived = copyFrom->nTimeReceived; + copyTo->nTimeSmart = copyFrom->nTimeSmart; + copyTo->fFromMe = copyFrom->fFromMe; + copyTo->strFromAccount = copyFrom->strFromAccount; + copyTo->nOrderPos = copyFrom->nOrderPos; + copyTo->WriteToDisk(&walletdb); + } + } + } + } + walletInstance->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); + + return walletInstance; +} + CKeyPool::CKeyPool() { nTime = GetTime(); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 6312735c9..d009211a9 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -874,6 +874,9 @@ public: /* Returns the wallets help message */ static std::string GetWalletHelpString(bool showDebug); + + /* initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ + static CWallet* InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString); }; /** A key allocated from the key pool. */