LCOV - code coverage report
Current view: top level - src - versionbits.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 59.3 % 177 105
Test Date: 2025-05-07 04:33:46 Functions: 75.0 % 16 12
Branches: 41.6 % 178 74

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2016-2022 The Bitcoin Core developers
       2                 :             : // Distributed under the MIT software license, see the accompanying
       3                 :             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4                 :             : 
       5                 :             : #include <consensus/params.h>
       6                 :             : #include <deploymentinfo.h>
       7                 :             : #include <kernel/chainparams.h>
       8                 :             : #include <util/check.h>
       9                 :             : #include <versionbits.h>
      10                 :             : #include <versionbits_impl.h>
      11                 :             : 
      12                 :             : using enum ThresholdState;
      13                 :             : 
      14                 :       40680 : std::string StateName(ThresholdState state)
      15                 :             : {
      16   [ +  +  +  +  :       40680 :     switch (state) {
                   +  - ]
      17                 :        8940 :     case DEFINED: return "defined";
      18                 :        7548 :     case STARTED: return "started";
      19                 :        3088 :     case LOCKED_IN: return "locked_in";
      20                 :        9316 :     case ACTIVE: return "active";
      21                 :       11788 :     case FAILED: return "failed";
      22                 :             :     }
      23                 :           0 :     return "invalid";
      24                 :             : }
      25                 :             : 
      26                 :      338829 : ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const
      27                 :             : {
      28                 :      338829 :     int nPeriod = Period();
      29                 :      338829 :     int nThreshold = Threshold();
      30                 :      338829 :     int min_activation_height = MinActivationHeight();
      31                 :      338829 :     int64_t nTimeStart = BeginTime();
      32                 :      338829 :     int64_t nTimeTimeout = EndTime();
      33                 :             : 
      34                 :             :     // Check if this deployment is always active.
      35         [ +  + ]:      338829 :     if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
      36                 :             :         return ThresholdState::ACTIVE;
      37                 :             :     }
      38                 :             : 
      39                 :             :     // Check if this deployment is never active.
      40         [ +  + ]:      322432 :     if (nTimeStart == Consensus::BIP9Deployment::NEVER_ACTIVE) {
      41                 :             :         return ThresholdState::FAILED;
      42                 :             :     }
      43                 :             : 
      44                 :             :     // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
      45         [ +  + ]:      291299 :     if (pindexPrev != nullptr) {
      46                 :      289089 :         pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
      47                 :             :     }
      48                 :             : 
      49                 :             :     // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
      50                 :      291299 :     std::vector<const CBlockIndex*> vToCompute;
      51         [ +  + ]:      325492 :     while (cache.count(pindexPrev) == 0) {
      52         [ +  + ]:       41186 :         if (pindexPrev == nullptr) {
      53                 :             :             // The genesis block is by definition defined.
      54         [ +  - ]:        4172 :             cache[pindexPrev] = ThresholdState::DEFINED;
      55                 :        4172 :             break;
      56                 :             :         }
      57         [ +  + ]:       37014 :         if (pindexPrev->GetMedianTimePast() < nTimeStart) {
      58                 :             :             // Optimization: don't recompute down further, as we know every earlier block will be before the start time
      59         [ +  - ]:        2821 :             cache[pindexPrev] = ThresholdState::DEFINED;
      60                 :        2821 :             break;
      61                 :             :         }
      62         [ +  - ]:       34193 :         vToCompute.push_back(pindexPrev);
      63         [ +  - ]:       34193 :         pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
      64                 :             :     }
      65                 :             : 
      66                 :             :     // At this point, cache[pindexPrev] is known
      67         [ -  + ]:      291299 :     assert(cache.count(pindexPrev));
      68         [ +  - ]:      291299 :     ThresholdState state = cache[pindexPrev];
      69                 :             : 
      70                 :             :     // Now walk forward and compute the state of descendants of pindexPrev
      71         [ +  + ]:      325492 :     while (!vToCompute.empty()) {
      72                 :       34193 :         ThresholdState stateNext = state;
      73                 :       34193 :         pindexPrev = vToCompute.back();
      74   [ +  +  +  + ]:       34193 :         vToCompute.pop_back();
      75                 :             : 
      76   [ +  +  +  + ]:       34193 :         switch (state) {
      77                 :        3270 :             case ThresholdState::DEFINED: {
      78         [ +  - ]:        3270 :                 if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
      79                 :        3270 :                     stateNext = ThresholdState::STARTED;
      80                 :             :                 }
      81                 :             :                 break;
      82                 :             :             }
      83                 :             :             case ThresholdState::STARTED: {
      84                 :             :                 // We need to count
      85                 :             :                 const CBlockIndex* pindexCount = pindexPrev;
      86                 :             :                 int count = 0;
      87         [ +  + ]:     3823968 :                 for (int i = 0; i < nPeriod; i++) {
      88   [ +  -  +  + ]:     3820144 :                     if (Condition(pindexCount)) {
      89                 :     1492754 :                         count++;
      90                 :             :                     }
      91                 :     3820144 :                     pindexCount = pindexCount->pprev;
      92                 :             :                 }
      93         [ +  + ]:        3824 :                 if (count >= nThreshold) {
      94                 :             :                     stateNext = ThresholdState::LOCKED_IN;
      95         [ +  + ]:        2646 :                 } else if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
      96                 :        1466 :                     stateNext = ThresholdState::FAILED;
      97                 :             :                 }
      98                 :             :                 break;
      99                 :             :             }
     100                 :        9030 :             case ThresholdState::LOCKED_IN: {
     101                 :             :                 // Progresses into ACTIVE provided activation height will have been reached.
     102         [ +  + ]:        9030 :                 if (pindexPrev->nHeight + 1 >= min_activation_height) {
     103                 :         887 :                     stateNext = ThresholdState::ACTIVE;
     104                 :             :                 }
     105                 :             :                 break;
     106                 :             :             }
     107                 :             :             case ThresholdState::FAILED:
     108                 :             :             case ThresholdState::ACTIVE: {
     109                 :             :                 // Nothing happens, these are terminal states.
     110                 :             :                 break;
     111                 :             :             }
     112                 :             :         }
     113         [ +  - ]:       34193 :         cache[pindexPrev] = state = stateNext;
     114                 :             :     }
     115                 :             : 
     116                 :      291299 :     return state;
     117                 :      291299 : }
     118                 :             : 
     119                 :           0 : BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, std::vector<bool>* signalling_blocks) const
     120                 :             : {
     121                 :           0 :     BIP9Stats stats = {};
     122                 :             : 
     123                 :           0 :     stats.period = Period();
     124                 :           0 :     stats.threshold = Threshold();
     125                 :             : 
     126         [ #  # ]:           0 :     if (pindex == nullptr) return stats;
     127                 :             : 
     128                 :             :     // Find how many blocks are in the current period
     129                 :           0 :     int blocks_in_period = 1 + (pindex->nHeight % stats.period);
     130                 :             : 
     131                 :             :     // Reset signalling_blocks
     132         [ #  # ]:           0 :     if (signalling_blocks) {
     133                 :           0 :         signalling_blocks->assign(blocks_in_period, false);
     134                 :             :     }
     135                 :             : 
     136                 :             :     // Count from current block to beginning of period
     137                 :             :     int elapsed = 0;
     138                 :             :     int count = 0;
     139                 :             :     const CBlockIndex* currentIndex = pindex;
     140                 :           0 :     do {
     141                 :           0 :         ++elapsed;
     142                 :           0 :         --blocks_in_period;
     143         [ #  # ]:           0 :         if (Condition(currentIndex)) {
     144                 :           0 :             ++count;
     145         [ #  # ]:           0 :             if (signalling_blocks) signalling_blocks->at(blocks_in_period) = true;
     146                 :             :         }
     147                 :           0 :         currentIndex = currentIndex->pprev;
     148         [ #  # ]:           0 :     } while(blocks_in_period > 0);
     149                 :             : 
     150                 :           0 :     stats.elapsed = elapsed;
     151                 :           0 :     stats.count = count;
     152                 :           0 :     stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
     153                 :             : 
     154                 :           0 :     return stats;
     155                 :             : }
     156                 :             : 
     157                 :       26428 : int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const
     158                 :             : {
     159                 :       26428 :     int64_t start_time = BeginTime();
     160         [ +  + ]:       26428 :     if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE || start_time == Consensus::BIP9Deployment::NEVER_ACTIVE) {
     161                 :             :         return 0;
     162                 :             :     }
     163                 :             : 
     164                 :       13214 :     const ThresholdState initialState = GetStateFor(pindexPrev, cache);
     165                 :             : 
     166                 :             :     // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
     167         [ +  + ]:       13214 :     if (initialState == ThresholdState::DEFINED) {
     168                 :             :         return 0;
     169                 :             :     }
     170                 :             : 
     171                 :        8960 :     const int nPeriod = Period();
     172                 :             : 
     173                 :             :     // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
     174                 :             :     // To ease understanding of the following height calculation, it helps to remember that
     175                 :             :     // right now pindexPrev points to the block prior to the block that we are computing for, thus:
     176                 :             :     // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
     177                 :             :     // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
     178                 :             :     // The parent of the genesis block is represented by nullptr.
     179                 :        8960 :     pindexPrev = Assert(pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod)));
     180                 :             : 
     181                 :        8960 :     const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
     182                 :             : 
     183   [ +  +  +  + ]:       38608 :     while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, cache) == initialState) {
     184                 :       20688 :         pindexPrev = previousPeriodParent;
     185                 :       20688 :         previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
     186                 :             :     }
     187                 :             : 
     188                 :             :     // Adjust the result because right now we point to the parent block.
     189                 :        8960 :     return pindexPrev->nHeight + 1;
     190                 :             : }
     191                 :             : 
     192                 :           0 : BIP9Info VersionBitsCache::Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id)
     193                 :             : {
     194         [ #  # ]:           0 :     BIP9Info result;
     195                 :             : 
     196                 :             :     VersionBitsConditionChecker checker(params, id);
     197                 :             : 
     198                 :           0 :     ThresholdState current_state, next_state;
     199                 :             : 
     200                 :           0 :     {
     201         [ #  # ]:           0 :         LOCK(m_mutex);
     202         [ #  # ]:           0 :         current_state = checker.GetStateFor(block_index.pprev, m_caches[id]);
     203         [ #  # ]:           0 :         next_state = checker.GetStateFor(&block_index, m_caches[id]);
     204   [ #  #  #  # ]:           0 :         result.since = checker.GetStateSinceHeightFor(block_index.pprev, m_caches[id]);
     205                 :           0 :     }
     206                 :             : 
     207         [ #  # ]:           0 :     result.current_state = StateName(current_state);
     208         [ #  # ]:           0 :     result.next_state = StateName(next_state);
     209                 :             : 
     210                 :           0 :     const bool has_signal = (STARTED == current_state || LOCKED_IN == current_state);
     211         [ #  # ]:           0 :     if (has_signal) {
     212         [ #  # ]:           0 :         result.stats.emplace(checker.GetStateStatisticsFor(&block_index, &result.signalling_blocks));
     213         [ #  # ]:           0 :         if (LOCKED_IN == current_state) {
     214                 :           0 :             result.stats->threshold = 0;
     215                 :           0 :             result.stats->possible = false;
     216                 :             :         }
     217                 :             :     }
     218                 :             : 
     219         [ #  # ]:           0 :     if (current_state == ACTIVE) {
     220                 :           0 :         result.active_since = result.since;
     221         [ #  # ]:           0 :     } else if (next_state == ACTIVE) {
     222                 :           0 :         result.active_since = block_index.nHeight + 1;
     223                 :             :     }
     224                 :             : 
     225                 :           0 :     return result;
     226                 :           0 : }
     227                 :             : 
     228                 :           0 : BIP9GBTStatus VersionBitsCache::GBTStatus(const CBlockIndex& block_index, const Consensus::Params& params)
     229                 :             : {
     230         [ #  # ]:           0 :     BIP9GBTStatus result;
     231                 :             : 
     232         [ #  # ]:           0 :     LOCK(m_mutex);
     233         [ #  # ]:           0 :     for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
     234                 :           0 :         auto pos = static_cast<Consensus::DeploymentPos>(i);
     235         [ #  # ]:           0 :         VersionBitsConditionChecker checker(params, pos);
     236         [ #  # ]:           0 :         ThresholdState state = checker.GetStateFor(&block_index, m_caches[pos]);
     237   [ #  #  #  # ]:           0 :         const VBDeploymentInfo& vbdepinfo = VersionBitsDeploymentInfo[pos];
     238   [ #  #  #  # ]:           0 :         BIP9GBTStatus::Info gbtinfo{.bit=params.vDeployments[pos].bit, .mask=checker.Mask(), .gbt_force=vbdepinfo.gbt_force};
     239                 :             : 
     240   [ #  #  #  # ]:           0 :         switch (state) {
     241                 :             :         case DEFINED:
     242                 :             :         case FAILED:
     243                 :             :             // Not exposed to GBT
     244                 :             :             break;
     245                 :           0 :         case STARTED:
     246   [ #  #  #  # ]:           0 :             result.signalling.try_emplace(vbdepinfo.name, gbtinfo);
     247                 :           0 :             break;
     248                 :           0 :         case LOCKED_IN:
     249   [ #  #  #  # ]:           0 :             result.locked_in.try_emplace(vbdepinfo.name, gbtinfo);
     250                 :           0 :             break;
     251                 :           0 :         case ACTIVE:
     252   [ #  #  #  # ]:           0 :             result.active.try_emplace(vbdepinfo.name, gbtinfo);
     253                 :           0 :             break;
     254                 :             :         }
     255                 :           0 :     }
     256         [ #  # ]:           0 :     return result;
     257                 :           0 : }
     258                 :             : 
     259                 :       17608 : bool VersionBitsCache::IsActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
     260                 :             : {
     261                 :       17608 :     LOCK(m_mutex);
     262   [ +  -  +  - ]:       17608 :     return ThresholdState::ACTIVE == VersionBitsConditionChecker(params, pos).GetStateFor(pindexPrev, m_caches[pos]);
     263                 :       17608 : }
     264                 :             : 
     265                 :       33955 : static int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params, std::array<ThresholdConditionCache, Consensus::MAX_VERSION_BITS_DEPLOYMENTS>& caches)
     266                 :             : {
     267                 :       33955 :     int32_t nVersion = VERSIONBITS_TOP_BITS;
     268                 :             : 
     269         [ +  + ]:      101865 :     for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
     270                 :       67910 :         Consensus::DeploymentPos pos = static_cast<Consensus::DeploymentPos>(i);
     271         [ +  - ]:       67910 :         VersionBitsConditionChecker checker(params, pos);
     272         [ +  - ]:       67910 :         ThresholdState state = checker.GetStateFor(pindexPrev, caches[pos]);
     273         [ +  + ]:       67910 :         if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
     274                 :       22971 :             nVersion |= checker.Mask();
     275                 :             :         }
     276                 :       67910 :     }
     277                 :             : 
     278                 :       33955 :     return nVersion;
     279                 :             : }
     280                 :             : 
     281                 :       33955 : int32_t VersionBitsCache::ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
     282                 :             : {
     283                 :       33955 :     LOCK(m_mutex);
     284   [ +  -  +  - ]:       33955 :     return ::ComputeBlockVersion(pindexPrev, params, m_caches);
     285                 :       33955 : }
     286                 :             : 
     287                 :         190 : void VersionBitsCache::Clear()
     288                 :             : {
     289                 :         190 :     LOCK(m_mutex);
     290         [ +  + ]:         570 :     for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
     291                 :         380 :         m_caches[d].clear();
     292                 :             :     }
     293                 :         190 : }
     294                 :             : 
     295                 :             : namespace {
     296                 :             : /**
     297                 :             :  * Threshold condition checker that triggers when unknown versionbits are seen on the network.
     298                 :             :  */
     299                 :      183831 : class WarningBitsConditionChecker : public AbstractThresholdConditionChecker
     300                 :             : {
     301                 :             : private:
     302                 :             :     const Consensus::Params& m_params;
     303                 :             :     std::array<ThresholdConditionCache, Consensus::MAX_VERSION_BITS_DEPLOYMENTS>& m_caches;
     304                 :             :     int m_bit;
     305                 :             :     int period{2016};
     306                 :             :     int threshold{1815}; // 90% threshold used in BIP 341
     307                 :             : 
     308                 :             : public:
     309                 :      183831 :     explicit WarningBitsConditionChecker(const CChainParams& chainparams, std::array<ThresholdConditionCache, Consensus::MAX_VERSION_BITS_DEPLOYMENTS>& caches, int bit)
     310                 :      183831 :     : m_params{chainparams.GetConsensus()}, m_caches{caches}, m_bit(bit)
     311                 :             :     {
     312         [ +  - ]:      183831 :         if (chainparams.IsTestChain()) {
     313                 :      183831 :             period = chainparams.GetConsensus().DifficultyAdjustmentInterval();
     314                 :      183831 :             threshold = period * 3 / 4; // 75% for test nets per BIP9 suggestion
     315                 :             :         }
     316                 :             :     }
     317                 :             : 
     318                 :      183831 :     int64_t BeginTime() const override { return 0; }
     319                 :      183831 :     int64_t EndTime() const override { return std::numeric_limits<int64_t>::max(); }
     320                 :      183831 :     int Period() const override { return period; }
     321                 :      183831 :     int Threshold() const override { return threshold; }
     322                 :             : 
     323                 :           0 :     bool Condition(const CBlockIndex* pindex) const override
     324                 :             :     {
     325                 :           0 :         return pindex->nHeight >= m_params.MinBIP9WarningHeight &&
     326         [ #  # ]:           0 :                ((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) &&
     327   [ #  #  #  # ]:           0 :                ((pindex->nVersion >> m_bit) & 1) != 0 &&
     328         [ #  # ]:           0 :                ((::ComputeBlockVersion(pindex->pprev, m_params, m_caches) >> m_bit) & 1) == 0;
     329                 :             :     }
     330                 :             : };
     331                 :             : } // anonymous namespace
     332                 :             : 
     333                 :        6339 : std::vector<std::pair<int, bool>> VersionBitsCache::CheckUnknownActivations(const CBlockIndex* pindex, const CChainParams& chainparams)
     334                 :             : {
     335                 :        6339 :     LOCK(m_mutex);
     336                 :        6339 :     std::vector<std::pair<int, bool>> result;
     337         [ +  + ]:      190170 :     for (int bit = 0; bit < VERSIONBITS_NUM_BITS; ++bit) {
     338         [ +  - ]:      183831 :         WarningBitsConditionChecker checker(chainparams, m_caches, bit);
     339   [ -  +  +  - ]:      183831 :         ThresholdState state = checker.GetStateFor(pindex, m_warning_caches.at(bit));
     340         [ -  + ]:      183831 :         if (state == ACTIVE || state == LOCKED_IN) {
     341         [ #  # ]:           0 :             result.emplace_back(bit, state == ACTIVE);
     342                 :             :         }
     343                 :      183831 :     }
     344         [ +  - ]:        6339 :     return result;
     345                 :        6339 : }
        

Generated by: LCOV version 2.0-1