diff options
Diffstat (limited to 'src/init.cpp')
-rw-r--r-- | src/init.cpp | 127 |
1 files changed, 89 insertions, 38 deletions
diff --git a/src/init.cpp b/src/init.cpp index 7e2cda6297..4d5720306d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2,7 +2,7 @@ // Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "db.h" +#include "txdb.h" #include "walletdb.h" #include "bitcoinrpc.h" #include "net.h" @@ -50,6 +50,8 @@ void StartShutdown() #endif } +static CCoinsViewDB *pcoinsdbview; + void Shutdown(void* parg) { static CCriticalSection cs_Shutdown; @@ -74,6 +76,14 @@ void Shutdown(void* parg) nTransactionsUpdated++; bitdb.Flush(false); StopNode(); + { + LOCK(cs_main); + pcoinsTip->Flush(); + pblocktree->Flush(); + delete pcoinsTip; + delete pcoinsdbview; + delete pblocktree; + } bitdb.Flush(true); boost::filesystem::remove(GetPidFile()); UnregisterWallet(pwalletMain); @@ -144,7 +154,7 @@ bool AppInit(int argc, char* argv[]) strUsage += "\n" + HelpMessage(); - fprintf(stderr, "%s", strUsage.c_str()); + fprintf(stdout, "%s", strUsage.c_str()); return false; } @@ -279,6 +289,7 @@ std::string HelpMessage() " -upgradewallet " + _("Upgrade wallet to latest format") + "\n" + " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n" + " -rescan " + _("Rescan the block chain for missing wallet transactions") + "\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" + " -loadblock=<file> " + _("Imports blocks from external blk000?.dat file") + "\n" + @@ -297,6 +308,7 @@ std::string HelpMessage() return strUsage; } + /** Initialize bitcoin. * @pre Parameters should be parsed and config file should be read. */ @@ -379,6 +391,11 @@ bool AppInit2() SoftSetBoolArg("-discover", false); } + if (GetBoolArg("-salvagewallet")) { + // Rewrite just private keys: rescan to find transactions + SoftSetBoolArg("-rescan", true); + } + // ********************************************************* Step 3: parameter-to-internal-flags fDebug = GetBoolArg("-debug"); @@ -434,13 +451,15 @@ bool AppInit2() // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log + std::string strDataDir = GetDataDir().string(); + // Make sure only a single Bitcoin process is using the data directory. boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. if (file) fclose(file); static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); if (!lock.try_lock()) - return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().string().c_str())); + return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), strDataDir.c_str())); #if !defined(WIN32) && !defined(QT_GUI) if (fDaemon) @@ -472,7 +491,7 @@ bool AppInit2() if (!fLogTimestamps) printf("Startup time: %s\n", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); printf("Default data directory %s\n", GetDefaultDataDir().string().c_str()); - printf("Used data directory %s\n", GetDataDir().string().c_str()); + printf("Used data directory %s\n", strDataDir.c_str()); std::ostringstream strErrors; if (fDaemon) @@ -480,7 +499,41 @@ bool AppInit2() int64 nStart; - // ********************************************************* Step 5: network initialization + // ********************************************************* Step 5: verify database integrity + + uiInterface.InitMessage(_("Verifying database integrity...")); + + if (!bitdb.Open(GetDataDir())) + { + string msg = strprintf(_("Error initializing database environment %s!" + " To recover, BACKUP THAT DIRECTORY, then remove" + " everything from it except for wallet.dat."), strDataDir.c_str()); + return InitError(msg); + } + + if (GetBoolArg("-salvagewallet")) + { + // Recover readable keypairs: + if (!CWalletDB::Recover(bitdb, "wallet.dat", true)) + return false; + } + + if (filesystem::exists(GetDataDir() / "wallet.dat")) + { + CDBEnv::VerifyResult r = bitdb.Verify("wallet.dat", CWalletDB::Recover); + if (r == CDBEnv::RECOVER_OK) + { + string msg = strprintf(_("Warning: wallet.dat corrupt, data salvaged!" + " Original wallet.dat saved as wallet.{timestamp}.bak in %s; if" + " your balance or transactions are incorrect you should" + " restore from a backup."), strDataDir.c_str()); + uiInterface.ThreadSafeMessageBox(msg, _("Bitcoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL); + } + if (r == CDBEnv::RECOVER_FAIL) + return InitError(_("wallet.dat corrupt, salvage failed")); + } + + // ********************************************************* Step 6: network initialization int nSocksVersion = GetArg("-socks", 5); @@ -586,21 +639,25 @@ bool AppInit2() BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"]) AddOneShot(strDest); - // ********************************************************* Step 6: load blockchain + // ********************************************************* Step 7: load blockchain - if (GetBoolArg("-loadblockindextest")) + if (!bitdb.Open(GetDataDir())) { - CTxDB txdb("r"); - txdb.LoadBlockIndex(); - PrintBlockTree(); - return false; + string msg = strprintf(_("Error initializing database environment %s!" + " To recover, BACKUP THAT DIRECTORY, then remove" + " everything from it except for wallet.dat."), strDataDir.c_str()); + return InitError(msg); } uiInterface.InitMessage(_("Loading block index...")); printf("Loading block index...\n"); nStart = GetTimeMillis(); + pblocktree = new CBlockTreeDB(); + pcoinsdbview = new CCoinsViewDB(); + pcoinsTip = new CCoinsViewCache(*pcoinsdbview); + if (!LoadBlockIndex()) - strErrors << _("Error loading blkindex.dat") << "\n"; + return InitError(_("Error loading blkindex.dat")); // as LoadBlockIndex can take several minutes, it's possible the user // requested to kill bitcoin-qt during the last operation. If so, exit. @@ -641,18 +698,24 @@ bool AppInit2() return false; } - // ********************************************************* Step 7: load wallet + // ********************************************************* Step 8: load wallet uiInterface.InitMessage(_("Loading wallet...")); printf("Loading wallet...\n"); nStart = GetTimeMillis(); bool fFirstRun = true; pwalletMain = new CWallet("wallet.dat"); - int nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun); + 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) + { + string msg(_("Warning: error reading wallet.dat! All keys read correctly, but transaction data" + " or address book entries might be missing or incorrect.")); + uiInterface.ThreadSafeMessageBox(msg, _("Bitcoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL); + } else if (nLoadWalletRet == DB_TOO_NEW) strErrors << _("Error loading wallet.dat: Wallet requires newer version of Bitcoin") << "\n"; else if (nLoadWalletRet == DB_NEED_REWRITE) @@ -718,33 +781,22 @@ bool AppInit2() printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart); } - // ********************************************************* Step 8: import blocks + // ********************************************************* Step 9: import blocks + + // scan for better chains in the block chain database, that are not yet connected in the active best chain + uiInterface.InitMessage(_("Importing blocks from block database...")); + if (!ConnectBestBlock()) + strErrors << "Failed to connect best block"; + std::vector<boost::filesystem::path> *vPath = new std::vector<boost::filesystem::path>(); if (mapArgs.count("-loadblock")) { - uiInterface.InitMessage(_("Importing blockchain data file.")); - BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"]) - { - FILE *file = fopen(strFile.c_str(), "rb"); - if (file) - LoadExternalBlockFile(file); - } - } - - filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; - if (filesystem::exists(pathBootstrap)) { - uiInterface.InitMessage(_("Importing bootstrap blockchain data file.")); - - FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); - if (file) { - filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; - LoadExternalBlockFile(file); - RenameOver(pathBootstrap, pathBootstrapOld); - } + vPath->push_back(strFile); } + NewThread(ThreadImport, vPath); - // ********************************************************* Step 9: load peers + // ********************************************************* Step 10: load peers uiInterface.InitMessage(_("Loading addresses...")); printf("Loading addresses...\n"); @@ -759,7 +811,7 @@ bool AppInit2() printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n", addrman.size(), GetTimeMillis() - nStart); - // ********************************************************* Step 10: start node + // ********************************************************* Step 11: start node if (!CheckDiskSpace()) return false; @@ -779,7 +831,7 @@ bool AppInit2() if (fServer) NewThread(ThreadRPCServer, NULL); - // ********************************************************* Step 11: finished + // ********************************************************* Step 12: finished uiInterface.InitMessage(_("Done loading")); printf("Done loading\n"); @@ -799,4 +851,3 @@ bool AppInit2() return true; } - |