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

Code before:
    if (!pinfo)
        return;

    AddrInfo& info = *pinfo;

    // update info
    info.m_last_try = time;
    if (fCountFailure && info.m_last_count_attempt < m_last_good) {
        info.m_last_count_attempt = time;
        info.nAttempts++;
    }
}

std::pair<CAddress, NodeSeconds> AddrManImpl::Select_(bool new_only, std::optional<Network> network) const
{
    AssertLockHeld(cs);

    if (vRandom.empty()) return {};

    size_t new_count = nNew;
    size_t tried_count = nTried;

    if (network.has_value()) {
        auto it = m_network_counts.find(*network);
        if (it == m_network_counts.end()) return {};

        auto counts = it->second;
        new_count = counts.n_new;
        tried_count = counts.n_tried;
    }

    if (new_only && new_count == 0) return {};
    if (new_count + tried_count == 0) return {};

    // Decide if we are going to search the new or tried table
    // If either option is viable, use a 50% chance to choose
    bool search_tried;
    if (new_only || tried_count == 0) {
        search_tried = false;
    } else if (new_count == 0) {
        search_tried = true;
    } else {
        search_tried = insecure_rand.randbool();
    }

    const int bucket_count{search_tried ? ADDRMAN_TRIED_BUCKET_COUNT : ADDRMAN_NEW_BUCKET_COUNT};

    // Loop through the addrman table until we find an appropriate entry
    double chance_factor = 1.0;
    while (1) {
        // Pick a bucket, and an initial position in that bucket.

Review comment (suggestion):
This should be `continue;`? If addrman has 0 addresses from some of the requested networks, it can still return an address from another requested network.

```suggestion
            if (it == m_network_counts.end()) {
                continue;
            }
```

Code after:
    if (!pinfo)
        return;

    AddrInfo& info = *pinfo;

    // update info
    info.m_last_try = time;
    if (fCountFailure && info.m_last_count_attempt < m_last_good) {
        info.m_last_count_attempt = time;
        info.nAttempts++;
    }
}

std::pair<CAddress, NodeSeconds> AddrManImpl::Select_(bool new_only, const std::unordered_set<Network>& networks) const
{
    AssertLockHeld(cs);

    if (vRandom.empty()) return {};

    size_t new_count = nNew;
    size_t tried_count = nTried;

    if (!networks.empty()) {
        new_count = 0;
        tried_count = 0;
        for (auto& network : networks) {
            auto it = m_network_counts.find(network);
            if (it == m_network_counts.end()) {
                continue;
            }
            auto counts = it->second;
            new_count += counts.n_new;
            tried_count += counts.n_tried;
        }
    }

    if (new_only && new_count == 0) return {};
    if (new_count + tried_count == 0) return {};

    // Decide if we are going to search the new or tried table
    // If either option is viable, use a 50% chance to choose
    bool search_tried;
    if (new_only || tried_count == 0) {
        search_tried = false;
    } else if (new_count == 0) {
        search_tried = true;
    } else {
        search_tried = insecure_rand.randbool();
    }

    const int bucket_count{search_tried ? ADDRMAN_TRIED_BUCKET_COUNT : ADDRMAN_NEW_BUCKET_COUNT};