LCOV - code coverage report
Current view: top level - src - versionbits.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 154 158 97.5 %
Date: 2022-04-21 14:51:19 Functions: 17 17 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 65 70 92.9 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2016-2021 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                 :            : ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
#       9                 :    1929046 : {
#      10                 :    1929046 :     int nPeriod = Period(params);
#      11                 :    1929046 :     int nThreshold = Threshold(params);
#      12                 :    1929046 :     int min_activation_height = MinActivationHeight(params);
#      13                 :    1929046 :     int64_t nTimeStart = BeginTime(params);
#      14                 :    1929046 :     int64_t nTimeTimeout = EndTime(params);
#      15                 :            : 
#      16                 :            :     // Check if this deployment is always active.
#      17         [ +  + ]:    1929046 :     if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
#      18                 :      51947 :         return ThresholdState::ACTIVE;
#      19                 :      51947 :     }
#      20                 :            : 
#      21                 :            :     // Check if this deployment is never active.
#      22         [ +  + ]:    1877099 :     if (nTimeStart == Consensus::BIP9Deployment::NEVER_ACTIVE) {
#      23                 :      31042 :         return ThresholdState::FAILED;
#      24                 :      31042 :     }
#      25                 :            : 
#      26                 :            :     // 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.
#      27         [ +  + ]:    1846057 :     if (pindexPrev != nullptr) {
#      28                 :    1843783 :         pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
#      29                 :    1843783 :     }
#      30                 :            : 
#      31                 :            :     // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
#      32                 :    1846057 :     std::vector<const CBlockIndex*> vToCompute;
#      33         [ +  + ]:    1894458 :     while (cache.count(pindexPrev) == 0) {
#      34         [ +  + ]:      68615 :         if (pindexPrev == nullptr) {
#      35                 :            :             // The genesis block is by definition defined.
#      36                 :      17338 :             cache[pindexPrev] = ThresholdState::DEFINED;
#      37                 :      17338 :             break;
#      38                 :      17338 :         }
#      39         [ +  + ]:      51277 :         if (pindexPrev->GetMedianTimePast() < nTimeStart) {
#      40                 :            :             // Optimization: don't recompute down further, as we know every earlier block will be before the start time
#      41                 :       2876 :             cache[pindexPrev] = ThresholdState::DEFINED;
#      42                 :       2876 :             break;
#      43                 :       2876 :         }
#      44                 :      48401 :         vToCompute.push_back(pindexPrev);
#      45                 :      48401 :         pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
#      46                 :      48401 :     }
#      47                 :            : 
#      48                 :            :     // At this point, cache[pindexPrev] is known
#      49                 :    1846057 :     assert(cache.count(pindexPrev));
#      50                 :          0 :     ThresholdState state = cache[pindexPrev];
#      51                 :            : 
#      52                 :            :     // Now walk forward and compute the state of descendants of pindexPrev
#      53         [ +  + ]:    1894458 :     while (!vToCompute.empty()) {
#      54                 :      48401 :         ThresholdState stateNext = state;
#      55                 :      48401 :         pindexPrev = vToCompute.back();
#      56                 :      48401 :         vToCompute.pop_back();
#      57                 :            : 
#      58         [ -  + ]:      48401 :         switch (state) {
#      59         [ +  + ]:      11954 :             case ThresholdState::DEFINED: {
#      60         [ +  - ]:      11954 :                 if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
#      61                 :      11954 :                     stateNext = ThresholdState::STARTED;
#      62                 :      11954 :                 }
#      63                 :      11954 :                 break;
#      64                 :          0 :             }
#      65         [ +  + ]:       9298 :             case ThresholdState::STARTED: {
#      66                 :            :                 // We need to count
#      67                 :       9298 :                 const CBlockIndex* pindexCount = pindexPrev;
#      68                 :       9298 :                 int count = 0;
#      69         [ +  + ]:    4607426 :                 for (int i = 0; i < nPeriod; i++) {
#      70         [ +  + ]:    4598128 :                     if (Condition(pindexCount, params)) {
#      71                 :    1464743 :                         count++;
#      72                 :    1464743 :                     }
#      73                 :    4598128 :                     pindexCount = pindexCount->pprev;
#      74                 :    4598128 :                 }
#      75         [ +  + ]:       9298 :                 if (count >= nThreshold) {
#      76                 :       1194 :                     stateNext = ThresholdState::LOCKED_IN;
#      77         [ +  + ]:       8104 :                 } else if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
#      78                 :       1484 :                     stateNext = ThresholdState::FAILED;
#      79                 :       1484 :                 }
#      80                 :       9298 :                 break;
#      81                 :          0 :             }
#      82         [ +  + ]:       9129 :             case ThresholdState::LOCKED_IN: {
#      83                 :            :                 // Progresses into ACTIVE provided activation height will have been reached.
#      84         [ +  + ]:       9129 :                 if (pindexPrev->nHeight + 1 >= min_activation_height) {
#      85                 :        905 :                     stateNext = ThresholdState::ACTIVE;
#      86                 :        905 :                 }
#      87                 :       9129 :                 break;
#      88                 :          0 :             }
#      89         [ +  + ]:       6950 :             case ThresholdState::FAILED:
#      90         [ +  + ]:      18020 :             case ThresholdState::ACTIVE: {
#      91                 :            :                 // Nothing happens, these are terminal states.
#      92                 :      18020 :                 break;
#      93                 :       6950 :             }
#      94                 :      48401 :         }
#      95                 :      48401 :         cache[pindexPrev] = state = stateNext;
#      96                 :      48401 :     }
#      97                 :            : 
#      98                 :    1846057 :     return state;
#      99                 :    1846057 : }
#     100                 :            : 
#     101                 :            : BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params, std::vector<bool>* signalling_blocks) const
#     102                 :         31 : {
#     103                 :         31 :     BIP9Stats stats = {};
#     104                 :            : 
#     105                 :         31 :     stats.period = Period(params);
#     106                 :         31 :     stats.threshold = Threshold(params);
#     107                 :            : 
#     108         [ -  + ]:         31 :     if (pindex == nullptr) return stats;
#     109                 :            : 
#     110                 :            :     // Find how many blocks are in the current period
#     111                 :         31 :     int blocks_in_period = 1 + (pindex->nHeight % stats.period);
#     112                 :            : 
#     113                 :            :     // Reset signalling_blocks
#     114         [ +  - ]:         31 :     if (signalling_blocks) {
#     115                 :         31 :         signalling_blocks->assign(blocks_in_period, false);
#     116                 :         31 :     }
#     117                 :            : 
#     118                 :            :     // Count from current block to beginning of period
#     119                 :         31 :     int elapsed = 0;
#     120                 :         31 :     int count = 0;
#     121                 :         31 :     const CBlockIndex* currentIndex = pindex;
#     122                 :       3184 :     do {
#     123                 :       3184 :         ++elapsed;
#     124                 :       3184 :         --blocks_in_period;
#     125         [ +  + ]:       3184 :         if (Condition(currentIndex, params)) {
#     126                 :       2374 :             ++count;
#     127         [ +  - ]:       2374 :             if (signalling_blocks) signalling_blocks->at(blocks_in_period) = true;
#     128                 :       2374 :         }
#     129                 :       3184 :         currentIndex = currentIndex->pprev;
#     130         [ +  + ]:       3184 :     } while(blocks_in_period > 0);
#     131                 :            : 
#     132                 :         31 :     stats.elapsed = elapsed;
#     133                 :         31 :     stats.count = count;
#     134                 :         31 :     stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
#     135                 :            : 
#     136                 :         31 :     return stats;
#     137                 :         31 : }
#     138                 :            : 
#     139                 :            : int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
#     140                 :      26871 : {
#     141                 :      26871 :     int64_t start_time = BeginTime(params);
#     142 [ +  + ][ +  + ]:      26871 :     if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE || start_time == Consensus::BIP9Deployment::NEVER_ACTIVE) {
#     143                 :      13478 :         return 0;
#     144                 :      13478 :     }
#     145                 :            : 
#     146                 :      13393 :     const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
#     147                 :            : 
#     148                 :            :     // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
#     149         [ +  + ]:      13393 :     if (initialState == ThresholdState::DEFINED) {
#     150                 :       4285 :         return 0;
#     151                 :       4285 :     }
#     152                 :            : 
#     153                 :       9108 :     const int nPeriod = Period(params);
#     154                 :            : 
#     155                 :            :     // 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.
#     156                 :            :     // To ease understanding of the following height calculation, it helps to remember that
#     157                 :            :     // right now pindexPrev points to the block prior to the block that we are computing for, thus:
#     158                 :            :     // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
#     159                 :            :     // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
#     160                 :            :     // The parent of the genesis block is represented by nullptr.
#     161                 :       9108 :     pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
#     162                 :            : 
#     163                 :       9108 :     const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
#     164                 :            : 
#     165 [ +  + ][ +  + ]:      29990 :     while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, params, cache) == initialState) {
#     166                 :      20882 :         pindexPrev = previousPeriodParent;
#     167                 :      20882 :         previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
#     168                 :      20882 :     }
#     169                 :            : 
#     170                 :            :     // Adjust the result because right now we point to the parent block.
#     171                 :       9108 :     return pindexPrev->nHeight + 1;
#     172                 :      13393 : }
#     173                 :            : 
#     174                 :            : namespace
#     175                 :            : {
#     176                 :            : /**
#     177                 :            :  * Class to implement versionbits logic.
#     178                 :            :  */
#     179                 :            : class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
#     180                 :            : private:
#     181                 :            :     const Consensus::DeploymentPos id;
#     182                 :            : 
#     183                 :            : protected:
#     184                 :     139174 :     int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
#     185                 :     138915 :     int64_t EndTime(const Consensus::Params& params) const override { return params.vDeployments[id].nTimeout; }
#     186                 :     138915 :     int MinActivationHeight(const Consensus::Params& params) const override { return params.vDeployments[id].min_activation_height; }
#     187                 :     138978 :     int Period(const Consensus::Params& params) const override { return params.nMinerConfirmationWindow; }
#     188                 :     138946 :     int Threshold(const Consensus::Params& params) const override { return params.nRuleChangeActivationThreshold; }
#     189                 :            : 
#     190                 :            :     bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
#     191                 :      30688 :     {
#     192 [ +  + ][ +  + ]:      30688 :         return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
#     193                 :      30688 :     }
#     194                 :            : 
#     195                 :            : public:
#     196                 :     183735 :     explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
#     197                 :      59384 :     uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
#     198                 :            : };
#     199                 :            : 
#     200                 :            : } // namespace
#     201                 :            : 
#     202                 :            : ThresholdState VersionBitsCache::State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
#     203                 :        454 : {
#     204                 :        454 :     LOCK(m_mutex);
#     205                 :        454 :     return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
#     206                 :        454 : }
#     207                 :            : 
#     208                 :            : BIP9Stats VersionBitsCache::Statistics(const CBlockIndex* pindex, const Consensus::Params& params, Consensus::DeploymentPos pos, std::vector<bool>* signalling_blocks)
#     209                 :         31 : {
#     210                 :         31 :     return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindex, params, signalling_blocks);
#     211                 :         31 : }
#     212                 :            : 
#     213                 :            : int VersionBitsCache::StateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
#     214                 :        259 : {
#     215                 :        259 :     LOCK(m_mutex);
#     216                 :        259 :     return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, m_caches[pos]);
#     217                 :        259 : }
#     218                 :            : 
#     219                 :            : uint32_t VersionBitsCache::Mask(const Consensus::Params& params, Consensus::DeploymentPos pos)
#     220                 :      44625 : {
#     221                 :      44625 :     return VersionBitsConditionChecker(pos).Mask(params);
#     222                 :      44625 : }
#     223                 :            : 
#     224                 :            : int32_t VersionBitsCache::ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
#     225                 :      69183 : {
#     226                 :      69183 :     LOCK(m_mutex);
#     227                 :      69183 :     int32_t nVersion = VERSIONBITS_TOP_BITS;
#     228                 :            : 
#     229         [ +  + ]:     207549 :     for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
#     230                 :     138366 :         Consensus::DeploymentPos pos = static_cast<Consensus::DeploymentPos>(i);
#     231                 :     138366 :         ThresholdState state = VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
#     232 [ +  + ][ +  + ]:     138366 :         if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
#     233                 :      44592 :             nVersion |= Mask(params, pos);
#     234                 :      44592 :         }
#     235                 :     138366 :     }
#     236                 :            : 
#     237                 :      69183 :     return nVersion;
#     238                 :      69183 : }
#     239                 :            : 
#     240                 :            : void VersionBitsCache::Clear()
#     241                 :       2116 : {
#     242                 :       2116 :     LOCK(m_mutex);
#     243         [ +  + ]:       6348 :     for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
#     244                 :       4232 :         m_caches[d].clear();
#     245                 :       4232 :     }
#     246                 :       2116 : }

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a