Fix segfault crash when shutdown the GUI in disablewallet mode
[bitcoinplatinum.git] / src / versionbits.cpp
blobd73f3405109d0843a289496d3e7aad1f9df3a812
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.
5 #include "versionbits.h"
7 #include "consensus/params.h"
9 const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = {
11 /*.name =*/ "testdummy",
12 /*.gbt_force =*/ true,
15 /*.name =*/ "csv",
16 /*.gbt_force =*/ true,
19 /*.name =*/ "segwit",
20 /*.gbt_force =*/ false,
24 ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
26 int nPeriod = Period(params);
27 int nThreshold = Threshold(params);
28 int64_t nTimeStart = BeginTime(params);
29 int64_t nTimeTimeout = EndTime(params);
31 // 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.
32 if (pindexPrev != NULL) {
33 pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
36 // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
37 std::vector<const CBlockIndex*> vToCompute;
38 while (cache.count(pindexPrev) == 0) {
39 if (pindexPrev == NULL) {
40 // The genesis block is by definition defined.
41 cache[pindexPrev] = THRESHOLD_DEFINED;
42 break;
44 if (pindexPrev->GetMedianTimePast() < nTimeStart) {
45 // Optimization: don't recompute down further, as we know every earlier block will be before the start time
46 cache[pindexPrev] = THRESHOLD_DEFINED;
47 break;
49 vToCompute.push_back(pindexPrev);
50 pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
53 // At this point, cache[pindexPrev] is known
54 assert(cache.count(pindexPrev));
55 ThresholdState state = cache[pindexPrev];
57 // Now walk forward and compute the state of descendants of pindexPrev
58 while (!vToCompute.empty()) {
59 ThresholdState stateNext = state;
60 pindexPrev = vToCompute.back();
61 vToCompute.pop_back();
63 switch (state) {
64 case THRESHOLD_DEFINED: {
65 if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
66 stateNext = THRESHOLD_FAILED;
67 } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
68 stateNext = THRESHOLD_STARTED;
70 break;
72 case THRESHOLD_STARTED: {
73 if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
74 stateNext = THRESHOLD_FAILED;
75 break;
77 // We need to count
78 const CBlockIndex* pindexCount = pindexPrev;
79 int count = 0;
80 for (int i = 0; i < nPeriod; i++) {
81 if (Condition(pindexCount, params)) {
82 count++;
84 pindexCount = pindexCount->pprev;
86 if (count >= nThreshold) {
87 stateNext = THRESHOLD_LOCKED_IN;
89 break;
91 case THRESHOLD_LOCKED_IN: {
92 // Always progresses into ACTIVE.
93 stateNext = THRESHOLD_ACTIVE;
94 break;
96 case THRESHOLD_FAILED:
97 case THRESHOLD_ACTIVE: {
98 // Nothing happens, these are terminal states.
99 break;
102 cache[pindexPrev] = state = stateNext;
105 return state;
108 int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
110 const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
112 // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
113 if (initialState == THRESHOLD_DEFINED) {
114 return 0;
117 const int nPeriod = Period(params);
119 // 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.
120 // To ease understanding of the following height calculation, it helps to remember that
121 // right now pindexPrev points to the block prior to the block that we are computing for, thus:
122 // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
123 // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
124 // The parent of the genesis block is represented by NULL.
125 pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
127 const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
129 while (previousPeriodParent != NULL && GetStateFor(previousPeriodParent, params, cache) == initialState) {
130 pindexPrev = previousPeriodParent;
131 previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
134 // Adjust the result because right now we point to the parent block.
135 return pindexPrev->nHeight + 1;
138 namespace
141 * Class to implement versionbits logic.
143 class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
144 private:
145 const Consensus::DeploymentPos id;
147 protected:
148 int64_t BeginTime(const Consensus::Params& params) const { return params.vDeployments[id].nStartTime; }
149 int64_t EndTime(const Consensus::Params& params) const { return params.vDeployments[id].nTimeout; }
150 int Period(const Consensus::Params& params) const { return params.nMinerConfirmationWindow; }
151 int Threshold(const Consensus::Params& params) const { return params.nRuleChangeActivationThreshold; }
153 bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const
155 return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
158 public:
159 VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
160 uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
165 ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
167 return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
170 int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
172 return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]);
175 uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos)
177 return VersionBitsConditionChecker(pos).Mask(params);
180 void VersionBitsCache::Clear()
182 for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
183 caches[d].clear();