mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-12 15:09:59 +01:00
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
This commit is contained in:
@@ -211,9 +211,7 @@ CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash)
|
|||||||
return pindex;
|
return pindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlockManager::LoadBlockIndex(
|
bool BlockManager::LoadBlockIndex(const Consensus::Params& consensus_params)
|
||||||
const Consensus::Params& consensus_params,
|
|
||||||
ChainstateManager& chainman)
|
|
||||||
{
|
{
|
||||||
if (!m_block_tree_db->LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); })) {
|
if (!m_block_tree_db->LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); })) {
|
||||||
return false;
|
return false;
|
||||||
@@ -230,26 +228,6 @@ bool BlockManager::LoadBlockIndex(
|
|||||||
return pa->nHeight < pb->nHeight;
|
return pa->nHeight < pb->nHeight;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Find start of assumed-valid region.
|
|
||||||
int first_assumed_valid_height = std::numeric_limits<int>::max();
|
|
||||||
|
|
||||||
for (const CBlockIndex* block : vSortedByHeight) {
|
|
||||||
if (block->IsAssumedValid()) {
|
|
||||||
auto chainstates = chainman.GetAll();
|
|
||||||
|
|
||||||
// If we encounter an assumed-valid block index entry, ensure that we have
|
|
||||||
// one chainstate that tolerates assumed-valid entries and another that does
|
|
||||||
// not (i.e. the background validation chainstate), since assumed-valid
|
|
||||||
// entries should always be pending validation by a fully-validated chainstate.
|
|
||||||
auto any_chain = [&](auto fnc) { return std::any_of(chainstates.cbegin(), chainstates.cend(), fnc); };
|
|
||||||
assert(any_chain([](auto chainstate) { return chainstate->reliesOnAssumedValid(); }));
|
|
||||||
assert(any_chain([](auto chainstate) { return !chainstate->reliesOnAssumedValid(); }));
|
|
||||||
|
|
||||||
first_assumed_valid_height = block->nHeight;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (CBlockIndex* pindex : vSortedByHeight) {
|
for (CBlockIndex* pindex : vSortedByHeight) {
|
||||||
if (ShutdownRequested()) return false;
|
if (ShutdownRequested()) return false;
|
||||||
pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex);
|
pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex);
|
||||||
@@ -275,43 +253,6 @@ bool BlockManager::LoadBlockIndex(
|
|||||||
pindex->nStatus |= BLOCK_FAILED_CHILD;
|
pindex->nStatus |= BLOCK_FAILED_CHILD;
|
||||||
m_dirty_blockindex.insert(pindex);
|
m_dirty_blockindex.insert(pindex);
|
||||||
}
|
}
|
||||||
if (pindex->IsAssumedValid() ||
|
|
||||||
(pindex->IsValid(BLOCK_VALID_TRANSACTIONS) &&
|
|
||||||
(pindex->HaveTxsDownloaded() || pindex->pprev == nullptr))) {
|
|
||||||
|
|
||||||
// Fill each chainstate's block candidate set. Only add assumed-valid
|
|
||||||
// blocks to the tip candidate set if the chainstate is allowed to rely on
|
|
||||||
// assumed-valid blocks.
|
|
||||||
//
|
|
||||||
// If all setBlockIndexCandidates contained the assumed-valid blocks, the
|
|
||||||
// background chainstate's ActivateBestChain() call would add assumed-valid
|
|
||||||
// blocks to the chain (based on how FindMostWorkChain() works). Obviously
|
|
||||||
// we don't want this since the purpose of the background validation chain
|
|
||||||
// is to validate assued-valid blocks.
|
|
||||||
//
|
|
||||||
// Note: This is considering all blocks whose height is greater or equal to
|
|
||||||
// the first assumed-valid block to be assumed-valid blocks, and excluding
|
|
||||||
// them from the background chainstate's setBlockIndexCandidates set. This
|
|
||||||
// does mean that some blocks which are not technically assumed-valid
|
|
||||||
// (later blocks on a fork beginning before the first assumed-valid block)
|
|
||||||
// might not get added to the background chainstate, but this is ok,
|
|
||||||
// because they will still be attached to the active chainstate if they
|
|
||||||
// actually contain more work.
|
|
||||||
//
|
|
||||||
// Instead of this height-based approach, an earlier attempt was made at
|
|
||||||
// detecting "holistically" whether the block index under consideration
|
|
||||||
// relied on an assumed-valid ancestor, but this proved to be too slow to
|
|
||||||
// be practical.
|
|
||||||
for (CChainState* chainstate : chainman.GetAll()) {
|
|
||||||
if (chainstate->reliesOnAssumedValid() ||
|
|
||||||
pindex->nHeight < first_assumed_valid_height) {
|
|
||||||
chainstate->setBlockIndexCandidates.insert(pindex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pindex->nStatus & BLOCK_FAILED_MASK && (!chainman.m_best_invalid || pindex->nChainWork > chainman.m_best_invalid->nChainWork)) {
|
|
||||||
chainman.m_best_invalid = pindex;
|
|
||||||
}
|
|
||||||
if (pindex->pprev) {
|
if (pindex->pprev) {
|
||||||
pindex->BuildSkip();
|
pindex->BuildSkip();
|
||||||
}
|
}
|
||||||
@@ -355,9 +296,9 @@ bool BlockManager::WriteBlockIndexDB()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlockManager::LoadBlockIndexDB(ChainstateManager& chainman)
|
bool BlockManager::LoadBlockIndexDB()
|
||||||
{
|
{
|
||||||
if (!LoadBlockIndex(::Params().GetConsensus(), chainman)) {
|
if (!LoadBlockIndex(::Params().GetConsensus())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,16 +127,15 @@ public:
|
|||||||
std::unique_ptr<CBlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main);
|
std::unique_ptr<CBlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main);
|
||||||
|
|
||||||
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||||
bool LoadBlockIndexDB(ChainstateManager& chainman) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
bool LoadBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the blocktree off disk and into memory. Populate certain metadata
|
* Load the blocktree off disk and into memory. Populate certain metadata
|
||||||
* per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral
|
* per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral
|
||||||
* collections like m_dirty_blockindex.
|
* collections like m_dirty_blockindex.
|
||||||
*/
|
*/
|
||||||
bool LoadBlockIndex(
|
bool LoadBlockIndex(const Consensus::Params& consensus_params)
|
||||||
const Consensus::Params& consensus_params,
|
EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
ChainstateManager& chainman) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
|
||||||
|
|
||||||
/** Clear all data members. */
|
/** Clear all data members. */
|
||||||
void Unload() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
void Unload() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||||
|
|||||||
@@ -4083,8 +4083,80 @@ bool ChainstateManager::LoadBlockIndex()
|
|||||||
// Load block index from databases
|
// Load block index from databases
|
||||||
bool needs_init = fReindex;
|
bool needs_init = fReindex;
|
||||||
if (!fReindex) {
|
if (!fReindex) {
|
||||||
bool ret = m_blockman.LoadBlockIndexDB(*this);
|
bool ret = m_blockman.LoadBlockIndexDB();
|
||||||
if (!ret) return false;
|
if (!ret) return false;
|
||||||
|
|
||||||
|
std::vector<CBlockIndex*> vSortedByHeight;
|
||||||
|
vSortedByHeight.reserve(m_blockman.m_block_index.size());
|
||||||
|
for (auto& [_, block_index] : m_blockman.m_block_index) {
|
||||||
|
vSortedByHeight.push_back(&block_index);
|
||||||
|
}
|
||||||
|
sort(vSortedByHeight.begin(), vSortedByHeight.end(),
|
||||||
|
[](const CBlockIndex* pa, const CBlockIndex* pb) {
|
||||||
|
return pa->nHeight < pb->nHeight;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find start of assumed-valid region.
|
||||||
|
int first_assumed_valid_height = std::numeric_limits<int>::max();
|
||||||
|
|
||||||
|
for (const CBlockIndex* block : vSortedByHeight) {
|
||||||
|
if (block->IsAssumedValid()) {
|
||||||
|
auto chainstates = GetAll();
|
||||||
|
|
||||||
|
// If we encounter an assumed-valid block index entry, ensure that we have
|
||||||
|
// one chainstate that tolerates assumed-valid entries and another that does
|
||||||
|
// not (i.e. the background validation chainstate), since assumed-valid
|
||||||
|
// entries should always be pending validation by a fully-validated chainstate.
|
||||||
|
auto any_chain = [&](auto fnc) { return std::any_of(chainstates.cbegin(), chainstates.cend(), fnc); };
|
||||||
|
assert(any_chain([](auto chainstate) { return chainstate->reliesOnAssumedValid(); }));
|
||||||
|
assert(any_chain([](auto chainstate) { return !chainstate->reliesOnAssumedValid(); }));
|
||||||
|
|
||||||
|
first_assumed_valid_height = block->nHeight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CBlockIndex* pindex : vSortedByHeight) {
|
||||||
|
if (ShutdownRequested()) return false;
|
||||||
|
if (pindex->IsAssumedValid() ||
|
||||||
|
(pindex->IsValid(BLOCK_VALID_TRANSACTIONS) &&
|
||||||
|
(pindex->HaveTxsDownloaded() || pindex->pprev == nullptr))) {
|
||||||
|
|
||||||
|
// Fill each chainstate's block candidate set. Only add assumed-valid
|
||||||
|
// blocks to the tip candidate set if the chainstate is allowed to rely on
|
||||||
|
// assumed-valid blocks.
|
||||||
|
//
|
||||||
|
// If all setBlockIndexCandidates contained the assumed-valid blocks, the
|
||||||
|
// background chainstate's ActivateBestChain() call would add assumed-valid
|
||||||
|
// blocks to the chain (based on how FindMostWorkChain() works). Obviously
|
||||||
|
// we don't want this since the purpose of the background validation chain
|
||||||
|
// is to validate assued-valid blocks.
|
||||||
|
//
|
||||||
|
// Note: This is considering all blocks whose height is greater or equal to
|
||||||
|
// the first assumed-valid block to be assumed-valid blocks, and excluding
|
||||||
|
// them from the background chainstate's setBlockIndexCandidates set. This
|
||||||
|
// does mean that some blocks which are not technically assumed-valid
|
||||||
|
// (later blocks on a fork beginning before the first assumed-valid block)
|
||||||
|
// might not get added to the background chainstate, but this is ok,
|
||||||
|
// because they will still be attached to the active chainstate if they
|
||||||
|
// actually contain more work.
|
||||||
|
//
|
||||||
|
// Instead of this height-based approach, an earlier attempt was made at
|
||||||
|
// detecting "holistically" whether the block index under consideration
|
||||||
|
// relied on an assumed-valid ancestor, but this proved to be too slow to
|
||||||
|
// be practical.
|
||||||
|
for (CChainState* chainstate : GetAll()) {
|
||||||
|
if (chainstate->reliesOnAssumedValid() ||
|
||||||
|
pindex->nHeight < first_assumed_valid_height) {
|
||||||
|
chainstate->setBlockIndexCandidates.insert(pindex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pindex->nStatus & BLOCK_FAILED_MASK && (!m_best_invalid || pindex->nChainWork > m_best_invalid->nChainWork)) {
|
||||||
|
m_best_invalid = pindex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
needs_init = m_blockman.m_block_index.empty();
|
needs_init = m_blockman.m_block_index.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -836,7 +836,7 @@ private:
|
|||||||
bool m_snapshot_validated{false};
|
bool m_snapshot_validated{false};
|
||||||
|
|
||||||
CBlockIndex* m_best_invalid;
|
CBlockIndex* m_best_invalid;
|
||||||
friend bool node::BlockManager::LoadBlockIndex(const Consensus::Params&, ChainstateManager&);
|
friend bool node::BlockManager::LoadBlockIndex(const Consensus::Params&);
|
||||||
|
|
||||||
//! Internal helper for ActivateSnapshot().
|
//! Internal helper for ActivateSnapshot().
|
||||||
[[nodiscard]] bool PopulateAndValidateSnapshot(
|
[[nodiscard]] bool PopulateAndValidateSnapshot(
|
||||||
|
|||||||
Reference in New Issue
Block a user