init: Handle dropped UPnP support more gracefully #31916

pull laanwj wants to merge 1 commits into bitcoin:master from laanwj:2025-02-upnp-setting-upgrade changing 1 files +26 −6
  1. laanwj commented at 4:08 pm on February 20, 2025: member

    Closes bitcoin-core/gui#843.

    In that issue it was brought up that users likely don’t care what kind of port forwarding is used, and that the setting is opportunistic anyway, so instead of showing an extensive warning, we can simply “upgrade” from UPNP to NAT-PMP+PCP.

    • Change the logic for removed runtime setting -upnp to set -natpmp instead, and log a message.

    • Also remove any lingering upnp from settings.json and replace it with natpmp, when it makes sense (this is important so that the UI shows the right values in the settings):

    0{
    1    "upnp": true
    2}
    

    becomes

    0{
    1    "natpmp": true
    2}
    

    and

    0{
    1    "upnp": false
    2}
    

    becomes

    0{
    1    "natpmp": false
    2}
    
  2. DrahtBot commented at 4:08 pm on February 20, 2025: contributor

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

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31916.

    Reviews

    See the guideline for information on the review process.

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #31974 (Drop testnet3 by Sjors)
    • #31649 (consensus: Remove checkpoints (take 2) by marcofleon)
    • #31260 (scripted-diff: Type-safe settings retrieval 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.

  3. in src/init.cpp:799 in bd4679a608 outdated
    792@@ -793,6 +793,31 @@ void InitParameterInteraction(ArgsManager& args)
    793             LogInfo("parameter interaction: -onlynet excludes IPv4 and IPv6 -> setting -dnsseed=0\n");
    794         }
    795     }
    796+
    797+    // We drop UPnP support but kept the arg as hidden for now to display a friendlier error to user who have the
    798+    // option in their config, and upgrade the setting to -natpmp. TODO: remove for version 30.0.
    799+    if (args.IsArgSet("-upnp")) {
    


    maflcko commented at 4:19 pm on February 20, 2025:

    Is this the right check to turn on natpmp? IIUC IsArgSet will return true even when the value is negated (-noupnp)?

    A fix could be to call args.SoftSetBoolArg("-natpmp", args.GetBoolArg("-upnp", false)) below?


    laanwj commented at 4:31 pm on February 20, 2025:
    Good catch, this is the wrong check. For the settings.json case i did consider the “is set” and “is set to true” case differently but consider them the same here.

    maflcko commented at 4:39 pm on February 20, 2025:

    I haven’t tried to compile, but the modern way of my suggestion would be:

    0    if (const auto arg{args.GetBoolArg("-upnp")}) {
    1        bool overridden = args.SoftSetBoolArg("-natpmp", *arg);
    

    laanwj commented at 8:17 am on February 21, 2025:

    Thank you!

    -upnp=0 setting the default for -natpmp to false sounds like reasonable behavior.

  4. hebasto added this to the milestone 29.0 on Feb 20, 2025
  5. achow101 requested review from davidgumberg on Feb 20, 2025
  6. achow101 requested review from jarolrod on Feb 20, 2025
  7. in src/init.cpp:808 in bd4679a608 outdated
    803+    }
    804+
    805+    // If dynamic settings are enabled, also replace it in settings.json.
    806+    fs::path path;
    807+    if (args.GetSettingsPath(&path, /* temp= */ false)) {
    808+        common::SettingsValue value = args.GetPersistentSetting("upnp");
    


    davidgumberg commented at 9:33 pm on February 20, 2025:
    Slightly surprisingly to me, GetPersistentSetting() gets values from bitcoin.conf, so if you set upnp=1 in bitcoin.conf, the branch below is executed, even if there’s no upnp setting in settings.json. Maybe this is intended, but in that case if (value.isTrue) below fails, so natpmp does not get enabled, despite the warning that gets logged.

    laanwj commented at 8:04 am on February 21, 2025:
    No, that’s not intended. i’ll look into a way to query the json only.

    Sjors commented at 9:00 am on February 21, 2025:
    Why would value.isTrue fail? I suspect what will happen (still have to test) is that you’ll keep upnp=1 in the config and also have natpmp: 1 in settings. If the former is ignored and the latter used, that should be fine.

    Sjors commented at 9:22 am on February 21, 2025:

    value.isTrue is indeed false when I set upnp=1 in bitcoin.conf, very strange.

    Another strange thing is that this code appears to be run twice, so I’m seeing the log entries twice.


    Sjors commented at 9:36 am on February 21, 2025:
    Aha, !value.IsBool() for upnp=1

    laanwj commented at 9:49 am on February 21, 2025:
    The real problem here is that GetPersistentSetting also looks into the (non-mutable) configuration file. i’ll add a flag to skip that and this should work as intended.

    laanwj commented at 10:18 am on February 21, 2025:
    Alternatively it could directly check the value and if necessary manipulate settings.rw_settings, inside the LockSettings lock. This also keeps it atomic (not that we care here). But it also gives the clearest code (super clear that this should only affect the dynamic settings) and doesn’t need API changes.
  8. davidgumberg commented at 9:33 pm on February 20, 2025: contributor

    Concept ACK

    I agree with the motivation that most users don’t “care about what method of automatic port forwarding method is used.” (https://github.com/bitcoin-core/gui/issues/843#issuecomment-2671668235)

    I think it is a little bit unfortunate that there might be some users of the GUI who don’t check the release notes or debug.log whose networks did support UPnP but don’t support NAT-PMP or PCP will never be warned that their port forwarding setup is broken, but I think the negatives of exposing UPnP deprecation to GUI users outweighs the benefits.1

    Sanity tested by enabling UPnP in bitcoin-qt v28.1.0 on a fresh datadir created the following settings.json

    0{
    1    "_warning_": "This file is automatically generated and updated by Bitcoin Core. Please do not edit this file while the node is running, as any changes might be ignored or overwritten.",
    2    "upnp": true
    3}
    

    Launching bitcoin-qt built with https://github.com/bitcoin/bitcoin/pull/31916/commits/bd4679a608b2cbc206fa60a180b0fc4ce8a39ec4 modified settings.json as described:

    0{
    1    "_warning_": "This file is automatically generated and updated by Bitcoin Core. Please do not edit this file while the node is running, as any changes might be ignored or overwritten.",
    2    "natpmp": true
    3}
    

    and the setting is displayed correctly in the settings tab.

    Screenshot from 2025-02-20 12-24-39


    1. Maybe a better and more general solution to that class of problem that is outside the scope of this PR and the issue it resolves is to provide some kind of indication to users about whether or not their node is reachable, maybe using a heuristic like node uptime > 1 hour, outbound slots filled, 0 inbound connections. ↩︎

  9. laanwj commented at 8:00 am on February 21, 2025: member

    I think it is a little bit unfortunate that there might be some users of the GUI who don’t check the release notes or debug.log whose networks did support UPnP but don’t support NAT-PMP or PCP will never be warned that their port forwarding setup is broken

    Maybe a better and more general solution to that class of problem that is outside the scope of this PR and the issue it resolves is to provide some kind of indication to users about whether or not their node is reachable, maybe using a heuristic like node uptime > 1 hour, outbound slots filled, 0 inbound connections.

    Exactly. The point @ryanofsky made in bitcoin-core/gui#843 is that there is, overall, no feedback wheher port forwarding is working. It could be broken in many other ways without warning (that’s what i meant with “oppertunistic”). If we had an icon in the GUI that showed the current port forwarding status (or as you say, whether there are incoming connections), this would be solved too. But that’s something for a future PR.

  10. maflcko commented at 8:14 am on February 21, 2025: member

    If we had an icon in the GUI that showed the current port forwarding status (or as you say, whether there are incoming connections), this would be solved too. But that’s something for a future PR.

    IIRC I designed the “connections” icon so that it shows 3 “arms” when there are 8 connections, thus likely no incoming ones. Though, this probably broke with block-relay-only connections and it now shows always 4 “arms”. One could address that, to have that approximation again, but as you say it would be a separate PR (I’d be happy to review).

  11. Sjors commented at 8:41 am on February 21, 2025: member
    I remember the arms feature being very useful for exactly that reason, but haven’t tried recently.
  12. in src/init.cpp:813 in bd4679a608 outdated
    792@@ -793,6 +793,31 @@ void InitParameterInteraction(ArgsManager& args)
    793             LogInfo("parameter interaction: -onlynet excludes IPv4 and IPv6 -> setting -dnsseed=0\n");
    794         }
    795     }
    796+
    797+    // We drop UPnP support but kept the arg as hidden for now to display a friendlier error to user who have the
    798+    // option in their config, and upgrade the setting to -natpmp. TODO: remove for version 30.0.
    


    Sjors commented at 8:51 am on February 21, 2025:
    We might want to wait longer, because people can upgrade many years later (e.g. because they suddenly remember they have a wallet). Maybe just drop the TODO.

    laanwj commented at 9:43 am on February 21, 2025:

    Probably not a good place to have this discussion.

    But i also don’t think TODOs in comments make much sense in general, planning should happen on github and not in the code repository, so will remove it.


    maflcko commented at 11:55 am on February 21, 2025:
    If the goal is to enable natpmp by default, then the TODO: remove for version 30.0. can be replaced by This can be removed when the default value for natpmp is true. ?

    laanwj commented at 5:40 pm on February 22, 2025:
    Yes, that would be another resolution that makes sense, not 100% sure what -upnp=0 should do in that case, Should that still set the default for -natpmp to 0? This is something to discuss seperately, i’ve just removed the TODO.
  13. in src/init.cpp:810 in bd4679a608 outdated
    805+    // If dynamic settings are enabled, also replace it in settings.json.
    806+    fs::path path;
    807+    if (args.GetSettingsPath(&path, /* temp= */ false)) {
    808+        common::SettingsValue value = args.GetPersistentSetting("upnp");
    809+        if (!value.isNull()) {
    810+            LogWarning("Option '-upnp' has a value in settings.json, replacing it with `-natpmp`");
    


    Sjors commented at 9:10 am on February 21, 2025:

    in bitcoin.conf or settings.json, replacing it with -natpmp in settings.json

    When it’s in bitcoin.conf the warning will get repeated every startup, which seems fine.


    laanwj commented at 9:40 am on February 21, 2025:
    Yup. That’s intentional. The first warning can happen as many times as needed, the json manipulation should ideally only happen once. Oh, i misread. No this one shouldn’t be happening every time.
  14. Sjors commented at 9:52 am on February 21, 2025: member

    The following works correctly for me on macOS when either setting upnp=1 in bitcoin.conf or "upnp": true, in settings.json.

     0diff --git a/src/init.cpp b/src/init.cpp
     1index ca708085d8..5ecbd6bc20 100644
     2--- a/src/init.cpp
     3+++ b/src/init.cpp
     4@@ -807,10 +807,10 @@ void InitParameterInteraction(ArgsManager& args)
     5     if (args.GetSettingsPath(&path, /* temp= */ false)) {
     6         common::SettingsValue value = args.GetPersistentSetting("upnp");
     7         if (!value.isNull()) {
     8-            LogWarning("Option '-upnp' has a value in settings.json, replacing it with `-natpmp`");
     9+            LogWarning("Option '-upnp' has a value in bitcoin.conf or settings.json, replacing it with '-natpmp' in settings.json");
    10             args.LockSettings([&](common::Settings& settings) {
    11                 settings.rw_settings.erase("upnp");
    12-                if (value.isTrue()) {
    13+                if ((value.isBool() && value.isTrue()) || (value.isStr() && value.get_str() == "1")) {
    14                     // Only set the natpmp setting if upnp was set.
    15                     settings.rw_settings["natpmp"] = UniValue(true);
    16                 }
    

    We can’t edit a bitcoin.conf file, so I don’t think there’s more we can do?

    Also when using noupnp=1 in bitcoin.conf this emits a log, but leaves natpmp off.

  15. laanwj commented at 9:59 am on February 21, 2025: member
    i’ll stop repeating it now, but that second if() for updating the JSON is not supposed to trigger at all if the value is in bitcoin.conf only and not in the json.
  16. Sjors commented at 11:21 am on February 21, 2025: member

    In #31916 (review)

    The real problem here is that GetPersistentSetting also looks into the (non-mutable) configuration file. i’ll add a flag to skip that and this should work as intended.

    I think that’s a useful flag, if only so we can distinguish the two cases.

    Though I’m confused about what you intend to happen for users who have upnp=1 in bitcoin.conf.

  17. laanwj commented at 11:47 am on February 21, 2025: member

    Though I’m confused about what you intend to happen for users who have upnp=1 in bitcoin.conf.

    The intent is to interpret -upnp=1 as -natpmp=1 and log a warning message. Both on the command line and in bitcoin.conf. Pretty much like the other parameter interaction. This is what the first if(args.IsArgSet("-upnp")) {...} does, or is supposed to do.

  18. Sjors commented at 12:44 pm on February 21, 2025: member

    That makes sense.

    I re-tested the bitcoin.conf behavior by disabling the GetPersistentSetting bit. It prints the right log message and enables PCP. However in the GUI options dialog the check box is unchecked. And there’s nothing in “options overriden by the command line”. So this might be confusing, although it works.

    In contrast, when I set natpmp=1 in bitcoin.conf the checkbox is marked.

  19. laanwj commented at 12:59 pm on February 21, 2025: member

    I re-tested the bitcoin.conf behavior by disabling the GetPersistentSetting bit. It prints the right log message and enables PCP. However in the GUI options dialog the check box is unchecked. And there’s nothing in “options overriden by the command line”. So this might be confusing, although it works.

    Yes that seems wrong, i’ll see if i find a way to get the checkbox correct without spurious “write-through of bitcoin.conf settings to settings.json” behavior.

  20. in src/init.cpp:821 in bd4679a608 outdated
    815+                    settings.rw_settings["natpmp"] = UniValue(true);
    816+                }
    817+            });
    818+            args.WriteSettingsFile();
    819+        }
    820+    }
    


    ryanofsky commented at 3:56 pm on February 21, 2025:

    In commit “init: Handle dropped UPnP support more gracefully” (bd4679a608b2cbc206fa60a180b0fc4ce8a39ec4)

    I think I might not understanding what this code is trying to do exactly, but it seems overcomplicated and maybe a little off. Like the check for GetSettingPath seems unnecessary, the LogWarning seems vague, the GetPersistentSetting calls not really checking for the right thing as mentioned in an earlier comment. Also the check for isTrue seems overly narrow and the UniValue(true) cast should be unnecessary. I would suggest following implementation:

     0    // If settings.json contains a "upnp" option, migrate it to use "natpmp" instead
     1    bool settings_changed{false}; // Whether settings.json file needs to be rewritten
     2    args.LockSettings([&](common::Settings& settings) {
     3        if (auto* upnp{FindKey(settings.rw_settings, "upnp")}) {
     4            if (!FindKey(settings.rw_settings, "natpmp")) {
     5                LogWarning(R"(Adding "natpmp": %s to settings.json to replace obsolete "upnp" setting)", upnp->write());
     6                settings.rw_settings["natpmp"] = *upnp;
     7            }
     8            LogWarning(R"(Removing obsolete "upnp" setting from settings.json)");
     9            settings.rw_settings.erase("upnp");
    10            settings_changed = true;
    11        }
    12    });
    13    if (settings_changed) args.WriteSettingsFile();
    

    with using common::FindKey at top of the file. This seems like the most simple and direct implementation and I think comments and log messages should be a little better too.


    laanwj commented at 4:21 pm on February 21, 2025:

    Like the check for GetSettingPath seems unnecessar

    WriteSettingsFile will raise an exception if that check fails, it seems to make a big point of “dynamic settings being enabled”.


    ryanofsky commented at 4:28 pm on February 21, 2025:

    WriteSettingsFile will raise an exception if that check fails, it seems to make a big point of “dynamic settings being enabled”.

    I think that is ok at least with code above because settings_changed will be false in that case.

  21. in src/init.cpp:821 in bd4679a608 outdated
    798+    // option in their config, and upgrade the setting to -natpmp. TODO: remove for version 30.0.
    799+    if (args.IsArgSet("-upnp")) {
    800+        bool overridden = args.SoftSetBoolArg("-natpmp", true);
    801+        LogWarning("Option '-upnp' is set but UPnP support was dropped in version 29.0.%s",
    802+                overridden ? " Setting '-natpmp' instead." : "");
    803+    }
    


    ryanofsky commented at 4:09 pm on February 21, 2025:

    In commit “init: Handle dropped UPnP support more gracefully” (bd4679a608b2cbc206fa60a180b0fc4ce8a39ec4)

    I think it would be better to move the settings.json update code before this code doing “if upnp then softset natpmp”. That way soft-setting natpmp only happens if -upnp is enabled in bitcoin.conf or on the command line, not if it is enabled in settings.json. So the separate cases will be handled independently and not interacting in a more complicated way.

  22. laanwj force-pushed on Feb 22, 2025
  23. laanwj force-pushed on Feb 22, 2025
  24. laanwj commented at 5:40 pm on February 22, 2025: member
    • Updated for @davidgumberg @maflcko @ryanofsky’s comments.

    • The checkbox mismatch mentioned by @Sjors is still open, but this seems a more general option handling issue, which applies to the other parameter interactions as well, and not addressable in the code changed here. It may be too risky to try to fix it here in this PR.

    • Added parameter value to the parameter interaction log message.

  25. laanwj force-pushed on Feb 23, 2025
  26. laanwj force-pushed on Feb 23, 2025
  27. laanwj added the label GUI on Feb 24, 2025
  28. laanwj added the label Settings on Feb 24, 2025
  29. in src/init.cpp:801 in 64de0a22db outdated
    792@@ -793,6 +793,32 @@ void InitParameterInteraction(ArgsManager& args)
    793             LogInfo("parameter interaction: -onlynet excludes IPv4 and IPv6 -> setting -dnsseed=0\n");
    794         }
    795     }
    796+
    797+    // If settings.json contains a "upnp" option, migrate it to use "natpmp" instead
    798+    bool settings_changed{false}; // Whether settings.json file needs to be rewritten
    799+    args.LockSettings([&](common::Settings& settings) {
    800+        if (auto* upnp{common::FindKey(settings.rw_settings, "upnp")}) {
    801+            if (!common::FindKey(settings.rw_settings, "natpmp")) {
    


    hodlinator commented at 2:20 pm on February 25, 2025:

    Could disambiguate between false/nullptr both for review and the compilers type check:

    0            if (common::FindKey(settings.rw_settings, "natpmp") == nullptr) {
    

    I know this is not performance critical, but could avoid duplicate lookups:

    0auto [_, inserted] = settings.rw_settings.try_emplace("natpmp", *upnp);
    1if (inserted) {
    2    LogWarning(R"(Added "natpmp": %s to settings.json to replace obsolete "upnp" setting)", upnp->write());
    3}
    
  30. in src/init.cpp:816 in 64de0a22db outdated
    811+
    812+    // We drop UPnP support but kept the arg as hidden for now to display a friendlier error to user who have the
    813+    // option in their config, and upgrade the setting to -natpmp.
    814+    if (const auto arg{args.GetBoolArg("-upnp")}) {
    815+        std::string message;
    816+        if (args.SoftSetBoolArg("-natpmp", *arg)) {
    


    hodlinator commented at 3:04 pm on February 25, 2025:
    Noticed there is some parameter interaction soft setting -natpmp to false when using a -proxy or !-listen. But the soft set here will not be allowed to re-enable it. :+1:

    laanwj commented at 12:29 pm on February 26, 2025:
    Yup, it shouldn’t ever override either explicit user preferences or other parameter interactions. Thanks for checking.
  31. Sjors commented at 9:03 pm on February 25, 2025: member

    Hopefully most GUI users at this point have the setting enabled without editing bitcoin.conf.

    It may be too risky to try to fix it here in this PR.

    Probably yes. Though the following would add it to the list of overridden options:

     0diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
     1index 5782a57a26..54ea8f9ee4 100644
     2--- a/src/qt/optionsmodel.cpp
     3+++ b/src/qt/optionsmodel.cpp
     4@@ -229,6 +229,13 @@ bool OptionsModel::Init(bilingual_str& error)
     5         }
     6     }
     7 
     8+    // UPnP support has been dropped and -upnp=1 is treated as -natpmp=1.
     9+    // However this leaves the GUI checkbox unset. Provide a hint to the user
    10+    // that they should check their config file.
    11+    if (gArgs.GetBoolArg("-upnp")) {
    12+        addOverriddenOption("-upnp");
    13+    }
    14+
    15     // If setting doesn't exist create it with defaults.
    

    That seems slightly better than having this functionality enabled without indication.

  32. darosior commented at 9:57 pm on February 25, 2025: member
    Concept ACK. WIll test soon.
  33. in src/init.cpp:812 in 64de0a22db outdated
    807+            settings_changed = true;
    808+        }
    809+    });
    810+    if (settings_changed) args.WriteSettingsFile();
    811+
    812+    // We drop UPnP support but kept the arg as hidden for now to display a friendlier error to user who have the
    


    hodlinator commented at 10:52 pm on February 25, 2025:

    Not sure if this comment is needed, the log message inside of the code block is enough IMO. Suggestions if kept:

    0    // We dropped UPnP support but kept the arg as hidden for now to display a friendlier error to user who has the
    

    laanwj commented at 12:34 pm on February 26, 2025:
    This comment was moved from the old site in AppInitParameterInteraction and i think it’s a little bit useful in describing why the code is there. Will update it.
  34. hodlinator commented at 11:27 pm on February 25, 2025: contributor

    Concept ACK 64de0a22dbd2eb72ff96d6dddb59abb2e22938b2

    Concept

    Good to help users migrate automatically, hopefully decreasing the number of nodes that drop off the public network due to UPnP-support being dropped in favor of more modern port forwarding protocols.

    PR description / commit message

    I think the prevention of nodes dropping off the public network-aspect could be called out.

    If this solution is acceptable i will add a functional test.

    This should be implemented or dropped. Not having a test isn’t a blocker for me, but the message without one is, and remains the only blocker for me, all other suggestions are (un)fortunately nits.

    “oppertunistic” typo remains in commit message.

    Testing

    Tested running 27.0 bitcoin-qt and enabled “Map port using UPnP”, leading to "upnp": true being written to settings.json. Confirmed it was replaced with "natpmp": true when running PR. (Repeated the same check successfully for false).

    Sjors’ suggestion to use addOverriddenOption("-upnp")

    Seems good, just want to to point out that the UI claims to be showing settings from the command line, when this one could be coming from bitcoin.conf.

    Screenshot From 2025-02-25 23-26-08

    (In a distant future we could use partially checked tristate-checkboxes to hint at bitcoin.conf/commandline having enabled a setting “by default”).

    Edit: Added public-qualifier.

  35. laanwj commented at 12:42 pm on February 26, 2025: member

    Probably yes. Though the following would add it to the list of overridden options: That seems slightly better than having this functionality enabled without indication.

    Thanks. Slightly better. From a user perspective, showing an option which isn’t documented as doing anything anymore might also be confusing. Would be better if it was marked as deprecated in some way, like in a different color or with [deprecated] after it. But would agree showing something is better than nothing.

    FWIW: The root cause of the bitcoin.conf checkbox mismatch is that SoftSetArg marks the option as Source::FORCED, which are ignored for common::GetSetting(ignore_nonpersistent=true). Even if the source of the migrated -upnp setting was the configuration file. That call is used to determine whether to consider the option set for the UI settings dialog.

    i guess one way to go about this would be to implement the migration differently, by considering forced_settings command_line_options ro_config (both global and per-network section) seperately, so that the source metadata is kept. However this will result in some complicated, and harder to reason about code. i think this is a rare enough case that doesn’t warrant going that far.

    Seems good, just want to to point out that the UI claims to be showing settings from the command line, when this one could be coming from bitcoin.conf.

    Yes, that’s also a potential source of confusion. Makes it a bit questionable thing to do.

    If this solution is acceptable i will add a functional test.

    This should be implemented or dropped. Not having a test isn’t a blocker for me, but the message without one is, > and remains the only blocker for me, all other suggestions are (un)fortunately nits.

    i have removed this. There seems to be a lot of time pressure, so it’s better to focus my attention on the code change itself than figuring out how to test some things from python.

  36. init: Handle dropped UPnP support more gracefully
    Closes bitcoin-core/gui#843.
    
    In that issue it was brought up that users likely don't care what kind
    of port forwarding is used, and the setting is opportunistic anyway, so
    instead of showing an extensive warning, we can simply migrate from
    UPNP to NAT-PMP+PCP. This prevents nodes dropping from the public
    network.
    
    - Change the logic for removed runtime setting `-upnp` to set `-natpmp`
      instead, and only log a message.
    
    - Also replace any lingering `upnp` in `settings.json` with `natpmp`.
    44041ae0ec
  37. laanwj force-pushed on Feb 26, 2025
  38. laanwj commented at 1:43 pm on February 26, 2025: member
    Force-push: addressed @hodlinator ’s comments.
  39. Sjors commented at 2:04 pm on February 26, 2025: member

    Seems good, just want to to point out that the UI claims to be showing settings from the command line, when this one could be coming from bitcoin.conf.

    Yes, that’s also a potential source of confusion. Makes it a bit questionable thing to do.

    I think most GUI users don’t start from the command line. And most users in general don’t care about the distinction between bitcoin.conf and command line arguments. I’m hoping this message triggers their memory of the last time they edited the config file.

    Another, more correct, solution could be to trigger an info / warning alert, either as a popup (annoying) or inline (like how we warn about testnet coins not having value).

  40. laanwj commented at 2:13 pm on February 26, 2025: member

    And most users in general don’t care about the distinction between bitcoin.conf and command line arguments

    Agree, but if the dialog mentions something specifically it would be more or less a lie.

    Another, more correct, solution could be to trigger an info / warning alert, either as a popup (annoying) or inline (like how we warn about testnet coins not having value).

    We just switched away from the warning popup here, we’re not bringing it back.

    A new inline alert in the options dialog would work, though! As this is more or less an orthogonal change (in the GUI code instead of init), this could be a new PR.

  41. ryanofsky approved
  42. ryanofsky commented at 2:15 pm on February 26, 2025: contributor
    Code review ACK 44041ae0eca9d2034b7c2bdef24724809cc35e90. Code changes look good. Could potentially add test coverage for this, though I don’t think it is too important.
  43. DrahtBot requested review from hodlinator on Feb 26, 2025
  44. DrahtBot requested review from darosior on Feb 26, 2025
  45. DrahtBot requested review from davidgumberg on Feb 26, 2025
  46. ryanofsky commented at 2:22 pm on February 26, 2025: contributor
    I’m a little confused by discussion above about options being overridden on the command line or configuration file, but maybe I need to think about it more. In general options being specified on command line should override GUI settings, but options specified in the GUI should override options specified in the config file.
  47. laanwj commented at 2:31 pm on February 26, 2025: member

    I’m a little confused by discussion above about options being overridden on the command line or configuration file, but maybe I need to think about it more. In general options being specified on command line should override GUI settings, but options specified in the GUI should override options specified in the config file.

    It’s all working as expected. The only thing is that the “Map port using PCP or NAT-PMP” checkbox isn’t checked (in the options dialog) when upnp=1 is specified in the configuration file.

    So for UI users, assuming they don’t check the logs, there is no feedback that NAT-PMP is in use, nor that there is a to-be-deprecated setting in bitcoin.conf.

    That said, UI users would generally change the UI setting and not edit the config file. The UI setting is migrated correctly and shown correctly after migration. So this problem is a bit of a rare edge-case, visual only, and if we decide to do any special-casing for it, i think it should be handled in a seperate GUI PR.

  48. ryanofsky commented at 3:05 pm on February 26, 2025: contributor

    The only thing is that the “Map port using PCP or NAT-PMP” checkbox isn’t checked (in the options dialog) when upnp=1 is specified in the configuration file.

    I see. Agree this is definitely an edge case. I think it could be fixed by replacing SoftSetBoolArg("-natpmp", *arg) with something like if (!IsArgSet("-natpmp") settings.ro_config[""]["natpmp"] = *upnp; but this might have other problems and current version does seem ok.

  49. laanwj commented at 3:15 pm on February 26, 2025: member

    with something like if (!IsArgSet("-natpmp") settings.rw_settings[""][“natpmp”] = *upnp; but this might have other problems and current version does seem ok.

    Doesn’t that make them saved options?

    Have thought about that when i started, but seems undesirable to have settings from the command line / config file “leak” into settings.json.

  50. ryanofsky commented at 4:41 pm on February 26, 2025: contributor

    Doesn’t that make them saved options?

    Sorry that was just a typo, that was supposed to say ro_config not rw_settings. Again though current approach seems ok. Only suggesting if we want to address issue of checkbox showing up as unchecked in this corner case.

  51. hodlinator approved
  52. hodlinator commented at 7:15 pm on February 26, 2025: contributor

    cr-ACK 44041ae0eca9d2034b7c2bdef24724809cc35e90

    Most significant aspect is that it migrates users/nodes who previously enabled UPnP in the GUI to now use the new NATPMP/PCP support. Without this those nodes would probably have little chance of accepting inbound connections (depending on their LAN setup), until the user realizes their node is behaving differently (if ever).

    Changes since previous review

    • Changed falsy condition to more specific nullptr-check.
    • Removed comment about possibly adding a test.
    • Other more minor text-only changes.
  53. darosior commented at 3:43 pm on February 28, 2025: member
    tACK 44041ae0eca9d2034b7c2bdef24724809cc35e90
  54. in src/init.cpp:810 in 44041ae0ec
    805+            LogWarning(R"(Removing obsolete "upnp" setting from settings.json)");
    806+            settings.rw_settings.erase("upnp");
    807+            settings_changed = true;
    808+        }
    809+    });
    810+    if (settings_changed) args.WriteSettingsFile();
    


    davidgumberg commented at 9:42 pm on March 3, 2025:
    Note: WriteSettingsFile() throws if the -nosettings argument is set, but in that case we would never find a value for upnp above, and settings_changed won’t be true, so that case is handled well.

    laanwj commented at 10:06 pm on March 3, 2025:
    Yes, i used to have an explicit check around this logic for dynamic settings to be enabled (so that it won’t throw), but removed it after a comment by @ryanofsky. It indeed doesn’t seem to be necessary because the dynamic settings won’t be populated in the first place.

    davidgumberg commented at 10:08 pm on March 3, 2025:
  55. DrahtBot requested review from davidgumberg on Mar 3, 2025
  56. davidgumberg commented at 10:14 pm on March 3, 2025: contributor

    lightly reviewed code, tested ACK https://github.com/bitcoin/bitcoin/commit/44041ae0eca9d2034b7c2bdef24724809cc35e90

    There are a lot of possible combinations of settings in bitcoin.conf, commandline arguments, and GUI settings, I sanity tested the happy path of upnp=true in settings.json, and a few cases I thought would be tricky with -nosettings and -upnp as a cli argument and in bitcoin.conf, and this solution handles them all well, and I can’t think of any unhandled cases from reviewing the code.

    To summarize my understanding of behavior after this PR:

    • If a upnp value was set in settings.json:1
      1. If no natpmp value was set then natpmp in settings.json is set equal to the value that exists for upnp, otherwise the natpmp setting is preserved.
      2. The upnp value is deleted from settings.json.
    • If a upnp value was set as an arg or in bitcoin.conf, -natpmp is soft-set2 to the value that was set for upnp.

    1. And -nosettings is not set to disable reading from settings.json ↩︎

    2. ArgsManager::SoftSetArg() won’t override an existing option, so explicit -natpmp settings are preserved. ↩︎

  57. achow101 assigned achow101 on Mar 4, 2025
  58. achow101 commented at 0:26 am on March 4, 2025: member
    ACK 44041ae0eca9d2034b7c2bdef24724809cc35e90
  59. achow101 merged this on Mar 4, 2025
  60. achow101 closed this on Mar 4, 2025


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: 2025-03-31 18:12 UTC

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