diff --git a/src/init.cpp b/src/init.cpp index 2f37dad5..15a46946 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -365,6 +365,8 @@ void ThreadImport(void *data) { pblocktree->WriteReindexing(false); fReindex = false; printf("Reindexing finished\n"); + // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked): + InitBlockIndex(); } } @@ -802,6 +804,10 @@ bool AppInit2() if (!LoadBlockIndex()) return InitError(_("Error loading block database")); + // Initialize the block index (no-op if non-empty database was already loaded) + if (!InitBlockIndex()) + return InitError(_("Error initializing block database")); + uiInterface.InitMessage(_("Verifying block database integrity...")); if (!VerifyDB()) diff --git a/src/main.cpp b/src/main.cpp index df8f7efa..cfb459c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2670,18 +2670,22 @@ bool LoadBlockIndex() if (!fReindex && !LoadBlockIndexDB()) return false; - // - // Init with genesis block - // - if (mapBlockIndex.empty()) - { - fTxIndex = GetBoolArg("-txindex", false); - pblocktree->WriteFlag("txindex", fTxIndex); - printf("Initializing databases...\n"); + return true; +} - if (fReindex) - return true; +bool InitBlockIndex() { + // Check whether we're already initialized + if (pindexGenesisBlock != NULL) + return true; + + // Use the provided setting for -txindex in the new database + fTxIndex = GetBoolArg("-txindex", false); + pblocktree->WriteFlag("txindex", fTxIndex); + printf("Initializing databases...\n"); + + // Only add the genesis block if not reindexing (in which case we reuse the one already on disk) + if (!fReindex) { // Genesis Block: // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1) // CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0) @@ -2722,15 +2726,19 @@ bool LoadBlockIndex() assert(hash == hashGenesisBlock); // Start new block file - unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); - CDiskBlockPos blockPos; - CValidationState state; - if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.nTime)) - return error("AcceptBlock() : FindBlockPos failed"); - if (!block.WriteToDisk(blockPos)) - return error("LoadBlockIndex() : writing genesis block to disk failed"); - if (!block.AddToBlockIndex(state, blockPos)) - return error("LoadBlockIndex() : genesis block not accepted"); + try { + unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); + CDiskBlockPos blockPos; + CValidationState state; + if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.nTime)) + return error("AcceptBlock() : FindBlockPos failed"); + if (!block.WriteToDisk(blockPos)) + return error("LoadBlockIndex() : writing genesis block to disk failed"); + if (!block.AddToBlockIndex(state, blockPos)) + return error("LoadBlockIndex() : genesis block not accepted"); + } catch(std::runtime_error &e) { + return error("LoadBlockIndex() : failed to initialize block database: %s", e.what()); + } } return true; diff --git a/src/main.h b/src/main.h index d8e6a1bd..d69aef94 100644 --- a/src/main.h +++ b/src/main.h @@ -135,6 +135,8 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Import blocks from an external file */ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL); +/** Initialize a new block tree database + block data on disk */ +bool InitBlockIndex(); /** Load the block tree and coins database from disk */ bool LoadBlockIndex(); /** Verify consistency of the block and coin databases */ diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index f75b762f..1116507a 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -28,7 +28,7 @@ struct TestingSetup { pblocktree = new CBlockTreeDB(1 << 20, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsTip = new CCoinsViewCache(*pcoinsdbview); - LoadBlockIndex(); + InitBlockIndex(); bool fFirstRun; pwalletMain = new CWallet("wallet.dat"); pwalletMain->LoadWallet(fFirstRun);