This is part of the net/net_processing split project.
This PR does not change any current behavior, though it does highlight some areas for improvement.
Background
All of this trouble is necessary for a single purpose: advertising our own network address to peers. This currently happens in PeerManagerImpl::MaybeSendAddr.
In order to advertise our network address, we need to know what to advertise. We make our best guess based on these criteria (ordered from worst to best):
enum
{
LOCAL_NONE, // unknown
LOCAL_IF, // address a local interface listens on
LOCAL_BIND, // address explicit bound to
LOCAL_MAPPED, // address reported by PCP
LOCAL_MANUAL, // address explicitly specified (-externalip=)
LOCAL_MAX
};
Because we may have more than one publicly visible network address (ipv4, ipv6, tor, etc), we do our best to advertise an address to peers that they would be able to reach. This avoids (for example) disclosing our public ipv4 address to a node connected to our onion service. Accordingly, in order to determine the best address for a given peer which maybe have connected through a proxy, in addition to their address, the LocalAddressManager must also know the network through which they are connected.
We have one last source of data for what our public network address may be: each peer (as part of the version handshake) tells us what they think our address is. This is untrustworthy data, so it is not added to our list of possible addresses for consideration for other peers. We currently only consider advertising it back to a peer (in GetLocalAddrForPeer) if it is routable AND either we don't have a good guess OR randomly. The LocalAddressManager introduced in this PR is unrelated to that logic.
What's happening in this PR (and how to review)
- Because local address management is unrelated to
CConnman, its reliance on them (viaCNode) is removed. LocalAddressManageris created in order to house the local network address functionality.- All functionality is still global in scope, though
LocalAddressManageris now instantiated when possible for testing and fuzzing - There should be no behavioral changes
Reviewers should be able to verify that there are no behavioral changes, and that the handling of local address management is now contained and more straightforward.
Next steps
I stopped at this point because the changes, while straightforward and boring, have already added up. The main obvious change that remains is to remove the CNode dependency from GetLocalAddrForPeer.
Beyond that:
- Store addrLocal in
Peerrather thanCNodeas it is an artifact of the message layer, not the networking layer - Move the
GetLocalAddrForPeerlogic toPeerManfor the same reason. - Instantiate
LocalAddressManagerwith options to avoid its use of globals where possible (fListen,fDiscover,fLogIPs). - Potentially remove
g_localaddressmanand store an instance inNodeContextinstead. - From a quick glance, I think that fuzzing is currently broken because
g_reachable_netsis not populated.
Potential behavioral improvements
- The (unchanged) logic in
LocalAddressManager::Getuses a peer's IP and the network through which they're connected to decide which of our addresses to advertise. This address doesn't have much meaning when the peer is connected through an outbound proxy or is inbound via tor. - Only advertise an address to a peer of the same network through which they're connected to us. OR codify and add tests for what the exceptions should be. The current logic in
LocalAddressManager::GetandGetLocalAddrForPeeris brittle and difficult to reason about.