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

Code before:
    static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
    g_setup = testing_setup.get();
}

PartiallyDownloadedBlock::CheckBlockFn FuzzedCheckBlock(std::optional<BlockValidationResult> result)
{
    return [result](const CBlock&, BlockValidationState& state, const Consensus::Params&, bool, bool) {
        if (result) {
            return state.Invalid(*result);
        }

        return true;
    };
}

FUZZ_TARGET(partially_downloaded_block, .init = initialize_pdb)
{
    FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};

    auto block{ConsumeDeserializable<CBlock>(fuzzed_data_provider, TX_WITH_WITNESS)};
    if (!block || block->vtx.size() == 0 ||
        block->vtx.size() >= std::numeric_limits<uint16_t>::max()) {
        return;
    }

    CBlockHeaderAndShortTxIDs cmpctblock{*block};

    bilingual_str error;
    CTxMemPool pool{MemPoolOptionsForTest(g_setup->m_node), error};
    Assert(error.empty());
    PartiallyDownloadedBlock pdb{&pool};

    // Set of available transactions (mempool or extra_txn)
    std::set<uint16_t> available;
    // The coinbase is always available
    available.insert(0);

    std::vector<CTransactionRef> extra_txn;
    for (size_t i = 1; i < block->vtx.size(); ++i) {
        auto tx{block->vtx[i]};

        bool add_to_extra_txn{fuzzed_data_provider.ConsumeBool()};
        bool add_to_mempool{fuzzed_data_provider.ConsumeBool()};

        if (add_to_extra_txn) {
            extra_txn.emplace_back(tx);
            available.insert(i);
        }

        if (add_to_mempool && !pool.exists(GenTxid::Txid(tx->GetHash()))) {
            LOCK2(cs_main, pool.cs);

Review comment (suggestion):
No need for the actual rng, we can just consume the nonce from the fuzz data.

```suggestion
    CBlockHeaderAndShortTxIDs cmpctblock{*block, fuzzed_data_provider.ConsumeIntegral<uint64_t>()};
```

Code after:
}

PartiallyDownloadedBlock::CheckBlockFn FuzzedCheckBlock(std::optional<BlockValidationResult> result)
{
    return [result](const CBlock&, BlockValidationState& state, const Consensus::Params&, bool, bool) {
        if (result) {
            return state.Invalid(*result);
        }

        return true;
    };
}

FUZZ_TARGET(partially_downloaded_block, .init = initialize_pdb)
{
    FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};

    auto block{ConsumeDeserializable<CBlock>(fuzzed_data_provider, TX_WITH_WITNESS)};
    if (!block || block->vtx.size() == 0 ||
        block->vtx.size() >= std::numeric_limits<uint16_t>::max()) {
        return;
    }

    CBlockHeaderAndShortTxIDs cmpctblock{*block, fuzzed_data_provider.ConsumeIntegral<uint64_t>()};

    CTxMemPool pool{MemPoolOptionsForTest(g_setup->m_node)};
    PartiallyDownloadedBlock pdb{&pool};

    // Set of available transactions (mempool or extra_txn)
    std::set<uint16_t> available;
    // The coinbase is always available
    available.insert(0);

    std::vector<CTransactionRef> extra_txn;
    for (size_t i = 1; i < block->vtx.size(); ++i) {
        auto tx{block->vtx[i]};

        bool add_to_extra_txn{fuzzed_data_provider.ConsumeBool()};
        bool add_to_mempool{fuzzed_data_provider.ConsumeBool()};

        if (add_to_extra_txn) {
            extra_txn.emplace_back(tx);
            available.insert(i);
        }

        if (add_to_mempool && !pool.exists(GenTxid::Txid(tx->GetHash()))) {
            LOCK2(cs_main, pool.cs);
            pool.addUnchecked(ConsumeTxMemPoolEntry(fuzzed_data_provider, *tx));
            available.insert(i);
        }
    }