Remove CNode dependency for local address functions and introduce LocalAddressManager #35040

pull theuni wants to merge 23 commits into bitcoin:master from theuni:addrlocal-refactor3 changing 23 files +421 −406
  1. theuni commented at 3:53 PM on April 9, 2026: member

    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 (via CNode) is removed.
    • LocalAddressManager is created in order to house the local network address functionality.
    • All functionality is still global in scope, though LocalAddressManager is 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 Peer rather than CNode as it is an artifact of the message layer, not the networking layer
    • Move the GetLocalAddrForPeer logic to PeerMan for the same reason.
    • Instantiate LocalAddressManager with options to avoid its use of globals where possible (fListen, fDiscover, fLogIPs).
    • Potentially remove g_localaddressman and store an instance in NodeContext instead.
    • From a quick glance, I think that fuzzing is currently broken because g_reachable_nets is not populated.

    Potential behavioral improvements

    • The (unchanged) logic in LocalAddressManager::Get uses 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::Get and GetLocalAddrForPeer is brittle and difficult to reason about.
  2. DrahtBot commented at 3:53 PM on April 9, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #34806 (refactor: logging: Various API improvements by ajtowns)
    • #34213 (net: preserve anchors when network is disabled by brunoerg)
    • #34028 (p2p: Prevent integer overflow in LocalServiceInfo::nScore by codeabysss)
    • #32394 (net: make m_nodes_mutex non-recursive by vasild)
    • #31260 (scripted-diff: Type-safe settings retrieval by ryanofsky)
    • #24230 (indexes: Stop using node internal types and locking cs_main, improve sync logic by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  3. net: rename variable to simplify review
    Otherwise all of the addr variables would start to blend together in subsequent
    commits.
    2be3875db7
  4. DrahtBot added the label Needs rebase on Apr 9, 2026
  5. theuni force-pushed on Apr 9, 2026
  6. net: Create IsPrivacyNetwork helper
    This will allow networks to be probed directly rather than requiring a valid
    CNetAddr.
    3ffd518cc6
  7. net: Don't require CNode for GetLocal
    Rather than using ConnectedThroughNetwork() and IsPrivacyNetwork() to determine
    whether this is an incoming Tor node, pass the connected-through network as a
    parameter instead.
    
    This is in preparation for moving the Local* functions to their own files.
    78c70f5c97
  8. net: Add tests for GetLocalAddress for inbound onion peers
    All nodes are changed to inbound for the tests, but it only matters for the
    onions.
    097b69f618
  9. net: have GetLocalAddress return an optional
    Rather than an invalid address to indicate failure
    a1a4c155db
  10. net: Don't require CNode for GetLocalAddress
    Similar to the previous change for GetLocal. Outside callers no longer have to
    use a CNode, so the tests have been simplified.
    98b291f8cb
  11. net: remove unnecessary AddLocal overload 1f64390a2e
  12. theuni force-pushed on Apr 9, 2026
  13. DrahtBot added the label CI failed on Apr 9, 2026
  14. DrahtBot commented at 4:32 PM on April 9, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task 32 bit ARM: https://github.com/bitcoin/bitcoin/actions/runs/24201296439/job/70645354883</sub> <sub>LLM reason (✨ experimental): CI failed due to a compilation error treated as fatal by -Werror: netaddress.h triggered -Werror=parentheses for return net == NET_ONION | net == NET_I2P;.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  15. DrahtBot removed the label Needs rebase on Apr 9, 2026
  16. fjahr commented at 6:35 PM on April 9, 2026: contributor

    Typo in title: "LocalAddressManger" :)

  17. theuni force-pushed on Apr 9, 2026
  18. theuni commented at 6:59 PM on April 9, 2026: member

    Typo in title: "LocalAddressManger" :)

    Clearly this was supposed to be LocalAddressMonger, peddler of the finest Local Addresses...

  19. theuni renamed this:
    Remove CNode dependency for local address functions and introduce LocalAddressManger
    Remove CNode dependency for local address functions and introduce LocalAddressManager
    on Apr 9, 2026
  20. theuni commented at 7:01 PM on April 9, 2026: member

    @maflcko I suspect you'll want to weigh in here on namespaces and/or file locations?

  21. theuni force-pushed on Apr 9, 2026
  22. maflcko commented at 8:51 PM on April 9, 2026: member

    @maflcko I suspect you'll want to weigh in here on namespaces and/or file locations?

    I think this one is easy: You are adding a new file to bitcoin_node lib, so it should be in the node folder, like the other p2p stuff, like node/eviction.cpp, or node/txorphanage.cpp.

  23. net: Move local address functions to a new file 317f80525f
  24. net: move GetnScore out of net a446c253be
  25. net: move getNetLocalAddresses out of net 7b73db35dc
  26. tests: Remove old test that doesn't test anything useful
    This test specificaly demonstrated the fix for a previously-undefined variable.
    It is not helpful for detecting new issues.
    1003a88878
  27. rpc: use local addresses from connman rather than accessing a global c1aeea1c04
  28. fuzz: avoid accessing mapLocalHost directly 00735ef1e6
  29. net: move mapLocalHost globals out of net and make them static d57ace41f0
  30. net: Create LocalAddressManager
    Move all local address related functions to a class and create a global
    instance of it. Make the global a unique_ptr so that in the future we can
    construct it with runtime-defined options at startup.
    
    Because usage in bitcoind is still global, this is mostly a no-op. But it
    allows for using non-global instances in tests.
    
    Note that the global class still access some other globals:
    fListen
    fDiscover
    fLogIPs
    g_reachable_nets
    
    These will be passed in to individual LocalAddressManager instances in the
    future.
    e8d0100697
  31. net: move mapLocalHost and its mutex to LocalAddressManager 282444f149
  32. net: Clean up log messages in LocalAddressManager f78c7ad341
  33. tests: Use instances of LocalAddressManager rather than global functions
    Because LocalAddressManager is scoped, per-instance removal happens
    automatically.
    bd29bc3990
  34. fuzz: use local instance of LocalAddressManager 9310e48b65
  35. net: Use global LocalAddressManager instance directly
    Also get rid of old forwarding functions.
    
    In the future, the global instance can be replaced with an instance held
    in NodeContext and passed to the subsystems which require it.
    a29a9aeda3
  36. net: Only require the necessary network class for LocalAddressManager functions
    Requiring CService or CAddress may lead callers to assume that the port or
    services are used in these functions.
    cb8f6b223b
  37. theuni force-pushed on Apr 9, 2026
  38. theuni commented at 7:20 PM on April 10, 2026: member

    The fix for the circular dependency problem here is non-trivial. Converting to draft while I investigate.

  39. theuni marked this as a draft on Apr 10, 2026
  40. FelipeNathansz commented at 5:09 PM on April 14, 2026: none

    This open attake quantize !!!!

  41. net: move GetReachabilityFrom to LocalAddressManager
    It is only used for determining which addresses can be advertised to a peer.
    24a168a4ba
  42. net: move globals from net.h to resolve circular dependency
    See comment in netglobals.h. This is a simple and temporary work-around for the
    circular dependency introduced by LocalAddressManager. These globals will be
    eliminated in a follow-up PR.
    dd8968cbd9
  43. theuni force-pushed on Apr 16, 2026
  44. bitcoin deleted a comment on Apr 16, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-18 15:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me