55
55
#include < validationinterface.h>
56
56
#include < warnings.h>
57
57
58
+ #include < algorithm>
58
59
#include < numeric>
59
60
#include < optional>
60
61
#include < string>
@@ -3607,7 +3608,7 @@ CBlockIndex * BlockManager::InsertBlockIndex(const uint256& hash)
3607
3608
3608
3609
bool BlockManager::LoadBlockIndex (
3609
3610
const Consensus::Params& consensus_params,
3610
- std::set<CBlockIndex*, CBlockIndexWorkComparator>& block_index_candidates )
3611
+ ChainstateManager& chainman )
3611
3612
{
3612
3613
if (!m_block_tree_db->LoadBlockIndexGuts (consensus_params, [this ](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED (cs_main) { return this ->InsertBlockIndex (hash); })) {
3613
3614
return false ;
@@ -3622,17 +3623,41 @@ bool BlockManager::LoadBlockIndex(
3622
3623
vSortedByHeight.push_back (std::make_pair (pindex->nHeight , pindex));
3623
3624
}
3624
3625
sort (vSortedByHeight.begin (), vSortedByHeight.end ());
3626
+
3627
+ // Find start of assumed-valid region.
3628
+ int first_assumed_valid_height = std::numeric_limits<int >::max ();
3629
+
3630
+ for (const auto & [height, block] : vSortedByHeight) {
3631
+ if (block->IsAssumedValid ()) {
3632
+ auto chainstates = chainman.GetAll ();
3633
+
3634
+ // If we encounter an assumed-valid block index entry, ensure that we have
3635
+ // one chainstate that tolerates assumed-valid entries and another that does
3636
+ // not (i.e. the background validation chainstate), since assumed-valid
3637
+ // entries should always be pending validation by a fully-validated chainstate.
3638
+ auto any_chain = [&](auto fnc) { return std::any_of (chainstates.cbegin (), chainstates.cend (), fnc); };
3639
+ assert (any_chain ([](auto chainstate) { return chainstate->reliesOnAssumedValid (); }));
3640
+ assert (any_chain ([](auto chainstate) { return !chainstate->reliesOnAssumedValid (); }));
3641
+
3642
+ first_assumed_valid_height = height;
3643
+ break ;
3644
+ }
3645
+ }
3646
+
3625
3647
for (const std::pair<int , CBlockIndex*>& item : vSortedByHeight)
3626
3648
{
3627
3649
if (ShutdownRequested ()) return false ;
3628
3650
CBlockIndex* pindex = item.second ;
3629
3651
pindex->nChainWork = (pindex->pprev ? pindex->pprev ->nChainWork : 0 ) + GetBlockProof (*pindex);
3630
3652
pindex->nTimeMax = (pindex->pprev ? std::max (pindex->pprev ->nTimeMax , pindex->nTime ) : pindex->nTime );
3631
- // We can link the chain of blocks for which we've received transactions at some point.
3653
+
3654
+ // We can link the chain of blocks for which we've received transactions at some point, or
3655
+ // blocks that are assumed-valid on the basis of snapshot load (see
3656
+ // PopulateAndValidateSnapshot()).
3632
3657
// Pruned nodes may have deleted the block.
3633
3658
if (pindex->nTx > 0 ) {
3634
3659
if (pindex->pprev ) {
3635
- if (pindex->pprev ->HaveTxsDownloaded () ) {
3660
+ if (pindex->pprev ->nChainTx > 0 ) {
3636
3661
pindex->nChainTx = pindex->pprev ->nChainTx + pindex->nTx ;
3637
3662
} else {
3638
3663
pindex->nChainTx = 0 ;
@@ -3649,7 +3674,36 @@ bool BlockManager::LoadBlockIndex(
3649
3674
if (pindex->IsAssumedValid () ||
3650
3675
(pindex->IsValid (BLOCK_VALID_TRANSACTIONS) &&
3651
3676
(pindex->HaveTxsDownloaded () || pindex->pprev == nullptr ))) {
3652
- block_index_candidates.insert (pindex);
3677
+
3678
+ // Fill each chainstate's block candidate set. Only add assumed-valid
3679
+ // blocks to the tip candidate set if the chainstate is allowed to rely on
3680
+ // assumed-valid blocks.
3681
+ //
3682
+ // If all setBlockIndexCandidates contained the assumed-valid blocks, the
3683
+ // background chainstate's ActivateBestChain() call would add assumed-valid
3684
+ // blocks to the chain (based on how FindMostWorkChain() works). Obviously
3685
+ // we don't want this since the purpose of the background validation chain
3686
+ // is to validate assued-valid blocks.
3687
+ //
3688
+ // Note: This is considering all blocks whose height is greater or equal to
3689
+ // the first assumed-valid block to be assumed-valid blocks, and excluding
3690
+ // them from the background chainstate's setBlockIndexCandidates set. This
3691
+ // does mean that some blocks which are not technically assumed-valid
3692
+ // (later blocks on a fork beginning before the first assumed-valid block)
3693
+ // might not get added to the the background chainstate, but this is ok,
3694
+ // because they will still be attached to the active chainstate if they
3695
+ // actually contain more work.
3696
+ //
3697
+ // Instad of this height-based approach, an earlier attempt was made at
3698
+ // detecting "holistically" whether the block index under consideration
3699
+ // relied on an assumed-valid ancestor, but this proved to be too slow to
3700
+ // be practical.
3701
+ for (CChainState* chainstate : chainman.GetAll ()) {
3702
+ if (chainstate->reliesOnAssumedValid () ||
3703
+ pindex->nHeight < first_assumed_valid_height) {
3704
+ chainstate->setBlockIndexCandidates .insert (pindex);
3705
+ }
3706
+ }
3653
3707
}
3654
3708
if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork ))
3655
3709
pindexBestInvalid = pindex;
@@ -3673,11 +3727,9 @@ void BlockManager::Unload() {
3673
3727
m_block_index.clear ();
3674
3728
}
3675
3729
3676
- bool BlockManager::LoadBlockIndexDB (std::set<CBlockIndex*, CBlockIndexWorkComparator>& setBlockIndexCandidates )
3730
+ bool BlockManager::LoadBlockIndexDB (ChainstateManager& chainman )
3677
3731
{
3678
- if (!LoadBlockIndex (
3679
- ::Params ().GetConsensus(),
3680
- setBlockIndexCandidates)) {
3732
+ if (!LoadBlockIndex (::Params ().GetConsensus (), chainman)) {
3681
3733
return false ;
3682
3734
}
3683
3735
@@ -4023,7 +4075,7 @@ bool ChainstateManager::LoadBlockIndex()
4023
4075
// Load block index from databases
4024
4076
bool needs_init = fReindex ;
4025
4077
if (!fReindex ) {
4026
- bool ret = m_blockman.LoadBlockIndexDB (ActiveChainstate (). setBlockIndexCandidates );
4078
+ bool ret = m_blockman.LoadBlockIndexDB (* this );
4027
4079
if (!ret) return false ;
4028
4080
needs_init = m_blockman.m_block_index .empty ();
4029
4081
}
0 commit comments