LCOV - code coverage report
Current view: top level - src - versionbits.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 90 92 97.8 %
Date: 2020-09-26 01:30:44 Functions: 16 16 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2016-2019 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 <versionbits.h>
       6             : #include <consensus/params.h>
       7             : 
       8     4856874 : ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
       9             : {
      10     4856874 :     int nPeriod = Period(params);
      11     4856874 :     int nThreshold = Threshold(params);
      12     4856874 :     int64_t nTimeStart = BeginTime(params);
      13     4856874 :     int64_t nTimeTimeout = EndTime(params);
      14             : 
      15             :     // Check if this deployment is always active.
      16     4856874 :     if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
      17        6287 :         return ThresholdState::ACTIVE;
      18             :     }
      19             : 
      20             :     // 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.
      21     4850587 :     if (pindexPrev != nullptr) {
      22     4834775 :         pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
      23     4834775 :     }
      24             : 
      25             :     // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
      26     4850587 :     std::vector<const CBlockIndex*> vToCompute;
      27     4872484 :     while (cache.count(pindexPrev) == 0) {
      28       34753 :         if (pindexPrev == nullptr) {
      29             :             // The genesis block is by definition defined.
      30       11435 :             cache[pindexPrev] = ThresholdState::DEFINED;
      31       11435 :             break;
      32             :         }
      33       23318 :         if (pindexPrev->GetMedianTimePast() < nTimeStart) {
      34             :             // Optimization: don't recompute down further, as we know every earlier block will be before the start time
      35        1421 :             cache[pindexPrev] = ThresholdState::DEFINED;
      36        1421 :             break;
      37             :         }
      38       21897 :         vToCompute.push_back(pindexPrev);
      39       21897 :         pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
      40             :     }
      41             : 
      42             :     // At this point, cache[pindexPrev] is known
      43     4850587 :     assert(cache.count(pindexPrev));
      44     4850587 :     ThresholdState state = cache[pindexPrev];
      45             : 
      46             :     // Now walk forward and compute the state of descendants of pindexPrev
      47     4872484 :     while (!vToCompute.empty()) {
      48             :         ThresholdState stateNext = state;
      49       21897 :         pindexPrev = vToCompute.back();
      50       21897 :         vToCompute.pop_back();
      51             : 
      52       21897 :         switch (state) {
      53             :             case ThresholdState::DEFINED: {
      54        7992 :                 if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
      55             :                     stateNext = ThresholdState::FAILED;
      56        7992 :                 } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
      57             :                     stateNext = ThresholdState::STARTED;
      58        7695 :                 }
      59             :                 break;
      60             :             }
      61             :             case ThresholdState::STARTED: {
      62        5189 :                 if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
      63             :                     stateNext = ThresholdState::FAILED;
      64         723 :                     break;
      65             :                 }
      66             :                 // We need to count
      67        4466 :                 const CBlockIndex* pindexCount = pindexPrev;
      68             :                 int count = 0;
      69     1358530 :                 for (int i = 0; i < nPeriod; i++) {
      70     1354064 :                     if (Condition(pindexCount, params)) {
      71      276528 :                         count++;
      72      276528 :                     }
      73     1354064 :                     pindexCount = pindexCount->pprev;
      74             :                 }
      75        4466 :                 if (count >= nThreshold) {
      76             :                     stateNext = ThresholdState::LOCKED_IN;
      77         351 :                 }
      78             :                 break;
      79           0 :             }
      80             :             case ThresholdState::LOCKED_IN: {
      81             :                 // Always progresses into ACTIVE.
      82             :                 stateNext = ThresholdState::ACTIVE;
      83         265 :                 break;
      84             :             }
      85             :             case ThresholdState::FAILED:
      86             :             case ThresholdState::ACTIVE: {
      87             :                 // Nothing happens, these are terminal states.
      88             :                 break;
      89             :             }
      90             :         }
      91       21897 :         cache[pindexPrev] = state = stateNext;
      92           0 :     }
      93             : 
      94             :     return state;
      95     4856874 : }
      96             : 
      97         273 : BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params) const
      98             : {
      99         273 :     BIP9Stats stats = {};
     100             : 
     101         273 :     stats.period = Period(params);
     102         273 :     stats.threshold = Threshold(params);
     103             : 
     104         273 :     if (pindex == nullptr)
     105             :         return stats;
     106             : 
     107             :     // Find beginning of period
     108         273 :     const CBlockIndex* pindexEndOfPrevPeriod = pindex->GetAncestor(pindex->nHeight - ((pindex->nHeight + 1) % stats.period));
     109         273 :     stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight;
     110             : 
     111             :     // Count from current block to beginning of period
     112             :     int count = 0;
     113             :     const CBlockIndex* currentIndex = pindex;
     114       17072 :     while (pindexEndOfPrevPeriod->nHeight != currentIndex->nHeight){
     115       16799 :         if (Condition(currentIndex, params))
     116       16073 :             count++;
     117       16799 :         currentIndex = currentIndex->pprev;
     118             :     }
     119             : 
     120         273 :     stats.count = count;
     121         273 :     stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
     122             : 
     123             :     return stats;
     124         273 : }
     125             : 
     126       12670 : int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
     127             : {
     128       12670 :     int64_t start_time = BeginTime(params);
     129       12670 :     if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
     130        6158 :         return 0;
     131             :     }
     132             : 
     133        6512 :     const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
     134             : 
     135             :     // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
     136        6512 :     if (initialState == ThresholdState::DEFINED) {
     137        2187 :         return 0;
     138             :     }
     139             : 
     140        4325 :     const int nPeriod = Period(params);
     141             : 
     142             :     // 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.
     143             :     // To ease understanding of the following height calculation, it helps to remember that
     144             :     // right now pindexPrev points to the block prior to the block that we are computing for, thus:
     145             :     // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
     146             :     // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
     147             :     // The parent of the genesis block is represented by nullptr.
     148        4325 :     pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
     149             : 
     150        4325 :     const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
     151             : 
     152       13466 :     while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, params, cache) == initialState) {
     153             :         pindexPrev = previousPeriodParent;
     154        9141 :         previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
     155             :     }
     156             : 
     157             :     // Adjust the result because right now we point to the parent block.
     158        4325 :     return pindexPrev->nHeight + 1;
     159       12670 : }
     160             : 
     161             : namespace
     162             : {
     163             : /**
     164             :  * Class to implement versionbits logic.
     165             :  */
     166             : class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
     167             : private:
     168             :     const Consensus::DeploymentPos id;
     169             : 
     170             : protected:
     171     3587051 :     int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
     172     3586697 :     int64_t EndTime(const Consensus::Params& params) const override { return params.vDeployments[id].nTimeout; }
     173     3587255 :     int Period(const Consensus::Params& params) const override { return params.nMinerConfirmationWindow; }
     174     3586970 :     int Threshold(const Consensus::Params& params) const override { return params.nRuleChangeActivationThreshold; }
     175             : 
     176       33503 :     bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
     177             :     {
     178       33503 :         return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
     179             :     }
     180             : 
     181             : public:
     182    10433500 :     explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
     183     1655994 :     uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
     184             : };
     185             : 
     186             : } // namespace
     187             : 
     188     3586282 : ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
     189             : {
     190     3586282 :     return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
     191             : }
     192             : 
     193         273 : BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
     194             : {
     195         273 :     return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params);
     196             : }
     197             : 
     198         354 : int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
     199             : {
     200         354 :     return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]);
     201             : }
     202             : 
     203     1629841 : uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos)
     204             : {
     205     1629841 :     return VersionBitsConditionChecker(pos).Mask(params);
     206             : }
     207             : 
     208         597 : void VersionBitsCache::Clear()
     209             : {
     210        1194 :     for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
     211         597 :         caches[d].clear();
     212             :     }
     213         597 : }

Generated by: LCOV version 1.15