Skip to content

Commit c600ee3

Browse files
committed
Only load BlockMan in BlockMan member functions
This commit effectively splits the "load block index itself" logic from "derive Chainstate variables from loaded block index" logic. This means that BlockManager::LoadBlockIndex{,DB} will only load what's relevant to the BlockManager. I strongly recommend reviewing with the following git-diff flags: --color-moved=dimmed_zebra --color-moved-ws=allow-indentation-change
1 parent 42e56d9 commit c600ee3

File tree

4 files changed

+80
-68
lines changed

4 files changed

+80
-68
lines changed

src/node/blockstorage.cpp

Lines changed: 3 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,7 @@ CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash)
211211
return pindex;
212212
}
213213

214-
bool BlockManager::LoadBlockIndex(
215-
const Consensus::Params& consensus_params,
216-
ChainstateManager& chainman)
214+
bool BlockManager::LoadBlockIndex(const Consensus::Params& consensus_params)
217215
{
218216
if (!m_block_tree_db->LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); })) {
219217
return false;
@@ -230,26 +228,6 @@ bool BlockManager::LoadBlockIndex(
230228
return pa->nHeight < pb->nHeight;
231229
});
232230

233-
// Find start of assumed-valid region.
234-
int first_assumed_valid_height = std::numeric_limits<int>::max();
235-
236-
for (const CBlockIndex* block : vSortedByHeight) {
237-
if (block->IsAssumedValid()) {
238-
auto chainstates = chainman.GetAll();
239-
240-
// If we encounter an assumed-valid block index entry, ensure that we have
241-
// one chainstate that tolerates assumed-valid entries and another that does
242-
// not (i.e. the background validation chainstate), since assumed-valid
243-
// entries should always be pending validation by a fully-validated chainstate.
244-
auto any_chain = [&](auto fnc) { return std::any_of(chainstates.cbegin(), chainstates.cend(), fnc); };
245-
assert(any_chain([](auto chainstate) { return chainstate->reliesOnAssumedValid(); }));
246-
assert(any_chain([](auto chainstate) { return !chainstate->reliesOnAssumedValid(); }));
247-
248-
first_assumed_valid_height = block->nHeight;
249-
break;
250-
}
251-
}
252-
253231
for (CBlockIndex* pindex : vSortedByHeight) {
254232
if (ShutdownRequested()) return false;
255233
pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex);
@@ -275,43 +253,6 @@ bool BlockManager::LoadBlockIndex(
275253
pindex->nStatus |= BLOCK_FAILED_CHILD;
276254
m_dirty_blockindex.insert(pindex);
277255
}
278-
if (pindex->IsAssumedValid() ||
279-
(pindex->IsValid(BLOCK_VALID_TRANSACTIONS) &&
280-
(pindex->HaveTxsDownloaded() || pindex->pprev == nullptr))) {
281-
282-
// Fill each chainstate's block candidate set. Only add assumed-valid
283-
// blocks to the tip candidate set if the chainstate is allowed to rely on
284-
// assumed-valid blocks.
285-
//
286-
// If all setBlockIndexCandidates contained the assumed-valid blocks, the
287-
// background chainstate's ActivateBestChain() call would add assumed-valid
288-
// blocks to the chain (based on how FindMostWorkChain() works). Obviously
289-
// we don't want this since the purpose of the background validation chain
290-
// is to validate assued-valid blocks.
291-
//
292-
// Note: This is considering all blocks whose height is greater or equal to
293-
// the first assumed-valid block to be assumed-valid blocks, and excluding
294-
// them from the background chainstate's setBlockIndexCandidates set. This
295-
// does mean that some blocks which are not technically assumed-valid
296-
// (later blocks on a fork beginning before the first assumed-valid block)
297-
// might not get added to the background chainstate, but this is ok,
298-
// because they will still be attached to the active chainstate if they
299-
// actually contain more work.
300-
//
301-
// Instead of this height-based approach, an earlier attempt was made at
302-
// detecting "holistically" whether the block index under consideration
303-
// relied on an assumed-valid ancestor, but this proved to be too slow to
304-
// be practical.
305-
for (CChainState* chainstate : chainman.GetAll()) {
306-
if (chainstate->reliesOnAssumedValid() ||
307-
pindex->nHeight < first_assumed_valid_height) {
308-
chainstate->setBlockIndexCandidates.insert(pindex);
309-
}
310-
}
311-
}
312-
if (pindex->nStatus & BLOCK_FAILED_MASK && (!chainman.m_best_invalid || pindex->nChainWork > chainman.m_best_invalid->nChainWork)) {
313-
chainman.m_best_invalid = pindex;
314-
}
315256
if (pindex->pprev) {
316257
pindex->BuildSkip();
317258
}
@@ -355,9 +296,9 @@ bool BlockManager::WriteBlockIndexDB()
355296
return true;
356297
}
357298

358-
bool BlockManager::LoadBlockIndexDB(ChainstateManager& chainman)
299+
bool BlockManager::LoadBlockIndexDB()
359300
{
360-
if (!LoadBlockIndex(::Params().GetConsensus(), chainman)) {
301+
if (!LoadBlockIndex(::Params().GetConsensus())) {
361302
return false;
362303
}
363304

src/node/blockstorage.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,15 @@ class BlockManager
127127
std::unique_ptr<CBlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main);
128128

129129
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
130-
bool LoadBlockIndexDB(ChainstateManager& chainman) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
130+
bool LoadBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
131131

132132
/**
133133
* Load the blocktree off disk and into memory. Populate certain metadata
134134
* per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral
135135
* collections like m_dirty_blockindex.
136136
*/
137-
bool LoadBlockIndex(
138-
const Consensus::Params& consensus_params,
139-
ChainstateManager& chainman) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
137+
bool LoadBlockIndex(const Consensus::Params& consensus_params)
138+
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
140139

141140
/** Clear all data members. */
142141
void Unload() EXCLUSIVE_LOCKS_REQUIRED(cs_main);

src/validation.cpp

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4083,8 +4083,80 @@ bool ChainstateManager::LoadBlockIndex()
40834083
// Load block index from databases
40844084
bool needs_init = fReindex;
40854085
if (!fReindex) {
4086-
bool ret = m_blockman.LoadBlockIndexDB(*this);
4086+
bool ret = m_blockman.LoadBlockIndexDB();
40874087
if (!ret) return false;
4088+
4089+
std::vector<CBlockIndex*> vSortedByHeight;
4090+
vSortedByHeight.reserve(m_blockman.m_block_index.size());
4091+
for (auto& [_, block_index] : m_blockman.m_block_index) {
4092+
vSortedByHeight.push_back(&block_index);
4093+
}
4094+
sort(vSortedByHeight.begin(), vSortedByHeight.end(),
4095+
[](const CBlockIndex* pa, const CBlockIndex* pb) {
4096+
return pa->nHeight < pb->nHeight;
4097+
});
4098+
4099+
// Find start of assumed-valid region.
4100+
int first_assumed_valid_height = std::numeric_limits<int>::max();
4101+
4102+
for (const CBlockIndex* block : vSortedByHeight) {
4103+
if (block->IsAssumedValid()) {
4104+
auto chainstates = GetAll();
4105+
4106+
// If we encounter an assumed-valid block index entry, ensure that we have
4107+
// one chainstate that tolerates assumed-valid entries and another that does
4108+
// not (i.e. the background validation chainstate), since assumed-valid
4109+
// entries should always be pending validation by a fully-validated chainstate.
4110+
auto any_chain = [&](auto fnc) { return std::any_of(chainstates.cbegin(), chainstates.cend(), fnc); };
4111+
assert(any_chain([](auto chainstate) { return chainstate->reliesOnAssumedValid(); }));
4112+
assert(any_chain([](auto chainstate) { return !chainstate->reliesOnAssumedValid(); }));
4113+
4114+
first_assumed_valid_height = block->nHeight;
4115+
break;
4116+
}
4117+
}
4118+
4119+
for (CBlockIndex* pindex : vSortedByHeight) {
4120+
if (ShutdownRequested()) return false;
4121+
if (pindex->IsAssumedValid() ||
4122+
(pindex->IsValid(BLOCK_VALID_TRANSACTIONS) &&
4123+
(pindex->HaveTxsDownloaded() || pindex->pprev == nullptr))) {
4124+
4125+
// Fill each chainstate's block candidate set. Only add assumed-valid
4126+
// blocks to the tip candidate set if the chainstate is allowed to rely on
4127+
// assumed-valid blocks.
4128+
//
4129+
// If all setBlockIndexCandidates contained the assumed-valid blocks, the
4130+
// background chainstate's ActivateBestChain() call would add assumed-valid
4131+
// blocks to the chain (based on how FindMostWorkChain() works). Obviously
4132+
// we don't want this since the purpose of the background validation chain
4133+
// is to validate assued-valid blocks.
4134+
//
4135+
// Note: This is considering all blocks whose height is greater or equal to
4136+
// the first assumed-valid block to be assumed-valid blocks, and excluding
4137+
// them from the background chainstate's setBlockIndexCandidates set. This
4138+
// does mean that some blocks which are not technically assumed-valid
4139+
// (later blocks on a fork beginning before the first assumed-valid block)
4140+
// might not get added to the background chainstate, but this is ok,
4141+
// because they will still be attached to the active chainstate if they
4142+
// actually contain more work.
4143+
//
4144+
// Instead of this height-based approach, an earlier attempt was made at
4145+
// detecting "holistically" whether the block index under consideration
4146+
// relied on an assumed-valid ancestor, but this proved to be too slow to
4147+
// be practical.
4148+
for (CChainState* chainstate : GetAll()) {
4149+
if (chainstate->reliesOnAssumedValid() ||
4150+
pindex->nHeight < first_assumed_valid_height) {
4151+
chainstate->setBlockIndexCandidates.insert(pindex);
4152+
}
4153+
}
4154+
}
4155+
if (pindex->nStatus & BLOCK_FAILED_MASK && (!m_best_invalid || pindex->nChainWork > m_best_invalid->nChainWork)) {
4156+
m_best_invalid = pindex;
4157+
}
4158+
}
4159+
40884160
needs_init = m_blockman.m_block_index.empty();
40894161
}
40904162

src/validation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,7 @@ class ChainstateManager
836836
bool m_snapshot_validated{false};
837837

838838
CBlockIndex* m_best_invalid;
839-
friend bool node::BlockManager::LoadBlockIndex(const Consensus::Params&, ChainstateManager&);
839+
friend bool node::BlockManager::LoadBlockIndex(const Consensus::Params&);
840840

841841
//! Internal helper for ActivateSnapshot().
842842
[[nodiscard]] bool PopulateAndValidateSnapshot(

0 commit comments

Comments
 (0)