1313#include < test/fuzz/fuzz.h>
1414#include < test/fuzz/util.h>
1515
16+ #include < algorithm>
1617#include < cstdint>
1718#include < limits>
1819#include < memory>
1920#include < vector>
2021
22+ bool operator ==(const SignalInfo& a, const SignalInfo& b)
23+ {
24+ return a.height == b.height && a.bip_version == b.bip_version && a.activate == b.activate ;
25+ }
26+
2127namespace {
2228class TestConditionChecker : public AbstractThresholdConditionChecker
2329{
@@ -165,6 +171,18 @@ FUZZ_TARGET_INIT(versionbits, initialize)
165171 // Now that we have chosen time and versions, setup to mine blocks
166172 Blocks blocks (block_start_time, interval);
167173
174+ const auto siginfo_nosignal = [&]() -> std::optional<SignalInfo> {
175+ int bip, bip_ver;
176+ if (checker.BIP (bip, bip_ver)) {
177+ if ((ver_nosignal & 0xFFFFFF00l ) == (ver_activate & 0xFFFFFF00l )) {
178+ return SignalInfo{.height = 0 , .bip_version = static_cast <uint8_t >(ver_nosignal & 0xFF ), .activate = true };
179+ } else if ((ver_nosignal & 0xFFFFFF00l ) == (ver_abandon & 0xFFFFFF00l )) {
180+ return SignalInfo{.height = 0 , .bip_version = static_cast <uint8_t >(ver_nosignal & 0xFF ), .activate = false };
181+ }
182+ }
183+ return std::nullopt ;
184+ }();
185+
168186 /* Strategy:
169187 * * we mine n*period blocks, with zero/one of
170188 * those blocks signalling activation, and zero/one of
@@ -207,8 +225,13 @@ FUZZ_TARGET_INIT(versionbits, initialize)
207225 bool sig_abandon = false ;
208226 int next_active = 0 ;
209227 int next_abandon = 0 ;
228+
229+ std::vector<SignalInfo> exp_siginfo = checker.GetSignalInfo (nullptr ); // dummy
230+ assert (exp_siginfo.empty ());
231+
210232 for (int b = 1 ; b <= period; ++b) {
211233 CBlockIndex* current_block = blocks.tip ();
234+ const int next_height = (current_block != nullptr ? current_block->nHeight + 1 : 0 );
212235
213236 if (current_block != nullptr ) {
214237 // state and since don't change within the period
@@ -221,14 +244,24 @@ FUZZ_TARGET_INIT(versionbits, initialize)
221244 while (b > next_abandon) next_abandon += 1 + fuzzed_data_provider.ConsumeIntegral <uint8_t >();
222245 while (b > next_active) next_active += 1 + fuzzed_data_provider.ConsumeIntegral <uint8_t >();
223246 if (b == next_abandon) {
247+ exp_siginfo.push_back ({.height = next_height, .bip_version =-1 , .activate =false });
224248 blocks.mine_block (ver_abandon);
225249 sig_abandon = true ;
226250 } else if (b == next_active) {
251+ exp_siginfo.push_back ({.height = next_height, .bip_version =-1 , .activate =true });
227252 blocks.mine_block (ver_activate);
228253 sig_active = true ;
229254 } else {
255+ if (siginfo_nosignal) {
256+ exp_siginfo.push_back (*siginfo_nosignal);
257+ exp_siginfo.back ().height = next_height;
258+ }
230259 blocks.mine_block (ver_nosignal);
231260 }
261+
262+ const std::vector<SignalInfo> siginfo = checker.GetSignalInfo (blocks.tip ());
263+ assert (siginfo.size () == exp_siginfo.size ());
264+ assert (std::equal (siginfo.begin (), siginfo.end (), exp_siginfo.rbegin (), exp_siginfo.rend ()));
232265 }
233266
234267 // grab the final block and the state it's left us in
0 commit comments