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

Code before:
    std::vector<CAddress> vAddr = addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt);

    size_t percent23 = (addrman->Size() * 23) / 100;
    BOOST_CHECK_EQUAL(vAddr.size(), percent23);
    BOOST_CHECK_EQUAL(vAddr.size(), 461U);
    // (addrman.Size() < number of addresses added) due to address collisions.
    BOOST_CHECK_EQUAL(addrman->Size(), 2006U);
}

BOOST_AUTO_TEST_CASE(getaddr_unfiltered)
{
    auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));

    // Set time on this addr so isTerrible = false
    CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
    addr1.nTime = Now<NodeSeconds>();
    // Not setting time so this addr should be isTerrible = true
    CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);

    CNetAddr source = ResolveIP("250.1.2.1");
    BOOST_CHECK(addrman->Add({addr1, addr2}, source));

    // Filtered GetAddr should only return addr1
    BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 1U);
    // Unfiltered GetAddr should return addr1 and addr2
    BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt, /*filtered=*/false).size(), 2U);
}

BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket_legacy)
{
    CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
    CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);

    CNetAddr source1 = ResolveIP("250.1.1.1");


    AddrInfo info1 = AddrInfo(addr1, source1);

    uint256 nKey1 = (HashWriter{} << 1).GetHash();
    uint256 nKey2 = (HashWriter{} << 2).GetHash();

    BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN), 40);

    // Test: Make sure key actually randomizes bucket placement. A fail on
    //  this test could be a security issue.
    BOOST_CHECK(info1.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN) != info1.GetTriedBucket(nKey2, EMPTY_NETGROUPMAN));

    // Test: Two addresses with same IP but different ports can map to
    //  different buckets because they have different keys.
    AddrInfo info2 = AddrInfo(addr2, source1);


Review comment (bug):
The time setting here seems to be critical and could be commented.  It looks like the threshold between success and failure is between `60s` and `61s`. Is that the case for you as well, and could you explain here why? (I apologize, but it's not clear to me.)

Code after:
    std::vector<CAddress> vAddr = addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt);

    size_t percent23 = (addrman->Size() * 23) / 100;
    BOOST_CHECK_EQUAL(vAddr.size(), percent23);
    BOOST_CHECK_EQUAL(vAddr.size(), 461U);
    // (addrman.Size() < number of addresses added) due to address collisions.
    BOOST_CHECK_EQUAL(addrman->Size(), 2006U);
}

BOOST_AUTO_TEST_CASE(getaddr_unfiltered)
{
    auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));

    // Set time on this addr so isTerrible = false
    CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
    addr1.nTime = Now<NodeSeconds>();
    // Not setting time so this addr should be isTerrible = true
    CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);

    CNetAddr source = ResolveIP("250.1.2.1");
    BOOST_CHECK(addrman->Add({addr1, addr2}, source));

    // Set time on this addr so isTerrible = false
    CAddress addr3 = CAddress(ResolveService("250.251.2.3", 9998), NODE_NONE);
    addr3.nTime = Now<NodeSeconds>();
    addrman->Good(addr3, /*time=*/Now<NodeSeconds>());
    BOOST_CHECK(addrman->Add({addr3}, source));
    // The time is set, but after ADDRMAN_RETRIES unsuccessful attempts not
    // retried in the last minute, this addr should be isTerrible = true
    for (size_t i = 0; i < 3; ++i) {
        addrman->Attempt(addr3, /*fCountFailure=*/true, /*time=*/Now<NodeSeconds>() - 61s);
    }

    // GetAddr filtered by quality (i.e. not IsTerrible) should only return addr1
    BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 1U);
    // Unfiltered GetAddr should return all addrs
    BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt, /*filtered=*/false).size(), 3U);
}

BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket_legacy)
{
    CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
    CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);

    CNetAddr source1 = ResolveIP("250.1.1.1");


    AddrInfo info1 = AddrInfo(addr1, source1);

    uint256 nKey1 = (HashWriter{} << 1).GetHash();
    uint256 nKey2 = (HashWriter{} << 2).GetHash();