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