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

Code before:

void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time)
{
    // Nothing to do for non-address-relay peers
    if (!peer.m_addr_relay_enabled) return;

    LOCK(peer.m_addr_send_times_mutex);
    // Periodically advertise our local address to the peer.
    if (fListen && !m_chainman.IsInitialBlockDownload() &&
        peer.m_next_local_addr_send < current_time) {
        // If we've sent before, clear the bloom filter for the peer, so that our
        // self-announcement will actually go out.
        // This might be unnecessary if the bloom filter has already rolled
        // over since our last self-announcement, but there is only a small
        // bandwidth cost that we can incur by doing this (which happens
        // once a day on average).
        if (peer.m_next_local_addr_send != 0us) {
            peer.m_addr_known->reset();
        }
        if (std::optional<CService> local_service = GetLocalAddrForPeer(node)) {
            CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
            if (peer.m_next_local_addr_send == 0us) {
                // Send the initial self-announcement in its own message. This makes sure
                // rate-limiting with limited start-tokens doesn't ignore it if the first
                // message ends up containing multiple addresses.
                if (local_addr.IsValid() && IsAddrCompatible(peer, local_addr)) {
                    std::vector<CAddress> self_announcement{local_addr};
                    if (peer.m_wants_addrv2) {
                        MakeAndPushMessage(node, NetMsgType::ADDRV2, CAddress::V2_NETWORK(self_announcement));
                    } else {
                        MakeAndPushMessage(node, NetMsgType::ADDR, CAddress::V1_NETWORK(self_announcement));
                    }
             }
            } else {
                // All later self-announcements are sent together with the other addresses.
                PushAddress(peer, local_addr);
            }
        }
        peer.m_next_local_addr_send = current_time + m_rng.rand_exp_duration(AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
    }

    // We sent an `addr` message to this peer recently. Nothing more to do.
    if (current_time <= peer.m_next_addr_send) return;

    peer.m_next_addr_send = current_time + m_rng.rand_exp_duration(AVG_ADDRESS_BROADCAST_INTERVAL);

    if (!Assume(peer.m_addrs_to_send.size() <= MAX_ADDR_TO_SEND)) {
        // Should be impossible since we always check size before adding to
        // m_addrs_to_send. Recover by trimming the vector.
        peer.m_addrs_to_send.resize(MAX_ADDR_TO_SEND);
    }

Review comment (suggestion):
I think checking `IsAddrCompatible` here is enough because `GetLocalAddrForPeer` only returns a service when [`IsRoutable` is true](https://github.com/bitcoin/bitcoin/blob/baa554f7089d8ce8ecb11e78ae097c10bfa85d8d/src/net.cpp#L262) and this[ includes an `IsValid` check](https://github.com/bitcoin/bitcoin/blob/baa554f7089d8ce8ecb11e78ae097c10bfa85d8d/src/netaddress.cpp#L464).

Code after:

void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time)
{
    // Nothing to do for non-address-relay peers
    if (!peer.m_addr_relay_enabled) return;

    LOCK(peer.m_addr_send_times_mutex);
    // Periodically advertise our local address to the peer.
    if (fListen && !m_chainman.IsInitialBlockDownload() &&
        peer.m_next_local_addr_send < current_time) {
        // If we've sent before, clear the bloom filter for the peer, so that our
        // self-announcement will actually go out.
        // This might be unnecessary if the bloom filter has already rolled
        // over since our last self-announcement, but there is only a small
        // bandwidth cost that we can incur by doing this (which happens
        // once a day on average).
        if (peer.m_next_local_addr_send != 0us) {
            peer.m_addr_known->reset();
        }
        if (std::optional<CService> local_service = GetLocalAddrForPeer(node)) {
            CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
            if (peer.m_next_local_addr_send == 0us) {
                // Send the initial self-announcement in its own message. This makes sure
                // rate-limiting with limited start-tokens doesn't ignore it if the first
                // message ends up containing multiple addresses.
                if (IsAddrCompatible(peer, local_addr)) {
                    std::vector<CAddress> self_announcement{local_addr};
                    if (peer.m_wants_addrv2) {
                        MakeAndPushMessage(node, NetMsgType::ADDRV2, CAddress::V2_NETWORK(self_announcement));
                    } else {
                        MakeAndPushMessage(node, NetMsgType::ADDR, CAddress::V1_NETWORK(self_announcement));
                    }
                }
            } else {
                // All later self-announcements are sent together with the other addresses.
                PushAddress(peer, local_addr);
            }
        }
        peer.m_next_local_addr_send = current_time + m_rng.rand_exp_duration(AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
    }

    // We sent an `addr` message to this peer recently. Nothing more to do.
    if (current_time <= peer.m_next_addr_send) return;

    peer.m_next_addr_send = current_time + m_rng.rand_exp_duration(AVG_ADDRESS_BROADCAST_INTERVAL);

    if (!Assume(peer.m_addrs_to_send.size() <= MAX_ADDR_TO_SEND)) {
        // Should be impossible since we always check size before adding to
        // m_addrs_to_send. Recover by trimming the vector.
        peer.m_addrs_to_send.resize(MAX_ADDR_TO_SEND);
    }