0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-01 09:35:52 -05:00

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`.
This commit is contained in:
marcofleon 2024-08-13 11:42:59 +01:00
parent a3f6f5acd8
commit a0eaa4749f
4 changed files with 14 additions and 2 deletions

View file

@ -134,7 +134,18 @@ bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t heig
return true; return true;
} }
// Bypasses the actual proof of work check during fuzz testing with a simplified validation checking whether
// the most signficant bit of the last byte of the hash is set.
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params) bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
{
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
return (hash.data()[31] & 0x80) == 0;
#else
return CheckProofOfWorkImpl(hash, nBits, params);
#endif
}
bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Params& params)
{ {
bool fNegative; bool fNegative;
bool fOverflow; bool fOverflow;

View file

@ -19,6 +19,7 @@ unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nF
/** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */
bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&); bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
bool CheckProofOfWorkImpl(uint256 hash, unsigned int nBits, const Consensus::Params&);
/** /**
* Return false if the proof-of-work requirement specified by new_nbits at a * Return false if the proof-of-work requirement specified by new_nbits at a

View file

@ -69,7 +69,7 @@ FUZZ_TARGET(integer, .init = initialize_integer)
const bool b = fuzzed_data_provider.ConsumeBool(); const bool b = fuzzed_data_provider.ConsumeBool();
const Consensus::Params& consensus_params = Params().GetConsensus(); const Consensus::Params& consensus_params = Params().GetConsensus();
(void)CheckProofOfWork(u256, u32, consensus_params); (void)CheckProofOfWorkImpl(u256, u32, consensus_params);
if (u64 <= MAX_MONEY) { if (u64 <= MAX_MONEY) {
const uint64_t compressed_money_amount = CompressAmount(u64); const uint64_t compressed_money_amount = CompressAmount(u64);
assert(u64 == DecompressAmount(compressed_money_amount)); assert(u64 == DecompressAmount(compressed_money_amount));

View file

@ -80,7 +80,7 @@ FUZZ_TARGET(pow, .init = initialize_pow)
{ {
const std::optional<uint256> hash = ConsumeDeserializable<uint256>(fuzzed_data_provider); const std::optional<uint256> hash = ConsumeDeserializable<uint256>(fuzzed_data_provider);
if (hash) { if (hash) {
(void)CheckProofOfWork(*hash, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), consensus_params); (void)CheckProofOfWorkImpl(*hash, fuzzed_data_provider.ConsumeIntegral<unsigned int>(), consensus_params);
} }
} }
} }