versionbits.cpp raw

   1  // Copyright (c) 2016-present 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  {
  16      switch (state) {
  17      case DEFINED: return "defined";
  18      case STARTED: return "started";
  19      case LOCKED_IN: return "locked_in";
  20      case ACTIVE: return "active";
  21      case FAILED: return "failed";
  22      }
  23      return "invalid";
  24  }
  25  
  26  ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const
  27  {
  28      int nPeriod = Period();
  29      int nThreshold = Threshold();
  30      int min_activation_height = MinActivationHeight();
  31      int64_t nTimeStart = BeginTime();
  32      int64_t nTimeTimeout = EndTime();
  33  
  34      // Check if this deployment is always active.
  35      if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
  36          return ThresholdState::ACTIVE;
  37      }
  38  
  39      // Check if this deployment is never active.
  40      if (nTimeStart == Consensus::BIP9Deployment::NEVER_ACTIVE) {
  41          return ThresholdState::FAILED;
  42      }
  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      if (pindexPrev != nullptr) {
  46          pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
  47      }
  48  
  49      // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
  50      std::vector<const CBlockIndex*> vToCompute;
  51      while (!cache.contains(pindexPrev)) {
  52          if (pindexPrev == nullptr) {
  53              // The genesis block is by definition defined.
  54              cache[pindexPrev] = ThresholdState::DEFINED;
  55              break;
  56          }
  57          if (pindexPrev->GetMedianTimePast() < nTimeStart) {
  58              // Optimization: don't recompute down further, as we know every earlier block will be before the start time
  59              cache[pindexPrev] = ThresholdState::DEFINED;
  60              break;
  61          }
  62          vToCompute.push_back(pindexPrev);
  63          pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
  64      }
  65  
  66      // At this point, cache[pindexPrev] is known
  67      assert(cache.contains(pindexPrev));
  68      ThresholdState state = cache[pindexPrev];
  69  
  70      // Now walk forward and compute the state of descendants of pindexPrev
  71      while (!vToCompute.empty()) {
  72          ThresholdState stateNext = state;
  73          pindexPrev = vToCompute.back();
  74          vToCompute.pop_back();
  75  
  76          switch (state) {
  77              case ThresholdState::DEFINED: {
  78                  if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
  79                      stateNext = ThresholdState::STARTED;
  80                  }
  81                  break;
  82              }
  83              case ThresholdState::STARTED: {
  84                  // We need to count
  85                  const CBlockIndex* pindexCount = pindexPrev;
  86                  int count = 0;
  87                  for (int i = 0; i < nPeriod; i++) {
  88                      if (Condition(pindexCount)) {
  89                          count++;
  90                      }
  91                      pindexCount = pindexCount->pprev;
  92                  }
  93                  if (count >= nThreshold) {
  94                      stateNext = ThresholdState::LOCKED_IN;
  95                  } else if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
  96                      stateNext = ThresholdState::FAILED;
  97                  }
  98                  break;
  99              }
 100              case ThresholdState::LOCKED_IN: {
 101                  // Progresses into ACTIVE provided activation height will have been reached.
 102                  if (pindexPrev->nHeight + 1 >= min_activation_height) {
 103                      stateNext = ThresholdState::ACTIVE;
 104                  }
 105                  break;
 106              }
 107              case ThresholdState::FAILED:
 108              case ThresholdState::ACTIVE: {
 109                  // Nothing happens, these are terminal states.
 110                  break;
 111              }
 112          }
 113          cache[pindexPrev] = state = stateNext;
 114      }
 115  
 116      return state;
 117  }
 118  
 119  BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, std::vector<bool>* signalling_blocks) const
 120  {
 121      BIP9Stats stats = {};
 122  
 123      stats.period = Period();
 124      stats.threshold = Threshold();
 125  
 126      if (pindex == nullptr) return stats;
 127  
 128      // Find how many blocks are in the current period
 129      int blocks_in_period = 1 + (pindex->nHeight % stats.period);
 130  
 131      // Reset signalling_blocks
 132      if (signalling_blocks) {
 133          signalling_blocks->assign(blocks_in_period, false);
 134      }
 135  
 136      // Count from current block to beginning of period
 137      int elapsed = 0;
 138      int count = 0;
 139      const CBlockIndex* currentIndex = pindex;
 140      do {
 141          ++elapsed;
 142          --blocks_in_period;
 143          if (Condition(currentIndex)) {
 144              ++count;
 145              if (signalling_blocks) signalling_blocks->at(blocks_in_period) = true;
 146          }
 147          currentIndex = currentIndex->pprev;
 148      } while(blocks_in_period > 0);
 149  
 150      stats.elapsed = elapsed;
 151      stats.count = count;
 152      stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
 153  
 154      return stats;
 155  }
 156  
 157  int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, ThresholdConditionCache& cache) const
 158  {
 159      int64_t start_time = BeginTime();
 160      if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE || start_time == Consensus::BIP9Deployment::NEVER_ACTIVE) {
 161          return 0;
 162      }
 163  
 164      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      if (initialState == ThresholdState::DEFINED) {
 168          return 0;
 169      }
 170  
 171      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      pindexPrev = Assert(pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod)));
 180  
 181      const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
 182  
 183      while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, cache) == initialState) {
 184          pindexPrev = previousPeriodParent;
 185          previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
 186      }
 187  
 188      // Adjust the result because right now we point to the parent block.
 189      return pindexPrev->nHeight + 1;
 190  }
 191  
 192  BIP9Info VersionBitsCache::Info(const CBlockIndex& block_index, const Consensus::Params& params, Consensus::DeploymentPos id)
 193  {
 194      BIP9Info result;
 195  
 196      VersionBitsConditionChecker checker(params, id);
 197  
 198      ThresholdState current_state, next_state;
 199  
 200      {
 201          LOCK(m_mutex);
 202          current_state = checker.GetStateFor(block_index.pprev, m_caches[id]);
 203          next_state = checker.GetStateFor(&block_index, m_caches[id]);
 204          result.since = checker.GetStateSinceHeightFor(block_index.pprev, m_caches[id]);
 205      }
 206  
 207      result.current_state = StateName(current_state);
 208      result.next_state = StateName(next_state);
 209  
 210      const bool has_signal = (STARTED == current_state || LOCKED_IN == current_state);
 211      if (has_signal) {
 212          result.stats.emplace(checker.GetStateStatisticsFor(&block_index, &result.signalling_blocks));
 213          if (LOCKED_IN == current_state) {
 214              result.stats->threshold = 0;
 215              result.stats->possible = false;
 216          }
 217      }
 218  
 219      if (current_state == ACTIVE) {
 220          result.active_since = result.since;
 221      } else if (next_state == ACTIVE) {
 222          result.active_since = block_index.nHeight + 1;
 223      }
 224  
 225      return result;
 226  }
 227  
 228  BIP9GBTStatus VersionBitsCache::GBTStatus(const CBlockIndex& block_index, const Consensus::Params& params)
 229  {
 230      BIP9GBTStatus result;
 231  
 232      LOCK(m_mutex);
 233      for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
 234          auto pos = static_cast<Consensus::DeploymentPos>(i);
 235          VersionBitsConditionChecker checker(params, pos);
 236          ThresholdState state = checker.GetStateFor(&block_index, m_caches[pos]);
 237          const VBDeploymentInfo& vbdepinfo = VersionBitsDeploymentInfo[pos];
 238          BIP9GBTStatus::Info gbtinfo{.bit=params.vDeployments[pos].bit, .mask=checker.Mask(), .gbt_optional_rule=vbdepinfo.gbt_optional_rule};
 239  
 240          switch (state) {
 241          case DEFINED:
 242          case FAILED:
 243              // Not exposed to GBT
 244              break;
 245          case STARTED:
 246              result.signalling.try_emplace(vbdepinfo.name, gbtinfo);
 247              break;
 248          case LOCKED_IN:
 249              result.locked_in.try_emplace(vbdepinfo.name, gbtinfo);
 250              break;
 251          case ACTIVE:
 252              result.active.try_emplace(vbdepinfo.name, gbtinfo);
 253              break;
 254          }
 255      }
 256      return result;
 257  }
 258  
 259  bool VersionBitsCache::IsActiveAfter(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos)
 260  {
 261      LOCK(m_mutex);
 262      return ThresholdState::ACTIVE == VersionBitsConditionChecker(params, pos).GetStateFor(pindexPrev, m_caches[pos]);
 263  }
 264  
 265  static int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params, std::array<ThresholdConditionCache, Consensus::MAX_VERSION_BITS_DEPLOYMENTS>& caches)
 266  {
 267      int32_t nVersion = VERSIONBITS_TOP_BITS;
 268  
 269      for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
 270          Consensus::DeploymentPos pos = static_cast<Consensus::DeploymentPos>(i);
 271          VersionBitsConditionChecker checker(params, pos);
 272          ThresholdState state = checker.GetStateFor(pindexPrev, caches[pos]);
 273          if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
 274              nVersion |= checker.Mask();
 275          }
 276      }
 277  
 278      return nVersion;
 279  }
 280  
 281  int32_t VersionBitsCache::ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
 282  {
 283      LOCK(m_mutex);
 284      return ::ComputeBlockVersion(pindexPrev, params, m_caches);
 285  }
 286  
 287  void VersionBitsCache::Clear()
 288  {
 289      LOCK(m_mutex);
 290      for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
 291          m_caches[d].clear();
 292      }
 293  }
 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      : m_params{chainparams.GetConsensus()}, m_caches{caches}, m_bit(bit)
 311      {
 312          if (chainparams.IsTestChain()) {
 313              period = chainparams.GetConsensus().DifficultyAdjustmentInterval();
 314              threshold = period * 3 / 4; // 75% for test nets per BIP9 suggestion
 315          }
 316      }
 317  
 318      int64_t BeginTime() const override { return 0; }
 319      int64_t EndTime() const override { return std::numeric_limits<int64_t>::max(); }
 320      int Period() const override { return period; }
 321      int Threshold() const override { return threshold; }
 322  
 323      bool Condition(const CBlockIndex* pindex) const override
 324      {
 325          return pindex->nHeight >= m_params.MinBIP9WarningHeight &&
 326                 ((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) &&
 327                 ((pindex->nVersion >> m_bit) & 1) != 0 &&
 328                 ((::ComputeBlockVersion(pindex->pprev, m_params, m_caches) >> m_bit) & 1) == 0;
 329      }
 330  };
 331  } // anonymous namespace
 332  
 333  std::vector<std::pair<int, bool>> VersionBitsCache::CheckUnknownActivations(const CBlockIndex* pindex, const CChainParams& chainparams)
 334  {
 335      LOCK(m_mutex);
 336      std::vector<std::pair<int, bool>> result;
 337      for (int bit = 0; bit < VERSIONBITS_NUM_BITS; ++bit) {
 338          WarningBitsConditionChecker checker(chainparams, m_caches, bit);
 339          ThresholdState state = checker.GetStateFor(pindex, m_warning_caches.at(bit));
 340          if (state == ACTIVE || state == LOCKED_IN) {
 341              result.emplace_back(bit, state == ACTIVE);
 342          }
 343      }
 344      return result;
 345  }
 346