aboutsummaryrefslogtreecommitdiff
path: root/src/validation.cpp
diff options
context:
space:
mode:
authorMatt Corallo <git@bluematt.me>2017-07-06 19:57:20 -0400
committerMatt Corallo <git@bluematt.me>2017-07-27 15:03:05 -0400
commiteda888e57352037ab2e60f6ef90098b3ce23a157 (patch)
treed8e500283bc5ba0e68f2cd4c6a255e8e04ccfd20 /src/validation.cpp
parent5cfdda2503c995cdd563b1a2a29162ac298d173d (diff)
downloadbitcoin-eda888e57352037ab2e60f6ef90098b3ce23a157.tar.xz
Fix some LoadChainTip-related init-order bugs.
* Move the writing of fTxIndex to LoadBlockIndex - this fixes a bug introduced in d6af06d68aae985436cbc942f0d11078041d121b 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.
Diffstat (limited to 'src/validation.cpp')
-rw-r--r--src/validation.cpp67
1 files changed, 40 insertions, 27 deletions
diff --git a/src/validation.cpp b/src/validation.cpp
index d7d880d24f..ebbdb7e651 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3864,42 +3864,55 @@ void UnloadBlockIndex()
bool LoadBlockIndex(const CChainParams& chainparams)
{
// Load block index from databases
- if (!fReindex && !LoadBlockIndexDB(chainparams))
- return false;
+ bool needs_init = fReindex;
+ 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;
}
-bool InitBlockIndex(const CChainParams& chainparams)
+bool LoadGenesisBlock(const CChainParams& chainparams)
{
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(chainparams.GenesisBlock().GetHash()))
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)
- if (!fReindex) {
- try {
- CBlock &block = const_cast<CBlock&>(chainparams.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, chainparams.MessageStart()))
- return error("LoadBlockIndex(): writing genesis block to disk failed");
- CBlockIndex *pindex = AddToBlockIndex(block);
- if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus()))
- 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<CBlock&>(chainparams.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, chainparams.MessageStart()))
+ return error("%s: writing genesis block to disk failed", __func__);
+ CBlockIndex *pindex = AddToBlockIndex(block);
+ if (!ReceivedBlockTransactions(block, state, pindex, blockPos, chainparams.GetConsensus()))
+ 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;