Branch data 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 : : ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
# 9 : 2288594 : {
# 10 : 2288594 : int nPeriod = Period(params);
# 11 : 2288594 : int nThreshold = Threshold(params);
# 12 : 2288594 : int min_activation_height = MinActivationHeight(params);
# 13 : 2288594 : int64_t nTimeStart = BeginTime(params);
# 14 : 2288594 : int64_t nTimeTimeout = EndTime(params);
# 15 : :
# 16 : : // Check if this deployment is always active.
# 17 [ + + ]: 2288594 : if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
# 18 : 201065 : return ThresholdState::ACTIVE;
# 19 : 201065 : }
# 20 : :
# 21 : : // Check if this deployment is never active.
# 22 [ + + ]: 2087529 : if (nTimeStart == Consensus::BIP9Deployment::NEVER_ACTIVE) {
# 23 : 31016 : return ThresholdState::FAILED;
# 24 : 31016 : }
# 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 [ + + ]: 2056513 : if (pindexPrev != nullptr) {
# 28 : 2054223 : pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
# 29 : 2054223 : }
# 30 : :
# 31 : : // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
# 32 : 2056513 : std::vector<const CBlockIndex*> vToCompute;
# 33 [ + + ]: 2104371 : while (cache.count(pindexPrev) == 0) {
# 34 [ + + ]: 65682 : if (pindexPrev == nullptr) {
# 35 : : // The genesis block is by definition defined.
# 36 : 14958 : cache[pindexPrev] = ThresholdState::DEFINED;
# 37 : 14958 : break;
# 38 : 14958 : }
# 39 [ + + ]: 50724 : if (pindexPrev->GetMedianTimePast() < nTimeStart) {
# 40 : : // Optimization: don't recompute down further, as we know every earlier block will be before the start time
# 41 : 2866 : cache[pindexPrev] = ThresholdState::DEFINED;
# 42 : 2866 : break;
# 43 : 2866 : }
# 44 : 47858 : vToCompute.push_back(pindexPrev);
# 45 : 47858 : pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
# 46 : 47858 : }
# 47 : :
# 48 : : // At this point, cache[pindexPrev] is known
# 49 : 2056513 : assert(cache.count(pindexPrev));
# 50 : 2056513 : ThresholdState state = cache[pindexPrev];
# 51 : :
# 52 : : // Now walk forward and compute the state of descendants of pindexPrev
# 53 [ + + ]: 2104371 : while (!vToCompute.empty()) {
# 54 : 47858 : ThresholdState stateNext = state;
# 55 : 47858 : pindexPrev = vToCompute.back();
# 56 : 47858 : vToCompute.pop_back();
# 57 : :
# 58 [ - + ]: 47858 : switch (state) {
# 59 [ + + ]: 10775 : case ThresholdState::DEFINED: {
# 60 [ + - ]: 10775 : if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
# 61 : 10775 : stateNext = ThresholdState::STARTED;
# 62 : 10775 : }
# 63 : 10775 : break;
# 64 : 0 : }
# 65 [ + + ]: 10524 : case ThresholdState::STARTED: {
# 66 : : // We need to count
# 67 : 10524 : const CBlockIndex* pindexCount = pindexPrev;
# 68 : 10524 : int count = 0;
# 69 [ + + ]: 4768076 : for (int i = 0; i < nPeriod; i++) {
# 70 [ + + ]: 4757552 : if (Condition(pindexCount, params)) {
# 71 : 1457639 : count++;
# 72 : 1457639 : }
# 73 : 4757552 : pindexCount = pindexCount->pprev;
# 74 : 4757552 : }
# 75 [ + + ]: 10524 : if (count >= nThreshold) {
# 76 : 1186 : stateNext = ThresholdState::LOCKED_IN;
# 77 [ + + ]: 9338 : } else if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
# 78 : 1471 : stateNext = ThresholdState::FAILED;
# 79 : 1471 : }
# 80 : 10524 : break;
# 81 : 0 : }
# 82 [ + + ]: 8950 : case ThresholdState::LOCKED_IN: {
# 83 : : // Progresses into ACTIVE provided activation height will have been reached.
# 84 [ + + ]: 8950 : if (pindexPrev->nHeight + 1 >= min_activation_height) {
# 85 : 889 : stateNext = ThresholdState::ACTIVE;
# 86 : 889 : }
# 87 : 8950 : break;
# 88 : 0 : }
# 89 [ + + ]: 7016 : case ThresholdState::FAILED:
# 90 [ + + ]: 17609 : case ThresholdState::ACTIVE: {
# 91 : : // Nothing happens, these are terminal states.
# 92 : 17609 : break;
# 93 : 47858 : }
# 94 : 47858 : }
# 95 : 47858 : cache[pindexPrev] = state = stateNext;
# 96 : 47858 : }
# 97 : :
# 98 : 2056513 : return state;
# 99 : 2056513 : }
# 100 : :
# 101 : : BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params) const
# 102 : 311 : {
# 103 : 311 : BIP9Stats stats = {};
# 104 : :
# 105 : 311 : stats.period = Period(params);
# 106 : 311 : stats.threshold = Threshold(params);
# 107 : :
# 108 [ - + ]: 311 : if (pindex == nullptr)
# 109 : 0 : return stats;
# 110 : :
# 111 : : // Find beginning of period
# 112 : 311 : const CBlockIndex* pindexEndOfPrevPeriod = pindex->GetAncestor(pindex->nHeight - ((pindex->nHeight + 1) % stats.period));
# 113 : 311 : stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight;
# 114 : :
# 115 : : // Count from current block to beginning of period
# 116 : 311 : int count = 0;
# 117 : 311 : const CBlockIndex* currentIndex = pindex;
# 118 [ + + ]: 19459 : while (pindexEndOfPrevPeriod->nHeight != currentIndex->nHeight){
# 119 [ + + ]: 19148 : if (Condition(currentIndex, params))
# 120 : 18367 : count++;
# 121 : 19148 : currentIndex = currentIndex->pprev;
# 122 : 19148 : }
# 123 : :
# 124 : 311 : stats.count = count;
# 125 : 311 : stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
# 126 : :
# 127 : 311 : return stats;
# 128 : 311 : }
# 129 : :
# 130 : : int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
# 131 : 27446 : {
# 132 : 27446 : int64_t start_time = BeginTime(params);
# 133 [ + + ][ + + ]: 27446 : if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE || start_time == Consensus::BIP9Deployment::NEVER_ACTIVE) {
# 134 : 13723 : return 0;
# 135 : 13723 : }
# 136 : :
# 137 : 13723 : const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
# 138 : :
# 139 : : // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
# 140 [ + + ]: 13723 : if (initialState == ThresholdState::DEFINED) {
# 141 : 4320 : return 0;
# 142 : 4320 : }
# 143 : :
# 144 : 9403 : const int nPeriod = Period(params);
# 145 : :
# 146 : : // 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.
# 147 : : // To ease understanding of the following height calculation, it helps to remember that
# 148 : : // right now pindexPrev points to the block prior to the block that we are computing for, thus:
# 149 : : // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
# 150 : : // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
# 151 : : // The parent of the genesis block is represented by nullptr.
# 152 : 9403 : pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
# 153 : :
# 154 : 9403 : const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
# 155 : :
# 156 [ + + ][ + + ]: 30172 : while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, params, cache) == initialState) {
# 157 : 20769 : pindexPrev = previousPeriodParent;
# 158 : 20769 : previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
# 159 : 20769 : }
# 160 : :
# 161 : : // Adjust the result because right now we point to the parent block.
# 162 : 9403 : return pindexPrev->nHeight + 1;
# 163 : 9403 : }
# 164 : :
# 165 : : namespace
# 166 : : {
# 167 : : /**
# 168 : : * Class to implement versionbits logic.
# 169 : : */
# 170 : : class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
# 171 : : private:
# 172 : : const Consensus::DeploymentPos id;
# 173 : :
# 174 : : protected:
# 175 : 293964 : int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
# 176 : 293178 : int64_t EndTime(const Consensus::Params& params) const override { return params.vDeployments[id].nTimeout; }
# 177 : 293178 : int MinActivationHeight(const Consensus::Params& params) const override { return params.vDeployments[id].min_activation_height; }
# 178 : 293812 : int Period(const Consensus::Params& params) const override { return params.nMinerConfirmationWindow; }
# 179 : 293489 : int Threshold(const Consensus::Params& params) const override { return params.nRuleChangeActivationThreshold; }
# 180 : :
# 181 : : bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
# 182 : 46508 : {
# 183 [ + + ][ + + ]: 46508 : return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
# 184 : 46508 : }
# 185 : :
# 186 : : public:
# 187 : 338025 : explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
# 188 : 74668 : uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
# 189 : : };
# 190 : :
# 191 : : } // namespace
# 192 : :
# 193 : : ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
# 194 : 292724 : {
# 195 : 292724 : return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
# 196 : 292724 : }
# 197 : :
# 198 : : BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
# 199 : 311 : {
# 200 : 311 : return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params);
# 201 : 311 : }
# 202 : :
# 203 : : int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
# 204 : 786 : {
# 205 : 786 : return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]);
# 206 : 786 : }
# 207 : :
# 208 : : uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos)
# 209 : 44204 : {
# 210 : 44204 : return VersionBitsConditionChecker(pos).Mask(params);
# 211 : 44204 : }
# 212 : :
# 213 : : void VersionBitsCache::Clear()
# 214 : 793 : {
# 215 [ + + ]: 2379 : for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
# 216 : 1586 : caches[d].clear();
# 217 : 1586 : }
# 218 : 793 : }
|