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,
16 /*.gbt_force =*/ true,
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
;
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
;
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();
64 case THRESHOLD_DEFINED
: {
65 if (pindexPrev
->GetMedianTimePast() >= nTimeTimeout
) {
66 stateNext
= THRESHOLD_FAILED
;
67 } else if (pindexPrev
->GetMedianTimePast() >= nTimeStart
) {
68 stateNext
= THRESHOLD_STARTED
;
72 case THRESHOLD_STARTED
: {
73 if (pindexPrev
->GetMedianTimePast() >= nTimeTimeout
) {
74 stateNext
= THRESHOLD_FAILED
;
78 const CBlockIndex
* pindexCount
= pindexPrev
;
80 for (int i
= 0; i
< nPeriod
; i
++) {
81 if (Condition(pindexCount
, params
)) {
84 pindexCount
= pindexCount
->pprev
;
86 if (count
>= nThreshold
) {
87 stateNext
= THRESHOLD_LOCKED_IN
;
91 case THRESHOLD_LOCKED_IN
: {
92 // Always progresses into ACTIVE.
93 stateNext
= THRESHOLD_ACTIVE
;
96 case THRESHOLD_FAILED
:
97 case THRESHOLD_ACTIVE
: {
98 // Nothing happens, these are terminal states.
102 cache
[pindexPrev
] = state
= stateNext
;
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
) {
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;
141 * Class to implement versionbits logic.
143 class VersionBitsConditionChecker
: public AbstractThresholdConditionChecker
{
145 const Consensus::DeploymentPos id
;
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);
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
++) {