Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2009-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef BITCOIN_TEST_FUZZ_UTIL_H6#define BITCOIN_TEST_FUZZ_UTIL_H8#include <addresstype.h>9#include <arith_uint256.h>10#include <coins.h>11#include <compat/compat.h>12#include <consensus/amount.h>13#include <consensus/consensus.h>14#include <key.h>15#include <merkleblock.h>16#include <pow.h>17#include <primitives/transaction.h>18#include <script/script.h>19#include <serialize.h>20#include <streams.h>21#include <test/fuzz/FuzzedDataProvider.h>22#include <test/fuzz/fuzz.h>23#include <uint256.h>24#include <validation.h>26#include <algorithm>27#include <array>28#include <cstdint>29#include <cstdio>30#include <optional>31#include <string>32#include <vector>34class PeerManager;36template <typename... Callables>37size_t CallOneOf(FuzzedDataProvider& fuzzed_data_provider, Callables... callables)38{39constexpr size_t call_size{sizeof...(callables)};40static_assert(call_size >= 1);41const size_t call_index{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, call_size - 1)};43size_t i{0};44((i++ == call_index ? callables() : void()), ...);45return call_size;46}48template <typename Collection>49auto PickIterator(FuzzedDataProvider& fuzzed_data_provider, Collection& col)50{51const auto sz{col.size()};52assert(sz >= 1);53return std::next(col.begin(), fuzzed_data_provider.ConsumeIntegralInRange<decltype(sz)>(0, sz - 1));54}56template <typename Collection>57auto& PickValue(FuzzedDataProvider& fuzzed_data_provider, Collection& col)58{59return *PickIterator(fuzzed_data_provider, col);60}62template<typename B = uint8_t>63[[nodiscard]] inline std::vector<B> ConsumeRandomLengthByteVector(FuzzedDataProvider& fuzzed_data_provider, const std::optional<size_t>& max_length = std::nullopt) noexcept64{65static_assert(sizeof(B) == 1);66const std::string s = max_length ?67fuzzed_data_provider.ConsumeRandomLengthString(*max_length) :68fuzzed_data_provider.ConsumeRandomLengthString();69std::vector<B> ret(s.size());70std::copy(s.begin(), s.end(), reinterpret_cast<char*>(ret.data()));71return ret;72}74[[nodiscard]] inline DataStream ConsumeDataStream(FuzzedDataProvider& fuzzed_data_provider, const std::optional<size_t>& max_length = std::nullopt) noexcept75{76return DataStream{ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length)};77}79[[nodiscard]] inline std::vector<std::string> ConsumeRandomLengthStringVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16, const size_t max_string_length = 16) noexcept80{81const size_t n_elements = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);82std::vector<std::string> r;83r.reserve(n_elements);84for (size_t i = 0; i < n_elements; ++i) {85r.push_back(fuzzed_data_provider.ConsumeRandomLengthString(max_string_length));86}87return r;88}90template <typename T>91[[nodiscard]] inline std::vector<T> ConsumeRandomLengthIntegralVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16) noexcept92{93const size_t n_elements = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, max_vector_size);94std::vector<T> r;95r.reserve(n_elements);96for (size_t i = 0; i < n_elements; ++i) {97r.push_back(fuzzed_data_provider.ConsumeIntegral<T>());98}99return r;100}102template <typename P>103[[nodiscard]] P ConsumeDeserializationParams(FuzzedDataProvider& fuzzed_data_provider) noexcept;105template <typename T, typename P>106[[nodiscard]] std::optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_data_provider, const P& params, const std::optional<size_t>& max_length = std::nullopt) noexcept107{108const std::vector<uint8_t> buffer{ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length)};109SpanReader ds{buffer};110T obj;111try {112ds >> params(obj);113} catch (const std::ios_base::failure&) {114return std::nullopt;115}116return obj;117}119template <typename T>120[[nodiscard]] inline std::optional<T> ConsumeDeserializable(FuzzedDataProvider& fuzzed_data_provider, const std::optional<size_t>& max_length = std::nullopt) noexcept121{122const std::vector<uint8_t> buffer = ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length);123SpanReader ds{buffer};124T obj;125try {126ds >> obj;127} catch (const std::ios_base::failure&) {128return std::nullopt;129}130return obj;131}133template <typename T>134[[nodiscard]] inline std::optional<T> ConsumeDeserializableConstructor(FuzzedDataProvider& fuzzed_data_provider, const std::optional<size_t>& max_length = std::nullopt) noexcept135{136const std::vector<uint8_t> buffer = ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length);137SpanReader ds{buffer};138try {139T obj(deserialize, ds);140return obj;141} catch (const std::ios_base::failure&) {142return std::nullopt;143}144}146template <typename WeakEnumType, size_t size>147[[nodiscard]] WeakEnumType ConsumeWeakEnum(FuzzedDataProvider& fuzzed_data_provider, const WeakEnumType (&all_types)[size]) noexcept148{149return fuzzed_data_provider.ConsumeBool() ?150fuzzed_data_provider.PickValueInArray<WeakEnumType>(all_types) :151WeakEnumType(fuzzed_data_provider.ConsumeIntegral<std::underlying_type_t<WeakEnumType>>());152}154[[nodiscard]] inline opcodetype ConsumeOpcodeType(FuzzedDataProvider& fuzzed_data_provider) noexcept155{156return static_cast<opcodetype>(fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, MAX_OPCODE));157}159[[nodiscard]] CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider, const std::optional<CAmount>& max = std::nullopt) noexcept;161[[nodiscard]] NodeSeconds ConsumeTime(FuzzedDataProvider& fuzzed_data_provider, const std::optional<int64_t>& min = std::nullopt, const std::optional<int64_t>& max = std::nullopt) noexcept;163template <class Dur>164// Having the compiler infer the template argument from the function argument165// is dangerous, because the desired return value generally has a different166// type than the function argument. So std::common_type is used to force the167// call site to specify the type of the return value.168[[nodiscard]] Dur ConsumeDuration(FuzzedDataProvider& fuzzed_data_provider, std::common_type_t<Dur> min, std::common_type_t<Dur> max) noexcept169{170return Dur{fuzzed_data_provider.ConsumeIntegralInRange(min.count(), max.count())};171}173[[nodiscard]] CMutableTransaction ConsumeTransaction(FuzzedDataProvider& fuzzed_data_provider, const std::optional<std::vector<Txid>>& prevout_txids, int max_num_in = 10, int max_num_out = 10) noexcept;175[[nodiscard]] CScriptWitness ConsumeScriptWitness(FuzzedDataProvider& fuzzed_data_provider, size_t max_stack_elem_size = 32) noexcept;177[[nodiscard]] CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider, bool maybe_p2wsh = false) noexcept;179[[nodiscard]] uint32_t ConsumeSequence(FuzzedDataProvider& fuzzed_data_provider) noexcept;181[[nodiscard]] inline CScriptNum ConsumeScriptNum(FuzzedDataProvider& fuzzed_data_provider) noexcept182{183return CScriptNum{fuzzed_data_provider.ConsumeIntegral<int64_t>()};184}186[[nodiscard]] inline uint160 ConsumeUInt160(FuzzedDataProvider& fuzzed_data_provider) noexcept187{188const std::vector<uint8_t> v160 = fuzzed_data_provider.ConsumeBytes<uint8_t>(160 / 8);189if (v160.size() != 160 / 8) {190return {};191}192return uint160{v160};193}195[[nodiscard]] inline uint256 ConsumeUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept196{197const std::vector<uint8_t> v256 = fuzzed_data_provider.ConsumeBytes<uint8_t>(256 / 8);198if (v256.size() != 256 / 8) {199return {};200}201return uint256{v256};202}204[[nodiscard]] inline arith_uint256 ConsumeArithUInt256(FuzzedDataProvider& fuzzed_data_provider) noexcept205{206return UintToArith256(ConsumeUInt256(fuzzed_data_provider));207}209[[nodiscard]] inline arith_uint256 ConsumeArithUInt256InRange(FuzzedDataProvider& fuzzed_data_provider, const arith_uint256& min, const arith_uint256& max) noexcept210{211assert(min <= max);212const arith_uint256 range = max - min;213const arith_uint256 value = ConsumeArithUInt256(fuzzed_data_provider);214arith_uint256 result = value;215// Avoid division by 0, in case range + 1 results in overflow.216if (range != ~arith_uint256(0)) {217const arith_uint256 quotient = value / (range + 1);218result = value - (quotient * (range + 1));219}220result += min;221assert(result >= min && result <= max);222return result;223}225[[nodiscard]] std::map<COutPoint, Coin> ConsumeCoins(FuzzedDataProvider& fuzzed_data_provider) noexcept;227[[nodiscard]] CTxDestination ConsumeTxDestination(FuzzedDataProvider& fuzzed_data_provider) noexcept;229[[nodiscard]] CKey ConsumePrivateKey(FuzzedDataProvider& fuzzed_data_provider, std::optional<bool> compressed = std::nullopt) noexcept;231template <typename T>232[[nodiscard]] bool MultiplicationOverflow(const T i, const T j) noexcept233{234static_assert(std::is_integral_v<T>, "Integral required.");235if (std::numeric_limits<T>::is_signed) {236if (i > 0) {237if (j > 0) {238return i > (std::numeric_limits<T>::max() / j);239} else {240return j < (std::numeric_limits<T>::min() / i);241}242} else {243if (j > 0) {244return i < (std::numeric_limits<T>::min() / j);245} else {246return i != 0 && (j < (std::numeric_limits<T>::max() / i));247}248}249} else {250return j != 0 && i > std::numeric_limits<T>::max() / j;
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.