net: advertise -externalip addresses #34538

pull willcl-ark wants to merge 4 commits into bitcoin:master from willcl-ark:onlynet-advertisments changing 5 files +64 −7
  1. willcl-ark commented at 12:16 PM on February 9, 2026: member

    -onlynet is documented to restrict automatic outbound connections, but it also currently prevents -externalip addresses from being advertised when their network is not in the -onlynet set. This happens because AddLocal() rejects addresses outside g_reachable_nets, regardless of whether the address was explicitly configured by the user.

    Previous attempts to fix this (#24835 and #25690) removed the g_reachable_nets check from AddLocal().

    This PR instead adds an explicit add_even_if_unreachable argument to AddLocal(). The argument defaults to false, and is set to true only when adding addresses from -externalip.

    As a result, explicitly configured -externalip addresses can still be advertised even when their network is excluded by -onlynet, while discovered, mapped, bound, Tor control, and I2P SAM addresses continue to use the existing reachable-network filter.

    This keeps the fix scoped to -externalip and addresses the concern raised in #25690:

    I think it might also be weird for a user to activate -onlynet and keep on advertising their clearnet address to the network

    The branch adds unit coverage for AddLocal() and functional coverage in p2p_addr_selfannouncement.py for -onlynet=ipv4 -externalip=<onion>.

    Fixes: #25336 Fixes: #25669

  2. DrahtBot added the label P2P on Feb 9, 2026
  3. DrahtBot commented at 12:17 PM on February 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.

    Type Reviewers
    ACK vasild
    Concept ACK chriszeng1010
    Stale ACK seduless

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #35027 (net: use -bind address for outgoing connections by 8144225309)

    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-->

  4. willcl-ark commented at 12:18 PM on February 9, 2026: member

    cc @mzumsande @vasild

    I've taken a very slightly different approach at fixing this, and would value your opinion(s) on :)

  5. chriszeng1010 commented at 6:48 PM on March 2, 2026: none

    Tested ACK

    Built and rantest_bitcoin --run_test=net_testson Windows/MSYS2. New addlocal_onlynet_externalip test passes.

  6. in src/test/net_tests.cpp:1569 in 383763f9ee
    1564 | +    CAddress addr_onion;
    1565 | +    BOOST_REQUIRE(addr_onion.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"));
    1566 | +    BOOST_REQUIRE(addr_onion.IsValid());
    1567 | +    BOOST_REQUIRE(addr_onion.IsTor());
    1568 | +
    1569 | +    // Simulate using -onlynet=ipv4
    


    seduless commented at 3:57 AM on March 3, 2026:

    nit: This simulates -onlynet=ipv4 but doesn't replicate -externalip's side effect of setting fDiscover=false. With fDiscover left as true (the test default), only the g_reachable_nets gate is exercised. Adding fDiscover = false; here would catch a regression on the fDiscover gate too.


    willcl-ark commented at 10:03 AM on March 3, 2026:

    Thanks for the review. I agree, and have taken this suggestion in 6e73dcf700796146b33f3788b2ff7f659244f909

  7. seduless commented at 4:03 AM on March 3, 2026: contributor

    Tested ACK 383763f9ee3ca307c2b881f0fcf4de660073aa84

    Reproduced #25336 on regtest: started a node with -onlynet=ipv4 -externalip=<onion_address>, confirmed getnetworkinfo shows empty localaddresses on master. With the fix applied, the onion address appears at score 4.

    Traced all LOCAL_MANUAL callers and found no inconsistency with IsPeerAddrLocalGood.

  8. DrahtBot requested review from chriszeng1010 on Mar 3, 2026
  9. willcl-ark force-pushed on Mar 3, 2026
  10. seduless commented at 11:24 PM on March 3, 2026: contributor

    re-ACK 6e73dcf700796146b33f3788b2ff7f659244f909

  11. in src/test/net_tests.cpp:1584 in 6e73dcf700
    1579 | +    BOOST_CHECK(AddLocal(addr_onion, LOCAL_MANUAL));
    1580 | +    BOOST_CHECK(IsLocal(addr_onion));
    1581 | +
    1582 | +    RemoveLocal(addr_onion);
    1583 | +    g_reachable_nets.Add(NET_ONION);
    1584 | +    fDiscover = true;
    


    vasild commented at 11:09 AM on March 5, 2026:

    I guess this is an attempt to restore the global state to what it was at the beginning of the test. Here are more robust ways to that:

    For g_reachable_nets:

    ... test ...
    // Assumes that g_reachable_nets was in its default-constructed state at the start of the test.
    g_reachable_nets.Reset();
    

    or (no assumptions)

    const auto reachable_nets_at_start{g_reachable_nets.All()};
    ... test ...
    g_reachable_nets.RemoveAll();
    for (const auto& net : reachable_nets_at_start) {
        g_reachable_nets.Add(net);
    }
    

    For fDiscover:

    const bool discover_orig{fDiscover};
    ... test ...
    fDiscover = discover_orig;
    

    willcl-ark commented at 12:18 PM on March 5, 2026:

    Good point, thanks, I agree. I changed the test to restore both global states as you suggested, in e459f651c89

  12. vasild approved
  13. vasild commented at 11:27 AM on March 5, 2026: contributor

    ACK 6e73dcf700796146b33f3788b2ff7f659244f909

    Note that AddLocal(..., LOCAL_MANUAL) is called from 3 places:

    1. For addresses given to -externalip=..., the focus of this PR.
    2. For our listening Tor address that is automatically created with the Tor router when -listenonion=1. So this setup will be affected by this PR: -onlynet=ipv4 -listenonion=1. Before this PR we would not advertise the Tor address and now we will.
    3. For our listening I2P address that is created with the I2P SAM proxy when -i2psam=... -i2pacceptincoming=1 is used. Similarly to Tor this would affect -onlynet=ipv4 -i2psam=... -i2pacceptincoming=1.

    I think those 2. and 3. are welcomed changes. Maybe deserve a release note.

    Will resolve https://github.com/bitcoin/bitcoin/issues/25669

  14. willcl-ark force-pushed on Mar 5, 2026
  15. willcl-ark commented at 12:19 PM on March 5, 2026: member

    I think those 2. and 3. are welcomed changes. Maybe deserve a release note.

    😃 Release note added in 3c63971454722a9ab399d49b1195fdd640867e31

  16. vasild approved
  17. vasild commented at 12:33 PM on March 5, 2026: contributor

    ACK 3c63971454722a9ab399d49b1195fdd640867e31

  18. DrahtBot requested review from seduless on Mar 5, 2026
  19. vasild commented at 12:36 PM on March 5, 2026: contributor

    Might want to add "Fixes: #25669" to the OP.

  20. seduless commented at 2:58 AM on March 10, 2026: contributor

    re-ACK 3c63971454722a9ab399d49b1195fdd640867e31

  21. sedited removed review request from chriszeng1010 on Mar 19, 2026
  22. sedited requested review from ajtowns on Mar 19, 2026
  23. sedited removed review request from chriszeng1010 on Mar 19, 2026
  24. sedited requested review from ajtowns on Mar 19, 2026
  25. ajtowns commented at 9:36 AM on March 20, 2026: contributor

    Might be better to set a bit somewhere for -externalip addresses rather than reusing score? Otherwise it seems possible that setting up a private node and then having some controlled peers connect to it would result in the score eventually being bumped above the LOCAL_MANUAL level and you'd start unexpectedly advertising your ip automatically, which might be a footgun for some.

    The configuration and expected/implicit behaviours here seem very confusing and fragile in general here; eg I think this code is (or reads as-if it is) treating IsRoutable as "will packets sent to/from here have any chance of arriving?" while other parts of the code are using it as the -onlynet "should we make outbound connections to this part of the internet?"

  26. DrahtBot requested review from chriszeng1010 on Mar 20, 2026
  27. willcl-ark force-pushed on Mar 20, 2026
  28. DrahtBot added the label Needs rebase on Apr 9, 2026
  29. in src/net.cpp:277 in 7b28ef4149
     273 | @@ -274,7 +274,7 @@ void ClearLocal()
     274 |  }
     275 |  
     276 |  // learn a new local address
     277 | -bool AddLocal(const CService& addr_, int nScore)
     278 | +bool AddLocal(const CService& addr_, int nScore, bool fExternalIP)
    


    vasild commented at 1:58 PM on April 13, 2026:

    Naming, feel free to ignore:

    The linkage between this argument and the -externalip configuration option is only outside of the AddLocal() function. So, looking at the function alone and not its callers, the name fExternalIP is odd.

    From the point of view of the AddLocal() function, the meaning of its new argument is "ignore reachable nets" or "add even if unreachable". It is better to name it after that.

    This would show in the future if there is a new caller of AddLocal() who wants to pass true to "add even if unreachable" for a reason other than that the address comes from -externalip. Then the caller would have to use /*fExternalIP=*/true even if he has nothing to do with -externalip.


    willcl-ark commented at 11:16 AM on April 30, 2026:

    Thanks. I addressed both of your review points at once by renaming the new param to add_even_if_unreachable in b1874343f0cf2c90605bff448ab174f3ed7a169a

  30. in src/net.cpp:305 in 7b28ef4149
     301 | @@ -302,9 +302,9 @@ bool AddLocal(const CService& addr_, int nScore)
     302 |      return true;
     303 |  }
     304 |  
     305 | -bool AddLocal(const CNetAddr &addr, int nScore)
     306 | +bool AddLocal(const CNetAddr& addr, int nScore, bool fExternalIP)
    


    vasild commented at 2:01 PM on April 13, 2026:

    My understanding and preference is that we follow the naming convention regardless of surrounding code that might use the old convention. That is, name the new parameter external_ip instead of fExternalIP. Then, if you want, in another commit, for consistency rename nScore to score.

  31. vasild approved
  32. vasild commented at 2:02 PM on April 13, 2026: contributor

    ACK 7b28ef41495f57d5b8f3fa67d467c16b0660b331

    <details> <summary>Show Signature</summary>

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA256
    
    ACK 7b28ef41495f57d5b8f3fa67d467c16b0660b331
    -----BEGIN PGP SIGNATURE-----
    
    iQQzBAEBCAAdFiEE5k2NRWFNsHVF2czBVN8G9ktVy78FAmnc9GUACgkQVN8G9ktV
    y7+ZJh//Zu1zi8Nw9TRVdTs4570wepmtW+Q111PgjBnhtogGa06gn2Qp5ootOu71
    EILvuN4XUFj16UhQ25ZXGaFjmozGSVlWkG54Rr92wjOGxkb8jEXoLmtwgoUoEpWG
    n6eUEUYKJ3xuwwCCgAmJTJc8Rxa/AIMSC5Qok0h+2DcoF5ff/+T4SoB2vs5xJllA
    VtokRm0nQbjV/oq2MvFcWTcgS6M0nKKQmKNmWuEwG8Q5Is4vN/xergGvPN7VkeNu
    WCHAz6N7LnWMwU6sqSQBrOEvGWB32xxdqSnq0JoAL1ZCvhOJcZxXMSCrhNdri2FS
    VWnGBNc8VwJotnIfshu/rR/p+TU+C43j7HsfV9gj+Y4FG971T2fTOzEa4n8Zvc0h
    a5JqexmXgurZNnqas0qsgbv+KymW2KCFzua7zccG2/PdLKf29HGf/w8uGiFe86ZU
    h7fDfjshXDTzck85r3niEZXxPBDrpt1/HeDFwW4FfK5EANgQhdTAGKzxwE6AIPMf
    BV1yPWIUJNFqZzvkuG4GbitTbpCjM9bV5O+6X/5d54shFdvRG7z1WYorC7tyutbo
    CyAYXRkppCjjQkZ3i4c4TsVoYE0H+Qc9BS0cIen83Yi3/eyw9ViwZ5E37xf9+F36
    AiN1PbzcsrUSiFBk5FM1VlNohhMNr3N885rjIyBDc2QCeS5FZ4/jm7DD1ItOERaH
    uux8roTCoaKlRkq0o0yxG9HbC2sxnJs/fa+MaKttWDaSvyqUotCfOSLiEzPShfHU
    OQ8NUOot1NeD/FBXhta6njptHpsy5075WLpGpQPF/QKrFDOZPxl/GTjrgPo0I//o
    X2KFRlBDMTBhYiEK5Hx0clRjqWW/gN5kqjCS7zGgZH0Vada6ohwuu7X3f7kMyBfH
    HqchUK9cen5I2UNoOPjMt3tvYZwbWWteYL5J2bqgOjrohFihC8uf8eKvHMf0gwFV
    oO/D1nu3IfqI3UXbIEgy2p5j3hActfC8Fa71LrSf07f0rgrG6TY3PGf1csqFLxgL
    XI8cnJSY06F2kvQERTJ2gVBzSBuqeU7tz3jWe4BxOAZwrlVTLytxsQGpPS6QzgR6
    glyD9jURPaEfBdieAw78RWTb7VL4R2dy4LXqx2zotGXNsicdj5paUuRUimCV6GMP
    8bHJBcHClMFpFsPkBR+u8sNZji0p+umJKI8WJr+/PYQknZui6JmJRpLjbmydYe3h
    qpjU6H/Co4aqV6ch/j13O0C19WkrBAwlubPztevmAoHZhh3ugg344Iy8u8McFREa
    VSl+zGaeicGed5GnkhGxG8RBjdZMa0AI+MhEEFGvGgFUqjLLcoGdmHEMVzLUbV3L
    gB/T6GCym0hKjz6rT3gDUrhy7dsG8g==
    =Sl7e
    -----END PGP SIGNATURE-----
    

    vasild's public key is on openpgp.org

    </details>

  33. DrahtBot requested review from seduless on Apr 13, 2026
  34. net: plumb an explicit -externalip flag through AddLocal
    Prepare for letting `-externalip` bypass the reachable-net filter
    without tying that behavior to `LOCAL_MANUAL` score.
    
    Do that by passing an explicit `fExternalIP` bool through `AddLocal()`,
    without changing behavior.
    b1874343f0
  35. net: let -externalip bypass -onlynet
    When `-onlynet` excludes a network, `AddLocal()` rejects local addresses
    from that network. This also rejects addresses explicitly configured via
    `-externalip`, so a configuration like `-onlynet=ipv4`
    `-externalip=<onion>` never advertises the onion address.
    
    Now that `AddLocal()` accepts an explicit `fExternalIP` flag, use that
    to let only those addresses bypass the reachable-net filter.
    4938471d50
  36. test: cover -externalip bypassing -onlynet
    Add a unit test covering the `-onlynet`/`-externalip` interaction.
    
    Check that an unreachable address with `LOCAL_MANUAL` still fails, while
    the same address succeeds when marked as coming from `-externalip`.
    f3078e02aa
  37. test: cover -externalip bypassing -onlynet in functional test
    Extend p2p_addr_selfannouncement to restart the node with
    -onlynet=ipv4 -externalip=<onion> and verify the onion address
    appears in localaddresses despite its network being unreachable.
    d63f6a97bf
  38. willcl-ark force-pushed on Apr 30, 2026
  39. vasild approved
  40. vasild commented at 12:50 PM on April 30, 2026: contributor

    ACK d63f6a97bf1e16305c1044e8b0bd7dff015966ec

    <details> <summary>Show Signature</summary>

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA256
    
    ACK d63f6a97bf1e16305c1044e8b0bd7dff015966ec
    -----BEGIN PGP SIGNATURE-----
    
    iQQzBAEBCAAdFiEE5k2NRWFNsHVF2czBVN8G9ktVy78FAmnzUA0ACgkQVN8G9ktV
    y7++CB/+JRiXIJkDGHb7DTN7SI6Qo1Ru5J7YGYQ63wTSLSBoKK/gZw7W+T6ki38V
    Dz6rB3hCwfkwFIiF9UWxTeVEvrpvk9znJbZ2nAXxjaYmy+op9TjH0C1qcTFRCH0B
    Q/UxAVbivRIvZ/cFlaKHIBjwxvD5tFoAVczp8TKrdaFJLudt+z1MKxfWMXK4xuui
    q9g/4ox1Qt3OupGpFrfqMcZfqYcx5+aOJm0M5MhUFhCLumnZhrjlOtnlNeJK/2kR
    A+TSyaDi4NpZKyosR+O3DIyhWh72aUv+WbIWUZq/k3S4KJrkDdSwGdq+DTw54zxS
    DJ74L2G5R7IclyidHIV4niZpR15VkmpbqmefKJZrQTHgnxyDn3SYuRfixX6UqgC3
    c1x1kqLWNKaIS+D15VIXRIQ6C8HSiyX/+W1UqcYhyz3V8oq9wieKVrSusxdkuNYL
    fbpFIlGj08rcRFqYiqNo7EF6wceyQy6/XAZO8Gs65tUQtchYvCqIF0TbsFA2Avmf
    6fiW/tOgE8laq5/A4w8q6iRp89fNIBN8oCG1rJPyF5mnov8mp8ZJrpVAm/HZQWCN
    +UJu5zil9GmwDpMRY+pUhli9x4o62AJjwY+FTzeiBthSzvcAitbL/CYIxw3A+Hqc
    yQM3kJFo+tmdODudx47ytxIRhZQexZIE+t4PrK2id3GpD5/xmFiF9s1tJ8ceZ8H4
    481O7mD6VgcNBzMK58k9d1GpH/IoYJExi5lwb50SvdRQ0udBTg+Lqmg7plvNJaNA
    ZlAFtZ0hgctL57b/9lJ9h1g/WD8cjozTYCPJd1QFJtxU5o5/ohBnLKT8jdtCX4yQ
    eQFexxS4b6LVOGQlO92mKdSVAEoYI4LjxFski60lio52ODLt2Fq0dYgugiafRG0z
    ZLUuoBsN/AO7/D9IK5WSXIah6hLyAGUYFSoCG5vS+dyWkk532G52mtV/V9m4I16V
    ORgjmUygHNMafjHsUjcNYFCmV5esJ8MKGXQisVGq/KP1II1mFaeJUKeNBE36oPXC
    /Ai2ykCC5pJbqBHHnEm2ieHH5O6i2nazNul4MgKuuPj0wE8tmuAAtToXfDwcWSbc
    37QxgV+Xmm98Hksx/4t3hVEOoKkdEaa66a3l8XoUvhDB1c/pqsWTlbWpMt5fqDIc
    qoTVsTVeTAXhEWQNFYWD4+OXpG5GsO0lEABTB+vGtis4x06fhnNl9B/bBgUM5jNr
    NFeczGcsfs3V0BO2RAzIHg+7jes/KsjkdB6OpxVtRBNA2kN6Jct9sgUvY0HXPWIc
    2FBxhjJKKG0cepwooZ/5CTcmTOHHtavrxutuO4Ng3NbbekF6f0yFXwUSuuZ+kobq
    ySi4Pw6X1oNSGB/Ig+dD2HGChVUZow==
    =oZXa
    -----END PGP SIGNATURE-----
    

    vasild's public key is on openpgp.org

    </details>

  41. DrahtBot removed the label Needs rebase on Apr 30, 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-05-12 06:12 UTC

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