Skip to content

Commit a0eaa47

Browse files
committed
Add FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION in PoW check
To avoid PoW being a blocker for fuzz tests, `FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` is used in fuzz builds to bypass the actual PoW validation in `CheckProofOfWork`. It's replaced with a check on the last byte of the hash, which allows the fuzzer to quickly generate (in)valid blocks by checking a single bit, rather than performing the full PoW computation. If PoW is the target of a fuzz test, then it should call `CheckProofOfWorkImpl`.
1 parent a3f6f5a commit a0eaa47

File tree

4 files changed

+14
-2
lines changed

4 files changed

+14
-2
lines changed

src/pow.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,18 @@ bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t heig
134134
return true;
135135
}
136136

137+
// Bypasses the actual proof of work check during fuzz testing with a simplified validation checking whether
138+
// the most signficant bit of the last byte of the hash is set.
137139
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
140+
{
141+
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
142+
return (hash.data()[31] & 0x80) == 0;
143+
#else
144+
return CheckProofOfWorkImpl(hash, nBits, params);
145+
#endif
146+
}
147+
148+
bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Params& params)
138149
{
139150
bool fNegative;
140151
bool fOverflow;

src/pow.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
1919

2020
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
2121
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
22+
bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Params&);
2223

2324
/**
2425
* Return false if the proof-of-work requirement specified by new_nbits at a

src/test/fuzz/integer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ FUZZ_TARGET(integer, .init = initialize_integer)
6969
const bool b = fuzzed_data_provider.ConsumeBool();
7070

7171
const Consensus::Params& consensus_params = Params().GetConsensus();
72-
(void)CheckProofOfWork(u256, u32, consensus_params);
72+
(void)CheckProofOfWorkImpl(u256, u32, consensus_params);
7373
if (u64 <= MAX_MONEY) {
7474
const uint64_t compressed_money_amount = CompressAmount(u64);
7575
assert(u64 == DecompressAmount(compressed_money_amount));

src/test/fuzz/pow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ FUZZ_TARGET(pow, .init = initialize_pow)
8080
{
8181
const std::optional<uint256> hash = ConsumeDeserializable<uint256>(fuzzed_data_provider);
8282
if (hash) {
83-
(void)CheckProofOfWork(*hash, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), consensus_params);
83+
(void)CheckProofOfWorkImpl(*hash, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), consensus_params);
8484
}
8585
}
8686
}

0 commit comments

Comments
 (0)