Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 2,283 Lines • ▼ Show 20 Lines | void NotifyEntryRemoved(CTransactionRef txRemoved, | ||||
assert(!blocksConnected.back().pindex); | assert(!blocksConnected.back().pindex); | ||||
if (reason == MemPoolRemovalReason::CONFLICT) { | if (reason == MemPoolRemovalReason::CONFLICT) { | ||||
blocksConnected.back().conflictedTxs->emplace_back( | blocksConnected.back().conflictedTxs->emplace_back( | ||||
std::move(txRemoved)); | std::move(txRemoved)); | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
static bool FinalizeBlockInternal(const Config &config, CValidationState &state, | |||||
CBlockIndex *pindex) { | |||||
AssertLockHeld(cs_main); | |||||
if (pindex->nStatus.isInvalid()) { | |||||
// We try to finalize an invalid block. | |||||
return state.DoS(100, | |||||
error("%s: Trying to finalize invalid block %s", | |||||
__func__, pindex->GetBlockHash().ToString()), | |||||
REJECT_INVALID, "finalize-invalid-block"); | |||||
} | |||||
// Check that the request is consistent with current finalization. | |||||
if (pindexFinalized && !AreOnTheSameFork(pindex, pindexFinalized)) { | |||||
return state.DoS( | |||||
20, error("%s: Trying to finalize block %s which conflicts " | |||||
"with already finalized block", | |||||
__func__, pindex->GetBlockHash().ToString()), | |||||
REJECT_AGAINST_FINALIZED, "bad-fork-prior-finalized"); | |||||
} | |||||
// Our candidate is valid, finalize it. | |||||
pindexFinalized = pindex; | |||||
return true; | |||||
} | |||||
/** | /** | ||||
* Connect a new block to chainActive. pblock is either nullptr or a pointer to | * Connect a new block to chainActive. pblock is either nullptr or a pointer to | ||||
* a CBlock corresponding to pindexNew, to bypass loading it again from disk. | * a CBlock corresponding to pindexNew, to bypass loading it again from disk. | ||||
* | * | ||||
* The block is always added to connectTrace (either after loading from disk or | * The block is always added to connectTrace (either after loading from disk or | ||||
* by copying pblock) - if that is not intended, care must be taken to remove | * by copying pblock) - if that is not intended, care must be taken to remove | ||||
* the last entry in blocksConnected in case of failure. | * the last entry in blocksConnected in case of failure. | ||||
*/ | */ | ||||
Show All 33 Lines | LogPrint(BCLog::BENCH, " - Load block from disk: %.2fms [%.2fs]\n", | ||||
InvalidBlockFound(pindexNew, state); | InvalidBlockFound(pindexNew, state); | ||||
} | } | ||||
return error("ConnectTip(): ConnectBlock %s failed (%s)", | return error("ConnectTip(): ConnectBlock %s failed (%s)", | ||||
pindexNew->GetBlockHash().ToString(), | pindexNew->GetBlockHash().ToString(), | ||||
FormatStateMessage(state)); | FormatStateMessage(state)); | ||||
} | } | ||||
// Update the finalized block. | |||||
int32_t nHeightToFinalize = | |||||
pindexNew->nHeight - | |||||
gArgs.GetArg("-maxreorgdepth", DEFAULT_MAX_REORG_DEPTH); | |||||
CBlockIndex *pindexToFinalize = | |||||
pindexNew->GetAncestor(nHeightToFinalize); | |||||
if (pindexToFinalize && | |||||
!FinalizeBlockInternal(config, state, pindexToFinalize)) { | |||||
state.SetCorruptionPossible(); | |||||
return error("ConnectTip(): FinalizeBlock %s failed (%s)", | |||||
pindexNew->GetBlockHash().ToString(), | |||||
FormatStateMessage(state)); | |||||
} | |||||
nTime3 = GetTimeMicros(); | nTime3 = GetTimeMicros(); | ||||
nTimeConnectTotal += nTime3 - nTime2; | nTimeConnectTotal += nTime3 - nTime2; | ||||
LogPrint(BCLog::BENCH, " - Connect total: %.2fms [%.2fs]\n", | LogPrint(BCLog::BENCH, " - Connect total: %.2fms [%.2fs]\n", | ||||
(nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001); | (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001); | ||||
bool flushed = view.Flush(); | bool flushed = view.Flush(); | ||||
assert(flushed); | assert(flushed); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 498 Lines • ▼ Show 20 Lines | static bool UnwindBlock(const Config &config, CValidationState &state, | ||||
if (invalidate) { | if (invalidate) { | ||||
InvalidChainFound(pindex); | InvalidChainFound(pindex); | ||||
} | } | ||||
uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev); | uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev); | ||||
return true; | return true; | ||||
} | } | ||||
bool FinalizeBlock(const Config &config, CValidationState &state, | bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex) { | CBlockIndex *pindex) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
if (pindex->nStatus.isInvalid()) { | if (!FinalizeBlockInternal(config, state, pindex)) { | ||||
// We try to finalize an invalid block. | // state is set by FinalizeBlockInternal. | ||||
return state.DoS(100, | return false; | ||||
error("%s: Trying to finalize invalid block %s", | |||||
__func__, pindex->GetBlockHash().ToString()), | |||||
REJECT_INVALID, "finalize-invalid-block"); | |||||
} | |||||
// Check that the request is consistent with current finalization. | |||||
if (pindexFinalized && !AreOnTheSameFork(pindex, pindexFinalized)) { | |||||
return state.DoS( | |||||
20, error("%s: Trying to finalize block %s which conflicts " | |||||
"with already finalized block", | |||||
__func__, pindex->GetBlockHash().ToString()), | |||||
REJECT_AGAINST_FINALIZED, "bad-fork-prior-finalized"); | |||||
} | } | ||||
// We have a valid candidate, make sure it is not parked. | // We have a valid candidate, make sure it is not parked. | ||||
pindexFinalized = pindex; | |||||
if (pindex->nStatus.isOnParkedChain()) { | if (pindex->nStatus.isOnParkedChain()) { | ||||
UnparkBlock(pindex); | UnparkBlock(pindex); | ||||
} | } | ||||
// If the finalized block is not on the active chain, we need to rewind. | // If the finalized block is not on the active chain, we need to rewind. | ||||
if (!AreOnTheSameFork(pindex, chainActive.Tip())) { | if (!AreOnTheSameFork(pindex, chainActive.Tip())) { | ||||
const CBlockIndex *pindexFork = chainActive.FindFork(pindex); | const CBlockIndex *pindexFork = chainActive.FindFork(pindex); | ||||
CBlockIndex *pindexToInvalidate = | CBlockIndex *pindexToInvalidate = | ||||
▲ Show 20 Lines • Show All 1,779 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
// 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); | ||||
setBlockIndexCandidates.clear(); | setBlockIndexCandidates.clear(); | ||||
chainActive.SetTip(nullptr); | chainActive.SetTip(nullptr); | ||||
pindexFinalized = nullptr; | |||||
pindexBestInvalid = nullptr; | pindexBestInvalid = nullptr; | ||||
pindexBestParked = nullptr; | pindexBestParked = nullptr; | ||||
pindexBestHeader = nullptr; | pindexBestHeader = nullptr; | ||||
mempool.clear(); | mempool.clear(); | ||||
mapBlocksUnlinked.clear(); | mapBlocksUnlinked.clear(); | ||||
vinfoBlockFile.clear(); | vinfoBlockFile.clear(); | ||||
nLastBlockFile = 0; | nLastBlockFile = 0; | ||||
nBlockSequenceId = 1; | nBlockSequenceId = 1; | ||||
▲ Show 20 Lines • Show All 729 Lines • Show Last 20 Lines |