Repository: bitcoin/bitcoin
File: src/test/fuzz/util.cpp (C++)

Code before:
#include <util/check.h>
#include <util/overflow.h>
#include <util/rbf.h>
#include <util/time.h>

#include <memory>

std::vector<uint8_t> ConstructPubKeyBytes(FuzzedDataProvider& fuzzed_data_provider, std::span<const uint8_t> byte_data, const bool compressed) noexcept
{
    uint8_t pk_type;
    if (compressed) {
        pk_type = fuzzed_data_provider.PickValueInArray({0x02, 0x03});
    } else {
        pk_type = fuzzed_data_provider.PickValueInArray({0x04, 0x06, 0x07});
    }
    std::vector<uint8_t> pk_data{byte_data.begin(), byte_data.begin() + (compressed ? CPubKey::COMPRESSED_SIZE : CPubKey::SIZE)};
    pk_data[0] = pk_type;
    return pk_data;
}

CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider, const std::optional<CAmount>& max) noexcept
{
    return fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(0, max.value_or(MAX_MONEY));
}

NodeSeconds ConsumeTime(FuzzedDataProvider& fuzzed_data_provider, const std::optional<int64_t>& min, const std::optional<int64_t>& max) noexcept
{
    // Avoid t=0 (1970-01-01T00:00:00Z) since SetMockTime(0) disables mocktime.
    static const int64_t time_min{ParseISO8601DateTime("2000-01-01T00:00:01Z").value()};
    static const int64_t time_max{ParseISO8601DateTime("2100-12-31T23:59:59Z").value()};
    return NodeSeconds{std::chrono::seconds{fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(min.value_or(time_min), max.value_or(time_max))}};
}

std::chrono::seconds ConsumeDuration(FuzzedDataProvider& fuzzed_data_provider, std::chrono::seconds min, std::chrono::seconds max) noexcept
{
    return std::chrono::seconds{fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(min.count(), max.count())};
}

CMutableTransaction ConsumeTransaction(FuzzedDataProvider& fuzzed_data_provider, const std::optional<std::vector<Txid>>& prevout_txids, const int max_num_in, const int max_num_out) noexcept
{
    CMutableTransaction tx_mut;
    const auto p2wsh_op_true = fuzzed_data_provider.ConsumeBool();
    tx_mut.version = fuzzed_data_provider.ConsumeBool() ?
                          CTransaction::CURRENT_VERSION :
                          fuzzed_data_provider.ConsumeIntegral<uint32_t>();
    tx_mut.nLockTime = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
    const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, max_num_in);
    const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, max_num_out);
    for (int i = 0; i < num_in; ++i) {
        const auto& txid_prev = prevout_txids ?
                                    PickValue(fuzzed_data_provider, *prevout_txids) :

Review comment (suggestion):
Since the extra min/max parameters are rarely used, we could transition these to native chrono types, which would enable us using the new duration consumer here:
```C++
return NodeSeconds{ConsumeDuration(fuzzed_data_provider, min.value_or(time_min), max.value_or(time_max))};
```
or if we keep the types:
```C++
return NodeSeconds{ConsumeDuration(fuzzed_data_provider, min.value_or(time_min) * 1s, max.value_or(time_max) * 1s)};
```



Code after:
#include <util/check.h>
#include <util/overflow.h>
#include <util/rbf.h>
#include <util/time.h>

#include <memory>

std::vector<uint8_t> ConstructPubKeyBytes(FuzzedDataProvider& fuzzed_data_provider, std::span<const uint8_t> byte_data, const bool compressed) noexcept
{
    uint8_t pk_type;
    if (compressed) {
        pk_type = fuzzed_data_provider.PickValueInArray({0x02, 0x03});
    } else {
        pk_type = fuzzed_data_provider.PickValueInArray({0x04, 0x06, 0x07});
    }
    std::vector<uint8_t> pk_data{byte_data.begin(), byte_data.begin() + (compressed ? CPubKey::COMPRESSED_SIZE : CPubKey::SIZE)};
    pk_data[0] = pk_type;
    return pk_data;
}

CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider, const std::optional<CAmount>& max) noexcept
{
    return fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(0, max.value_or(MAX_MONEY));
}

NodeSeconds ConsumeTime(FuzzedDataProvider& fuzzed_data_provider, const std::optional<int64_t>& min, const std::optional<int64_t>& max) noexcept
{
    // Avoid t=0 (1970-01-01T00:00:00Z) since SetMockTime(0) disables mocktime.
    static const int64_t time_min{ParseISO8601DateTime("2000-01-01T00:00:01Z").value()};
    static const int64_t time_max{ParseISO8601DateTime("2100-12-31T23:59:59Z").value()};
    return NodeSeconds{ConsumeDuration(fuzzed_data_provider, min.value_or(time_min) * 1s, max.value_or(time_max) * 1s)};
}

std::chrono::seconds ConsumeDuration(FuzzedDataProvider& fuzzed_data_provider, std::chrono::seconds min, std::chrono::seconds max) noexcept
{
    return 1s * fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(min.count(), max.count());
}

CMutableTransaction ConsumeTransaction(FuzzedDataProvider& fuzzed_data_provider, const std::optional<std::vector<Txid>>& prevout_txids, const int max_num_in, const int max_num_out) noexcept
{
    CMutableTransaction tx_mut;
    const auto p2wsh_op_true = fuzzed_data_provider.ConsumeBool();
    tx_mut.version = fuzzed_data_provider.ConsumeBool() ?
                          CTransaction::CURRENT_VERSION :
                          fuzzed_data_provider.ConsumeIntegral<uint32_t>();
    tx_mut.nLockTime = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
    const auto num_in = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, max_num_in);
    const auto num_out = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, max_num_out);
    for (int i = 0; i < num_in; ++i) {
        const auto& txid_prev = prevout_txids ?
                                    PickValue(fuzzed_data_provider, *prevout_txids) :