Skip to content

Commit 8c0bd87

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#23785: refactor: Move stuff to ChainstateManager
fab6d6b Move pindexBestInvalid to ChainstateManager (MarcoFalke) facd213 Move m_failed_blocks to ChainstateManager (MarcoFalke) fa47b5c Move AcceptBlockHeader to ChainstateManager (MarcoFalke) fa3d62c Move FindForkInGlobalIndex from BlockManager to CChainState (MarcoFalke) Pull request description: Move globals or members of the wrong class to the right class. ACKs for top commit: naumenkogs: ACK fab6d6b Sjors: ACK fab6d6b shaavan: ACK fab6d6b Tree-SHA512: 926cbdfa22838517497bacb79ed5f521f64117c2aacf96a0176f62831b4713314a32abc0213df5ee067edf63e4a4300f752a26006d36e5aab415bb91209a271f
2 parents 6b212cb + fab6d6b commit 8c0bd87

File tree

5 files changed

+77
-74
lines changed

5 files changed

+77
-74
lines changed

src/index/base.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ bool BaseIndex::Init()
6565
if (locator.IsNull()) {
6666
m_best_block_index = nullptr;
6767
} else {
68-
m_best_block_index = m_chainstate->m_blockman.FindForkInGlobalIndex(active_chain, locator);
68+
m_best_block_index = m_chainstate->FindForkInGlobalIndex(locator);
6969
}
7070
m_synced = m_best_block_index.load() == active_chain.Tip();
7171
if (!m_synced) {

src/net_processing.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3083,7 +3083,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
30833083
LOCK(cs_main);
30843084

30853085
// Find the last block the caller has in the main chain
3086-
const CBlockIndex* pindex = m_chainman.m_blockman.FindForkInGlobalIndex(m_chainman.ActiveChain(), locator);
3086+
const CBlockIndex* pindex = m_chainman.ActiveChainstate().FindForkInGlobalIndex(locator);
30873087

30883088
// Send the rest of the chain
30893089
if (pindex)
@@ -3203,7 +3203,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
32033203
else
32043204
{
32053205
// Find the last block the caller has in the main chain
3206-
pindex = m_chainman.m_blockman.FindForkInGlobalIndex(m_chainman.ActiveChain(), locator);
3206+
pindex = m_chainman.ActiveChainstate().FindForkInGlobalIndex(locator);
32073207
if (pindex)
32083208
pindex = m_chainman.ActiveChain().Next(pindex);
32093209
}

src/node/interfaces.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,8 +494,8 @@ class ChainImpl : public Chain
494494
std::optional<int> findLocatorFork(const CBlockLocator& locator) override
495495
{
496496
LOCK(cs_main);
497-
const CChain& active = Assert(m_node.chainman)->ActiveChain();
498-
if (CBlockIndex* fork = m_node.chainman->m_blockman.FindForkInGlobalIndex(active, locator)) {
497+
const CChainState& active = Assert(m_node.chainman)->ActiveChainstate();
498+
if (CBlockIndex* fork = active.FindForkInGlobalIndex(locator)) {
499499
return fork->nHeight;
500500
}
501501
return std::nullopt;

src/validation.cpp

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,6 @@ arith_uint256 nMinimumChainWork;
133133

134134
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
135135

136-
// Internal stuff
137-
namespace {
138-
CBlockIndex* pindexBestInvalid = nullptr;
139-
} // namespace
140-
141136
// Internal stuff from blockstorage ...
142137
extern RecursiveMutex cs_LastBlockFile;
143138
extern std::vector<CBlockFileInfo> vinfoBlockFile;
@@ -155,23 +150,24 @@ CBlockIndex* BlockManager::LookupBlockIndex(const uint256& hash) const
155150
return it == m_block_index.end() ? nullptr : it->second;
156151
}
157152

158-
CBlockIndex* BlockManager::FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator)
153+
CBlockIndex* CChainState::FindForkInGlobalIndex(const CBlockLocator& locator) const
159154
{
160155
AssertLockHeld(cs_main);
161156

162157
// Find the latest block common to locator and chain - we expect that
163158
// locator.vHave is sorted descending by height.
164159
for (const uint256& hash : locator.vHave) {
165-
CBlockIndex* pindex = LookupBlockIndex(hash);
160+
CBlockIndex* pindex{m_blockman.LookupBlockIndex(hash)};
166161
if (pindex) {
167-
if (chain.Contains(pindex))
162+
if (m_chain.Contains(pindex)) {
168163
return pindex;
169-
if (pindex->GetAncestor(chain.Height()) == chain.Tip()) {
170-
return chain.Tip();
164+
}
165+
if (pindex->GetAncestor(m_chain.Height()) == m_chain.Tip()) {
166+
return m_chain.Tip();
171167
}
172168
}
173169
}
174-
return chain.Genesis();
170+
return m_chain.Genesis();
175171
}
176172

177173
bool CheckInputScripts(const CTransaction& tx, TxValidationState& state,
@@ -1478,7 +1474,7 @@ void CChainState::CheckForkWarningConditions()
14781474
return;
14791475
}
14801476

1481-
if (pindexBestInvalid && pindexBestInvalid->nChainWork > m_chain.Tip()->nChainWork + (GetBlockProof(*m_chain.Tip()) * 6)) {
1477+
if (m_chainman.m_best_invalid && m_chainman.m_best_invalid->nChainWork > m_chain.Tip()->nChainWork + (GetBlockProof(*m_chain.Tip()) * 6)) {
14821478
LogPrintf("%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__);
14831479
SetfLargeWorkInvalidChainFound(true);
14841480
} else {
@@ -1489,8 +1485,9 @@ void CChainState::CheckForkWarningConditions()
14891485
// Called both upon regular invalid block discovery *and* InvalidateBlock
14901486
void CChainState::InvalidChainFound(CBlockIndex* pindexNew)
14911487
{
1492-
if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
1493-
pindexBestInvalid = pindexNew;
1488+
if (!m_chainman.m_best_invalid || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork) {
1489+
m_chainman.m_best_invalid = pindexNew;
1490+
}
14941491
if (pindexBestHeader != nullptr && pindexBestHeader->GetAncestor(pindexNew->nHeight) == pindexNew) {
14951492
pindexBestHeader = m_chain.Tip();
14961493
}
@@ -1512,7 +1509,7 @@ void CChainState::InvalidBlockFound(CBlockIndex* pindex, const BlockValidationSt
15121509
{
15131510
if (state.GetResult() != BlockValidationResult::BLOCK_MUTATED) {
15141511
pindex->nStatus |= BLOCK_FAILED_VALID;
1515-
m_blockman.m_failed_blocks.insert(pindex);
1512+
m_chainman.m_failed_blocks.insert(pindex);
15161513
setDirtyBlockIndex.insert(pindex);
15171514
setBlockIndexCandidates.erase(pindex);
15181515
InvalidChainFound(pindex);
@@ -2653,8 +2650,9 @@ CBlockIndex* CChainState::FindMostWorkChain() {
26532650
bool fMissingData = !(pindexTest->nStatus & BLOCK_HAVE_DATA);
26542651
if (fFailedChain || fMissingData) {
26552652
// Candidate chain is not usable (either invalid or missing data)
2656-
if (fFailedChain && (pindexBestInvalid == nullptr || pindexNew->nChainWork > pindexBestInvalid->nChainWork))
2657-
pindexBestInvalid = pindexNew;
2653+
if (fFailedChain && (m_chainman.m_best_invalid == nullptr || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork)) {
2654+
m_chainman.m_best_invalid = pindexNew;
2655+
}
26582656
CBlockIndex *pindexFailed = pindexNew;
26592657
// Remove the entire chain from the set.
26602658
while (pindexTest != pindexFailed) {
@@ -3065,7 +3063,7 @@ bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pind
30653063
to_mark_failed->nStatus |= BLOCK_FAILED_VALID;
30663064
setDirtyBlockIndex.insert(to_mark_failed);
30673065
setBlockIndexCandidates.erase(to_mark_failed);
3068-
m_blockman.m_failed_blocks.insert(to_mark_failed);
3066+
m_chainman.m_failed_blocks.insert(to_mark_failed);
30693067

30703068
// If any new blocks somehow arrived while we were disconnecting
30713069
// (above), then the pre-calculation of what should go into
@@ -3106,11 +3104,11 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
31063104
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(m_chain.Tip(), it->second)) {
31073105
setBlockIndexCandidates.insert(it->second);
31083106
}
3109-
if (it->second == pindexBestInvalid) {
3107+
if (it->second == m_chainman.m_best_invalid) {
31103108
// Reset invalid block marker if it was pointing to one of those.
3111-
pindexBestInvalid = nullptr;
3109+
m_chainman.m_best_invalid = nullptr;
31123110
}
3113-
m_blockman.m_failed_blocks.erase(it->second);
3111+
m_chainman.m_failed_blocks.erase(it->second);
31143112
}
31153113
it++;
31163114
}
@@ -3120,7 +3118,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
31203118
if (pindex->nStatus & BLOCK_FAILED_MASK) {
31213119
pindex->nStatus &= ~BLOCK_FAILED_MASK;
31223120
setDirtyBlockIndex.insert(pindex);
3123-
m_blockman.m_failed_blocks.erase(pindex);
3121+
m_chainman.m_failed_blocks.erase(pindex);
31243122
}
31253123
pindex = pindex->pprev;
31263124
}
@@ -3481,14 +3479,14 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat
34813479
return true;
34823480
}
34833481

3484-
bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex)
3482+
bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex)
34853483
{
34863484
AssertLockHeld(cs_main);
34873485
// Check for duplicate
34883486
uint256 hash = block.GetHash();
3489-
BlockMap::iterator miSelf = m_block_index.find(hash);
3487+
BlockMap::iterator miSelf{m_blockman.m_block_index.find(hash)};
34903488
if (hash != chainparams.GetConsensus().hashGenesisBlock) {
3491-
if (miSelf != m_block_index.end()) {
3489+
if (miSelf != m_blockman.m_block_index.end()) {
34923490
// Block header is already known.
34933491
CBlockIndex* pindex = miSelf->second;
34943492
if (ppindex)
@@ -3507,8 +3505,8 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS
35073505

35083506
// Get prev block index
35093507
CBlockIndex* pindexPrev = nullptr;
3510-
BlockMap::iterator mi = m_block_index.find(block.hashPrevBlock);
3511-
if (mi == m_block_index.end()) {
3508+
BlockMap::iterator mi{m_blockman.m_block_index.find(block.hashPrevBlock)};
3509+
if (mi == m_blockman.m_block_index.end()) {
35123510
LogPrint(BCLog::VALIDATION, "%s: %s prev block not found\n", __func__, hash.ToString());
35133511
return state.Invalid(BlockValidationResult::BLOCK_MISSING_PREV, "prev-blk-not-found");
35143512
}
@@ -3517,7 +3515,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS
35173515
LogPrint(BCLog::VALIDATION, "%s: %s prev block invalid\n", __func__, hash.ToString());
35183516
return state.Invalid(BlockValidationResult::BLOCK_INVALID_PREV, "bad-prevblk");
35193517
}
3520-
if (!ContextualCheckBlockHeader(block, state, *this, chainparams, pindexPrev, GetAdjustedTime())) {
3518+
if (!ContextualCheckBlockHeader(block, state, m_blockman, chainparams, pindexPrev, GetAdjustedTime())) {
35213519
LogPrint(BCLog::VALIDATION, "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString());
35223520
return false;
35233521
}
@@ -3561,7 +3559,7 @@ bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationS
35613559
}
35623560
}
35633561
}
3564-
CBlockIndex* pindex = AddToBlockIndex(block);
3562+
CBlockIndex* pindex{m_blockman.AddToBlockIndex(block)};
35653563

35663564
if (ppindex)
35673565
*ppindex = pindex;
@@ -3577,8 +3575,7 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>&
35773575
LOCK(cs_main);
35783576
for (const CBlockHeader& header : headers) {
35793577
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
3580-
bool accepted = m_blockman.AcceptBlockHeader(
3581-
header, state, chainparams, &pindex);
3578+
bool accepted{AcceptBlockHeader(header, state, chainparams, &pindex)};
35823579
ActiveChainstate().CheckBlockIndex();
35833580

35843581
if (!accepted) {
@@ -3608,7 +3605,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, Block
36083605
CBlockIndex *pindexDummy = nullptr;
36093606
CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
36103607

3611-
bool accepted_header = m_blockman.AcceptBlockHeader(block, state, m_params, &pindex);
3608+
bool accepted_header{m_chainman.AcceptBlockHeader(block, state, m_params, &pindex)};
36123609
CheckBlockIndex();
36133610

36143611
if (!accepted_header)
@@ -4014,8 +4011,9 @@ bool BlockManager::LoadBlockIndex(
40144011
}
40154012
}
40164013
}
4017-
if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork))
4018-
pindexBestInvalid = pindex;
4014+
if (pindex->nStatus & BLOCK_FAILED_MASK && (!chainman.m_best_invalid || pindex->nChainWork > chainman.m_best_invalid->nChainWork)) {
4015+
chainman.m_best_invalid = pindex;
4016+
}
40194017
if (pindex->pprev)
40204018
pindex->BuildSkip();
40214019
if (pindex->IsValid(BLOCK_VALID_TREE) && (pindexBestHeader == nullptr || CBlockIndexWorkComparator()(pindexBestHeader, pindex)))
@@ -4026,7 +4024,6 @@ bool BlockManager::LoadBlockIndex(
40264024
}
40274025

40284026
void BlockManager::Unload() {
4029-
m_failed_blocks.clear();
40304027
m_blocks_unlinked.clear();
40314028

40324029
for (const BlockMap::value_type& entry : m_block_index) {
@@ -4364,7 +4361,6 @@ void UnloadBlockIndex(CTxMemPool* mempool, ChainstateManager& chainman)
43644361
{
43654362
LOCK(cs_main);
43664363
chainman.Unload();
4367-
pindexBestInvalid = nullptr;
43684364
pindexBestHeader = nullptr;
43694365
if (mempool) mempool->clear();
43704366
vinfoBlockFile.clear();
@@ -5341,7 +5337,9 @@ void ChainstateManager::Unload()
53415337
chainstate->UnloadBlockIndex();
53425338
}
53435339

5340+
m_failed_blocks.clear();
53445341
m_blockman.Unload();
5342+
m_best_invalid = nullptr;
53455343
}
53465344

53475345
void ChainstateManager::Reset()

src/validation.h

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -421,26 +421,6 @@ class BlockManager
421421
public:
422422
BlockMap m_block_index GUARDED_BY(cs_main);
423423

424-
/** In order to efficiently track invalidity of headers, we keep the set of
425-
* blocks which we tried to connect and found to be invalid here (ie which
426-
* were set to BLOCK_FAILED_VALID since the last restart). We can then
427-
* walk this set and check if a new header is a descendant of something in
428-
* this set, preventing us from having to walk m_block_index when we try
429-
* to connect a bad block and fail.
430-
*
431-
* While this is more complicated than marking everything which descends
432-
* from an invalid block as invalid at the time we discover it to be
433-
* invalid, doing so would require walking all of m_block_index to find all
434-
* descendants. Since this case should be very rare, keeping track of all
435-
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as
436-
* well.
437-
*
438-
* Because we already walk m_block_index in height-order at startup, we go
439-
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that time,
440-
* instead of putting things in this set.
441-
*/
442-
std::set<CBlockIndex*> m_failed_blocks;
443-
444424
/**
445425
* All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
446426
* Pruned nodes may have entries where B is missing data.
@@ -470,21 +450,8 @@ class BlockManager
470450
//! Mark one block file as pruned (modify associated database entries)
471451
void PruneOneBlockFile(const int fileNumber) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
472452

473-
/**
474-
* If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
475-
* that it doesn't descend from an invalid block, and then add it to m_block_index.
476-
*/
477-
bool AcceptBlockHeader(
478-
const CBlockHeader& block,
479-
BlockValidationState& state,
480-
const CChainParams& chainparams,
481-
CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
482-
483453
CBlockIndex* LookupBlockIndex(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
484454

485-
/** Find the last common block between the parameter chain and a locator. */
486-
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
487-
488455
//! Returns last CBlockIndex* that is a checkpoint
489456
CBlockIndex* GetLastCheckpoint(const CCheckpointData& data) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
490457

@@ -772,6 +739,9 @@ class CChainState
772739
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
773740
bool IsInitialBlockDownload() const;
774741

742+
/** Find the last common block of this chain and a locator. */
743+
CBlockIndex* FindForkInGlobalIndex(const CBlockLocator& locator) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
744+
775745
/**
776746
* Make various assertions about the state of the block index.
777747
*
@@ -912,18 +882,53 @@ class ChainstateManager
912882
//! by the background validation chainstate.
913883
bool m_snapshot_validated{false};
914884

885+
CBlockIndex* m_best_invalid;
886+
friend bool BlockManager::LoadBlockIndex(const Consensus::Params&, ChainstateManager&);
887+
915888
//! Internal helper for ActivateSnapshot().
916889
[[nodiscard]] bool PopulateAndValidateSnapshot(
917890
CChainState& snapshot_chainstate,
918891
CAutoFile& coins_file,
919892
const SnapshotMetadata& metadata);
920893

894+
/**
895+
* If a block header hasn't already been seen, call CheckBlockHeader on it, ensure
896+
* that it doesn't descend from an invalid block, and then add it to m_block_index.
897+
*/
898+
bool AcceptBlockHeader(
899+
const CBlockHeader& block,
900+
BlockValidationState& state,
901+
const CChainParams& chainparams,
902+
CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
903+
friend CChainState;
904+
921905
public:
922906
std::thread m_load_block;
923907
//! A single BlockManager instance is shared across each constructed
924908
//! chainstate to avoid duplicating block metadata.
925909
BlockManager m_blockman GUARDED_BY(::cs_main);
926910

911+
/**
912+
* In order to efficiently track invalidity of headers, we keep the set of
913+
* blocks which we tried to connect and found to be invalid here (ie which
914+
* were set to BLOCK_FAILED_VALID since the last restart). We can then
915+
* walk this set and check if a new header is a descendant of something in
916+
* this set, preventing us from having to walk m_block_index when we try
917+
* to connect a bad block and fail.
918+
*
919+
* While this is more complicated than marking everything which descends
920+
* from an invalid block as invalid at the time we discover it to be
921+
* invalid, doing so would require walking all of m_block_index to find all
922+
* descendants. Since this case should be very rare, keeping track of all
923+
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as
924+
* well.
925+
*
926+
* Because we already walk m_block_index in height-order at startup, we go
927+
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that time,
928+
* instead of putting things in this set.
929+
*/
930+
std::set<CBlockIndex*> m_failed_blocks;
931+
927932
//! The total number of bytes available for us to use across all in-memory
928933
//! coins caches. This will be split somehow across chainstates.
929934
int64_t m_total_coinstip_cache{0};

0 commit comments

Comments
 (0)