Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 2,138 Lines • ▼ Show 20 Lines | try { | ||||
e.what()); | e.what()); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
void FlushStateToDisk() { | void FlushStateToDisk() { | ||||
CValidationState state; | CValidationState state; | ||||
const CChainParams &chainparams = Params(); | const CChainParams &chainparams = Params(); | ||||
FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS); | if (!FlushStateToDisk(chainparams, state, FlushStateMode::ALWAYS)) { | ||||
LogPrintf("%s: failed to flush state (%s)\n", __func__, | |||||
FormatStateMessage(state)); | |||||
} | |||||
} | } | ||||
void PruneAndFlush() { | void PruneAndFlush() { | ||||
CValidationState state; | CValidationState state; | ||||
fCheckForPruning = true; | fCheckForPruning = true; | ||||
const CChainParams &chainparams = Params(); | const CChainParams &chainparams = Params(); | ||||
FlushStateToDisk(chainparams, state, FlushStateMode::NONE); | if (!FlushStateToDisk(chainparams, state, FlushStateMode::NONE)) { | ||||
LogPrintf("%s: failed to flush state (%s)\n", __func__, | |||||
FormatStateMessage(state)); | |||||
} | |||||
} | } | ||||
/** Check warning conditions and do some notifications on new chain tip set. */ | /** Check warning conditions and do some notifications on new chain tip set. */ | ||||
static void UpdateTip(const Config &config, CBlockIndex *pindexNew) { | static void UpdateTip(const Config &config, CBlockIndex *pindexNew) { | ||||
// New best block | // New best block | ||||
g_mempool.AddTransactionsUpdated(1); | g_mempool.AddTransactionsUpdated(1); | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,920 Lines • ▼ Show 20 Lines | AssertLockNotHeld(cs_main); | ||||
// Store to disk | // Store to disk | ||||
ret = g_chainstate.AcceptBlock( | ret = g_chainstate.AcceptBlock( | ||||
config, pblock, state, fForceProcessing, nullptr, fNewBlock); | config, pblock, state, fForceProcessing, nullptr, fNewBlock); | ||||
} | } | ||||
if (!ret) { | if (!ret) { | ||||
GetMainSignals().BlockChecked(*pblock, state); | GetMainSignals().BlockChecked(*pblock, state); | ||||
return error("%s: AcceptBlock FAILED (%s)", __func__, | return error("%s: AcceptBlock FAILED (%s)", __func__, | ||||
state.GetDebugMessage()); | FormatStateMessage(state)); | ||||
} | } | ||||
} | } | ||||
NotifyHeaderTip(); | NotifyHeaderTip(); | ||||
// Only used to report errors, not invalidity - ignore it | // Only used to report errors, not invalidity - ignore it | ||||
CValidationState state; | CValidationState state; | ||||
if (!g_chainstate.ActivateBestChain(config, state, pblock)) { | if (!g_chainstate.ActivateBestChain(config, state, pblock)) { | ||||
return error("%s: ActivateBestChain failed", __func__); | return error("%s: ActivateBestChain failed (%s)", __func__, | ||||
FormatStateMessage(state)); | |||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool TestBlockValidity(const Config &config, CValidationState &state, | bool TestBlockValidity(const Config &config, CValidationState &state, | ||||
const CBlock &block, CBlockIndex *pindexPrev, | const CBlock &block, CBlockIndex *pindexPrev, | ||||
BlockValidationOptions validationOptions) { | BlockValidationOptions validationOptions) { | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | static void FindFilesToPruneManual(std::set<int> &setFilesToPrune, | ||||
LogPrintf("Prune (Manual): prune_height=%d removed %d blk/rev pairs\n", | LogPrintf("Prune (Manual): prune_height=%d removed %d blk/rev pairs\n", | ||||
nLastBlockWeCanPrune, count); | nLastBlockWeCanPrune, count); | ||||
} | } | ||||
/* This function is called from the RPC code for pruneblockchain */ | /* This function is called from the RPC code for pruneblockchain */ | ||||
void PruneBlockFilesManual(int nManualPruneHeight) { | void PruneBlockFilesManual(int nManualPruneHeight) { | ||||
CValidationState state; | CValidationState state; | ||||
const CChainParams &chainparams = Params(); | const CChainParams &chainparams = Params(); | ||||
FlushStateToDisk(chainparams, state, FlushStateMode::NONE, | if (!FlushStateToDisk(chainparams, state, FlushStateMode::NONE, | ||||
nManualPruneHeight); | nManualPruneHeight)) { | ||||
LogPrintf("%s: failed to flush state (%s)\n", __func__, | |||||
FormatStateMessage(state)); | |||||
} | |||||
} | } | ||||
/** | /** | ||||
* Prune block and undo files (blk???.dat and undo???.dat) so that the disk | * Prune block and undo files (blk???.dat and undo???.dat) so that the disk | ||||
* space used is less than a user-defined target. The user sets the target (in | * space used is less than a user-defined target. The user sets the target (in | ||||
* MB) on the command line or in config file. This will be run on startup and | * MB) on the command line or in config file. This will be run on startup and | ||||
* whenever new space is allocated in a block or undo file, staying below the | * whenever new space is allocated in a block or undo file, staying below the | ||||
* target. Changing back to unpruned requires a reindex (which in this case | * target. Changing back to unpruned requires a reindex (which in this case | ||||
▲ Show 20 Lines • Show All 257 Lines • ▼ Show 20 Lines | bool LoadChainTip(const Config &config) { | ||||
} | } | ||||
if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) { | if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) { | ||||
// In case we just added the genesis block, connect it now, so | // In case we just added the genesis block, connect it now, so | ||||
// that we always have a chainActive.Tip() when we return. | // that we always have a chainActive.Tip() when we return. | ||||
LogPrintf("%s: Connecting genesis block...\n", __func__); | LogPrintf("%s: Connecting genesis block...\n", __func__); | ||||
CValidationState state; | CValidationState state; | ||||
if (!ActivateBestChain(config, state)) { | if (!ActivateBestChain(config, state)) { | ||||
LogPrintf("%s: failed to activate chain (%s)\n", __func__, | |||||
FormatStateMessage(state)); | |||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
// Load pointer to end of best chain | // Load pointer to end of best chain | ||||
CBlockIndex *pindex = LookupBlockIndex(pcoinsTip->GetBestBlock()); | CBlockIndex *pindex = LookupBlockIndex(pcoinsTip->GetBestBlock()); | ||||
if (!pindex) { | if (!pindex) { | ||||
return false; | return false; | ||||
▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | if (nCheckLevel >= 4) { | ||||
CBlock block; | CBlock block; | ||||
if (!ReadBlockFromDisk(block, pindex, config)) { | if (!ReadBlockFromDisk(block, pindex, config)) { | ||||
return error( | return error( | ||||
"VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", | "VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", | ||||
pindex->nHeight, pindex->GetBlockHash().ToString()); | pindex->nHeight, pindex->GetBlockHash().ToString()); | ||||
} | } | ||||
if (!g_chainstate.ConnectBlock(config, block, state, pindex, | if (!g_chainstate.ConnectBlock(config, block, state, pindex, | ||||
coins)) { | coins)) { | ||||
return error( | return error("VerifyDB(): *** found unconnectable block at %d, " | ||||
"VerifyDB(): *** found unconnectable block at %d, hash=%s", | "hash=%s (%s)", | ||||
pindex->nHeight, pindex->GetBlockHash().ToString()); | pindex->nHeight, pindex->GetBlockHash().ToString(), | ||||
FormatStateMessage(state)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
LogPrintf("[DONE].\n"); | LogPrintf("[DONE].\n"); | ||||
LogPrintf("No coin database inconsistencies in last %i blocks (%i " | LogPrintf("No coin database inconsistencies in last %i blocks (%i " | ||||
"transactions)\n", | "transactions)\n", | ||||
chainActive.Height() - pindexState->nHeight, nGoodTransactions); | chainActive.Height() - pindexState->nHeight, nGoodTransactions); | ||||
▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | while (chainActive.Height() >= nHeight) { | ||||
// If pruning, don't try rewinding past the HAVE_DATA point; since | // If pruning, don't try rewinding past the HAVE_DATA point; since | ||||
// older blocks can't be served anyway, there's no need to walk | // older blocks can't be served anyway, there's no need to walk | ||||
// further, and trying to DisconnectTip() will fail (and require a | // further, and trying to DisconnectTip() will fail (and require a | ||||
// needless reindex/redownload of the blockchain). | // needless reindex/redownload of the blockchain). | ||||
break; | break; | ||||
} | } | ||||
if (!DisconnectTip(config, state, nullptr)) { | if (!DisconnectTip(config, state, nullptr)) { | ||||
return error( | return error("RewindBlockIndex: unable to disconnect block at " | ||||
"RewindBlockIndex: unable to disconnect block at height %i", | "height %i (%s)", | ||||
pindex->nHeight); | pindex->nHeight, FormatStateMessage(state)); | ||||
} | } | ||||
// Occasionally flush state to disk. | // Occasionally flush state to disk. | ||||
if (!FlushStateToDisk(params, state, FlushStateMode::PERIODIC)) { | if (!FlushStateToDisk(params, state, FlushStateMode::PERIODIC)) { | ||||
LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", | |||||
FormatStateMessage(state)); | |||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
// Reduce validity flag and have-data flags. | // Reduce validity flag and have-data flags. | ||||
// We do this after actual disconnecting, otherwise we'll end up writing the | // We do this after actual disconnecting, otherwise we'll end up writing the | ||||
// lack of data to disk before writing the chainstate, resulting in a | // lack of data to disk before writing the chainstate, resulting in a | ||||
// failure to continue if interrupted. | // failure to continue if interrupted. | ||||
Show All 23 Lines | bool RewindBlockIndex(const Config &config) { | ||||
if (chainActive.Tip() != nullptr) { | if (chainActive.Tip() != nullptr) { | ||||
// FlushStateToDisk can possibly read chainActive. Be conservative | // FlushStateToDisk can possibly read chainActive. Be conservative | ||||
// and skip it here, we're about to -reindex-chainstate anyway, so | // and skip it here, we're about to -reindex-chainstate anyway, so | ||||
// it'll get called a bunch real soon. | // it'll get called a bunch real soon. | ||||
CValidationState state; | CValidationState state; | ||||
if (!FlushStateToDisk(config.GetChainParams(), state, | if (!FlushStateToDisk(config.GetChainParams(), state, | ||||
FlushStateMode::ALWAYS)) { | FlushStateMode::ALWAYS)) { | ||||
LogPrintf("RewindBlockIndex: unable to flush state to disk (%s)\n", | |||||
FormatStateMessage(state)); | |||||
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 | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | try { | ||||
CBlock &block = const_cast<CBlock &>(chainparams.GenesisBlock()); | CBlock &block = const_cast<CBlock &>(chainparams.GenesisBlock()); | ||||
FlatFilePos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr); | FlatFilePos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr); | ||||
if (blockPos.IsNull()) { | if (blockPos.IsNull()) { | ||||
return error("%s: writing genesis block to disk failed", __func__); | return error("%s: writing genesis block to disk failed", __func__); | ||||
} | } | ||||
CBlockIndex *pindex = AddToBlockIndex(block); | CBlockIndex *pindex = AddToBlockIndex(block); | ||||
CValidationState state; | CValidationState state; | ||||
if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) { | if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) { | ||||
return error("%s: genesis block not accepted", __func__); | return error("%s: genesis block not accepted (%s)", __func__, | ||||
FormatStateMessage(state)); | |||||
} | } | ||||
} catch (const std::runtime_error &e) { | } catch (const std::runtime_error &e) { | ||||
return error("%s: failed to write genesis block: %s", __func__, | return error("%s: failed to write genesis block: %s", __func__, | ||||
e.what()); | e.what()); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 674 Lines • Show Last 20 Lines |