Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

versionbits.cpp
Go to the documentation of this file.
1 // Copyright (c) 2016 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  /*.check_mn_protocol =*/ false,
13  },
14  {
15  /*.name =*/ "csv",
16  /*.gbt_force =*/ true,
17  /*.check_mn_protocol =*/ false,
18  },
19  {
20  /*.name =*/ "dip0001",
21  /*.gbt_force =*/ true,
22  /*.check_mn_protocol =*/ true,
23  },
24  {
25  /*.name =*/ "bip147",
26  /*.gbt_force =*/ true,
27  /*.check_mn_protocol =*/ false,
28  },
29  {
30  /*.name =*/ "dip0003",
31  /*.gbt_force =*/ true,
32  /*.check_mn_protocol =*/ false,
33  },
34  {
35  /*.name =*/ "dip0008",
36  /*.gbt_force =*/ true,
37  /*.check_mn_protocol =*/ false,
38  },
39  {
40  /*.name =*/ "realloc",
41  /*.gbt_force =*/ true,
42  /*.check_mn_protocol =*/ false,
43  },
44 };
45 
47 {
48  int nPeriod = Period(params);
49  int64_t nTimeStart = BeginTime(params);
50  int64_t nTimeTimeout = EndTime(params);
51 
52  // 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.
53  if (pindexPrev != nullptr) {
54  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
55  }
56 
57  // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
58  std::vector<const CBlockIndex*> vToCompute;
59  while (cache.count(pindexPrev) == 0) {
60  if (pindexPrev == nullptr) {
61  // The genesis block is by definition defined.
62  cache[pindexPrev] = THRESHOLD_DEFINED;
63  break;
64  }
65  if (pindexPrev->GetMedianTimePast() < nTimeStart) {
66  // Optimization: don't recompute down further, as we know every earlier block will be before the start time
67  cache[pindexPrev] = THRESHOLD_DEFINED;
68  break;
69  }
70  vToCompute.push_back(pindexPrev);
71  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
72  }
73 
74  // At this point, cache[pindexPrev] is known
75  assert(cache.count(pindexPrev));
76  ThresholdState state = cache[pindexPrev];
77 
78  int nStartHeight{std::numeric_limits<int>::max()};
79  for (const auto& pair : cache) {
80  if (pair.second == THRESHOLD_STARTED && nStartHeight > pair.first->nHeight + 1) {
81  nStartHeight = pair.first->nHeight + 1;
82  }
83  }
84 
85  // Now walk forward and compute the state of descendants of pindexPrev
86  while (!vToCompute.empty()) {
87  ThresholdState stateNext = state;
88  pindexPrev = vToCompute.back();
89  vToCompute.pop_back();
90 
91  switch (state) {
92  case THRESHOLD_DEFINED: {
93  if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
94  stateNext = THRESHOLD_FAILED;
95  } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
96  stateNext = THRESHOLD_STARTED;
97  nStartHeight = pindexPrev->nHeight + 1;
98  }
99  break;
100  }
101  case THRESHOLD_STARTED: {
102  if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
103  stateNext = THRESHOLD_FAILED;
104  break;
105  }
106  // We need to count
107  const CBlockIndex* pindexCount = pindexPrev;
108  int count = 0;
109  for (int i = 0; i < nPeriod; i++) {
110  if (Condition(pindexCount, params)) {
111  count++;
112  }
113  pindexCount = pindexCount->pprev;
114  }
115  assert(nStartHeight > 0 && nStartHeight < std::numeric_limits<int>::max());
116  int nAttempt = (pindexCount->nHeight + 1 - nStartHeight) / nPeriod;
117  if (count >= Threshold(params, nAttempt)) {
118  stateNext = THRESHOLD_LOCKED_IN;
119  }
120  break;
121  }
122  case THRESHOLD_LOCKED_IN: {
123  // Always progresses into ACTIVE.
124  stateNext = THRESHOLD_ACTIVE;
125  break;
126  }
127  case THRESHOLD_FAILED:
128  case THRESHOLD_ACTIVE: {
129  // Nothing happens, these are terminal states.
130  break;
131  }
132  }
133  cache[pindexPrev] = state = stateNext;
134  }
135 
136  return state;
137 }
138 
139 // return the numerical statistics of blocks signalling the specified BIP9 condition in this current period
141 {
142  BIP9Stats stats = {};
143 
144  stats.period = Period(params);
145  stats.threshold = Threshold(params, 0);
146 
147  if (pindex == nullptr)
148  return stats;
149 
150  // Find beginning of period
151  const CBlockIndex* pindexEndOfPrevPeriod = pindex->GetAncestor(pindex->nHeight - ((pindex->nHeight + 1) % stats.period));
152  stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight;
153 
154  // Re-calculate current threshold
155  int nAttempt{0};
156  const ThresholdState state = GetStateFor(pindexEndOfPrevPeriod, params, cache);
157  if (state == THRESHOLD_STARTED) {
158  int nStartHeight = GetStateSinceHeightFor(pindexEndOfPrevPeriod, params, cache);
159  nAttempt = (pindexEndOfPrevPeriod->nHeight + 1 - nStartHeight)/stats.period;
160  }
161  stats.threshold = Threshold(params, nAttempt);
162 
163  // Count from current block to beginning of period
164  int count = 0;
165  const CBlockIndex* currentIndex = pindex;
166  while (pindexEndOfPrevPeriod->nHeight != currentIndex->nHeight){
167  if (Condition(currentIndex, params))
168  count++;
169  currentIndex = currentIndex->pprev;
170  }
171 
172  stats.count = count;
173  stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
174 
175  return stats;
176 }
177 
179 {
180  const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
181 
182  // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
183  if (initialState == THRESHOLD_DEFINED) {
184  return 0;
185  }
186 
187  const int nPeriod = Period(params);
188 
189  // 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.
190  // To ease understanding of the following height calculation, it helps to remember that
191  // right now pindexPrev points to the block prior to the block that we are computing for, thus:
192  // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
193  // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
194  // The parent of the genesis block is represented by nullptr.
195  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
196 
197  const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
198 
199  while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, params, cache) == initialState) {
200  pindexPrev = previousPeriodParent;
201  previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
202  }
203 
204  // Adjust the result because right now we point to the parent block.
205  return pindexPrev->nHeight + 1;
206 }
207 
208 namespace
209 {
213 class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
214 private:
215  const Consensus::DeploymentPos id;
216 
217 protected:
218  int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
219  int64_t EndTime(const Consensus::Params& params) const override { return params.vDeployments[id].nTimeout; }
220  int Period(const Consensus::Params& params) const override { return params.vDeployments[id].nWindowSize ? params.vDeployments[id].nWindowSize : params.nMinerConfirmationWindow; }
221  int Threshold(const Consensus::Params& params, int nAttempt) const override
222  {
223  if (params.vDeployments[id].nThresholdStart == 0) {
224  return params.nRuleChangeActivationThreshold;
225  }
226  if (params.vDeployments[id].nThresholdMin == 0 || params.vDeployments[id].nFalloffCoeff == 0) {
227  return params.vDeployments[id].nThresholdStart;
228  }
229  int64_t nThresholdCalc = params.vDeployments[id].nThresholdStart - nAttempt * nAttempt * Period(params) / 100 / params.vDeployments[id].nFalloffCoeff;
230  return std::max(params.vDeployments[id].nThresholdMin, nThresholdCalc);
231  }
232 
233  bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
234  {
235  return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
236  }
237 
238 public:
239  explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
240  uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
241 };
242 
243 } // namespace
244 
246 {
247  return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
248 }
249 
251 {
252  return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params, cache.caches[pos]);
253 }
254 
256 {
257  return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]);
258 }
259 
261 {
262  return VersionBitsConditionChecker(pos).Mask(params);
263 }
264 
266 {
267  for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
268  caches[d].clear();
269  }
270 }
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:177
virtual int64_t EndTime(const Consensus::Params &params) const =0
int GetStateSinceHeightFor(const CBlockIndex *pindexPrev, const Consensus::Params &params, ThresholdConditionCache &cache) const
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
const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS]
Definition: versionbits.cpp:8
virtual int Threshold(const Consensus::Params &params, int nAttempt) const =0
ThresholdConditionCache caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS]
Definition: versionbits.h:72
ThresholdState
Definition: versionbits.h:20
uint32_t VersionBitsMask(const Consensus::Params &params, Consensus::DeploymentPos pos)
BIP9Stats GetStateStatisticsFor(const CBlockIndex *pindex, const Consensus::Params &params, ThresholdConditionCache &cache) const
int threshold
Definition: versionbits.h:44
int64_t nFalloffCoeff
A coefficient which adjusts the speed a required number of signaling blocks is decreasing from nThres...
Definition: params.h:45
DeploymentPos
Definition: params.h:15
int period
Definition: versionbits.h:43
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:35
Abstract class that implements BIP9-style threshold logic, and caches results.
Definition: versionbits.h:55
int64_t nWindowSize
The number of past blocks (including the block under consideration) to be taken into account for lock...
Definition: params.h:39
uint32_t nMinerConfirmationWindow
Definition: params.h:170
Parameters that influence chain consensus.
Definition: params.h:130
int64_t GetMedianTimePast() const
Definition: chain.h:309
int64_t nThresholdMin
A minimum number of blocks, in the range of 1..nWindowSize, which must signal for a fork in order to ...
Definition: params.h:43
std::map< const CBlockIndex *, ThresholdState > ThresholdConditionCache
Definition: versionbits.h:31
int32_t nVersion
block header
Definition: chain.h:210
int64_t nTimeout
Timeout/expiry MedianTime for the deployment attempt.
Definition: params.h:37
ThresholdState GetStateFor(const CBlockIndex *pindexPrev, const Consensus::Params &params, ThresholdConditionCache &cache) const
Definition: versionbits.cpp:46
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:170
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:45
int elapsed
Definition: versionbits.h:45
int64_t nThresholdStart
A starting number of blocks, in the range of 1..nWindowSize, which must signal for a fork in order to...
Definition: params.h:41
bool possible
Definition: versionbits.h:47
uint32_t nRuleChangeActivationThreshold
Minimum blocks including miner confirmation of the total of nMinerConfirmationWindow blocks in a reta...
Definition: params.h:168
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: chain.h:183
int bit
Bit position to select the particular bit in nVersion.
Definition: params.h:33
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:110
ThresholdState VersionBitsState(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos, VersionBitsCache &cache)
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS]
Definition: params.h:171
BIP9Stats VersionBitsStatistics(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos, VersionBitsCache &cache)
Released under the MIT license