diff --git a/src/init.cpp b/src/init.cpp index cc2c917397f61..a179ea5bf73c3 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -688,7 +688,7 @@ void ThreadImport(const std::vector& vImportFiles) fReindex = false; LogPrintf("Reindexing finished\n"); // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked): - InitBlockIndex(); + LoadGenesisBlock(); } // hardcoded $DATADIR/bootstrap.dat @@ -1620,7 +1620,7 @@ bool AppInitMain() return UIError(_("Incorrect or no genesis block found. Wrong datadir for network?")); // Initialize the block index (no-op if non-empty database was already loaded) - if (!InitBlockIndex()) { + if (!LoadGenesisBlock()) { strLoadError = _("Error initializing block database"); break; } diff --git a/src/test/test_pivx.cpp b/src/test/test_pivx.cpp index d1aa0e6baca56..5e009205a53ae 100644 --- a/src/test/test_pivx.cpp +++ b/src/test/test_pivx.cpp @@ -72,7 +72,7 @@ TestingSetup::TestingSetup() pblocktree = new CBlockTreeDB(1 << 20, true); pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsTip = new CCoinsViewCache(pcoinsdbview); - InitBlockIndex(); + LoadGenesisBlock(); { CValidationState state; bool ok = ActivateBestChain(state); diff --git a/src/validation.cpp b/src/validation.cpp index b18919d97158d..5e882b3b21ed3 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3743,45 +3743,56 @@ void UnloadBlockIndex() bool LoadBlockIndex(std::string& strError) { - // Load block index from databases - if (!fReindex && !LoadBlockIndexDB(strError)) - return false; + bool needs_init = fReindex; + if (!fReindex) { + if (!LoadBlockIndexDB(strError)) + return false; + needs_init = mapBlockIndex.empty(); + } + + if (needs_init) { + // Everything here is for *new* reindex/DBs. Thus, though + // LoadBlockIndexDB may have set fReindex if we shut down + // mid-reindex previously, we don't check fReindex and + // instead only check it prior to LoadBlockIndexDB to set + // needs_init. + + LogPrintf("Initializing databases...\n"); + // Use the provided setting for -txindex in the new database + fTxIndex = gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX); + pblocktree->WriteFlag("txindex", fTxIndex); + } return true; } -bool InitBlockIndex() +bool LoadGenesisBlock() { LOCK(cs_main); - // Check whether we're already initialized - if (chainActive.Genesis() != NULL) + // Check whether we're already initialized by checking for genesis in + // mapBlockIndex. Note that we can't use chainActive here, since it is + // set based on the coins db, not the block index db, which is the only + // thing loaded at this point. + if (mapBlockIndex.count(Params().GenesisBlock().GetHash())) return true; - // Use the provided setting for -txindex in the new database - fTxIndex = gArgs.GetBoolArg("-txindex", true); - pblocktree->WriteFlag("txindex", fTxIndex); - LogPrintf("Initializing databases...\n"); - - // Only add the genesis block if not reindexing (in which case we reuse the one already on disk) - if (!fReindex) { - try { - CBlock& block = const_cast(Params().GenesisBlock()); - // 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.GetBlockTime())) - return error("LoadBlockIndex() : FindBlockPos failed"); - if (!WriteBlockToDisk(block, blockPos)) - return error("LoadBlockIndex() : writing genesis block to disk failed"); - CBlockIndex* pindex = AddToBlockIndex(block); - if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) - return error("LoadBlockIndex() : genesis block not accepted"); - } catch (const std::runtime_error& e) { - return error("LoadBlockIndex() : failed to initialize block database: %s", e.what()); - } - } + try { + CBlock& block = const_cast(Params().GenesisBlock()); + // 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.GetBlockTime())) + return error("%s: FindBlockPos failed", __func__); + if (!WriteBlockToDisk(block, blockPos)) + return error("%s: writing genesis block to disk failed", __func__); + CBlockIndex *pindex = AddToBlockIndex(block); + if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) + return error("%s: genesis block not accepted", __func__); + } catch (const std::runtime_error& e) { + return error("%s: failed to write genesis block: %s", __func__, e.what()); + } return true; } diff --git a/src/validation.h b/src/validation.h index 407455208ba98..d0ff2c1d9f3f2 100644 --- a/src/validation.h +++ b/src/validation.h @@ -183,9 +183,10 @@ FILE* OpenUndoFile(const CDiskBlockPos& pos, bool fReadOnly = false); fs::path GetBlockPosFilename(const CDiskBlockPos& pos, const char* prefix); /** 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 */ +/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */ +bool LoadGenesisBlock(); +/** Load the block tree and coins database from disk, + * initializing state if we're running with -reindex. */ bool LoadBlockIndex(std::string& strError); /** Update the chain tip based on database information. */ void LoadChainTip(const CChainParams& chainparams);