mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
Fix some LoadChainTip-related init-order bugs.
* Move the writing of fTxIndex to LoadBlockIndex - this fixes a
bug introduced in d6af06d68a
where
InitBlockIndex was writing to fTxIndex which had not yet been
checked (because LoadChainTip hadn't yet initialized the
chainActive, which would otherwise have resulted in
InitBlockIndex being a NOP), allowing you to modify -txindex
without reindex, potentially corrupting your chainstate!
* Rename InitBlockIndex to LoadGenesisBlock, which is now a more
natural name for it. Also check mapBlockIndex instead of
chainActive, fixing a bug where we'd write the genesis block out
on every start.
This commit is contained in:
parent
5cfdda2503
commit
eda888e573
4 changed files with 47 additions and 33 deletions
|
@ -646,7 +646,7 @@ void ThreadImport(std::vector<fs::path> vImportFiles)
|
||||||
fReindex = false;
|
fReindex = false;
|
||||||
LogPrintf("Reindexing finished\n");
|
LogPrintf("Reindexing finished\n");
|
||||||
// To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
|
// To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
|
||||||
InitBlockIndex(chainparams);
|
LoadGenesisBlock(chainparams);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hardcoded $DATADIR/bootstrap.dat
|
// hardcoded $DATADIR/bootstrap.dat
|
||||||
|
@ -1419,7 +1419,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
|
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
|
||||||
|
|
||||||
// Initialize the block index (no-op if non-empty database was already loaded)
|
// Initialize the block index (no-op if non-empty database was already loaded)
|
||||||
if (!InitBlockIndex(chainparams)) {
|
if (!fReindex && !LoadGenesisBlock(chainparams)) {
|
||||||
strLoadError = _("Error initializing block database");
|
strLoadError = _("Error initializing block database");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
|
||||||
pblocktree = new CBlockTreeDB(1 << 20, true);
|
pblocktree = new CBlockTreeDB(1 << 20, true);
|
||||||
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
|
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
|
||||||
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
|
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
|
||||||
if (!InitBlockIndex(chainparams)) {
|
if (!LoadGenesisBlock(chainparams)) {
|
||||||
throw std::runtime_error("InitBlockIndex failed.");
|
throw std::runtime_error("InitBlockIndex failed.");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
|
@ -3864,42 +3864,55 @@ void UnloadBlockIndex()
|
||||||
bool LoadBlockIndex(const CChainParams& chainparams)
|
bool LoadBlockIndex(const CChainParams& chainparams)
|
||||||
{
|
{
|
||||||
// Load block index from databases
|
// Load block index from databases
|
||||||
if (!fReindex && !LoadBlockIndexDB(chainparams))
|
bool needs_init = fReindex;
|
||||||
return false;
|
if (!fReindex) {
|
||||||
|
bool ret = LoadBlockIndexDB(chainparams);
|
||||||
|
if (!ret) 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 = GetBoolArg("-txindex", DEFAULT_TXINDEX);
|
||||||
|
pblocktree->WriteFlag("txindex", fTxIndex);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InitBlockIndex(const CChainParams& chainparams)
|
bool LoadGenesisBlock(const CChainParams& chainparams)
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
// Check whether we're already initialized
|
// Check whether we're already initialized by checking for genesis in
|
||||||
if (chainActive.Genesis() != NULL)
|
// 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(chainparams.GenesisBlock().GetHash()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Use the provided setting for -txindex in the new database
|
|
||||||
fTxIndex = GetBoolArg("-txindex", DEFAULT_TXINDEX);
|
|
||||||
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)
|
// Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
|
||||||
if (!fReindex) {
|
try {
|
||||||
try {
|
CBlock &block = const_cast<CBlock&>(chainparams.GenesisBlock());
|
||||||
CBlock &block = const_cast<CBlock&>(chainparams.GenesisBlock());
|
// Start new block file
|
||||||
// Start new block file
|
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
|
||||||
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
|
CDiskBlockPos blockPos;
|
||||||
CDiskBlockPos blockPos;
|
CValidationState state;
|
||||||
CValidationState state;
|
if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.GetBlockTime()))
|
||||||
if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.GetBlockTime()))
|
return error("%s: FindBlockPos failed", __func__);
|
||||||
return error("LoadBlockIndex(): FindBlockPos failed");
|
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
|
||||||
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart()))
|
return error("%s: writing genesis block to disk failed", __func__);
|
||||||
return error("LoadBlockIndex(): writing genesis block to disk failed");
|
CBlockIndex *pindex = AddToBlockIndex(block);
|
||||||
CBlockIndex *pindex = AddToBlockIndex(block);
|
if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus()))
|
||||||
if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus()))
|
return error("%s: genesis block not accepted", __func__);
|
||||||
return error("LoadBlockIndex(): genesis block not accepted");
|
} catch (const std::runtime_error& e) {
|
||||||
} catch (const std::runtime_error& e) {
|
return error("%s: failed to write genesis block: %s", __func__, e.what());
|
||||||
return error("LoadBlockIndex(): failed to initialize block database: %s", e.what());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -256,9 +256,10 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
|
||||||
fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix);
|
fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix);
|
||||||
/** Import blocks from an external file */
|
/** Import blocks from an external file */
|
||||||
bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = NULL);
|
bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = NULL);
|
||||||
/** Initialize a new block tree database + block data on disk */
|
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
|
||||||
bool InitBlockIndex(const CChainParams& chainparams);
|
bool LoadGenesisBlock(const CChainParams& chainparams);
|
||||||
/** Load the block tree and coins database from disk */
|
/** Load the block tree and coins database from disk,
|
||||||
|
* initializing state if we're running with -reindex. */
|
||||||
bool LoadBlockIndex(const CChainParams& chainparams);
|
bool LoadBlockIndex(const CChainParams& chainparams);
|
||||||
/** Update the chain tip based on database information. */
|
/** Update the chain tip based on database information. */
|
||||||
void LoadChainTip(const CChainParams& chainparams);
|
void LoadChainTip(const CChainParams& chainparams);
|
||||||
|
|
Loading…
Add table
Reference in a new issue