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>
6 #include <consensus/params.h>
8 const struct VBDeploymentInfo VersionBitsDeploymentInfo
[Consensus::MAX_VERSION_BITS_DEPLOYMENTS
] = {
10 /*.name =*/ "testdummy",
11 /*.gbt_force =*/ true,
15 /*.gbt_force =*/ true,
19 /*.gbt_force =*/ true,
23 ThresholdState
AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, ThresholdConditionCache
& cache
) const
25 int nPeriod
= Period(params
);
26 int nThreshold
= Threshold(params
);
27 int64_t nTimeStart
= BeginTime(params
);
28 int64_t nTimeTimeout
= EndTime(params
);
30 // Check if this deployment is always active.
31 if (nTimeStart
== Consensus::BIP9Deployment::ALWAYS_ACTIVE
) {
32 return THRESHOLD_ACTIVE
;
35 // 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.
36 if (pindexPrev
!= nullptr) {
37 pindexPrev
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- ((pindexPrev
->nHeight
+ 1) % nPeriod
));
40 // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
41 std::vector
<const CBlockIndex
*> vToCompute
;
42 while (cache
.count(pindexPrev
) == 0) {
43 if (pindexPrev
== nullptr) {
44 // The genesis block is by definition defined.
45 cache
[pindexPrev
] = THRESHOLD_DEFINED
;
48 if (pindexPrev
->GetMedianTimePast() < nTimeStart
) {
49 // Optimization: don't recompute down further, as we know every earlier block will be before the start time
50 cache
[pindexPrev
] = THRESHOLD_DEFINED
;
53 vToCompute
.push_back(pindexPrev
);
54 pindexPrev
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- nPeriod
);
57 // At this point, cache[pindexPrev] is known
58 assert(cache
.count(pindexPrev
));
59 ThresholdState state
= cache
[pindexPrev
];
61 // Now walk forward and compute the state of descendants of pindexPrev
62 while (!vToCompute
.empty()) {
63 ThresholdState stateNext
= state
;
64 pindexPrev
= vToCompute
.back();
65 vToCompute
.pop_back();
68 case THRESHOLD_DEFINED
: {
69 if (pindexPrev
->GetMedianTimePast() >= nTimeTimeout
) {
70 stateNext
= THRESHOLD_FAILED
;
71 } else if (pindexPrev
->GetMedianTimePast() >= nTimeStart
) {
72 stateNext
= THRESHOLD_STARTED
;
76 case THRESHOLD_STARTED
: {
77 if (pindexPrev
->GetMedianTimePast() >= nTimeTimeout
) {
78 stateNext
= THRESHOLD_FAILED
;
82 const CBlockIndex
* pindexCount
= pindexPrev
;
84 for (int i
= 0; i
< nPeriod
; i
++) {
85 if (Condition(pindexCount
, params
)) {
88 pindexCount
= pindexCount
->pprev
;
90 if (count
>= nThreshold
) {
91 stateNext
= THRESHOLD_LOCKED_IN
;
95 case THRESHOLD_LOCKED_IN
: {
96 // Always progresses into ACTIVE.
97 stateNext
= THRESHOLD_ACTIVE
;
100 case THRESHOLD_FAILED
:
101 case THRESHOLD_ACTIVE
: {
102 // Nothing happens, these are terminal states.
106 cache
[pindexPrev
] = state
= stateNext
;
112 // return the numerical statistics of blocks signalling the specified BIP9 condition in this current period
113 BIP9Stats
AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex
* pindex
, const Consensus::Params
& params
) const
115 BIP9Stats stats
= {};
117 stats
.period
= Period(params
);
118 stats
.threshold
= Threshold(params
);
120 if (pindex
== nullptr)
123 // Find beginning of period
124 const CBlockIndex
* pindexEndOfPrevPeriod
= pindex
->GetAncestor(pindex
->nHeight
- ((pindex
->nHeight
+ 1) % stats
.period
));
125 stats
.elapsed
= pindex
->nHeight
- pindexEndOfPrevPeriod
->nHeight
;
127 // Count from current block to beginning of period
129 const CBlockIndex
* currentIndex
= pindex
;
130 while (pindexEndOfPrevPeriod
->nHeight
!= currentIndex
->nHeight
){
131 if (Condition(currentIndex
, params
))
133 currentIndex
= currentIndex
->pprev
;
137 stats
.possible
= (stats
.period
- stats
.threshold
) >= (stats
.elapsed
- count
);
142 int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, ThresholdConditionCache
& cache
) const
144 int64_t start_time
= BeginTime(params
);
145 if (start_time
== Consensus::BIP9Deployment::ALWAYS_ACTIVE
) {
149 const ThresholdState initialState
= GetStateFor(pindexPrev
, params
, cache
);
151 // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
152 if (initialState
== THRESHOLD_DEFINED
) {
156 const int nPeriod
= Period(params
);
158 // 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.
159 // To ease understanding of the following height calculation, it helps to remember that
160 // right now pindexPrev points to the block prior to the block that we are computing for, thus:
161 // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
162 // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
163 // The parent of the genesis block is represented by nullptr.
164 pindexPrev
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- ((pindexPrev
->nHeight
+ 1) % nPeriod
));
166 const CBlockIndex
* previousPeriodParent
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- nPeriod
);
168 while (previousPeriodParent
!= nullptr && GetStateFor(previousPeriodParent
, params
, cache
) == initialState
) {
169 pindexPrev
= previousPeriodParent
;
170 previousPeriodParent
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- nPeriod
);
173 // Adjust the result because right now we point to the parent block.
174 return pindexPrev
->nHeight
+ 1;
180 * Class to implement versionbits logic.
182 class VersionBitsConditionChecker
: public AbstractThresholdConditionChecker
{
184 const Consensus::DeploymentPos id
;
187 int64_t BeginTime(const Consensus::Params
& params
) const override
{ return params
.vDeployments
[id
].nStartTime
; }
188 int64_t EndTime(const Consensus::Params
& params
) const override
{ return params
.vDeployments
[id
].nTimeout
; }
189 int Period(const Consensus::Params
& params
) const override
{ return params
.nMinerConfirmationWindow
; }
190 int Threshold(const Consensus::Params
& params
) const override
{ return params
.nRuleChangeActivationThreshold
; }
192 bool Condition(const CBlockIndex
* pindex
, const Consensus::Params
& params
) const override
194 return (((pindex
->nVersion
& VERSIONBITS_TOP_MASK
) == VERSIONBITS_TOP_BITS
) && (pindex
->nVersion
& Mask(params
)) != 0);
198 explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_
) : id(id_
) {}
199 uint32_t Mask(const Consensus::Params
& params
) const { return ((uint32_t)1) << params
.vDeployments
[id
].bit
; }
204 ThresholdState
VersionBitsState(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, Consensus::DeploymentPos pos
, VersionBitsCache
& cache
)
206 return VersionBitsConditionChecker(pos
).GetStateFor(pindexPrev
, params
, cache
.caches
[pos
]);
209 BIP9Stats
VersionBitsStatistics(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, Consensus::DeploymentPos pos
)
211 return VersionBitsConditionChecker(pos
).GetStateStatisticsFor(pindexPrev
, params
);
214 int VersionBitsStateSinceHeight(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, Consensus::DeploymentPos pos
, VersionBitsCache
& cache
)
216 return VersionBitsConditionChecker(pos
).GetStateSinceHeightFor(pindexPrev
, params
, cache
.caches
[pos
]);
219 uint32_t VersionBitsMask(const Consensus::Params
& params
, Consensus::DeploymentPos pos
)
221 return VersionBitsConditionChecker(pos
).Mask(params
);
224 void VersionBitsCache::Clear()
226 for (unsigned int d
= 0; d
< Consensus::MAX_VERSION_BITS_DEPLOYMENTS
; d
++) {