Bitcoin Core 22.99.0
P2P Digital Currency
versionbits.cpp
Go to the documentation of this file.
1// Copyright (c) 2016-2019 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.
4
5#include <versionbits.h>
6#include <consensus/params.h>
7
9{
10 int nPeriod = Period(params);
11 int nThreshold = Threshold(params);
12 int min_activation_height = MinActivationHeight(params);
13 int64_t nTimeStart = BeginTime(params);
14 int64_t nTimeTimeout = EndTime(params);
15
16 // Check if this deployment is always active.
19 }
20
21 // Check if this deployment is never active.
24 }
25
26 // 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.
27 if (pindexPrev != nullptr) {
28 pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
29 }
30
31 // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
32 std::vector<const CBlockIndex*> vToCompute;
33 while (cache.count(pindexPrev) == 0) {
34 if (pindexPrev == nullptr) {
35 // The genesis block is by definition defined.
36 cache[pindexPrev] = ThresholdState::DEFINED;
37 break;
38 }
39 if (pindexPrev->GetMedianTimePast() < nTimeStart) {
40 // Optimization: don't recompute down further, as we know every earlier block will be before the start time
41 cache[pindexPrev] = ThresholdState::DEFINED;
42 break;
43 }
44 vToCompute.push_back(pindexPrev);
45 pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
46 }
47
48 // At this point, cache[pindexPrev] is known
49 assert(cache.count(pindexPrev));
50 ThresholdState state = cache[pindexPrev];
51
52 // Now walk forward and compute the state of descendants of pindexPrev
53 while (!vToCompute.empty()) {
54 ThresholdState stateNext = state;
55 pindexPrev = vToCompute.back();
56 vToCompute.pop_back();
57
58 switch (state) {
60 if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
61 stateNext = ThresholdState::STARTED;
62 }
63 break;
64 }
66 // We need to count
67 const CBlockIndex* pindexCount = pindexPrev;
68 int count = 0;
69 for (int i = 0; i < nPeriod; i++) {
70 if (Condition(pindexCount, params)) {
71 count++;
72 }
73 pindexCount = pindexCount->pprev;
74 }
75 if (count >= nThreshold) {
76 stateNext = ThresholdState::LOCKED_IN;
77 } else if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
78 stateNext = ThresholdState::FAILED;
79 }
80 break;
81 }
83 // Progresses into ACTIVE provided activation height will have been reached.
84 if (pindexPrev->nHeight + 1 >= min_activation_height) {
85 stateNext = ThresholdState::ACTIVE;
86 }
87 break;
88 }
91 // Nothing happens, these are terminal states.
92 break;
93 }
94 }
95 cache[pindexPrev] = state = stateNext;
96 }
97
98 return state;
99}
100
102{
103 BIP9Stats stats = {};
104
105 stats.period = Period(params);
106 stats.threshold = Threshold(params);
107
108 if (pindex == nullptr)
109 return stats;
110
111 // Find beginning of period
112 const CBlockIndex* pindexEndOfPrevPeriod = pindex->GetAncestor(pindex->nHeight - ((pindex->nHeight + 1) % stats.period));
113 stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight;
114
115 // Count from current block to beginning of period
116 int count = 0;
117 const CBlockIndex* currentIndex = pindex;
118 while (pindexEndOfPrevPeriod->nHeight != currentIndex->nHeight){
119 if (Condition(currentIndex, params))
120 count++;
121 currentIndex = currentIndex->pprev;
122 }
123
124 stats.count = count;
125 stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count);
126
127 return stats;
128}
129
131{
132 int64_t start_time = BeginTime(params);
134 return 0;
135 }
136
137 const ThresholdState initialState = GetStateFor(pindexPrev, params, cache);
138
139 // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment."
140 if (initialState == ThresholdState::DEFINED) {
141 return 0;
142 }
143
144 const int nPeriod = Period(params);
145
146 // 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.
147 // To ease understanding of the following height calculation, it helps to remember that
148 // right now pindexPrev points to the block prior to the block that we are computing for, thus:
149 // if we are computing for the last block of a period, then pindexPrev points to the second to last block of the period, and
150 // if we are computing for the first block of a period, then pindexPrev points to the last block of the previous period.
151 // The parent of the genesis block is represented by nullptr.
152 pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
153
154 const CBlockIndex* previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
155
156 while (previousPeriodParent != nullptr && GetStateFor(previousPeriodParent, params, cache) == initialState) {
157 pindexPrev = previousPeriodParent;
158 previousPeriodParent = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
159 }
160
161 // Adjust the result because right now we point to the parent block.
162 return pindexPrev->nHeight + 1;
163}
164
165namespace
166{
170class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
171private:
173
174protected:
175 int64_t BeginTime(const Consensus::Params& params) const override { return params.vDeployments[id].nStartTime; }
176 int64_t EndTime(const Consensus::Params& params) const override { return params.vDeployments[id].nTimeout; }
177 int MinActivationHeight(const Consensus::Params& params) const override { return params.vDeployments[id].min_activation_height; }
178 int Period(const Consensus::Params& params) const override { return params.nMinerConfirmationWindow; }
179 int Threshold(const Consensus::Params& params) const override { return params.nRuleChangeActivationThreshold; }
180
181 bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override
182 {
183 return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
184 }
185
186public:
187 explicit VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
188 uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
189};
190
191} // namespace
192
194{
195 LOCK(m_mutex);
196 return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
197}
198
200{
201 return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params);
202}
203
205{
206 LOCK(m_mutex);
207 return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, m_caches[pos]);
208}
209
211{
212 return VersionBitsConditionChecker(pos).Mask(params);
213}
214
216{
217 LOCK(m_mutex);
218 int32_t nVersion = VERSIONBITS_TOP_BITS;
219
220 for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
222 ThresholdState state = VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, m_caches[pos]);
223 if (state == ThresholdState::LOCKED_IN || state == ThresholdState::STARTED) {
224 nVersion |= Mask(params, pos);
225 }
226 }
227
228 return nVersion;
229}
230
232{
233 LOCK(m_mutex);
234 for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
235 m_caches[d].clear();
236 }
237}
Abstract class that implements BIP9-style threshold logic, and caches results.
Definition: versionbits.h:57
virtual bool Condition(const CBlockIndex *pindex, const Consensus::Params &params) const =0
virtual int Period(const Consensus::Params &params) const =0
BIP9Stats GetStateStatisticsFor(const CBlockIndex *pindex, const Consensus::Params &params) const
Returns the numerical statistics of an in-progress BIP9 softfork in the current period.
ThresholdState GetStateFor(const CBlockIndex *pindexPrev, const Consensus::Params &params, ThresholdConditionCache &cache) const
Returns the state for pindex A based on parent pindexPrev B.
Definition: versionbits.cpp:8
virtual int64_t EndTime(const Consensus::Params &params) const =0
virtual int MinActivationHeight(const Consensus::Params &params) const
Definition: versionbits.h:62
int GetStateSinceHeightFor(const CBlockIndex *pindexPrev, const Consensus::Params &params, ThresholdConditionCache &cache) const
Returns the height since when the ThresholdState has started for pindex A based on parent pindexPrev ...
virtual int64_t BeginTime(const Consensus::Params &params) const =0
virtual int Threshold(const Consensus::Params &params) const =0
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:146
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:152
int64_t GetMedianTimePast() const
Definition: chain.h:280
int32_t nVersion
block header
Definition: chain.h:198
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
Definition: chain.cpp:111
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:158
static BIP9Stats Statistics(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos)
Get the numerical statistics for a given deployment for the signalling period that includes the block...
ThresholdState State(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos)
Get the BIP9 state for a given deployment for the block after pindexPrev.
int32_t ComputeBlockVersion(const CBlockIndex *pindexPrev, const Consensus::Params &params)
Determine what nVersion a new block should use.
int StateSinceHeight(const CBlockIndex *pindexPrev, const Consensus::Params &params, Consensus::DeploymentPos pos)
Get the block height at which the BIP9 deployment switched into the state for the block after pindexP...
static uint32_t Mask(const Consensus::Params &params, Consensus::DeploymentPos pos)
static NodeId id
DeploymentPos
Definition: params.h:28
@ MAX_VERSION_BITS_DEPLOYMENTS
Definition: params.h:32
Display status of an in-progress BIP9 softfork.
Definition: versionbits.h:41
int count
Number of blocks with the version bit set since the beginning of the current period.
Definition: versionbits.h:49
int elapsed
Number of blocks elapsed since the beginning of the current period.
Definition: versionbits.h:47
int threshold
Number of blocks with the version bit set required to activate the softfork.
Definition: versionbits.h:45
bool possible
False if there are not enough blocks left in this period to pass activation threshold.
Definition: versionbits.h:51
int period
Length of blocks of the BIP9 signalling period.
Definition: versionbits.h:43
int min_activation_height
If lock in occurs, delay activation until at least this block height.
Definition: params.h:50
int bit
Bit position to select the particular bit in nVersion.
Definition: params.h:41
static constexpr int64_t ALWAYS_ACTIVE
Special value for nStartTime indicating that the deployment is always active.
Definition: params.h:59
static constexpr int64_t NEVER_ACTIVE
Special value for nStartTime indicating that the deployment is never active.
Definition: params.h:64
int64_t nTimeout
Timeout/expiry MedianTime for the deployment attempt.
Definition: params.h:45
int64_t nStartTime
Start MedianTime for version bits miner confirmation.
Definition: params.h:43
Parameters that influence chain consensus.
Definition: params.h:70
uint32_t nMinerConfirmationWindow
Definition: params.h:97
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS]
Definition: params.h:98
uint32_t nRuleChangeActivationThreshold
Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period,...
Definition: params.h:96
#define LOCK(cs)
Definition: sync.h:226
static int count
Definition: tests.c:41
assert(!tx.IsCoinBase())
std::map< const CBlockIndex *, ThresholdState > ThresholdConditionCache
Definition: versionbits.h:38
static const int32_t VERSIONBITS_TOP_BITS
What bits to set in version for versionbits blocks.
Definition: versionbits.h:16
static const int32_t VERSIONBITS_TOP_MASK
What bitmask determines whether versionbits is in use.
Definition: versionbits.h:18
ThresholdState
BIP 9 defines a finite-state-machine to deploy a softfork in multiple stages.
Definition: versionbits.h:27