Dash Core  0.12.2.1
P2P Digital Currency
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 
7 #include "consensus/params.h"
8 
10  {
11  /*.name =*/ "testdummy",
12  /*.gbt_force =*/ true,
13  /*.check_mn_protocol =*/ false,
14  },
15  {
16  /*.name =*/ "csv",
17  /*.gbt_force =*/ true,
18  /*.check_mn_protocol =*/ false,
19  },
20  {
21  /*.name =*/ "dip0001",
22  /*.gbt_force =*/ true,
23  /*.check_mn_protocol =*/ true,
24  }
25 };
26 
28 {
29  int nPeriod = Period(params);
30  int nThreshold = Threshold(params);
31  int64_t nTimeStart = BeginTime(params);
32  int64_t nTimeTimeout = EndTime(params);
33 
34  // 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.
35  if (pindexPrev != NULL) {
36  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
37  }
38 
39  // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
40  std::vector<const CBlockIndex*> vToCompute;
41  while (cache.count(pindexPrev) == 0) {
42  if (pindexPrev == NULL) {
43  // The genesis block is by definition defined.
44  cache[pindexPrev] = THRESHOLD_DEFINED;
45  break;
46  }
47  if (pindexPrev->GetMedianTimePast() < nTimeStart) {
48  // Optimizaton: don't recompute down further, as we know every earlier block will be before the start time
49  cache[pindexPrev] = THRESHOLD_DEFINED;
50  break;
51  }
52  vToCompute.push_back(pindexPrev);
53  pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
54  }
55 
56  // At this point, cache[pindexPrev] is known
57  assert(cache.count(pindexPrev));
58  ThresholdState state = cache[pindexPrev];
59 
60  // Now walk forward and compute the state of descendants of pindexPrev
61  while (!vToCompute.empty()) {
62  ThresholdState stateNext = state;
63  pindexPrev = vToCompute.back();
64  vToCompute.pop_back();
65 
66  switch (state) {
67  case THRESHOLD_DEFINED: {
68  if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
69  stateNext = THRESHOLD_FAILED;
70  } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
71  stateNext = THRESHOLD_STARTED;
72  }
73  break;
74  }
75  case THRESHOLD_STARTED: {
76  if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
77  stateNext = THRESHOLD_FAILED;
78  break;
79  }
80  // We need to count
81  const CBlockIndex* pindexCount = pindexPrev;
82  int count = 0;
83  for (int i = 0; i < nPeriod; i++) {
84  if (Condition(pindexCount, params)) {
85  count++;
86  }
87  pindexCount = pindexCount->pprev;
88  }
89  if (count >= nThreshold) {
90  stateNext = THRESHOLD_LOCKED_IN;
91  }
92  break;
93  }
94  case THRESHOLD_LOCKED_IN: {
95  // Always progresses into ACTIVE.
96  stateNext = THRESHOLD_ACTIVE;
97  break;
98  }
99  case THRESHOLD_FAILED:
100  case THRESHOLD_ACTIVE: {
101  // Nothing happens, these are terminal states.
102  break;
103  }
104  }
105  cache[pindexPrev] = state = stateNext;
106  }
107 
108  return state;
109 }
110 
111 namespace
112 {
116 class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
117 private:
118  const Consensus::DeploymentPos id;
119 
120 protected:
121  int64_t BeginTime(const Consensus::Params& params) const { return params.vDeployments[id].nStartTime; }
122  int64_t EndTime(const Consensus::Params& params) const { return params.vDeployments[id].nTimeout; }
123  int Period(const Consensus::Params& params) const { return params.vDeployments[id].nWindowSize ? params.vDeployments[id].nWindowSize : params.nMinerConfirmationWindow; }
124  int Threshold(const Consensus::Params& params) const { return params.vDeployments[id].nThreshold ? params.vDeployments[id].nThreshold : params.nRuleChangeActivationThreshold; }
125 
126  bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const
127  {
128  return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
129  }
130 
131 public:
132  VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
133  uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
134 };
135 
136 }
137 
139 {
140  return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
141 }
142 
144 {
145  return VersionBitsConditionChecker(pos).Mask(params);
146 }
147 
149 {
150  for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
151  caches[d].clear();
152  }
153 }
virtual bool Condition(const CBlockIndex *pindex, const Consensus::Params &params) const =0
virtual int Period(const Consensus::Params &params) const =0
static const int32_t VERSIONBITS_TOP_MASK
Definition: versionbits.h:16
virtual int64_t BeginTime(const Consensus::Params &params) const =0
ThresholdConditionCache caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS]
Definition: versionbits.h:62
ThresholdState
Definition: versionbits.h:20
uint32_t VersionBitsMask(const Consensus::Params &params, Consensus::DeploymentPos pos)
uint32_t nRuleChangeActivationThreshold
Definition: params.h:72
DeploymentPos
Definition: params.h:15
uint32_t nMinerConfirmationWindow
Definition: params.h:74
virtual int Threshold(const Consensus::Params &params) const =0
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS]
Definition: params.h:75
std::map< const CBlockIndex *, ThresholdState > ThresholdConditionCache
Definition: versionbits.h:31
static const int32_t VERSIONBITS_TOP_BITS
Definition: versionbits.h:14
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:78
static int count
Definition: tests.c:41
int64_t GetMedianTimePast() const
Definition: chain.h:230
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:107
ThresholdState VersionBitsState(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos, VersionBitsCache &cache)
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:113
int nVersion
block header
Definition: chain.h:140
ThresholdState GetStateFor(const CBlockIndex *pindexPrev, const Consensus::Params &params, ThresholdConditionCache &cache) const
Definition: versionbits.cpp:27
const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS]
Definition: versionbits.cpp:9
virtual int64_t EndTime(const Consensus::Params &params) const =0