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 ThresholdState
AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, ThresholdConditionCache
& cache
) const
9 int nPeriod
= Period(params
);
10 int nThreshold
= Threshold(params
);
11 int64_t nTimeStart
= BeginTime(params
);
12 int64_t nTimeTimeout
= EndTime(params
);
14 // 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.
15 if (pindexPrev
!= NULL
) {
16 pindexPrev
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- ((pindexPrev
->nHeight
+ 1) % nPeriod
));
19 // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
20 std::vector
<const CBlockIndex
*> vToCompute
;
21 while (cache
.count(pindexPrev
) == 0) {
22 if (pindexPrev
== NULL
) {
23 // The genesis block is by definition defined.
24 cache
[pindexPrev
] = THRESHOLD_DEFINED
;
27 if (pindexPrev
->GetMedianTimePast() < nTimeStart
) {
28 // Optimization: don't recompute down further, as we know every earlier block will be before the start time
29 cache
[pindexPrev
] = THRESHOLD_DEFINED
;
32 vToCompute
.push_back(pindexPrev
);
33 pindexPrev
= pindexPrev
->GetAncestor(pindexPrev
->nHeight
- nPeriod
);
36 // At this point, cache[pindexPrev] is known
37 assert(cache
.count(pindexPrev
));
38 ThresholdState state
= cache
[pindexPrev
];
40 // Now walk forward and compute the state of descendants of pindexPrev
41 while (!vToCompute
.empty()) {
42 ThresholdState stateNext
= state
;
43 pindexPrev
= vToCompute
.back();
44 vToCompute
.pop_back();
47 case THRESHOLD_DEFINED
: {
48 if (pindexPrev
->GetMedianTimePast() >= nTimeTimeout
) {
49 stateNext
= THRESHOLD_FAILED
;
50 } else if (pindexPrev
->GetMedianTimePast() >= nTimeStart
) {
51 stateNext
= THRESHOLD_STARTED
;
55 case THRESHOLD_STARTED
: {
56 if (pindexPrev
->GetMedianTimePast() >= nTimeTimeout
) {
57 stateNext
= THRESHOLD_FAILED
;
61 const CBlockIndex
* pindexCount
= pindexPrev
;
63 for (int i
= 0; i
< nPeriod
; i
++) {
64 if (Condition(pindexCount
, params
)) {
67 pindexCount
= pindexCount
->pprev
;
69 if (count
>= nThreshold
) {
70 stateNext
= THRESHOLD_LOCKED_IN
;
74 case THRESHOLD_LOCKED_IN
: {
75 // Always progresses into ACTIVE.
76 stateNext
= THRESHOLD_ACTIVE
;
79 case THRESHOLD_FAILED
:
80 case THRESHOLD_ACTIVE
: {
81 // Nothing happens, these are terminal states.
85 cache
[pindexPrev
] = state
= stateNext
;
94 * Class to implement versionbits logic.
96 class VersionBitsConditionChecker
: public AbstractThresholdConditionChecker
{
98 const Consensus::DeploymentPos id
;
101 int64_t BeginTime(const Consensus::Params
& params
) const { return params
.vDeployments
[id
].nStartTime
; }
102 int64_t EndTime(const Consensus::Params
& params
) const { return params
.vDeployments
[id
].nTimeout
; }
103 int Period(const Consensus::Params
& params
) const { return params
.nMinerConfirmationWindow
; }
104 int Threshold(const Consensus::Params
& params
) const { return params
.nRuleChangeActivationThreshold
; }
106 bool Condition(const CBlockIndex
* pindex
, const Consensus::Params
& params
) const
108 return (((pindex
->nVersion
& VERSIONBITS_TOP_MASK
) == VERSIONBITS_TOP_BITS
) && (pindex
->nVersion
& Mask(params
)) != 0);
112 VersionBitsConditionChecker(Consensus::DeploymentPos id_
) : id(id_
) {}
113 uint32_t Mask(const Consensus::Params
& params
) const { return ((uint32_t)1) << params
.vDeployments
[id
].bit
; }
118 ThresholdState
VersionBitsState(const CBlockIndex
* pindexPrev
, const Consensus::Params
& params
, Consensus::DeploymentPos pos
, VersionBitsCache
& cache
)
120 return VersionBitsConditionChecker(pos
).GetStateFor(pindexPrev
, params
, cache
.caches
[pos
]);
123 uint32_t VersionBitsMask(const Consensus::Params
& params
, Consensus::DeploymentPos pos
)
125 return VersionBitsConditionChecker(pos
).Mask(params
);
128 void VersionBitsCache::Clear()
130 for (unsigned int d
= 0; d
< Consensus::MAX_VERSION_BITS_DEPLOYMENTS
; d
++) {