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