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

Code before:
        SignatureData empty;
        BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL, empty));
        // Reuse same signature for other inputs
        // (they don't have to be valid for this test)
        for (unsigned int j = 1; j < tx.vin.size(); j++)
            tx.vin[j].scriptSig = tx.vin[0].scriptSig;

        BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), i));
    }

    // Test EraseOrphansFor:
    for (NodeId i = 0; i < 3; i++)
    {
        size_t sizeBefore = orphanage.CountOrphans();
        orphanage.EraseForPeer(i);
        BOOST_CHECK(orphanage.CountOrphans() < sizeBefore);
    }

    // Test LimitOrphanTxSize() function:
    FastRandomContext rng{/*fDeterministic=*/true};
    orphanage.LimitOrphans(40, rng);
    BOOST_CHECK(orphanage.CountOrphans() <= 40);
    orphanage.LimitOrphans(10, rng);
    BOOST_CHECK(orphanage.CountOrphans() <= 10);
    orphanage.LimitOrphans(0, rng);
    BOOST_CHECK(orphanage.CountOrphans() == 0);
}

BOOST_AUTO_TEST_CASE(same_txid_diff_witness)
{
    FastRandomContext det_rand{true};
    TxOrphanage orphanage;
    NodeId peer{0};

    std::vector<COutPoint> empty_outpoints;
    auto parent = MakeTransactionSpending(empty_outpoints, det_rand);

    // Create children to go into orphanage.
    auto child_normal = MakeTransactionSpending({{parent->GetHash(), 0}}, det_rand);
    auto child_mutated = MakeMutation(child_normal);

    const auto& normal_wtxid = child_normal->GetWitnessHash();
    const auto& mutated_wtxid = child_mutated->GetWitnessHash();
    BOOST_CHECK(normal_wtxid != mutated_wtxid);

    BOOST_CHECK(orphanage.AddTx(child_normal, peer));
    // EraseTx fails as transaction by this wtxid doesn't exist.
    BOOST_CHECK_EQUAL(orphanage.EraseTx(mutated_wtxid), 0);
    BOOST_CHECK(orphanage.HaveTx(normal_wtxid));
    BOOST_CHECK(!orphanage.HaveTx(mutated_wtxid));


Review comment (suggestion):
nit: just update the value beforehand?
```suggestion
        expected_num_orphans -= 2;
        BOOST_CHECK(orphanage.CountOrphans() == expected_num_orphans);
```

Code after:
        {
            tx.vin[j].prevout.n = j;
            tx.vin[j].prevout.hash = txPrev->GetHash();
        }
        SignatureData empty;
        BOOST_CHECK(SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL, empty));
        // Reuse same signature for other inputs
        // (they don't have to be valid for this test)
        for (unsigned int j = 1; j < tx.vin.size(); j++)
            tx.vin[j].scriptSig = tx.vin[0].scriptSig;

        BOOST_CHECK(!orphanage.AddTx(MakeTransactionRef(tx), i));
    }

    size_t expected_num_orphans = orphanage.CountOrphans();

    // Non-existent peer; nothing should be deleted
    orphanage.EraseForPeer(/*peer=*/-1);
    BOOST_CHECK_EQUAL(orphanage.CountOrphans(), expected_num_orphans);

    // Each of first three peers stored
    // two transactions each.
    for (NodeId i = 0; i < 3; i++)
    {
        orphanage.EraseForPeer(i);
        expected_num_orphans -= 2;
        BOOST_CHECK(orphanage.CountOrphans() == expected_num_orphans);
    }

    // Test LimitOrphanTxSize() function, nothing should timeout:
    FastRandomContext rng{/*fDeterministic=*/true};
    orphanage.LimitOrphans(/*max_orphans=*/expected_num_orphans, rng);
    BOOST_CHECK_EQUAL(orphanage.CountOrphans(), expected_num_orphans);
    expected_num_orphans -= 1;
    orphanage.LimitOrphans(/*max_orphans=*/expected_num_orphans, rng);
    BOOST_CHECK_EQUAL(orphanage.CountOrphans(), expected_num_orphans);
    assert(expected_num_orphans > 40);
    orphanage.LimitOrphans(40, rng);
    BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 40);
    orphanage.LimitOrphans(10, rng);
    BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 10);
    orphanage.LimitOrphans(0, rng);
    BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 0);

    // Add one more orphan, check timeout logic
    auto timeout_tx = MakeTransactionSpending(/*outpoints=*/{}, rng);
    orphanage.AddTx(timeout_tx, 0);
    orphanage.LimitOrphans(1, rng);
    BOOST_CHECK_EQUAL(orphanage.CountOrphans(), 1);

    // One second shy of expiration