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 // 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.
31 if (pindexPrev
!= nullptr) {
32 pindexPrev
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- ((pindexPrev
->nHeight
+ 1) % nPeriod
));
35 // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
36 std::vector
<const CBlockIndex
*> vToCompute
;
37 while (cache
.count(pindexPrev
) == 0) {
38 if (pindexPrev
== nullptr) {
39 // The genesis block is by definition defined.
40 cache
[pindexPrev
] = THRESHOLD_DEFINED
;
43 if (pindexPrev
->GetMedianTimePast() < nTimeStart
) {
44 // Optimization: don't recompute down further, as we know every earlier block will be before the start time
45 cache
[pindexPrev
] = THRESHOLD_DEFINED
;
48 vToCompute
.push_back(pindexPrev
);
49 pindexPrev
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- nPeriod
);
52 // At this point, cache[pindexPrev] is known
53 assert(cache
.count(pindexPrev
));
54 ThresholdState state
= cache
[pindexPrev
];
56 // Now walk forward and compute the state of descendants of pindexPrev
57 while (!vToCompute
.empty()) {
58 ThresholdState stateNext
= state
;
59 pindexPrev
= vToCompute
.back();
60 vToCompute
.pop_back();
63 case THRESHOLD_DEFINED
: {
64 if (pindexPrev
->GetMedianTimePast() >= nTimeTimeout
) {
65 stateNext
= THRESHOLD_FAILED
;
66 } else if (pindexPrev
->GetMedianTimePast() >= nTimeStart
) {
67 stateNext
= THRESHOLD_STARTED
;
71 case THRESHOLD_STARTED
: {
72 if (pindexPrev
->GetMedianTimePast() >= nTimeTimeout
) {
73 stateNext
= THRESHOLD_FAILED
;
77 const CBlockIndex
* pindexCount
= pindexPrev
;
79 for (int i
= 0; i
< nPeriod
; i
++) {
80 if (Condition(pindexCount
, params
)) {
83 pindexCount
= pindexCount
->pprev
;
85 if (count
>= nThreshold
) {
86 stateNext
= THRESHOLD_LOCKED_IN
;
90 case THRESHOLD_LOCKED_IN
: {
91 // Always progresses into ACTIVE.
92 stateNext
= THRESHOLD_ACTIVE
;
95 case THRESHOLD_FAILED
:
96 case THRESHOLD_ACTIVE
: {
97 // Nothing happens, these are terminal states.
101 cache
[pindexPrev
] = state
= stateNext
;
107 // return the numerical statistics of blocks signalling the specified BIP9 condition in this current period
108 BIP9Stats
AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex
* pindex
, const Consensus::Params
& params
) const
110 BIP9Stats stats
= {};
112 stats
.period
= Period(params
);
113 stats
.threshold
= Threshold(params
);
115 if (pindex
== nullptr)
118 // Find beginning of period
119 const CBlockIndex
* pindexEndOfPrevPeriod
= pindex
->GetAncestor(pindex
->nHeight
- ((pindex
->nHeight
+ 1) % stats
.period
));
120 stats
.elapsed
= pindex
->nHeight
- pindexEndOfPrevPeriod
->nHeight
;
122 // Count from current block to beginning of period
124 const CBlockIndex
* currentIndex
= pindex
;
125 while (pindexEndOfPrevPeriod
->nHeight
!= currentIndex
->nHeight
){
126 if (Condition(currentIndex
, params
))
128 currentIndex
= currentIndex
->pprev
;
132 stats
.possible
= (stats
.period
- stats
.threshold
) >= (stats
.elapsed
- count
);
137 int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, ThresholdConditionCache
& cache
) const
139 const ThresholdState initialState
= GetStateFor(pindexPrev
, params
, cache
);
141 // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
142 if (initialState
== THRESHOLD_DEFINED
) {
146 const int nPeriod
= Period(params
);
148 // 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.
149 // To ease understanding of the following height calculation, it helps to remember that
150 // right now pindexPrev points to the block prior to the block that we are computing for, thus:
151 // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
152 // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
153 // The parent of the genesis block is represented by nullptr.
154 pindexPrev
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- ((pindexPrev
->nHeight
+ 1) % nPeriod
));
156 const CBlockIndex
* previousPeriodParent
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- nPeriod
);
158 while (previousPeriodParent
!= nullptr && GetStateFor(previousPeriodParent
, params
, cache
) == initialState
) {
159 pindexPrev
= previousPeriodParent
;
160 previousPeriodParent
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- nPeriod
);
163 // Adjust the result because right now we point to the parent block.
164 return pindexPrev
->nHeight
+ 1;
170 * Class to implement versionbits logic.
172 class VersionBitsConditionChecker
: public AbstractThresholdConditionChecker
{
174 const Consensus::DeploymentPos id
;
177 int64_t BeginTime(const Consensus::Params
& params
) const override
{ return params
.vDeployments
[id
].nStartTime
; }
178 int64_t EndTime(const Consensus::Params
& params
) const override
{ return params
.vDeployments
[id
].nTimeout
; }
179 int Period(const Consensus::Params
& params
) const override
{ return params
.nMinerConfirmationWindow
; }
180 int Threshold(const Consensus::Params
& params
) const override
{ return params
.nRuleChangeActivationThreshold
; }
182 bool Condition(const CBlockIndex
* pindex
, const Consensus::Params
& params
) const override
184 return (((pindex
->nVersion
& VERSIONBITS_TOP_MASK
) == VERSIONBITS_TOP_BITS
) && (pindex
->nVersion
& Mask(params
)) != 0);
188 explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_
) : id(id_
) {}
189 uint32_t Mask(const Consensus::Params
& params
) const { return ((uint32_t)1) << params
.vDeployments
[id
].bit
; }
194 ThresholdState
VersionBitsState(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, Consensus::DeploymentPos pos
, VersionBitsCache
& cache
)
196 return VersionBitsConditionChecker(pos
).GetStateFor(pindexPrev
, params
, cache
.caches
[pos
]);
199 BIP9Stats
VersionBitsStatistics(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, Consensus::DeploymentPos pos
)
201 return VersionBitsConditionChecker(pos
).GetStateStatisticsFor(pindexPrev
, params
);
204 int VersionBitsStateSinceHeight(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, Consensus::DeploymentPos pos
, VersionBitsCache
& cache
)
206 return VersionBitsConditionChecker(pos
).GetStateSinceHeightFor(pindexPrev
, params
, cache
.caches
[pos
]);
209 uint32_t VersionBitsMask(const Consensus::Params
& params
, Consensus::DeploymentPos pos
)
211 return VersionBitsConditionChecker(pos
).Mask(params
);
214 void VersionBitsCache::Clear()
216 for (unsigned int d
= 0; d
< Consensus::MAX_VERSION_BITS_DEPLOYMENTS
; d
++) {