Bitcoin ABC  0.22.12
P2P Digital Currency
versionbits.cpp
Go to the documentation of this file.
1 // Copyright (c) 2016-2018 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 <versionbits.h>
7 
9  const CBlockIndex *pindexPrev, const Consensus::Params &params,
10  ThresholdConditionCache &cache) const {
11  int nPeriod = Period(params);
12  int nThreshold = Threshold(params);
13  int64_t nTimeStart = BeginTime(params);
14  int64_t nTimeTimeout = EndTime(params);
15 
16  // Check if this deployment is always active.
17  if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
19  }
20 
21  // A block's state is always the same as that of the first of its period, so
22  // it is computed based on a pindexPrev whose height equals a multiple of
23  // nPeriod - 1.
24  if (pindexPrev != nullptr) {
25  pindexPrev = pindexPrev->GetAncestor(
26  pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
27  }
28 
29  // Walk backwards in steps of nPeriod to find a pindexPrev whose information
30  // is known
31  std::vector<const CBlockIndex *> vToCompute;
32  while (cache.count(pindexPrev) == 0) {
33  if (pindexPrev == nullptr) {
34  // The genesis block is by definition defined.
35  cache[pindexPrev] = ThresholdState::DEFINED;
36  break;
37  }
38  if (pindexPrev->GetMedianTimePast() < nTimeStart) {
39  // Optimization: don't recompute down further, as we know every
40  // earlier block will be before the start time
41  cache[pindexPrev] = ThresholdState::DEFINED;
42  break;
43  }
44  vToCompute.push_back(pindexPrev);
45  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
46  }
47 
48  // At this point, cache[pindexPrev] is known
49  assert(cache.count(pindexPrev));
50  ThresholdState state = cache[pindexPrev];
51 
52  // Now walk forward and compute the state of descendants of pindexPrev
53  while (!vToCompute.empty()) {
54  ThresholdState stateNext = state;
55  pindexPrev = vToCompute.back();
56  vToCompute.pop_back();
57 
58  switch (state) {
60  if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
61  stateNext = ThresholdState::FAILED;
62  } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
63  stateNext = ThresholdState::STARTED;
64  }
65  break;
66  }
68  if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
69  stateNext = ThresholdState::FAILED;
70  break;
71  }
72  // We need to count
73  const CBlockIndex *pindexCount = pindexPrev;
74  int count = 0;
75  for (int i = 0; i < nPeriod; i++) {
76  if (Condition(pindexCount, params)) {
77  count++;
78  }
79  pindexCount = pindexCount->pprev;
80  }
81  if (count >= nThreshold) {
82  stateNext = ThresholdState::LOCKED_IN;
83  }
84  break;
85  }
87  // Always progresses into ACTIVE.
88  stateNext = ThresholdState::ACTIVE;
89  break;
90  }
93  // Nothing happens, these are terminal states.
94  break;
95  }
96  }
97  cache[pindexPrev] = state = stateNext;
98  }
99 
100  return state;
101 }
102 
104  const CBlockIndex *pindex, const Consensus::Params &params) const {
105  BIP9Stats stats = {};
106 
107  stats.period = Period(params);
108  stats.threshold = Threshold(params);
109 
110  if (pindex == nullptr) {
111  return stats;
112  }
113 
114  // Find beginning of period
115  const CBlockIndex *pindexEndOfPrevPeriod = pindex->GetAncestor(
116  pindex->nHeight - ((pindex->nHeight + 1) % stats.period));
117  stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight;
118 
119  // Count from current block to beginning of period
120  int count = 0;
121  const CBlockIndex *currentIndex = pindex;
122  while (pindexEndOfPrevPeriod->nHeight != currentIndex->nHeight) {
123  if (Condition(currentIndex, params)) {
124  count++;
125  }
126  currentIndex = currentIndex->pprev;
127  }
128 
129  stats.count = count;
130  stats.possible =
131  (stats.period - stats.threshold) >= (stats.elapsed - count);
132 
133  return stats;
134 }
135 
137  const CBlockIndex *pindexPrev, const Consensus::Params &params,
138  ThresholdConditionCache &cache) const {
139  int64_t start_time = BeginTime(params);
140  if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE) {
141  return 0;
142  }
143 
144  const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
145 
146  // BIP 9 about state DEFINED: "The genesis block is by definition in this
147  // state for each deployment."
148  if (initialState == ThresholdState::DEFINED) {
149  return 0;
150  }
151 
152  const int nPeriod = Period(params);
153 
154  // A block's state is always the same as that of the first of its period, so
155  // it is computed based on a pindexPrev whose height equals a multiple of
156  // nPeriod - 1. To ease understanding of the following height calculation,
157  // it helps to remember that right now pindexPrev points to the block prior
158  // to the block that we are computing for, thus: if we are computing for the
159  // last block of a period, then pindexPrev points to the second to last
160  // block of the period, and if we are computing for the first block of a
161  // period, then pindexPrev points to the last block of the previous period.
162  // The parent of the genesis block is represented by nullptr.
163  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight -
164  ((pindexPrev->nHeight + 1) % nPeriod));
165 
166  const CBlockIndex *previousPeriodParent =
167  pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
168 
169  while (previousPeriodParent != nullptr &&
170  GetStateFor(previousPeriodParent, params, cache) == initialState) {
171  pindexPrev = previousPeriodParent;
172  previousPeriodParent =
173  pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
174  }
175 
176  // Adjust the result because right now we point to the parent block.
177  return pindexPrev->nHeight + 1;
178 }
179 
180 namespace {
184 class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
185 private:
186  const Consensus::DeploymentPos id;
187 
188 protected:
189  int64_t BeginTime(const Consensus::Params &params) const override {
190  return params.vDeployments[id].nStartTime;
191  }
192  int64_t EndTime(const Consensus::Params &params) const override {
193  return params.vDeployments[id].nTimeout;
194  }
195  int Period(const Consensus::Params &params) const override {
196  return params.nMinerConfirmationWindow;
197  }
198  int Threshold(const Consensus::Params &params) const override {
199  return params.vDeployments[id].nActivationThreshold;
200  }
201 
202  bool Condition(const CBlockIndex *pindex,
203  const Consensus::Params &params) const override {
204  return (((pindex->nVersion & VERSIONBITS_TOP_MASK) ==
206  (pindex->nVersion & Mask(params)) != 0);
207  }
208 
209 public:
210  explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_)
211  : id(id_) {}
212  uint32_t Mask(const Consensus::Params &params) const {
213  return uint32_t(1) << params.vDeployments[id].bit;
214  }
215 };
216 
217 } // namespace
218 
220  const Consensus::Params &params,
222  VersionBitsCache &cache) {
223  return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params,
224  cache.caches[pos]);
225 }
226 
228  const Consensus::Params &params,
230  return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev,
231  params);
232 }
233 
235  const Consensus::Params &params,
237  VersionBitsCache &cache) {
238  return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(
239  pindexPrev, params, cache.caches[pos]);
240 }
241 
242 uint32_t VersionBitsMask(const Consensus::Params &params,
244  return VersionBitsConditionChecker(pos).Mask(params);
245 }
246 
248  for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
249  caches[d].clear();
250  }
251 }
Display status of an in-progress BIP9 softfork.
Definition: versionbits.h:44
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: blockindex.h:30
virtual int64_t EndTime(const Consensus::Params &params) const =0
int GetStateSinceHeightFor(const CBlockIndex *pindexPrev, const Consensus::Params &params, ThresholdConditionCache &cache) const
Returns the height since when the ThresholdState has started for pindex.
static const int32_t VERSIONBITS_TOP_MASK
What bitmask determines whether versionbits is in use.
Definition: versionbits.h:16
virtual bool Condition(const CBlockIndex *pindex, const Consensus::Params &params) const =0
static constexpr int64_t ALWAYS_ACTIVE
Special value for nStartTime indicating that the deployment is always active.
Definition: params.h:53
ThresholdConditionCache caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS]
Definition: versionbits.h:111
ThresholdState
BIP 9 defines a finite-state-machine to deploy a softfork in multiple stages.
Definition: versionbits.h:26
uint32_t VersionBitsMask(const Consensus::Params &params, Consensus::DeploymentPos pos)
int threshold
Number of blocks with the version bit set required to activate the softfork.
Definition: versionbits.h:51
BIP 9 allows multiple softforks to be deployed in parallel.
Definition: versionbits.h:110
DeploymentPos
Definition: params.h:16
int period
Length of blocks of the BIP9 signalling period.
Definition: versionbits.h:46
uint32_t nActivationThreshold
Minimum number of blocks within an activation window that must signal to activate the deployement...
Definition: params.h:34
int VersionBitsStateSinceHeight(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos, VersionBitsCache &cache)
int64_t nStartTime
Start MedianTime for version bits miner confirmation.
Definition: params.h:39
Abstract class that implements BIP9-style threshold logic, and caches results.
Definition: versionbits.h:72
int count
Number of blocks with the version bit set since the beginning of the current period.
Definition: versionbits.h:60
uint32_t nMinerConfirmationWindow
Definition: params.h:93
Parameters that influence chain consensus.
Definition: params.h:59
int64_t GetMedianTimePast() const
Definition: blockindex.h:172
virtual int Threshold(const Consensus::Params &params) const =0
int32_t nVersion
block header
Definition: blockindex.h:79
BIP9Stats GetStateStatisticsFor(const CBlockIndex *pindex, const Consensus::Params &params) const
Returns the numerical statistics of an in-progress BIP9 softfork in the current period.
int64_t nTimeout
Timeout/expiry MedianTime for the deployment attempt.
Definition: params.h:41
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:8
std::map< const CBlockIndex *, ThresholdState > ThresholdConditionCache
Definition: versionbits.h:41
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: blockindex.h:23
static const int32_t VERSIONBITS_TOP_BITS
What bits to set in version for versionbits blocks.
Definition: versionbits.h:14
virtual int64_t BeginTime(const Consensus::Params &params) const =0
static int count
Definition: tests.c:35
int elapsed
Number of blocks elapsed since the beginning of the current period.
Definition: versionbits.h:55
bool possible
False if there are not enough blocks left in this period to pass activation threshold.
Definition: versionbits.h:65
virtual int Period(const Consensus::Params &params) const =0
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: blockindex.h:36
int bit
Bit position to select the particular bit in nVersion.
Definition: params.h:28
BIP9Stats VersionBitsStatistics(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos)
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: blockindex.cpp:71
ThresholdState VersionBitsState(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos, VersionBitsCache &cache)
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS]
Definition: params.h:94