/Users/eugenesiegel/btc/bitcoin/src/versionbits.cpp
| Line | Count | Source (jump to first uncovered line) | 
| 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 |  | std::string StateName(ThresholdState state) | 
| 15 | 0 | { | 
| 16 | 0 |     switch (state) { | 
| 17 | 0 |     case DEFINED: return "defined"; | 
| 18 | 0 |     case STARTED: return "started"; | 
| 19 | 0 |     case LOCKED_IN: return "locked_in"; | 
| 20 | 0 |     case ACTIVE: return "active"; | 
| 21 | 0 |     case FAILED: return "failed"; | 
| 22 | 0 |     } | 
| 23 | 0 |     return "invalid"; | 
| 24 | 0 | } | 
| 25 |  |  | 
| 26 |  | ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const | 
| 27 | 593k | { | 
| 28 | 593k |     int nPeriod = Period(); | 
| 29 | 593k |     int nThreshold = Threshold(); | 
| 30 | 593k |     int min_activation_height = MinActivationHeight(); | 
| 31 | 593k |     int64_t nTimeStart = BeginTime(); | 
| 32 | 593k |     int64_t nTimeTimeout = EndTime(); | 
| 33 |  |  | 
| 34 |  |     // Check if this deployment is always active. | 
| 35 | 593k |     if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) { | 
| 36 | 0 |         return ThresholdState::ACTIVE; | 
| 37 | 0 |     } | 
| 38 |  |  | 
| 39 |  |     // Check if this deployment is never active. | 
| 40 | 593k |     if (nTimeStart == Consensus::BIP9Deployment::NEVER_ACTIVE) { | 
| 41 | 0 |         return ThresholdState::FAILED; | 
| 42 | 0 |     } | 
| 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 | 593k |     if (pindexPrev != nullptr) { | 
| 46 | 593k |         pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod)); | 
| 47 | 593k |     } | 
| 48 |  |  | 
| 49 |  |     // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known | 
| 50 | 593k |     std::vector<const CBlockIndex*> vToCompute; | 
| 51 | 992k |     while (cache.count(pindexPrev) == 0) { | 
| 52 | 798k |         if (pindexPrev == nullptr) { | 
| 53 |  |             // The genesis block is by definition defined. | 
| 54 | 399k |             cache[pindexPrev] = ThresholdState::DEFINED; | 
| 55 | 399k |             break; | 
| 56 | 399k |         } | 
| 57 | 399k |         if (pindexPrev->GetMedianTimePast() < nTimeStart) { | 
| 58 |  |             // Optimization: don't recompute down further, as we know every earlier block will be before the start time | 
| 59 | 0 |             cache[pindexPrev] = ThresholdState::DEFINED; | 
| 60 | 0 |             break; | 
| 61 | 0 |         } | 
| 62 | 399k |         vToCompute.push_back(pindexPrev); | 
| 63 | 399k |         pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod); | 
| 64 | 399k |     } | 
| 65 |  |  | 
| 66 |  |     // At this point, cache[pindexPrev] is known | 
| 67 | 593k |     assert(cache.count(pindexPrev)); | 
| 68 | 593k |     ThresholdState state = cache[pindexPrev]; | 
| 69 |  |  | 
| 70 |  |     // Now walk forward and compute the state of descendants of pindexPrev | 
| 71 | 992k |     while (!vToCompute.empty()) { | 
| 72 | 399k |         ThresholdState stateNext = state; | 
| 73 | 399k |         pindexPrev = vToCompute.back(); | 
| 74 | 399k |         vToCompute.pop_back(); | 
| 75 |  |  | 
| 76 | 399k |         switch (state) { | 
| 77 | 399k |             case ThresholdState::DEFINED: { | 
| 78 | 399k |                 if (pindexPrev->GetMedianTimePast() >= nTimeStart) { | 
| 79 | 399k |                     stateNext = ThresholdState::STARTED; | 
| 80 | 399k |                 } | 
| 81 | 399k |                 break; | 
| 82 | 0 |             } | 
| 83 | 0 |             case ThresholdState::STARTED: { | 
| 84 |  |                 // We need to count | 
| 85 | 0 |                 const CBlockIndex* pindexCount = pindexPrev; | 
| 86 | 0 |                 int count = 0; | 
| 87 | 0 |                 for (int i = 0; i < nPeriod; i++) { | 
| 88 | 0 |                     if (Condition(pindexCount)) { | 
| 89 | 0 |                         count++; | 
| 90 | 0 |                     } | 
| 91 | 0 |                     pindexCount = pindexCount->pprev; | 
| 92 | 0 |                 } | 
| 93 | 0 |                 if (count >= nThreshold) { | 
| 94 | 0 |                     stateNext = ThresholdState::LOCKED_IN; | 
| 95 | 0 |                 } else if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) { | 
| 96 | 0 |                     stateNext = ThresholdState::FAILED; | 
| 97 | 0 |                 } | 
| 98 | 0 |                 break; | 
| 99 | 0 |             } | 
| 100 | 0 |             case ThresholdState::LOCKED_IN: { | 
| 101 |  |                 // Progresses into ACTIVE provided activation height will have been reached. | 
| 102 | 0 |                 if (pindexPrev->nHeight + 1 >= min_activation_height) { | 
| 103 | 0 |                     stateNext = ThresholdState::ACTIVE; | 
| 104 | 0 |                 } | 
| 105 | 0 |                 break; | 
| 106 | 0 |             } | 
| 107 | 0 |             case ThresholdState::FAILED: | 
| 108 | 0 |             case ThresholdState::ACTIVE: { | 
| 109 |  |                 // Nothing happens, these are terminal states. | 
| 110 | 0 |                 break; | 
| 111 | 0 |             } | 
| 112 | 399k |         } | 
| 113 | 399k |         cache[pindexPrev] = state = stateNext; | 
| 114 | 399k |     } | 
| 115 |  |  | 
| 116 | 593k |     return state; | 
| 117 | 593k | } | 
| 118 |  |  | 
| 119 |  | BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, std::vector<bool>* signalling_blocks) const | 
| 120 | 0 | { | 
| 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 | 0 |     } | 
| 135 |  |  | 
| 136 |  |     // Count from current block to beginning of period | 
| 137 | 0 |     int elapsed = 0; | 
| 138 | 0 |     int count = 0; | 
| 139 | 0 |     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 | 0 |         } | 
| 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 | 0 | } | 
| 156 |  |  | 
| 157 |  | int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const | 
| 158 | 0 | { | 
| 159 | 0 |     int64_t start_time = BeginTime(); | 
| 160 | 0 |     if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE || start_time == Consensus::BIP9Deployment::NEVER_ACTIVE) { | 
| 161 | 0 |         return 0; | 
| 162 | 0 |     } | 
| 163 |  |  | 
| 164 | 0 |     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 | 0 |     if (initialState == ThresholdState::DEFINED) { | 
| 168 | 0 |         return 0; | 
| 169 | 0 |     } | 
| 170 |  |  | 
| 171 | 0 |     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 | 0 |     pindexPrev = Assert(pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod))); | Line | Count | Source |  | 106 | 0 | #define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val) | 
 | 
| 180 |  | 
 | 
| 181 | 0 |     const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod); | 
| 182 |  | 
 | 
| 183 | 0 |     while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, cache) == initialState) { | 
| 184 | 0 |         pindexPrev = previousPeriodParent; | 
| 185 | 0 |         previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod); | 
| 186 | 0 |     } | 
| 187 |  |  | 
| 188 |  |     // Adjust the result because right now we point to the parent block. | 
| 189 | 0 |     return pindexPrev->nHeight + 1; | 
| 190 | 0 | } | 
| 191 |  |  | 
| 192 |  | BIP9Info VersionBitsCache::Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id) | 
| 193 | 0 | { | 
| 194 | 0 |     BIP9Info result; | 
| 195 |  | 
 | 
| 196 | 0 |     VersionBitsConditionChecker checker(params, id); | 
| 197 |  | 
 | 
| 198 | 0 |     ThresholdState current_state, next_state; | 
| 199 |  | 
 | 
| 200 | 0 |     { | 
| 201 | 0 |         LOCK(m_mutex); | Line | Count | Source |  | 259 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) | Line | Count | Source |  | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) | Line | Count | Source |  | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) | Line | Count | Source |  | 8 | 0 | #define PASTE(x, y) x ## y | 
 | 
 | 
 | 
 | 
| 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 | 0 |         } | 
| 217 | 0 |     } | 
| 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 | 0 |     } | 
| 224 |  | 
 | 
| 225 | 0 |     return result; | 
| 226 | 0 | } | 
| 227 |  |  | 
| 228 |  | BIP9GBTStatus VersionBitsCache::GBTStatus(const CBlockIndex& block_index, const Consensus::Params& params) | 
| 229 | 0 | { | 
| 230 | 0 |     BIP9GBTStatus result; | 
| 231 |  | 
 | 
| 232 | 0 |     LOCK(m_mutex); | Line | Count | Source |  | 259 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) | Line | Count | Source |  | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) | Line | Count | Source |  | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) | Line | Count | Source |  | 8 | 0 | #define PASTE(x, y) x ## y | 
 | 
 | 
 | 
 | 
| 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_optional_rule=vbdepinfo.gbt_optional_rule}; | 
| 239 |  | 
 | 
| 240 | 0 |         switch (state) { | 
| 241 | 0 |         case DEFINED: | 
| 242 | 0 |         case FAILED: | 
| 243 |  |             // Not exposed to GBT | 
| 244 | 0 |             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 | 0 |         } | 
| 255 | 0 |     } | 
| 256 | 0 |     return result; | 
| 257 | 0 | } | 
| 258 |  |  | 
| 259 |  | bool VersionBitsCache::IsActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos) | 
| 260 | 0 | { | 
| 261 | 0 |     LOCK(m_mutex); | Line | Count | Source |  | 259 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) | Line | Count | Source |  | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) | Line | Count | Source |  | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) | Line | Count | Source |  | 8 | 0 | #define PASTE(x, y) x ## y | 
 | 
 | 
 | 
 | 
| 262 | 0 |     return ThresholdState::ACTIVE == VersionBitsConditionChecker(params, pos).GetStateFor(pindexPrev, m_caches[pos]); | 
| 263 | 0 | } | 
| 264 |  |  | 
| 265 |  | static int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params, std::array<ThresholdConditionCache, Consensus::MAX_VERSION_BITS_DEPLOYMENTS>& caches) | 
| 266 | 0 | { | 
| 267 | 0 |     int32_t nVersion = VERSIONBITS_TOP_BITS; | 
| 268 |  | 
 | 
| 269 | 0 |     for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) { | 
| 270 | 0 |         Consensus::DeploymentPos pos = static_cast<Consensus::DeploymentPos>(i); | 
| 271 | 0 |         VersionBitsConditionChecker checker(params, pos); | 
| 272 | 0 |         ThresholdState state = checker.GetStateFor(pindexPrev, caches[pos]); | 
| 273 | 0 |         if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) { | 
| 274 | 0 |             nVersion |= checker.Mask(); | 
| 275 | 0 |         } | 
| 276 | 0 |     } | 
| 277 |  | 
 | 
| 278 | 0 |     return nVersion; | 
| 279 | 0 | } | 
| 280 |  |  | 
| 281 |  | int32_t VersionBitsCache::ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params) | 
| 282 | 0 | { | 
| 283 | 0 |     LOCK(m_mutex); | Line | Count | Source |  | 259 | 0 | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) | Line | Count | Source |  | 11 | 0 | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) | Line | Count | Source |  | 9 | 0 | #define PASTE2(x, y) PASTE(x, y) | Line | Count | Source |  | 8 | 0 | #define PASTE(x, y) x ## y | 
 | 
 | 
 | 
 | 
| 284 | 0 |     return ::ComputeBlockVersion(pindexPrev, params, m_caches); | 
| 285 | 0 | } | 
| 286 |  |  | 
| 287 |  | void VersionBitsCache::Clear() | 
| 288 | 51.2k | { | 
| 289 | 51.2k |     LOCK(m_mutex); | Line | Count | Source |  | 259 | 51.2k | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) | Line | Count | Source |  | 11 | 51.2k | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) | Line | Count | Source |  | 9 | 51.2k | #define PASTE2(x, y) PASTE(x, y) | Line | Count | Source |  | 8 | 51.2k | #define PASTE(x, y) x ## y | 
 | 
 | 
 | 
 | 
| 290 | 153k |     for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++102k) { | 
| 291 | 102k |         m_caches[d].clear(); | 
| 292 | 102k |     } | 
| 293 | 51.2k | } | 
| 294 |  |  | 
| 295 |  | namespace { | 
| 296 |  | /** | 
| 297 |  |  * Threshold condition checker that triggers when unknown versionbits are seen on the network. | 
| 298 |  |  */ | 
| 299 |  | 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 |  |     explicit WarningBitsConditionChecker(const CChainParams& chainparams, std::array<ThresholdConditionCache, Consensus::MAX_VERSION_BITS_DEPLOYMENTS>& caches, int bit) | 
| 310 | 593k |     : m_params{chainparams.GetConsensus()}, m_caches{caches}, m_bit(bit) | 
| 311 | 593k |     { | 
| 312 | 593k |         if (chainparams.IsTestChain()) { | 
| 313 | 593k |             period = chainparams.GetConsensus().DifficultyAdjustmentInterval(); | 
| 314 | 593k |             threshold = period * 3 / 4; // 75% for test nets per BIP9 suggestion | 
| 315 | 593k |         } | 
| 316 | 593k |     } | 
| 317 |  |  | 
| 318 | 593k |     int64_t BeginTime() const override { return 0; } | 
| 319 | 593k |     int64_t EndTime() const override { return std::numeric_limits<int64_t>::max(); } | 
| 320 | 593k |     int Period() const override { return period; } | 
| 321 | 593k |     int Threshold() const override { return threshold; } | 
| 322 |  |  | 
| 323 |  |     bool Condition(const CBlockIndex* pindex) const override | 
| 324 | 0 |     { | 
| 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 | 0 |     } | 
| 330 |  | }; | 
| 331 |  | } // anonymous namespace | 
| 332 |  |  | 
| 333 |  | std::vector<std::pair<int, bool>> VersionBitsCache::CheckUnknownActivations(const CBlockIndex* pindex, const CChainParams& chainparams) | 
| 334 | 20.4k | { | 
| 335 | 20.4k |     LOCK(m_mutex); | Line | Count | Source |  | 259 | 20.4k | #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) | Line | Count | Source |  | 11 | 20.4k | #define UNIQUE_NAME(name) PASTE2(name, __COUNTER__) | Line | Count | Source |  | 9 | 20.4k | #define PASTE2(x, y) PASTE(x, y) | Line | Count | Source |  | 8 | 20.4k | #define PASTE(x, y) x ## y | 
 | 
 | 
 | 
 | 
| 336 | 20.4k |     std::vector<std::pair<int, bool>> result; | 
| 337 | 613k |     for (int bit = 0; bit < VERSIONBITS_NUM_BITS; ++bit593k) { | 
| 338 | 593k |         WarningBitsConditionChecker checker(chainparams, m_caches, bit); | 
| 339 | 593k |         ThresholdState state = checker.GetStateFor(pindex, m_warning_caches.at(bit)); | 
| 340 | 593k |         if (state == ACTIVE || state == LOCKED_IN) { | 
| 341 | 0 |             result.emplace_back(bit, state == ACTIVE); | 
| 342 | 0 |         } | 
| 343 | 593k |     } | 
| 344 | 20.4k |     return result; | 
| 345 | 20.4k | } |