Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 875 Lines • ▼ Show 20 Lines | CoinsViews::CoinsViews(std::string ldb_name, size_t cache_size_bytes, | ||||
: m_dbview(GetDataDir() / ldb_name, cache_size_bytes, in_memory, | : m_dbview(GetDataDir() / ldb_name, cache_size_bytes, in_memory, | ||||
should_wipe), | should_wipe), | ||||
m_catcherview(&m_dbview) {} | m_catcherview(&m_dbview) {} | ||||
void CoinsViews::InitCache() { | void CoinsViews::InitCache() { | ||||
m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview); | m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview); | ||||
} | } | ||||
CChainState::CChainState(BlockManager &blockman, | CChainState::CChainState(CTxMemPool &mempool, BlockManager &blockman, | ||||
BlockHash from_snapshot_blockhash) | BlockHash from_snapshot_blockhash) | ||||
: m_blockman(blockman), m_from_snapshot_blockhash(from_snapshot_blockhash) { | : m_blockman(blockman), m_mempool(mempool), | ||||
} | m_from_snapshot_blockhash(from_snapshot_blockhash) {} | ||||
void CChainState::InitCoinsDB(size_t cache_size_bytes, bool in_memory, | void CChainState::InitCoinsDB(size_t cache_size_bytes, bool in_memory, | ||||
bool should_wipe, std::string leveldb_name) { | bool should_wipe, std::string leveldb_name) { | ||||
if (!m_from_snapshot_blockhash.IsNull()) { | if (!m_from_snapshot_blockhash.IsNull()) { | ||||
leveldb_name += "_" + m_from_snapshot_blockhash.ToString(); | leveldb_name += "_" + m_from_snapshot_blockhash.ToString(); | ||||
} | } | ||||
m_coins_views = std::make_unique<CoinsViews>(leveldb_name, cache_size_bytes, | m_coins_views = std::make_unique<CoinsViews>(leveldb_name, cache_size_bytes, | ||||
in_memory, should_wipe); | in_memory, should_wipe); | ||||
▲ Show 20 Lines • Show All 1,227 Lines • ▼ Show 20 Lines | bool CChainState::FlushStateToDisk(const CChainParams &chainparams, | ||||
const size_t coins_count = CoinsTip().GetCacheSize(); | const size_t coins_count = CoinsTip().GetCacheSize(); | ||||
const size_t coins_mem_usage = CoinsTip().DynamicMemoryUsage(); | const size_t coins_mem_usage = CoinsTip().DynamicMemoryUsage(); | ||||
try { | try { | ||||
{ | { | ||||
bool fFlushForPrune = false; | bool fFlushForPrune = false; | ||||
bool fDoFullFlush = false; | bool fDoFullFlush = false; | ||||
CoinsCacheSizeState cache_state = | CoinsCacheSizeState cache_state = | ||||
GetCoinsCacheSizeState(&::g_mempool); | GetCoinsCacheSizeState(&m_mempool); | ||||
LOCK(cs_LastBlockFile); | LOCK(cs_LastBlockFile); | ||||
if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && | if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && | ||||
!fReindex) { | !fReindex) { | ||||
if (nManualPruneHeight > 0) { | if (nManualPruneHeight > 0) { | ||||
LOG_TIME_MILLIS_WITH_CATEGORY( | LOG_TIME_MILLIS_WITH_CATEGORY( | ||||
"find files to prune (manual)", BCLog::BENCH); | "find files to prune (manual)", BCLog::BENCH); | ||||
FindFilesToPruneManual(g_chainman, setFilesToPrune, | FindFilesToPruneManual(g_chainman, setFilesToPrune, | ||||
nManualPruneHeight); | nManualPruneHeight); | ||||
▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | void CChainState::PruneAndFlush() { | ||||
const CChainParams &chainparams = Params(); | const CChainParams &chainparams = Params(); | ||||
if (!this->FlushStateToDisk(chainparams, state, FlushStateMode::NONE)) { | if (!this->FlushStateToDisk(chainparams, state, FlushStateMode::NONE)) { | ||||
LogPrintf("%s: failed to flush state (%s)\n", __func__, | LogPrintf("%s: failed to flush state (%s)\n", __func__, | ||||
state.ToString()); | state.ToString()); | ||||
} | } | ||||
} | } | ||||
/** 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 CChainParams ¶ms, CBlockIndex *pindexNew) | static void UpdateTip(CTxMemPool &mempool, const CChainParams ¶ms, | ||||
CBlockIndex *pindexNew) | |||||
EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { | ||||
// New best block | // New best block | ||||
g_mempool.AddTransactionsUpdated(1); | mempool.AddTransactionsUpdated(1); | ||||
{ | { | ||||
LOCK(g_best_block_mutex); | LOCK(g_best_block_mutex); | ||||
g_best_block = pindexNew->GetBlockHash(); | g_best_block = pindexNew->GetBlockHash(); | ||||
g_best_block_cv.notify_all(); | g_best_block_cv.notify_all(); | ||||
} | } | ||||
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%ld " | LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%f tx=%ld " | ||||
Show All 19 Lines | |||||
* If disconnectpool is nullptr, then no disconnected transactions are added to | * If disconnectpool is nullptr, then no disconnected transactions are added to | ||||
* disconnectpool (note that the caller is responsible for mempool consistency | * disconnectpool (note that the caller is responsible for mempool consistency | ||||
* in any case). | * in any case). | ||||
*/ | */ | ||||
bool CChainState::DisconnectTip(const CChainParams ¶ms, | bool CChainState::DisconnectTip(const CChainParams ¶ms, | ||||
BlockValidationState &state, | BlockValidationState &state, | ||||
DisconnectedBlockTransactions *disconnectpool) { | DisconnectedBlockTransactions *disconnectpool) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
AssertLockHeld(m_mempool.cs); | |||||
CBlockIndex *pindexDelete = m_chain.Tip(); | CBlockIndex *pindexDelete = m_chain.Tip(); | ||||
const Consensus::Params &consensusParams = params.GetConsensus(); | const Consensus::Params &consensusParams = params.GetConsensus(); | ||||
assert(pindexDelete); | assert(pindexDelete); | ||||
// Read block from disk. | // Read block from disk. | ||||
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); | std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); | ||||
CBlock &block = *pblock; | CBlock &block = *pblock; | ||||
Show All 28 Lines | bool CChainState::DisconnectTip(const CChainParams ¶ms, | ||||
// in front of disconnectpool for reprocessing in a future | // in front of disconnectpool for reprocessing in a future | ||||
// updateMempoolForReorg call | // updateMempoolForReorg call | ||||
if (pindexDelete->pprev != nullptr && | if (pindexDelete->pprev != nullptr && | ||||
GetNextBlockScriptFlags(consensusParams, pindexDelete) != | GetNextBlockScriptFlags(consensusParams, pindexDelete) != | ||||
GetNextBlockScriptFlags(consensusParams, pindexDelete->pprev)) { | GetNextBlockScriptFlags(consensusParams, pindexDelete->pprev)) { | ||||
LogPrint(BCLog::MEMPOOL, | LogPrint(BCLog::MEMPOOL, | ||||
"Disconnecting mempool due to rewind of upgrade block\n"); | "Disconnecting mempool due to rewind of upgrade block\n"); | ||||
if (disconnectpool) { | if (disconnectpool) { | ||||
disconnectpool->importMempool(g_mempool); | disconnectpool->importMempool(m_mempool); | ||||
} | } | ||||
g_mempool.clear(); | m_mempool.clear(); | ||||
} | } | ||||
if (disconnectpool) { | if (disconnectpool) { | ||||
disconnectpool->addForBlock(block.vtx, g_mempool); | disconnectpool->addForBlock(block.vtx, m_mempool); | ||||
} | } | ||||
// If the tip is finalized, then undo it. | // If the tip is finalized, then undo it. | ||||
if (m_finalizedBlockIndex == pindexDelete) { | if (m_finalizedBlockIndex == pindexDelete) { | ||||
m_finalizedBlockIndex = pindexDelete->pprev; | m_finalizedBlockIndex = pindexDelete->pprev; | ||||
} | } | ||||
m_chain.SetTip(pindexDelete->pprev); | m_chain.SetTip(pindexDelete->pprev); | ||||
// Update ::ChainActive() and related variables. | // Update ::ChainActive() and related variables. | ||||
UpdateTip(params, pindexDelete->pprev); | UpdateTip(m_mempool, params, pindexDelete->pprev); | ||||
// Let wallets know transactions went from 1-confirmed to | // Let wallets know transactions went from 1-confirmed to | ||||
// 0-confirmed or conflicted: | // 0-confirmed or conflicted: | ||||
GetMainSignals().BlockDisconnected(pblock, pindexDelete); | GetMainSignals().BlockDisconnected(pblock, pindexDelete); | ||||
return true; | return true; | ||||
} | } | ||||
static int64_t nTimeReadFromDisk = 0; | static int64_t nTimeReadFromDisk = 0; | ||||
static int64_t nTimeConnectTotal = 0; | static int64_t nTimeConnectTotal = 0; | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | |||||
* the last entry in blocksConnected in case of failure. | * the last entry in blocksConnected in case of failure. | ||||
*/ | */ | ||||
bool CChainState::ConnectTip(const Config &config, BlockValidationState &state, | bool CChainState::ConnectTip(const Config &config, BlockValidationState &state, | ||||
CBlockIndex *pindexNew, | CBlockIndex *pindexNew, | ||||
const std::shared_ptr<const CBlock> &pblock, | const std::shared_ptr<const CBlock> &pblock, | ||||
ConnectTrace &connectTrace, | ConnectTrace &connectTrace, | ||||
DisconnectedBlockTransactions &disconnectpool) { | DisconnectedBlockTransactions &disconnectpool) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
AssertLockHeld(g_mempool.cs); | AssertLockHeld(m_mempool.cs); | ||||
const CChainParams ¶ms = config.GetChainParams(); | const CChainParams ¶ms = config.GetChainParams(); | ||||
const Consensus::Params &consensusParams = params.GetConsensus(); | const Consensus::Params &consensusParams = params.GetConsensus(); | ||||
assert(pindexNew->pprev == m_chain.Tip()); | assert(pindexNew->pprev == m_chain.Tip()); | ||||
// Read block from disk. | // Read block from disk. | ||||
int64_t nTime1 = GetTimeMicros(); | int64_t nTime1 = GetTimeMicros(); | ||||
std::shared_ptr<const CBlock> pthisBlock; | std::shared_ptr<const CBlock> pthisBlock; | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | bool CChainState::ConnectTip(const Config &config, BlockValidationState &state, | ||||
int64_t nTime5 = GetTimeMicros(); | int64_t nTime5 = GetTimeMicros(); | ||||
nTimeChainState += nTime5 - nTime4; | nTimeChainState += nTime5 - nTime4; | ||||
LogPrint(BCLog::BENCH, | LogPrint(BCLog::BENCH, | ||||
" - Writing chainstate: %.2fms [%.2fs (%.2fms/blk)]\n", | " - Writing chainstate: %.2fms [%.2fs (%.2fms/blk)]\n", | ||||
(nTime5 - nTime4) * MILLI, nTimeChainState * MICRO, | (nTime5 - nTime4) * MILLI, nTimeChainState * MICRO, | ||||
nTimeChainState * MILLI / nBlocksTotal); | nTimeChainState * MILLI / nBlocksTotal); | ||||
// Remove conflicting transactions from the mempool.; | // Remove conflicting transactions from the mempool.; | ||||
g_mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); | m_mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); | ||||
disconnectpool.removeForBlock(blockConnecting.vtx); | disconnectpool.removeForBlock(blockConnecting.vtx); | ||||
// If this block is activating a fork, we move all mempool transactions | // If this block is activating a fork, we move all mempool transactions | ||||
// in front of disconnectpool for reprocessing in a future | // in front of disconnectpool for reprocessing in a future | ||||
// updateMempoolForReorg call | // updateMempoolForReorg call | ||||
if (pindexNew->pprev != nullptr && | if (pindexNew->pprev != nullptr && | ||||
GetNextBlockScriptFlags(consensusParams, pindexNew) != | GetNextBlockScriptFlags(consensusParams, pindexNew) != | ||||
GetNextBlockScriptFlags(consensusParams, pindexNew->pprev)) { | GetNextBlockScriptFlags(consensusParams, pindexNew->pprev)) { | ||||
LogPrint(BCLog::MEMPOOL, | LogPrint(BCLog::MEMPOOL, | ||||
"Disconnecting mempool due to acceptance of upgrade block\n"); | "Disconnecting mempool due to acceptance of upgrade block\n"); | ||||
disconnectpool.importMempool(g_mempool); | disconnectpool.importMempool(m_mempool); | ||||
} | } | ||||
// Update m_chain & related variables. | // Update m_chain & related variables. | ||||
m_chain.SetTip(pindexNew); | m_chain.SetTip(pindexNew); | ||||
UpdateTip(params, pindexNew); | UpdateTip(m_mempool, params, pindexNew); | ||||
int64_t nTime6 = GetTimeMicros(); | int64_t nTime6 = GetTimeMicros(); | ||||
nTimePostConnect += nTime6 - nTime5; | nTimePostConnect += nTime6 - nTime5; | ||||
nTimeTotal += nTime6 - nTime1; | nTimeTotal += nTime6 - nTime1; | ||||
LogPrint(BCLog::BENCH, | LogPrint(BCLog::BENCH, | ||||
" - Connect postprocess: %.2fms [%.2fs (%.2fms/blk)]\n", | " - Connect postprocess: %.2fms [%.2fs (%.2fms/blk)]\n", | ||||
(nTime6 - nTime5) * MILLI, nTimePostConnect * MICRO, | (nTime6 - nTime5) * MILLI, nTimePostConnect * MICRO, | ||||
nTimePostConnect * MILLI / nBlocksTotal); | nTimePostConnect * MILLI / nBlocksTotal); | ||||
▲ Show 20 Lines • Show All 196 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* @returns true unless a system error occurred | * @returns true unless a system error occurred | ||||
*/ | */ | ||||
bool CChainState::ActivateBestChainStep( | bool CChainState::ActivateBestChainStep( | ||||
const Config &config, BlockValidationState &state, | const Config &config, BlockValidationState &state, | ||||
CBlockIndex *pindexMostWork, const std::shared_ptr<const CBlock> &pblock, | CBlockIndex *pindexMostWork, const std::shared_ptr<const CBlock> &pblock, | ||||
bool &fInvalidFound, ConnectTrace &connectTrace) { | bool &fInvalidFound, ConnectTrace &connectTrace) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
AssertLockHeld(m_mempool.cs); | |||||
const CBlockIndex *pindexOldTip = m_chain.Tip(); | const CBlockIndex *pindexOldTip = m_chain.Tip(); | ||||
const CBlockIndex *pindexFork = m_chain.FindFork(pindexMostWork); | const CBlockIndex *pindexFork = m_chain.FindFork(pindexMostWork); | ||||
// Disconnect active blocks which are no longer in the best chain. | // Disconnect active blocks which are no longer in the best chain. | ||||
bool fBlocksDisconnected = false; | bool fBlocksDisconnected = false; | ||||
DisconnectedBlockTransactions disconnectpool; | DisconnectedBlockTransactions disconnectpool; | ||||
while (m_chain.Tip() && m_chain.Tip() != pindexFork) { | while (m_chain.Tip() && m_chain.Tip() != pindexFork) { | ||||
if (!DisconnectTip(config.GetChainParams(), state, &disconnectpool)) { | if (!DisconnectTip(config.GetChainParams(), state, &disconnectpool)) { | ||||
// This is likely a fatal error, but keep the mempool consistent, | // This is likely a fatal error, but keep the mempool consistent, | ||||
// just in case. Only remove from the mempool in this case. | // just in case. Only remove from the mempool in this case. | ||||
disconnectpool.updateMempoolForReorg(config, false, g_mempool); | disconnectpool.updateMempoolForReorg(config, false, m_mempool); | ||||
// If we're unable to disconnect a block during normal operation, | // If we're unable to disconnect a block during normal operation, | ||||
// then that is a failure of our local system -- we should abort | // then that is a failure of our local system -- we should abort | ||||
// rather than stay on a less work chain. | // rather than stay on a less work chain. | ||||
AbortNode(state, | AbortNode(state, | ||||
"Failed to disconnect block; see debug.log for details"); | "Failed to disconnect block; see debug.log for details"); | ||||
return false; | return false; | ||||
} | } | ||||
Show All 36 Lines | while (fContinue && nHeight != pindexMostWork->nHeight) { | ||||
fInvalidFound = true; | fInvalidFound = true; | ||||
fContinue = false; | fContinue = false; | ||||
break; | break; | ||||
} | } | ||||
// A system error occurred (disk space, database error, ...). | // A system error occurred (disk space, database error, ...). | ||||
// Make the mempool consistent with the current tip, just in | // Make the mempool consistent with the current tip, just in | ||||
// case any observers try to use it before shutdown. | // case any observers try to use it before shutdown. | ||||
disconnectpool.updateMempoolForReorg(config, false, g_mempool); | disconnectpool.updateMempoolForReorg(config, false, m_mempool); | ||||
return false; | return false; | ||||
} else { | } else { | ||||
PruneBlockIndexCandidates(); | PruneBlockIndexCandidates(); | ||||
if (!pindexOldTip || | if (!pindexOldTip || | ||||
m_chain.Tip()->nChainWork > pindexOldTip->nChainWork) { | m_chain.Tip()->nChainWork > pindexOldTip->nChainWork) { | ||||
// We're in a better position than we were. Return | // We're in a better position than we were. Return | ||||
// temporarily to release the lock. | // temporarily to release the lock. | ||||
fContinue = false; | fContinue = false; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (fBlocksDisconnected || !disconnectpool.isEmpty()) { | if (fBlocksDisconnected || !disconnectpool.isEmpty()) { | ||||
// If any blocks were disconnected, we need to update the mempool even | // If any blocks were disconnected, we need to update the mempool even | ||||
// if disconnectpool is empty. The disconnectpool may also be non-empty | // if disconnectpool is empty. The disconnectpool may also be non-empty | ||||
// if the mempool was imported due to new validation rules being in | // if the mempool was imported due to new validation rules being in | ||||
// effect. | // effect. | ||||
LogPrint(BCLog::MEMPOOL, "Updating mempool due to reorganization or " | LogPrint(BCLog::MEMPOOL, "Updating mempool due to reorganization or " | ||||
"rules upgrade/downgrade\n"); | "rules upgrade/downgrade\n"); | ||||
disconnectpool.updateMempoolForReorg(config, true, g_mempool); | disconnectpool.updateMempoolForReorg(config, true, m_mempool); | ||||
} | } | ||||
g_mempool.check(&CoinsTip()); | m_mempool.check(&CoinsTip()); | ||||
// Callbacks/notifications for a new best chain. | // Callbacks/notifications for a new best chain. | ||||
if (fInvalidFound) { | if (fInvalidFound) { | ||||
CheckForkWarningConditionsOnNewFork(pindexMostWork); | CheckForkWarningConditionsOnNewFork(pindexMostWork); | ||||
} else { | } else { | ||||
CheckForkWarningConditions(); | CheckForkWarningConditions(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | do { | ||||
// never happen in normal operation, however may happen during | // never happen in normal operation, however may happen during | ||||
// reindex, causing memory blowup if we run too far ahead. | // reindex, causing memory blowup if we run too far ahead. | ||||
// Note that if a validationinterface callback ends up calling | // Note that if a validationinterface callback ends up calling | ||||
// ActivateBestChain this may lead to a deadlock! We should | // ActivateBestChain this may lead to a deadlock! We should | ||||
// probably have a DEBUG_LOCKORDER test for this in the future. | // probably have a DEBUG_LOCKORDER test for this in the future. | ||||
LimitValidationInterfaceQueue(); | LimitValidationInterfaceQueue(); | ||||
{ | { | ||||
LOCK(cs_main); | |||||
// Lock transaction pool for at least as long as it takes for | // Lock transaction pool for at least as long as it takes for | ||||
// connectTrace to be consumed | // connectTrace to be consumed | ||||
LOCK2(cs_main, ::g_mempool.cs); | LOCK(m_mempool.cs); | ||||
CBlockIndex *starting_tip = m_chain.Tip(); | CBlockIndex *starting_tip = m_chain.Tip(); | ||||
bool blocks_connected = false; | bool blocks_connected = false; | ||||
do { | do { | ||||
// We absolutely may not unlock cs_main until we've made forward | // We absolutely may not unlock cs_main until we've made forward | ||||
// progress (with the exception of shutdown due to hardware | // progress (with the exception of shutdown due to hardware | ||||
// issues, low disk space, etc). | // issues, low disk space, etc). | ||||
// Destructed before cs_main is unlocked | // Destructed before cs_main is unlocked | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | while (true) { | ||||
// Make sure the queue of validation callbacks doesn't grow unboundedly. | // Make sure the queue of validation callbacks doesn't grow unboundedly. | ||||
LimitValidationInterfaceQueue(); | LimitValidationInterfaceQueue(); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// Lock for as long as disconnectpool is in scope to make sure | // Lock for as long as disconnectpool is in scope to make sure | ||||
// UpdateMempoolForReorg is called after DisconnectTip without unlocking | // UpdateMempoolForReorg is called after DisconnectTip without unlocking | ||||
// in between | // in between | ||||
LOCK(::g_mempool.cs); | LOCK(m_mempool.cs); | ||||
if (!m_chain.Contains(pindex)) { | if (!m_chain.Contains(pindex)) { | ||||
break; | break; | ||||
} | } | ||||
pindex_was_in_chain = true; | pindex_was_in_chain = true; | ||||
CBlockIndex *invalid_walk_tip = m_chain.Tip(); | CBlockIndex *invalid_walk_tip = m_chain.Tip(); | ||||
// ActivateBestChain considers blocks already in m_chain | // ActivateBestChain considers blocks already in m_chain | ||||
// unconditionally valid already, so force disconnect away from it. | // unconditionally valid already, so force disconnect away from it. | ||||
DisconnectedBlockTransactions disconnectpool; | DisconnectedBlockTransactions disconnectpool; | ||||
bool ret = DisconnectTip(chainparams, state, &disconnectpool); | bool ret = DisconnectTip(chainparams, state, &disconnectpool); | ||||
// DisconnectTip will add transactions to disconnectpool. | // DisconnectTip will add transactions to disconnectpool. | ||||
// Adjust the mempool to be consistent with the new tip, adding | // Adjust the mempool to be consistent with the new tip, adding | ||||
// transactions back to the mempool if disconnecting was successful, | // transactions back to the mempool if disconnecting was successful, | ||||
// and we're not doing a very deep invalidation (in which case | // and we're not doing a very deep invalidation (in which case | ||||
// keeping the mempool up to date is probably futile anyway). | // keeping the mempool up to date is probably futile anyway). | ||||
disconnectpool.updateMempoolForReorg( | disconnectpool.updateMempoolForReorg( | ||||
config, /* fAddToMempool = */ (++disconnected <= 10) && ret, | config, /* fAddToMempool = */ (++disconnected <= 10) && ret, | ||||
::g_mempool); | m_mempool); | ||||
if (!ret) { | if (!ret) { | ||||
return false; | return false; | ||||
} | } | ||||
assert(invalid_walk_tip->pprev == m_chain.Tip()); | assert(invalid_walk_tip->pprev == m_chain.Tip()); | ||||
// We immediately mark the disconnected blocks as invalid. | // We immediately mark the disconnected blocks as invalid. | ||||
▲ Show 20 Lines • Show All 2,793 Lines • ▼ Show 20 Lines | std::vector<CChainState *> ChainstateManager::GetAll() { | ||||
if (m_snapshot_chainstate) { | if (m_snapshot_chainstate) { | ||||
out.push_back(m_snapshot_chainstate.get()); | out.push_back(m_snapshot_chainstate.get()); | ||||
} | } | ||||
return out; | return out; | ||||
} | } | ||||
CChainState & | CChainState & | ||||
ChainstateManager::InitializeChainstate(const BlockHash &snapshot_blockhash) { | ChainstateManager::InitializeChainstate(CTxMemPool &mempool, | ||||
const BlockHash &snapshot_blockhash) { | |||||
bool is_snapshot = !snapshot_blockhash.IsNull(); | bool is_snapshot = !snapshot_blockhash.IsNull(); | ||||
std::unique_ptr<CChainState> &to_modify = | std::unique_ptr<CChainState> &to_modify = | ||||
is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate; | is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate; | ||||
if (to_modify) { | if (to_modify) { | ||||
throw std::logic_error("should not be overwriting a chainstate"); | throw std::logic_error("should not be overwriting a chainstate"); | ||||
} | } | ||||
to_modify.reset(new CChainState(mempool, m_blockman, snapshot_blockhash)); | |||||
to_modify.reset(new CChainState(m_blockman, snapshot_blockhash)); | |||||
// Snapshot chainstates and initial IBD chaintates always become active. | // Snapshot chainstates and initial IBD chaintates always become active. | ||||
if (is_snapshot || (!is_snapshot && !m_active_chainstate)) { | if (is_snapshot || (!is_snapshot && !m_active_chainstate)) { | ||||
LogPrintf("Switching active chainstate to %s\n", to_modify->ToString()); | LogPrintf("Switching active chainstate to %s\n", to_modify->ToString()); | ||||
m_active_chainstate = to_modify.get(); | m_active_chainstate = to_modify.get(); | ||||
} else { | } else { | ||||
throw std::logic_error("unexpected chainstate activation"); | throw std::logic_error("unexpected chainstate activation"); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 73 Lines • Show Last 20 Lines |