Bitcoin Core  22.99.0
P2P Digital Currency
versionbits.cpp
Go to the documentation of this file.
1 // Copyright (c) 2016-2019 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 
102 {
103  BIP9Stats stats = {};
104 
105  stats.period = Period(params);
106  stats.threshold = Threshold(params);
107 
108  if (pindex == nullptr)
109  return stats;
110 
111  // Find beginning of period
112  const CBlockIndex* pindexEndOfPrevPeriod = pindex->GetAncestor(pindex->nHeight - ((pindex->nHeight + 1) % stats.period));
113  stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight;
114 
115  // Count from current block to beginning of period
116  int count = 0;
117  const CBlockIndex* currentIndex = pindex;
118  while (pindexEndOfPrevPeriod->nHeight != currentIndex->nHeight){
119  if (Condition(currentIndex, params))
120  count++;
121  currentIndex = currentIndex->pprev;
122  }
123 
124  stats.count = count;
125  stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
126 
127  return stats;
128 }
129 
131 {
132  int64_t start_time = BeginTime(params);
134  return 0;
135  }
136 
137  const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
138 
139  // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
140  if (initialState == ThresholdState::DEFINED) {
141  return 0;
142  }
143 
144  const int nPeriod = Period(params);
145 
146  // 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.
147  // To ease understanding of the following height calculation, it helps to remember that
148  // right now pindexPrev points to the block prior to the block that we are computing for, thus:
149  // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
150  // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
151  // The parent of the genesis block is represented by nullptr.
152  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
153 
154  const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
155 
156  while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, params, cache) == initialState) {
157  pindexPrev = previousPeriodParent;
158  previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
159  }
160 
161  // Adjust the result because right now we point to the parent block.
162  return pindexPrev->nHeight + 1;
163 }
164 
165 namespace
166 {
170 class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
171 private:
173 
174 protected:
175  int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
176  int64_t EndTime(const Consensus::Params& params) const override { return params.vDeployments[id].nTimeout; }
177  int MinActivationHeight(const Consensus::Params& params) const override { return params.vDeployments[id].min_activation_height; }
178  int Period(const Consensus::Params& params) const override { return params.nMinerConfirmationWindow; }
179  int Threshold(const Consensus::Params& params) const override { return params.nRuleChangeActivationThreshold; }
180 
181  bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
182  {
183  return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
184  }
185 
186 public:
187  explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
188  uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
189 };
190 
191 } // namespace
192 
194 {
195  LOCK(m_mutex);
196  return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
197 }
198 
200 {
201  return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params);
202 }
203 
205 {
206  LOCK(m_mutex);
207  return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, m_caches[pos]);
208 }
209 
211 {
212  return VersionBitsConditionChecker(pos).Mask(params);
213 }
214 
215 int32_t VersionBitsCache::ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
216 {
217  LOCK(m_mutex);
218  int32_t nVersion = VERSIONBITS_TOP_BITS;
219 
220  for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
222  ThresholdState state = VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
223  if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
224  nVersion |= Mask(params, pos);
225  }
226  }
227 
228  return nVersion;
229 }
230 
232 {
233  LOCK(m_mutex);
234  for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
235  m_caches[d].clear();
236  }
237 }
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:111
count
static int count
Definition: tests.c:41
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:193
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:215
Consensus::MAX_VERSION_BITS_DEPLOYMENTS
@ MAX_VERSION_BITS_DEPLOYMENTS
Definition: params.h:32
VersionBitsCache::Clear
void Clear()
Definition: versionbits.cpp:231
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:152
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:158
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:81
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
VersionBitsCache::Statistics
static BIP9Stats Statistics(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos)
Get the numerical statistics for a given deployment for the signalling period that includes the block...
Definition: versionbits.cpp:199
Consensus::Params
Parameters that influence chain consensus.
Definition: params.h:70
Consensus::DeploymentPos
DeploymentPos
Definition: params.h:28
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:130
CBlockIndex::GetMedianTimePast
int64_t GetMedianTimePast() const
Definition: chain.h:280
AbstractThresholdConditionChecker::BeginTime
virtual int64_t BeginTime(const Consensus::Params &params) const =0
CBlockIndex::nVersion
int32_t nVersion
block header
Definition: chain.h:198
ThresholdState::DEFINED
@ DEFINED
VersionBitsCache::Mask
static uint32_t Mask(const Consensus::Params &params, Consensus::DeploymentPos pos)
Definition: versionbits.cpp:210
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
AbstractThresholdConditionChecker::GetStateStatisticsFor
BIP9Stats GetStateStatisticsFor(const CBlockIndex *pindex, const Consensus::Params &params) const
Returns the numerical statistics of an in-progress BIP9 softfork in the current period.
Definition: versionbits.cpp:101
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:204
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:145
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