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

Code before:
                                std::inserter(missing_stage_cmp, missing_stage_cmp.end()),
                                std::greater{});
            assert(stage_cmp_diagram.size() + missing_stage_cmp.size() == stage_real_diagram.size());
            // The missing chunks must be equal across main & staging (otherwise they couldn't have
            // been omitted).
            assert(missing_main_cmp == missing_stage_cmp);

            // The missing part must include at least all transactions in staging which have not been
            // modified, or been in a cluster together with modified transactions, since they were
            // copied from main. Note that due to the reordering of removals w.r.t. dependency
            // additions, it is possible that the real implementation found more unaffected things.
            FeeFrac missing_real;
            for (const auto& feerate : missing_main_cmp) missing_real += feerate;
            FeeFrac missing_expected = sims[1].graph.FeeRate(sims[1].graph.Positions() - sims[1].modified);
            // Note that missing_real.fee < missing_expected.fee is possible to due the presence of
            // negative-fee transactions.
            assert(missing_real.size >= missing_expected.size);
        }
    }

    assert(real->HaveStaging() == (sims.size() > 1));

    // Try to run a full comparison, for both main_only=false and main_only=true in TxGraph
    // inspector functions that support both.
    for (int main_only = 0; main_only < 2; ++main_only) {
        auto& sim = main_only ? sims[0] : sims.back();
        // Compare simple properties of the graph with the simulation.
        assert(real->IsOversized(main_only) == sim.IsOversized());
        assert(real->GetTransactionCount(main_only) == sim.GetTransactionCount());
        // If the graph (and the simulation) are not oversized, perform a full comparison.
        if (!sim.IsOversized()) {
            auto todo = sim.graph.Positions();
            // Iterate over all connected components of the resulting (simulated) graph, each of which
            // should correspond to a cluster in the real one.
            while (todo.Any()) {
                auto component = sim.graph.FindConnectedComponent(todo);
                todo -= component;
                // Iterate over the transactions in that component.
                for (auto i : component) {
                    // Check its individual feerate against simulation.
                    assert(sim.graph.FeeRate(i) == real->GetIndividualFeerate(*sim.GetRef(i)));
                    // Check its ancestors against simulation.
                    auto expect_anc = sim.graph.Ancestors(i);
                    auto anc = sim.MakeSet(real->GetAncestors(*sim.GetRef(i), main_only));
                    assert(anc.Count() <= max_cluster_count);
                    assert(anc == expect_anc);
                    // Check its descendants against simulation.
                    auto expect_desc = sim.graph.Descendants(i);
                    auto desc = sim.MakeSet(real->GetDescendants(*sim.GetRef(i), main_only));
                    assert(desc.Count() <= max_cluster_count);
                    assert(desc == expect_desc);

Review comment (suggestion):
Can be written as:

```cpp
for (auto level : { TxGraph::Level::TOP, TxGraph::Level::MAIN }) {
```

Code after:
                                std::inserter(missing_stage_cmp, missing_stage_cmp.end()),
                                std::greater{});
            assert(stage_cmp_diagram.size() + missing_stage_cmp.size() == stage_real_diagram.size());
            // The missing chunks must be equal across main & staging (otherwise they couldn't have
            // been omitted).
            assert(missing_main_cmp == missing_stage_cmp);

            // The missing part must include at least all transactions in staging which have not been
            // modified, or been in a cluster together with modified transactions, since they were
            // copied from main. Note that due to the reordering of removals w.r.t. dependency
            // additions, it is possible that the real implementation found more unaffected things.
            FeeFrac missing_real;
            for (const auto& feerate : missing_main_cmp) missing_real += feerate;
            FeeFrac missing_expected = sims[1].graph.FeeRate(sims[1].graph.Positions() - sims[1].modified);
            // Note that missing_real.fee < missing_expected.fee is possible to due the presence of
            // negative-fee transactions.
            assert(missing_real.size >= missing_expected.size);
        }
    }

    assert(real->HaveStaging() == (sims.size() > 1));

    // Try to run a full comparison, for both TxGraph::Level::MAIN and TxGraph::Level::TOP in
    // TxGraph inspector functions that support both.
    for (auto level : {TxGraph::Level::TOP, TxGraph::Level::MAIN}) {
        auto& sim = level == TxGraph::Level::TOP ? sims.back() : sims.front();
        // Compare simple properties of the graph with the simulation.
        assert(real->IsOversized(level) == sim.IsOversized());
        assert(real->GetTransactionCount(level) == sim.GetTransactionCount());
        // If the graph (and the simulation) are not oversized, perform a full comparison.
        if (!sim.IsOversized()) {
            auto todo = sim.graph.Positions();
            // Iterate over all connected components of the resulting (simulated) graph, each of which
            // should correspond to a cluster in the real one.
            while (todo.Any()) {
                auto component = sim.graph.FindConnectedComponent(todo);
                todo -= component;
                // Iterate over the transactions in that component.
                for (auto i : component) {
                    // Check its individual feerate against simulation.
                    assert(sim.graph.FeeRate(i) == real->GetIndividualFeerate(*sim.GetRef(i)));
                    // Check its ancestors against simulation.
                    auto expect_anc = sim.graph.Ancestors(i);
                    auto anc = sim.MakeSet(real->GetAncestors(*sim.GetRef(i), level));
                    assert(anc.Count() <= max_cluster_count);
                    assert(anc == expect_anc);
                    // Check its descendants against simulation.
                    auto expect_desc = sim.graph.Descendants(i);
                    auto desc = sim.MakeSet(real->GetDescendants(*sim.GetRef(i), level));
                    assert(desc.Count() <= max_cluster_count);
                    assert(desc == expect_desc);