29 const int64_t m_begin;
32 const int m_threshold;
33 const int m_min_activation_height;
36 TestConditionChecker(int64_t begin, int64_t end,
int period,
int threshold,
int min_activation_height,
int bit)
37 : m_begin{begin}, m_end{end}, m_period{period}, m_threshold{threshold}, m_min_activation_height{min_activation_height}, m_bit{bit}
40 assert(0 <= m_threshold && m_threshold <= m_period);
42 assert(0 <= m_min_activation_height);
58 uint32_t mask = (uint32_t{1}) << m_bit;
69 std::vector<std::unique_ptr<CBlockIndex>> m_blocks;
70 const uint32_t m_start_time;
71 const uint32_t m_interval;
72 const int32_t m_signal;
73 const int32_t m_no_signal;
76 Blocks(uint32_t start_time, uint32_t interval, int32_t signal, int32_t no_signal)
77 : m_start_time{start_time}, m_interval{interval}, m_signal{signal}, m_no_signal{no_signal} {}
79 size_t size()
const {
return m_blocks.size(); }
83 return m_blocks.empty() ? nullptr : m_blocks.back().get();
89 header.
nVersion = signal ? m_signal : m_no_signal;
90 header.
nTime = m_start_time + m_blocks.size() * m_interval;
91 header.
nBits = 0x1d00ffff;
93 auto current_block = std::make_unique<CBlockIndex>(header);
94 current_block->pprev = tip();
95 current_block->nHeight = m_blocks.size();
96 current_block->BuildSkip();
98 return m_blocks.emplace_back(std::move(current_block)).get();
102 std::unique_ptr<const CChainParams> g_params;
108 assert(g_params !=
nullptr);
111 constexpr uint32_t MAX_START_TIME = 4102444800;
118 assert(interval < std::numeric_limits<int32_t>::max());
123 const int period = 32;
124 const size_t max_periods = 16;
125 const size_t max_blocks = 2 * period * max_periods;
127 const int threshold = fuzzed_data_provider.ConsumeIntegralInRange(1, period);
128 assert(0 < threshold && threshold <= period);
132 assert(std::numeric_limits<uint32_t>::max() - MAX_START_TIME > interval * max_blocks);
134 const int64_t block_start_time = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(params.
GenesisBlock().
nTime, MAX_START_TIME);
137 const int32_t ver_signal = fuzzed_data_provider.ConsumeIntegral<int32_t>();
138 const int32_t ver_nosignal = fuzzed_data_provider.ConsumeIntegral<int32_t>();
143 bool always_active_test =
false;
144 bool never_active_test =
false;
147 if (fuzzed_data_provider.ConsumeBool()) {
150 int start_block = fuzzed_data_provider.ConsumeIntegralInRange<
int>(0, period * (max_periods - 3));
151 int end_block = fuzzed_data_provider.ConsumeIntegralInRange<
int>(0, period * (max_periods - 3));
153 start_time = block_start_time + start_block * interval;
154 timeout = block_start_time + end_block * interval;
157 if (fuzzed_data_provider.ConsumeBool()) start_time += interval / 2;
158 if (fuzzed_data_provider.ConsumeBool()) timeout += interval / 2;
160 if (fuzzed_data_provider.ConsumeBool()) {
162 always_active_test =
true;
165 never_active_test =
true;
169 int min_activation = fuzzed_data_provider.ConsumeIntegralInRange<
int>(0, period * max_periods);
174 if (!checker.Condition(ver_signal))
return;
175 if (checker.Condition(ver_nosignal))
return;
176 if (ver_nosignal < 0)
return;
184 Blocks blocks(block_start_time, interval, ver_signal, ver_nosignal);
199 const uint32_t signalling_mask = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
202 while (fuzzed_data_provider.remaining_bytes() > 0) {
204 bool signal = fuzzed_data_provider.ConsumeBool();
205 for (
int b = 0; b < period; ++b) {
206 blocks.mine_block(signal);
210 if (blocks.size() + 2 * period > max_blocks)
break;
221 const int exp_since = checker.GetStateSinceHeightFor(prev);
226 last_stats.
period = period;
229 last_stats.
possible = (period >= threshold);
230 std::vector<bool> last_signals{};
232 int prev_next_height = (prev ==
nullptr ? 0 : prev->
nHeight + 1);
233 assert(exp_since <= prev_next_height);
236 for (
int b = 1; b < period; ++b) {
237 const bool signal = (signalling_mask >> (b % 32)) & 1;
238 if (signal) ++blocks_sig;
240 CBlockIndex* current_block = blocks.mine_block(signal);
243 assert(checker.Condition(current_block) == signal);
247 const int since = checker.GetStateSinceHeightFor(current_block);
248 assert(state == exp_state);
249 assert(since == exp_since);
252 std::vector<bool> signals;
253 const BIP9Stats stats = checker.GetStateStatisticsFor(current_block, &signals);
254 const BIP9Stats stats_no_signals = checker.GetStateStatisticsFor(current_block);
266 assert(signals.size() == last_signals.size() + 1);
267 assert(signals.back() == signal);
268 last_signals.push_back(signal);
269 assert(signals == last_signals);
278 bool signal = (signalling_mask >> (period % 32)) & 1;
279 if (signal) ++blocks_sig;
280 CBlockIndex* current_block = blocks.mine_block(signal);
281 assert(checker.Condition(current_block) == signal);
283 const BIP9Stats stats = checker.GetStateStatisticsFor(current_block);
292 const int since = checker.GetStateSinceHeightFor(current_block);
295 assert(since % period == 0);
297 if (state == exp_state) {
298 assert(since == exp_since);
313 assert(blocks_sig < threshold);
324 assert(blocks_sig >= threshold);
328 assert(always_active_test || min_activation <= current_block->
nHeight + 1);
334 assert(blocks_sig < threshold);
343 if (blocks.size() >= period * max_periods) {
348 if (always_active_test) {
353 }
else if (never_active_test) {
std::unique_ptr< const CChainParams > CreateChainParams(const ArgsManager &args, const std::string &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...
static const std::string MAIN
Chain name strings.
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 Consensus::Params & GetConsensus() const
const CBlock & GenesisBlock() 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
#define FUZZ_TARGET_INIT(name, init_fun)
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.