6#include <chainparams.h>
30 const int64_t m_begin;
33 const int m_threshold;
34 const int m_min_activation_height;
37 TestConditionChecker(int64_t begin, int64_t end,
int period,
int threshold,
int min_activation_height,
int bit)
38 : m_begin{begin}, m_end{end}, m_period{period}, m_threshold{threshold}, m_min_activation_height{min_activation_height}, m_bit{bit}
41 assert(0 <= m_threshold && m_threshold <= m_period);
43 assert(0 <= m_min_activation_height);
59 uint32_t mask = (uint32_t{1}) << m_bit;
70 std::vector<std::unique_ptr<CBlockIndex>> m_blocks;
71 const uint32_t m_start_time;
72 const uint32_t m_interval;
73 const int32_t m_signal;
74 const int32_t m_no_signal;
77 Blocks(uint32_t start_time, uint32_t interval, int32_t signal, int32_t no_signal)
78 : m_start_time{start_time}, m_interval{interval}, m_signal{signal}, m_no_signal{no_signal} {}
80 size_t size()
const {
return m_blocks.size(); }
84 return m_blocks.empty() ? nullptr : m_blocks.back().get();
90 header.
nVersion = signal ? m_signal : m_no_signal;
91 header.
nTime = m_start_time + m_blocks.size() * m_interval;
92 header.
nBits = 0x1d00ffff;
94 auto current_block = std::make_unique<CBlockIndex>(header);
95 current_block->pprev = tip();
96 current_block->nHeight = m_blocks.size();
97 current_block->BuildSkip();
99 return m_blocks.emplace_back(std::move(current_block)).get();
103std::unique_ptr<const CChainParams> g_params;
109 assert(g_params !=
nullptr);
112constexpr uint32_t MAX_START_TIME = 4102444800;
119 assert(interval < std::numeric_limits<int32_t>::max());
124 const int period = 32;
125 const size_t max_periods = 16;
126 const size_t max_blocks = 2 * period * max_periods;
128 const int threshold = fuzzed_data_provider.ConsumeIntegralInRange(1, period);
129 assert(0 < threshold && threshold <= period);
133 assert(std::numeric_limits<uint32_t>::max() - MAX_START_TIME > interval * max_blocks);
135 const int64_t block_start_time = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(params.
GenesisBlock().
nTime, MAX_START_TIME);
138 const int32_t ver_signal = fuzzed_data_provider.ConsumeIntegral<int32_t>();
139 const int32_t ver_nosignal = fuzzed_data_provider.ConsumeIntegral<int32_t>();
144 bool always_active_test =
false;
145 bool never_active_test =
false;
148 if (fuzzed_data_provider.ConsumeBool()) {
151 int start_block = fuzzed_data_provider.ConsumeIntegralInRange<
int>(0, period * (max_periods - 3));
152 int end_block = fuzzed_data_provider.ConsumeIntegralInRange<
int>(0, period * (max_periods - 3));
154 start_time = block_start_time + start_block * interval;
155 timeout = block_start_time + end_block * interval;
158 if (fuzzed_data_provider.ConsumeBool()) start_time += interval / 2;
159 if (fuzzed_data_provider.ConsumeBool()) timeout += interval / 2;
161 if (fuzzed_data_provider.ConsumeBool()) {
163 always_active_test =
true;
166 never_active_test =
true;
170 int min_activation = fuzzed_data_provider.ConsumeIntegralInRange<
int>(0, period * max_periods);
175 if (!checker.Condition(ver_signal))
return;
176 if (checker.Condition(ver_nosignal))
return;
177 if (ver_nosignal < 0)
return;
185 Blocks blocks(block_start_time, interval, ver_signal, ver_nosignal);
200 const uint32_t signalling_mask = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
203 while (fuzzed_data_provider.remaining_bytes() > 0) {
205 bool signal = fuzzed_data_provider.ConsumeBool();
206 for (
int b = 0; b < period; ++b) {
207 blocks.mine_block(signal);
211 if (blocks.size() + 2 * period > max_blocks)
break;
222 const int exp_since = checker.GetStateSinceHeightFor(prev);
227 last_stats.
period = period;
230 last_stats.
possible = (period >= threshold);
231 std::vector<bool> last_signals{};
233 int prev_next_height = (prev ==
nullptr ? 0 : prev->
nHeight + 1);
234 assert(exp_since <= prev_next_height);
237 for (
int b = 1; b < period; ++b) {
238 const bool signal = (signalling_mask >> (b % 32)) & 1;
239 if (signal) ++blocks_sig;
241 CBlockIndex* current_block = blocks.mine_block(signal);
244 assert(checker.Condition(current_block) == signal);
248 const int since = checker.GetStateSinceHeightFor(current_block);
249 assert(state == exp_state);
250 assert(since == exp_since);
253 std::vector<bool> signals;
254 const BIP9Stats stats = checker.GetStateStatisticsFor(current_block, &signals);
255 const BIP9Stats stats_no_signals = checker.GetStateStatisticsFor(current_block);
267 assert(signals.size() == last_signals.size() + 1);
268 assert(signals.back() == signal);
269 last_signals.push_back(signal);
270 assert(signals == last_signals);
279 bool signal = (signalling_mask >> (period % 32)) & 1;
280 if (signal) ++blocks_sig;
281 CBlockIndex* current_block = blocks.mine_block(signal);
282 assert(checker.Condition(current_block) == signal);
284 const BIP9Stats stats = checker.GetStateStatisticsFor(current_block);
293 const int since = checker.GetStateSinceHeightFor(current_block);
296 assert(since % period == 0);
298 if (state == exp_state) {
299 assert(since == exp_since);
314 assert(blocks_sig < threshold);
325 assert(blocks_sig >= threshold);
329 assert(always_active_test || min_activation <= current_block->
nHeight + 1);
335 assert(blocks_sig < threshold);
344 if (blocks.size() >= period * max_periods) {
349 if (always_active_test) {
354 }
else if (never_active_test) {
std::unique_ptr< const CChainParams > CreateChainParams(const ArgsManager &args, const ChainType chain)
Creates and returns a std::unique_ptr<CChainParams> of the chosen chain.
Abstract class that implements BIP9-style threshold logic, and caches results.
ThresholdState GetStateFor(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, ThresholdConditionCache &cache) const
Returns the state for pindex A based on parent pindexPrev B.
virtual int MinActivationHeight(const Consensus::Params ¶ms) const
int GetStateSinceHeightFor(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, ThresholdConditionCache &cache) const
Returns the height since when the ThresholdState has started for pindex A based on parent pindexPrev ...
BIP9Stats GetStateStatisticsFor(const CBlockIndex *pindex, const Consensus::Params ¶ms, std::vector< bool > *signalling_blocks=nullptr) const
Returns the numerical statistics of an in-progress BIP9 softfork in the period including pindex If pr...
The block chain is a tree shaped structure starting with the genesis block at the root,...
int64_t GetMedianTimePast() const
int32_t nVersion
block header
int nHeight
height of the entry in the chain. The genesis block has height 0
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const CBlock & GenesisBlock() const
const Consensus::Params & GetConsensus() const
int Threshold(const Consensus::Params ¶ms) const override
int Period(const Consensus::Params ¶ms) const override
int64_t BeginTime(const Consensus::Params ¶ms) const override
bool Condition(const CBlockIndex *pindex, const Consensus::Params ¶ms) const override
ThresholdState GetStateFor(const CBlockIndex *pindexPrev) const
int64_t EndTime(const Consensus::Params ¶ms) const override
int GetStateSinceHeightFor(const CBlockIndex *pindexPrev) const
Display status of an in-progress BIP9 softfork.
int count
Number of blocks with the version bit set since the beginning of the current period.
int elapsed
Number of blocks elapsed since the beginning of the current period.
int threshold
Number of blocks with the version bit set required to activate the softfork.
bool possible
False if there are not enough blocks left in this period to pass activation threshold.
int period
Length of blocks of the BIP9 signalling period.
static constexpr int64_t ALWAYS_ACTIVE
Special value for nStartTime indicating that the deployment is always active.
static constexpr int64_t NEVER_ACTIVE
Special value for nStartTime indicating that the deployment is never active.
static constexpr int64_t NO_TIMEOUT
Constant for nTimeout very far in the future.
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::map< const CBlockIndex *, ThresholdState > ThresholdConditionCache
static const int32_t VERSIONBITS_NUM_BITS
Total bits available for versionbits.
static const int32_t VERSIONBITS_TOP_BITS
What bits to set in version for versionbits blocks.
static const int32_t VERSIONBITS_LAST_OLD_BLOCK_VERSION
What block version to use for new blocks (pre versionbits)
static const int32_t VERSIONBITS_TOP_MASK
What bitmask determines whether versionbits is in use.
ThresholdState
BIP 9 defines a finite-state-machine to deploy a softfork in multiple stages.