Skip to content

Commit 9bcc942

Browse files
committed
Fix some LoadChainTip-related init-order bugs.
>>> adapts bitcoin/bitcoin@eda888e * Move the writing of fTxIndex to LoadBlockIndex - this fixes a bug introduced in d6af06d 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.
1 parent 99f478b commit 9bcc942

File tree

4 files changed

+48
-36
lines changed

4 files changed

+48
-36
lines changed

src/init.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ void ThreadImport(const std::vector<fs::path>& vImportFiles)
688688
fReindex = false;
689689
LogPrintf("Reindexing finished\n");
690690
// To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
691-
InitBlockIndex();
691+
LoadGenesisBlock();
692692
}
693693

694694
// hardcoded $DATADIR/bootstrap.dat
@@ -1620,7 +1620,7 @@ bool AppInitMain()
16201620
return UIError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
16211621

16221622
// Initialize the block index (no-op if non-empty database was already loaded)
1623-
if (!InitBlockIndex()) {
1623+
if (!LoadGenesisBlock()) {
16241624
strLoadError = _("Error initializing block database");
16251625
break;
16261626
}

src/test/test_pivx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ TestingSetup::TestingSetup()
7272
pblocktree = new CBlockTreeDB(1 << 20, true);
7373
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
7474
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
75-
InitBlockIndex();
75+
LoadGenesisBlock();
7676
{
7777
CValidationState state;
7878
bool ok = ActivateBestChain(state);

src/validation.cpp

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3743,45 +3743,56 @@ void UnloadBlockIndex()
37433743

37443744
bool LoadBlockIndex(std::string& strError)
37453745
{
3746-
// Load block index from databases
3747-
if (!fReindex && !LoadBlockIndexDB(strError))
3748-
return false;
3746+
bool needs_init = fReindex;
3747+
if (!fReindex) {
3748+
if (!LoadBlockIndexDB(strError))
3749+
return false;
3750+
needs_init = mapBlockIndex.empty();
3751+
}
3752+
3753+
if (needs_init) {
3754+
// Everything here is for *new* reindex/DBs. Thus, though
3755+
// LoadBlockIndexDB may have set fReindex if we shut down
3756+
// mid-reindex previously, we don't check fReindex and
3757+
// instead only check it prior to LoadBlockIndexDB to set
3758+
// needs_init.
3759+
3760+
LogPrintf("Initializing databases...\n");
3761+
// Use the provided setting for -txindex in the new database
3762+
fTxIndex = gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX);
3763+
pblocktree->WriteFlag("txindex", fTxIndex);
3764+
}
37493765
return true;
37503766
}
37513767

37523768

3753-
bool InitBlockIndex()
3769+
bool LoadGenesisBlock()
37543770
{
37553771
LOCK(cs_main);
37563772

3757-
// Check whether we're already initialized
3758-
if (chainActive.Genesis() != NULL)
3773+
// Check whether we're already initialized by checking for genesis in
3774+
// mapBlockIndex. Note that we can't use chainActive here, since it is
3775+
// set based on the coins db, not the block index db, which is the only
3776+
// thing loaded at this point.
3777+
if (mapBlockIndex.count(Params().GenesisBlock().GetHash()))
37593778
return true;
37603779

3761-
// Use the provided setting for -txindex in the new database
3762-
fTxIndex = gArgs.GetBoolArg("-txindex", true);
3763-
pblocktree->WriteFlag("txindex", fTxIndex);
3764-
LogPrintf("Initializing databases...\n");
3765-
3766-
// Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
3767-
if (!fReindex) {
3768-
try {
3769-
CBlock& block = const_cast<CBlock&>(Params().GenesisBlock());
3770-
// Start new block file
3771-
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
3772-
CDiskBlockPos blockPos;
3773-
CValidationState state;
3774-
if (!FindBlockPos(state, blockPos, nBlockSize + 8, 0, block.GetBlockTime()))
3775-
return error("LoadBlockIndex() : FindBlockPos failed");
3776-
if (!WriteBlockToDisk(block, blockPos))
3777-
return error("LoadBlockIndex() : writing genesis block to disk failed");
3778-
CBlockIndex* pindex = AddToBlockIndex(block);
3779-
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
3780-
return error("LoadBlockIndex() : genesis block not accepted");
3781-
} catch (const std::runtime_error& e) {
3782-
return error("LoadBlockIndex() : failed to initialize block database: %s", e.what());
3783-
}
3784-
}
3780+
try {
3781+
CBlock& block = const_cast<CBlock&>(Params().GenesisBlock());
3782+
// Start new block file
3783+
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
3784+
CDiskBlockPos blockPos;
3785+
CValidationState state;
3786+
if (!FindBlockPos(state, blockPos, nBlockSize + 8, 0, block.GetBlockTime()))
3787+
return error("%s: FindBlockPos failed", __func__);
3788+
if (!WriteBlockToDisk(block, blockPos))
3789+
return error("%s: writing genesis block to disk failed", __func__);
3790+
CBlockIndex *pindex = AddToBlockIndex(block);
3791+
if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
3792+
return error("%s: genesis block not accepted", __func__);
3793+
} catch (const std::runtime_error& e) {
3794+
return error("%s: failed to write genesis block: %s", __func__, e.what());
3795+
}
37853796

37863797
return true;
37873798
}

src/validation.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,10 @@ FILE* OpenUndoFile(const CDiskBlockPos& pos, bool fReadOnly = false);
183183
fs::path GetBlockPosFilename(const CDiskBlockPos& pos, const char* prefix);
184184
/** Import blocks from an external file */
185185
bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos* dbp = NULL);
186-
/** Initialize a new block tree database + block data on disk */
187-
bool InitBlockIndex();
188-
/** Load the block tree and coins database from disk */
186+
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
187+
bool LoadGenesisBlock();
188+
/** Load the block tree and coins database from disk,
189+
* initializing state if we're running with -reindex. */
189190
bool LoadBlockIndex(std::string& strError);
190191
/** Update the chain tip based on database information. */
191192
void LoadChainTip(const CChainParams& chainparams);

0 commit comments

Comments
 (0)