Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 4,040 Lines • ▼ Show 20 Lines | static bool LoadBlockIndexDB(const Config &config) { | ||||
// Check whether we have a transaction index | // Check whether we have a transaction index | ||||
pblocktree->ReadFlag("txindex", fTxIndex); | pblocktree->ReadFlag("txindex", fTxIndex); | ||||
LogPrintf("%s: transaction index %s\n", __func__, | LogPrintf("%s: transaction index %s\n", __func__, | ||||
fTxIndex ? "enabled" : "disabled"); | fTxIndex ? "enabled" : "disabled"); | ||||
return true; | return true; | ||||
} | } | ||||
void LoadChainTip(const CChainParams &chainparams) { | bool LoadChainTip(const Config &config) { | ||||
if (chainActive.Tip() && | if (chainActive.Tip() && | ||||
chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) { | chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) { | ||||
return; | return true; | ||||
} | |||||
if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) { | |||||
// In case we just added the genesis block, connect it now, so | |||||
// that we always have a chainActive.Tip() when we return. | |||||
LogPrintf("%s: Connecting genesis block...\n", __func__); | |||||
CValidationState state; | |||||
if (!ActivateBestChain(config, state)) { | |||||
return false; | |||||
} | |||||
} | } | ||||
// Load pointer to end of best chain | // Load pointer to end of best chain | ||||
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); | BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); | ||||
if (it == mapBlockIndex.end()) { | if (it == mapBlockIndex.end()) { | ||||
return; | return false; | ||||
} | } | ||||
chainActive.SetTip(it->second); | chainActive.SetTip(it->second); | ||||
PruneBlockIndexCandidates(); | PruneBlockIndexCandidates(); | ||||
LogPrintf( | LogPrintf( | ||||
"Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n", | "Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n", | ||||
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), | chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), | ||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", | DateTimeStrFormat("%Y-%m-%d %H:%M:%S", | ||||
chainActive.Tip()->GetBlockTime()), | chainActive.Tip()->GetBlockTime()), | ||||
GuessVerificationProgress(chainparams.TxData(), chainActive.Tip())); | GuessVerificationProgress(config.GetChainParams().TxData(), | ||||
chainActive.Tip())); | |||||
return true; | |||||
} | } | ||||
CVerifyDB::CVerifyDB() { | CVerifyDB::CVerifyDB() { | ||||
uiInterface.ShowProgress(_("Verifying blocks..."), 0); | uiInterface.ShowProgress(_("Verifying blocks..."), 0); | ||||
} | } | ||||
CVerifyDB::~CVerifyDB() { | CVerifyDB::~CVerifyDB() { | ||||
uiInterface.ShowProgress("", 100); | uiInterface.ShowProgress("", 100); | ||||
▲ Show 20 Lines • Show All 319 Lines • ▼ Show 20 Lines | bool RewindBlockIndex(const Config &config) { | ||||
for (const std::pair<uint256, CBlockIndex *> &p : mapBlockIndex) { | for (const std::pair<uint256, CBlockIndex *> &p : mapBlockIndex) { | ||||
CBlockIndex *pindexIter = p.second; | CBlockIndex *pindexIter = p.second; | ||||
if (pindexIter->IsValid(BlockValidity::TRANSACTIONS) && | if (pindexIter->IsValid(BlockValidity::TRANSACTIONS) && | ||||
pindexIter->nChainTx) { | pindexIter->nChainTx) { | ||||
setBlockIndexCandidates.insert(pindexIter); | setBlockIndexCandidates.insert(pindexIter); | ||||
} | } | ||||
} | } | ||||
if (chainActive.Tip() != nullptr) { | |||||
// We can't prune block index candidates based on our tip if we have | |||||
// no tip due to chainActive being empty! | |||||
PruneBlockIndexCandidates(); | PruneBlockIndexCandidates(); | ||||
CheckBlockIndex(params.GetConsensus()); | CheckBlockIndex(params.GetConsensus()); | ||||
// FlushStateToDisk can possibly read chainActive. Be conservative | |||||
// and skip it here, we're about to -reindex-chainstate anyway, so | |||||
// it'll get called a bunch real soon. | |||||
if (!FlushStateToDisk(params, state, FLUSH_STATE_ALWAYS)) { | if (!FlushStateToDisk(params, state, FLUSH_STATE_ALWAYS)) { | ||||
return false; | return false; | ||||
} | } | ||||
} | |||||
return true; | return true; | ||||
} | } | ||||
// May NOT be used after any connections are up as much of the peer-processing | // May NOT be used after any connections are up as much of the peer-processing | ||||
// logic assumes a consistent block index state | // logic assumes a consistent block index state | ||||
void UnloadBlockIndex() { | void UnloadBlockIndex() { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Show All 15 Lines | void UnloadBlockIndex() { | ||||
} | } | ||||
mapBlockIndex.clear(); | mapBlockIndex.clear(); | ||||
fHavePruned = false; | fHavePruned = false; | ||||
} | } | ||||
bool LoadBlockIndex(const Config &config) { | bool LoadBlockIndex(const Config &config) { | ||||
// Load block index from databases | // Load block index from databases | ||||
if (!fReindex && !LoadBlockIndexDB(config)) { | bool needs_init = fReindex; | ||||
if (!fReindex) { | |||||
bool ret = LoadBlockIndexDB(config); | |||||
if (!ret) { | |||||
return false; | 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; | return true; | ||||
} | } | ||||
bool InitBlockIndex(const Config &config) { | 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() != nullptr) { | // 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 = gArgs.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 | // Only add the genesis block if not reindexing (in which case we reuse the | ||||
// one already on disk) | // one already on disk) | ||||
if (!fReindex) { | |||||
try { | try { | ||||
const CChainParams &chainparams = config.GetChainParams(); | |||||
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 = | unsigned int nBlockSize = | ||||
::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); | ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION); | ||||
CDiskBlockPos blockPos; | CDiskBlockPos blockPos; | ||||
CValidationState state; | CValidationState state; | ||||
if (!FindBlockPos(state, blockPos, nBlockSize + 8, 0, | if (!FindBlockPos(state, blockPos, nBlockSize + 8, 0, | ||||
block.GetBlockTime())) { | block.GetBlockTime())) { | ||||
return error("LoadBlockIndex(): FindBlockPos failed"); | return error("%s: FindBlockPos failed", __func__); | ||||
} | } | ||||
if (!WriteBlockToDisk(block, blockPos, chainparams.DiskMagic())) { | if (!WriteBlockToDisk(block, blockPos, chainparams.DiskMagic())) { | ||||
return error( | return error("%s: writing genesis block to disk failed", __func__); | ||||
"LoadBlockIndex(): writing genesis block to disk failed"); | |||||
} | } | ||||
CBlockIndex *pindex = AddToBlockIndex(block); | CBlockIndex *pindex = AddToBlockIndex(block); | ||||
if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) { | if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) { | ||||
return error("LoadBlockIndex(): genesis block not accepted"); | return error("%s: genesis block not accepted", __func__); | ||||
} | } | ||||
} catch (const std::runtime_error &e) { | } catch (const std::runtime_error &e) { | ||||
return error( | return error("%s: failed to write genesis block: %s", __func__, | ||||
"LoadBlockIndex(): failed to initialize block database: %s", | |||||
e.what()); | e.what()); | ||||
} | } | ||||
} | |||||
return true; | return true; | ||||
} | } | ||||
bool LoadExternalBlockFile(const Config &config, FILE *fileIn, | bool LoadExternalBlockFile(const Config &config, FILE *fileIn, | ||||
CDiskBlockPos *dbp) { | CDiskBlockPos *dbp) { | ||||
// Map of disk positions for blocks with unknown parent (only used for | // Map of disk positions for blocks with unknown parent (only used for | ||||
// reindex) | // reindex) | ||||
▲ Show 20 Lines • Show All 643 Lines • Show Last 20 Lines |