Fabcoin Core  0.16.2
P2P Digital Currency
versionbits.cpp
Go to the documentation of this file.
1 // Copyright (c)2016-2017 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  /*.name =*/ "testdummy",
11  /*.gbt_force =*/ true,
12  },
13  {
14  /*.name =*/ "csv",
15  /*.gbt_force =*/ true,
16  },
17  {
18  /*.name =*/ "segwit",
19  /*.gbt_force =*/ true,
20  }
21 };
22 
24 {
25  int nPeriod = Period(params);
26  int nThreshold = Threshold(params);
27  int64_t nTimeStart = BeginTime(params);
28  int64_t nTimeTimeout = EndTime(params);
29 
30  // 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.
31  if (pindexPrev != nullptr) {
32  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
33  }
34 
35  // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
36  std::vector<const CBlockIndex*> vToCompute;
37  while (cache.count(pindexPrev) == 0) {
38  if (pindexPrev == nullptr) {
39  // The genesis block is by definition defined.
40  cache[pindexPrev] = THRESHOLD_DEFINED;
41  break;
42  }
43  if (pindexPrev->GetMedianTimePast() < nTimeStart) {
44  // Optimization: don't recompute down further, as we know every earlier block will be before the start time
45  cache[pindexPrev] = THRESHOLD_DEFINED;
46  break;
47  }
48  vToCompute.push_back(pindexPrev);
49  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
50  }
51 
52  // At this point, cache[pindexPrev] is known
53  assert(cache.count(pindexPrev));
54  ThresholdState state = cache[pindexPrev];
55 
56  // Now walk forward and compute the state of descendants of pindexPrev
57  while (!vToCompute.empty()) {
58  ThresholdState stateNext = state;
59  pindexPrev = vToCompute.back();
60  vToCompute.pop_back();
61 
62  switch (state) {
63  case THRESHOLD_DEFINED: {
64  if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
65  stateNext = THRESHOLD_FAILED;
66  } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
67  stateNext = THRESHOLD_STARTED;
68  }
69  break;
70  }
71  case THRESHOLD_STARTED: {
72  if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
73  stateNext = THRESHOLD_FAILED;
74  break;
75  }
76  // We need to count
77  const CBlockIndex* pindexCount = pindexPrev;
78  int count = 0;
79  for (int i = 0; i < nPeriod; i++) {
80  if (Condition(pindexCount, params)) {
81  count++;
82  }
83  pindexCount = pindexCount->pprev;
84  }
85  if (count >= nThreshold) {
86  stateNext = THRESHOLD_LOCKED_IN;
87  }
88  break;
89  }
90  case THRESHOLD_LOCKED_IN: {
91  // Always progresses into ACTIVE.
92  stateNext = THRESHOLD_ACTIVE;
93  break;
94  }
95  case THRESHOLD_FAILED:
96  case THRESHOLD_ACTIVE: {
97  // Nothing happens, these are terminal states.
98  break;
99  }
100  }
101  cache[pindexPrev] = state = stateNext;
102  }
103 
104  return state;
105 }
106 
107 // return the numerical statistics of blocks signalling the specified BIP9 condition in this current period
109 {
110  BIP9Stats stats = {};
111 
112  stats.period = Period(params);
113  stats.threshold = Threshold(params);
114 
115  if (pindex == nullptr)
116  return stats;
117 
118  // Find beginning of period
119  const CBlockIndex* pindexEndOfPrevPeriod = pindex->GetAncestor(pindex->nHeight - ((pindex->nHeight + 1) % stats.period));
120  stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight;
121 
122  // Count from current block to beginning of period
123  int count = 0;
124  const CBlockIndex* currentIndex = pindex;
125  while (pindexEndOfPrevPeriod->nHeight != currentIndex->nHeight){
126  if (Condition(currentIndex, params))
127  count++;
128  currentIndex = currentIndex->pprev;
129  }
130 
131  stats.count = count;
132  stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
133 
134  return stats;
135 }
136 
138 {
139  const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
140 
141  // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
142  if (initialState == THRESHOLD_DEFINED) {
143  return 0;
144  }
145 
146  const int nPeriod = Period(params);
147 
148  // 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.
149  // To ease understanding of the following height calculation, it helps to remember that
150  // right now pindexPrev points to the block prior to the block that we are computing for, thus:
151  // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
152  // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
153  // The parent of the genesis block is represented by nullptr.
154  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
155 
156  const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
157 
158  while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, params, cache) == initialState) {
159  pindexPrev = previousPeriodParent;
160  previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
161  }
162 
163  // Adjust the result because right now we point to the parent block.
164  return pindexPrev->nHeight + 1;
165 }
166 
167 namespace
168 {
172 class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
173 private:
174  const Consensus::DeploymentPos id;
175 
176 protected:
177  int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
178  int64_t EndTime(const Consensus::Params& params) const override { return params.vDeployments[id].nTimeout; }
179  int Period(const Consensus::Params& params) const override { return params.nMinerConfirmationWindow; }
180  int Threshold(const Consensus::Params& params) const override { return params.nRuleChangeActivationThreshold; }
181 
182  bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
183  {
184  return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
185  }
186 
187 public:
188  VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
189  uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
190 };
191 
192 } // namespace
193 
195 {
196  return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
197 }
198 
200 {
201  return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params);
202 }
203 
205 {
206  return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]);
207 }
208 
210 {
211  return VersionBitsConditionChecker(pos).Mask(params);
212 }
213 
215 {
216  for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
217  caches[d].clear();
218  }
219 }
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:184
ThresholdState GetStateFor(const CBlockIndex *pindexPrev, const Consensus::Params &params, ThresholdConditionCache &cache) const
Definition: versionbits.cpp:23
size_t count
Definition: ExecStats.cpp:37
const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS]
Definition: versionbits.cpp:8
ThresholdConditionCache caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS]
Definition: versionbits.h:70
assert(len-trim+(2 *lenIndices)<=WIDTH)
ThresholdState
Definition: versionbits.h:20
uint32_t VersionBitsMask(const Consensus::Params &params, Consensus::DeploymentPos pos)
int threshold
Definition: versionbits.h:42
int GetStateSinceHeightFor(const CBlockIndex *pindexPrev, const Consensus::Params &params, ThresholdConditionCache &cache) const
DeploymentPos
Definition: params.h:15
int period
Definition: versionbits.h:41
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:31
Abstract class that implements BIP9-style threshold logic, and caches results.
Definition: versionbits.h:53
BIP9Stats GetStateStatisticsFor(const CBlockIndex *pindex, const Consensus::Params &params) const
uint32_t nMinerConfirmationWindow
Definition: params.h:71
Parameters that influence chain consensus.
Definition: params.h:39
std::map< const CBlockIndex *, ThresholdState > ThresholdConditionCache
Definition: versionbits.h:31
int nVersion
block header
Definition: chain.h:220
int64_t nTimeout
Timeout/expiry MedianTime for the deployment attempt.
Definition: params.h:33
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:177
int elapsed
Definition: versionbits.h:43
bool possible
Definition: versionbits.h:45
uint32_t nRuleChangeActivationThreshold
Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period...
Definition: params.h:70
#define d(i)
Definition: sha.cpp:732
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:193
int bit
Bit position to select the particular bit in nVersion.
Definition: params.h:29
BIP9Stats VersionBitsStatistics(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos)
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:85
ThresholdState VersionBitsState(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos, VersionBitsCache &cache)
int64_t GetMedianTimePast() const
Definition: chain.h:341
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS]
Definition: params.h:72