Bitcoin Core  27.99.0
P2P Digital Currency
versionbits.cpp
Go to the documentation of this file.
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 
10 {
11  int nPeriod = Period(params);
12  int nThreshold = Threshold(params);
13  int min_activation_height = MinActivationHeight(params);
14  int64_t nTimeStart = BeginTime(params);
15  int64_t nTimeTimeout = EndTime(params);
16 
17  // Check if this deployment is always active.
18  if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
20  }
21 
22  // Check if this deployment is never active.
23  if (nTimeStart == Consensus::BIP9Deployment::NEVER_ACTIVE) {
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  if (pindexPrev != nullptr) {
29  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
30  }
31 
32  // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
33  std::vector<const CBlockIndex*> vToCompute;
34  while (cache.count(pindexPrev) == 0) {
35  if (pindexPrev == nullptr) {
36  // The genesis block is by definition defined.
37  cache[pindexPrev] = ThresholdState::DEFINED;
38  break;
39  }
40  if (pindexPrev->GetMedianTimePast() < nTimeStart) {
41  // Optimization: don't recompute down further, as we know every earlier block will be before the start time
42  cache[pindexPrev] = ThresholdState::DEFINED;
43  break;
44  }
45  vToCompute.push_back(pindexPrev);
46  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
47  }
48 
49  // At this point, cache[pindexPrev] is known
50  assert(cache.count(pindexPrev));
51  ThresholdState state = cache[pindexPrev];
52 
53  // Now walk forward and compute the state of descendants of pindexPrev
54  while (!vToCompute.empty()) {
55  ThresholdState stateNext = state;
56  pindexPrev = vToCompute.back();
57  vToCompute.pop_back();
58 
59  switch (state) {
61  if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
62  stateNext = ThresholdState::STARTED;
63  }
64  break;
65  }
67  // We need to count
68  const CBlockIndex* pindexCount = pindexPrev;
69  int count = 0;
70  for (int i = 0; i < nPeriod; i++) {
71  if (Condition(pindexCount, params)) {
72  count++;
73  }
74  pindexCount = pindexCount->pprev;
75  }
76  if (count >= nThreshold) {
77  stateNext = ThresholdState::LOCKED_IN;
78  } else if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
79  stateNext = ThresholdState::FAILED;
80  }
81  break;
82  }
84  // Progresses into ACTIVE provided activation height will have been reached.
85  if (pindexPrev->nHeight + 1 >= min_activation_height) {
86  stateNext = ThresholdState::ACTIVE;
87  }
88  break;
89  }
92  // Nothing happens, these are terminal states.
93  break;
94  }
95  }
96  cache[pindexPrev] = state = stateNext;
97  }
98 
99  return state;
100 }
101 
102 BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params, std::vector<bool>* signalling_blocks) const
103 {
104  BIP9Stats stats = {};
105 
106  stats.period = Period(params);
107  stats.threshold = Threshold(params);
108 
109  if (pindex == nullptr) return stats;
110 
111  // Find how many blocks are in the current period
112  int blocks_in_period = 1 + (pindex->nHeight % stats.period);
113 
114  // Reset signalling_blocks
115  if (signalling_blocks) {
116  signalling_blocks->assign(blocks_in_period, false);
117  }
118 
119  // Count from current block to beginning of period
120  int elapsed = 0;
121  int count = 0;
122  const CBlockIndex* currentIndex = pindex;
123  do {
124  ++elapsed;
125  --blocks_in_period;
126  if (Condition(currentIndex, params)) {
127  ++count;
128  if (signalling_blocks) signalling_blocks->at(blocks_in_period) = true;
129  }
130  currentIndex = currentIndex->pprev;
131  } while(blocks_in_period > 0);
132 
133  stats.elapsed = elapsed;
134  stats.count = count;
135  stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
136 
137  return stats;
138 }
139 
141 {
142  int64_t start_time = BeginTime(params);
144  return 0;
145  }
146 
147  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  if (initialState == ThresholdState::DEFINED) {
151  return 0;
152  }
153 
154  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  pindexPrev = Assert(pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod)));
163 
164  const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
165 
166  while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, params, cache) == initialState) {
167  pindexPrev = previousPeriodParent;
168  previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
169  }
170 
171  // Adjust the result because right now we point to the parent block.
172  return pindexPrev->nHeight + 1;
173 }
174 
175 namespace
176 {
180 class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
181 private:
182  const Consensus::DeploymentPos id;
183 
184 protected:
185  int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
186  int64_t EndTime(const Consensus::Params& params) const override { return params.vDeployments[id].nTimeout; }
187  int MinActivationHeight(const Consensus::Params& params) const override { return params.vDeployments[id].min_activation_height; }
188  int Period(const Consensus::Params& params) const override { return params.nMinerConfirmationWindow; }
189  int Threshold(const Consensus::Params& params) const override { return params.nRuleChangeActivationThreshold; }
190 
191  bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
192  {
193  return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
194  }
195 
196 public:
197  explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
198  uint32_t Mask(const Consensus::Params& params) const { return (uint32_t{1}) << params.vDeployments[id].bit; }
199 };
200 
201 } // namespace
202 
204 {
205  LOCK(m_mutex);
206  return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
207 }
208 
209 BIP9Stats VersionBitsCache::Statistics(const CBlockIndex* pindex, const Consensus::Params& params, Consensus::DeploymentPos pos, std::vector<bool>* signalling_blocks)
210 {
211  return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindex, params, signalling_blocks);
212 }
213 
215 {
216  LOCK(m_mutex);
217  return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, m_caches[pos]);
218 }
219 
221 {
222  return VersionBitsConditionChecker(pos).Mask(params);
223 }
224 
225 int32_t VersionBitsCache::ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
226 {
227  LOCK(m_mutex);
228  int32_t nVersion = VERSIONBITS_TOP_BITS;
229 
230  for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
232  ThresholdState state = VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
233  if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
234  nVersion |= Mask(params, pos);
235  }
236  }
237 
238  return nVersion;
239 }
240 
242 {
243  LOCK(m_mutex);
244  for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
245  m_caches[d].clear();
246  }
247 }
#define Assert(val)
Identity function.
Definition: check.h:77
Abstract class that implements BIP9-style threshold logic, and caches results.
Definition: versionbits.h:57
virtual bool Condition(const CBlockIndex *pindex, const Consensus::Params &params) const =0
virtual int Period(const Consensus::Params &params) const =0
ThresholdState GetStateFor(const CBlockIndex *pindexPrev, const Consensus::Params &params, ThresholdConditionCache &cache) const
Returns the state for pindex A based on parent pindexPrev B.
Definition: versionbits.cpp:9
virtual int64_t EndTime(const Consensus::Params &params) const =0
virtual int MinActivationHeight(const Consensus::Params &params) const
Definition: versionbits.h:62
int GetStateSinceHeightFor(const CBlockIndex *pindexPrev, const Consensus::Params &params, ThresholdConditionCache &cache) const
Returns the height since when the ThresholdState has started for pindex A based on parent pindexPrev ...
virtual int64_t BeginTime(const Consensus::Params &params) const =0
virtual int Threshold(const Consensus::Params &params) const =0
BIP9Stats GetStateStatisticsFor(const CBlockIndex *pindex, const Consensus::Params &params, std::vector< bool > *signalling_blocks=nullptr) const
Returns the numerical statistics of an in-progress BIP9 softfork in the period including pindex If pr...
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:141
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:147
int64_t GetMedianTimePast() const
Definition: chain.h:279
int32_t nVersion
block header
Definition: chain.h:188
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:120
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:153
int StateSinceHeight(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the block height at which the BIP9 deployment switched into the state for the block after pindexP...
static BIP9Stats Statistics(const CBlockIndex *pindex, const Consensus::Params &params, Consensus::DeploymentPos pos, std::vector< bool > *signalling_blocks=nullptr)
Get the numerical statistics for a given deployment for the signalling period that includes pindex.
int32_t ComputeBlockVersion(const CBlockIndex *pindexPrev, const Consensus::Params &params) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Determine what nVersion a new block should use.
static uint32_t Mask(const Consensus::Params &params, Consensus::DeploymentPos pos)
ThresholdState State(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Get the BIP9 state for a given deployment for the block after pindexPrev.
void Clear() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
constexpr I Mask()
Return a value of type I with its bits lowest bits set (bits must be > 0).
Definition: int_utils.h:127
DeploymentPos
Definition: params.h:32
@ MAX_VERSION_BITS_DEPLOYMENTS
Definition: params.h:36
Display status of an in-progress BIP9 softfork.
Definition: versionbits.h:41
int count
Number of blocks with the version bit set since the beginning of the current period.
Definition: versionbits.h:49
int elapsed
Number of blocks elapsed since the beginning of the current period.
Definition: versionbits.h:47
int threshold
Number of blocks with the version bit set required to activate the softfork.
Definition: versionbits.h:45
bool possible
False if there are not enough blocks left in this period to pass activation threshold.
Definition: versionbits.h:51
int period
Length of blocks of the BIP9 signalling period.
Definition: versionbits.h:43
int min_activation_height
If lock in occurs, delay activation until at least this block height.
Definition: params.h:54
int bit
Bit position to select the particular bit in nVersion.
Definition: params.h:45
static constexpr int64_t ALWAYS_ACTIVE
Special value for nStartTime indicating that the deployment is always active.
Definition: params.h:63
static constexpr int64_t NEVER_ACTIVE
Special value for nStartTime indicating that the deployment is never active.
Definition: params.h:68
int64_t nTimeout
Timeout/expiry MedianTime for the deployment attempt.
Definition: params.h:49
int64_t nStartTime
Start MedianTime for version bits miner confirmation.
Definition: params.h:47
Parameters that influence chain consensus.
Definition: params.h:74
uint32_t nMinerConfirmationWindow
Definition: params.h:106
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS]
Definition: params.h:107
uint32_t nRuleChangeActivationThreshold
Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period,...
Definition: params.h:105
#define LOCK(cs)
Definition: sync.h:257
static int count
assert(!tx.IsCoinBase())
std::map< const CBlockIndex *, ThresholdState > ThresholdConditionCache
Definition: versionbits.h:38
static const int32_t VERSIONBITS_TOP_BITS
What bits to set in version for versionbits blocks.
Definition: versionbits.h:16
static const int32_t VERSIONBITS_TOP_MASK
What bitmask determines whether versionbits is in use.
Definition: versionbits.h:18
ThresholdState
BIP 9 defines a finite-state-machine to deploy a softfork in multiple stages.
Definition: versionbits.h:27