Skip to content

Commit f95071a

Browse files
committed
Merge #21489: fuzz: cleanups for versionbits fuzzer
aa7f418 fuzz: cleanups for versionbits fuzzer (Anthony Towns) Pull request description: Followups for #21380, shouldn't change coverage. Marking as draft to avoid introducing conflicts for the speedy trial PRs. ACKs for top commit: MarcoFalke: cr ACK aa7f418 practicalswift: Tested ACK aa7f418 Tree-SHA512: 6792364e3bb036cc903b4a5f5805d00afceeae475ce84660da962d28335bd98e59d5f45e68718657d3aa526123e351edadda39e99e49f1c6cfab629e98df35ed
2 parents fa2a5b8 + aa7f418 commit f95071a

File tree

1 file changed

+24
-18
lines changed

1 file changed

+24
-18
lines changed

src/test/fuzz/versionbits.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,18 @@ class TestConditionChecker : public AbstractThresholdConditionChecker
2525
const Consensus::Params dummy_params{};
2626

2727
public:
28-
const int64_t m_begin = 0;
29-
const int64_t m_end = 0;
30-
const int m_period = 0;
31-
const int m_threshold = 0;
32-
const int m_bit = 0;
28+
const int64_t m_begin;
29+
const int64_t m_end;
30+
const int m_period;
31+
const int m_threshold;
32+
const int m_bit;
3333

3434
TestConditionChecker(int64_t begin, int64_t end, int period, int threshold, int bit)
3535
: m_begin{begin}, m_end{end}, m_period{period}, m_threshold{threshold}, m_bit{bit}
3636
{
3737
assert(m_period > 0);
3838
assert(0 <= m_threshold && m_threshold <= m_period);
39-
assert(0 <= m_bit && m_bit <= 32 && m_bit < VERSIONBITS_NUM_BITS);
39+
assert(0 <= m_bit && m_bit < 32 && m_bit < VERSIONBITS_NUM_BITS);
4040
}
4141

4242
bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { return Condition(pindex->nVersion); }
@@ -49,9 +49,10 @@ class TestConditionChecker : public AbstractThresholdConditionChecker
4949
int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, dummy_params, m_cache); }
5050
BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateStatisticsFor(pindexPrev, dummy_params); }
5151

52-
bool Condition(int64_t version) const
52+
bool Condition(int32_t version) const
5353
{
54-
return ((version >> m_bit) & 1) != 0 && (version & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS;
54+
uint32_t mask = ((uint32_t)1) << m_bit;
55+
return (((version & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (version & mask) != 0);
5556
}
5657

5758
bool Condition(const CBlockIndex* pindex) const { return Condition(pindex->nVersion); }
@@ -94,18 +95,20 @@ class Blocks
9495
}
9596
};
9697

98+
std::unique_ptr<const CChainParams> g_params;
99+
97100
void initialize()
98101
{
99-
SelectParams(CBaseChainParams::MAIN);
102+
// this is actually comparatively slow, so only do it once
103+
g_params = CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN);
104+
assert(g_params != nullptr);
100105
}
101-
} // namespace
102106

103-
constexpr uint32_t MAX_TIME = 4102444800; // 2100-01-01
107+
constexpr uint32_t MAX_START_TIME = 4102444800; // 2100-01-01
104108

105109
FUZZ_TARGET_INIT(versionbits, initialize)
106110
{
107-
const CChainParams& params = Params();
108-
111+
const CChainParams& params = *g_params;
109112
const int64_t interval = params.GetConsensus().nPowTargetSpacing;
110113
assert(interval > 1); // need to be able to halve it
111114
assert(interval < std::numeric_limits<int32_t>::max());
@@ -122,9 +125,9 @@ FUZZ_TARGET_INIT(versionbits, initialize)
122125

123126
// too many blocks at 10min each might cause uint32_t time to overflow if
124127
// block_start_time is at the end of the range above
125-
assert(std::numeric_limits<uint32_t>::max() - MAX_TIME > interval * max_blocks);
128+
assert(std::numeric_limits<uint32_t>::max() - MAX_START_TIME > interval * max_blocks);
126129

127-
const int64_t block_start_time = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(params.GenesisBlock().nTime, MAX_TIME);
130+
const int64_t block_start_time = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(params.GenesisBlock().nTime, MAX_START_TIME);
128131

129132
// what values for version will we use to signal / not signal?
130133
const int32_t ver_signal = fuzzed_data_provider.ConsumeIntegral<int32_t>();
@@ -173,8 +176,10 @@ FUZZ_TARGET_INIT(versionbits, initialize)
173176
if (checker.Condition(ver_nosignal)) return;
174177
if (ver_nosignal < 0) return;
175178

176-
// TOP_BITS should ensure version will be positive
179+
// TOP_BITS should ensure version will be positive and meet min
180+
// version requirement
177181
assert(ver_signal > 0);
182+
assert(ver_signal >= VERSIONBITS_LAST_OLD_BLOCK_VERSION);
178183

179184
// Now that we have chosen time and versions, setup to mine blocks
180185
Blocks blocks(block_start_time, interval, ver_signal, ver_nosignal);
@@ -203,7 +208,7 @@ FUZZ_TARGET_INIT(versionbits, initialize)
203208
}
204209

205210
// don't risk exceeding max_blocks or times may wrap around
206-
if (blocks.size() + period*2 > max_blocks) break;
211+
if (blocks.size() + 2 * period > max_blocks) break;
207212
}
208213
// NOTE: fuzzed_data_provider may be fully consumed at this point and should not be used further
209214

@@ -316,7 +321,7 @@ FUZZ_TARGET_INIT(versionbits, initialize)
316321
assert(false);
317322
}
318323

319-
if (blocks.size() >= max_periods * period) {
324+
if (blocks.size() >= period * max_periods) {
320325
// we chose the timeout (and block times) so that by the time we have this many blocks it's all over
321326
assert(state == ThresholdState::ACTIVE || state == ThresholdState::FAILED);
322327
}
@@ -343,3 +348,4 @@ FUZZ_TARGET_INIT(versionbits, initialize)
343348
}
344349
}
345350
}
351+
} // namespace

0 commit comments

Comments
 (0)