interfaces: Expose settings.json methods to GUI #15936

pull ryanofsky wants to merge 3 commits into bitcoin:master from ryanofsky:pr/qtset changing 8 files +123 −17
  1. ryanofsky commented at 9:50 pm on May 1, 2019: member

    Add interfaces::Node updateSetting, forceSetting, resetSettings, isSettingIgnored, and getPersistentSetting methods so GUI is able to manipulate settings.json file and use and modify node settings.

    (Originally this PR also contained GUI changes to unify bitcoin-qt and bitcoind persistent settings and call these methods, but the GUI commits have been dropped from this PR and moved to bitcoin-core/gui/pull/602)

  2. DrahtBot added the label Build system on May 1, 2019
  3. DrahtBot added the label GUI on May 1, 2019
  4. DrahtBot added the label Tests on May 1, 2019
  5. DrahtBot added the label Utils/log/libs on May 1, 2019
  6. DrahtBot commented at 0:42 am on May 2, 2019: member

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

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #24479 (Bugfix: util: Correctly handle Number value types in GetArg/GetBoolArg by luke-jr)

    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.

  7. ryanofsky referenced this in commit f6a9cf0700 on May 3, 2019
  8. ryanofsky force-pushed on May 3, 2019
  9. ryanofsky referenced this in commit 39005eb09f on May 7, 2019
  10. ryanofsky force-pushed on May 7, 2019
  11. ryanofsky referenced this in commit 70675c3e49 on May 8, 2019
  12. ryanofsky force-pushed on May 8, 2019
  13. jonasschnelli commented at 10:23 am on May 18, 2019: contributor
    Concept ACK
  14. laanwj added the label Feature on Sep 30, 2019
  15. ryanofsky referenced this in commit 5873a9c6ce on Dec 3, 2019
  16. ryanofsky force-pushed on Dec 3, 2019
  17. ryanofsky commented at 2:31 am on December 4, 2019: member

    Travis compile error in https://travis-ci.org/bitcoin/bitcoin/jobs/620388014#L3988 seems to be due to a clang bug with macros and raw strings: https://reviews.llvm.org/D39279

    0qt/test/optiontests.cpp:56:100: warning: missing terminating '"' character [-Winvalid-pp-token]
    1)", "std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()).c_str()", "R\"({
    2                                                                                                   ^
    3qt/test/optiontests.cpp:56:100: error: expected expression
    

    Maybe can work around by adding parentheses, otherwise could declare temp variable.


    Other travis error https://travis-ci.org/bitcoin/bitcoin/jobs/620388019#L2929 seems like a qsettings int value gets stringified on mac (doesn’t happen on linux):

    Actual: "dbcache": "600", Expected: "dbcache": 600,

    It would probably be good to fix this by adding an explicit type argument to ToSetting instead of trying to guess the setting type from the variant type


    Rebased 0ab41dd770c1f13983df528b111cfc8a51fe016a -> 955f7c00a161d6477172fa9760d1b2b5626d1761 (pr/qtset.4 -> pr/qtset.5) after #15934 merge Rebased 955f7c00a161d6477172fa9760d1b2b5626d1761 -> 821268f1b8fedd3082c7e4872c2c03c35bc6f431 (pr/qtset.5 -> pr/qtset.6, compare) due to conflicts with #17473, #17696, #17453, and #18914 and with attempted fixes for travis errors above Updated 821268f1b8fedd3082c7e4872c2c03c35bc6f431 -> dc4da098498b910690b5ec3520c6d5446f08daf7 (pr/qtset.6 -> pr/qtset.7, compare) with travis and appveyor fixes for https://travis-ci.org/github/bitcoin/bitcoin/jobs/694791815#L2411 and https://ci.appveyor.com/project/DrahtBot/bitcoin/builds/33325125#L55 Rebased dc4da098498b910690b5ec3520c6d5446f08daf7 -> ccd6331bec926edee571045dc0f5b4d88a089244 (pr/qtset.7 -> pr/qtset.8, compare) due to conflict with #19233, on updated base pr #15935 pr/rwset.11 Rebased ccd6331bec926edee571045dc0f5b4d88a089244 -> 196f6661fc1938f862b6a2897e3ec66a25162698 (pr/qtset.8 -> pr/qtset.9, compare) on top of #15934 pr/rwset.13 Rebased 196f6661fc1938f862b6a2897e3ec66a25162698 -> 1b216f0ae333ccbe95be7c66967ec8c3d1765c1c (pr/qtset.9 -> pr/qtset.10, compare) after #19412 to fix TSAN feature_block timeout https://travis-ci.org/github/bitcoin/bitcoin/jobs/703174898 Rebased 1b216f0ae333ccbe95be7c66967ec8c3d1765c1c -> 9ad8ee9e41eb7660bb5f2e6c482171cd2ef9848d (pr/qtset.10 -> pr/qtset.11, compare) on top of #15935 pr/rwset.14 Rebased 9ad8ee9e41eb7660bb5f2e6c482171cd2ef9848d -> 8aa59dbd667883836fcdaad284fcd7f1fc1b4a7f (pr/qtset.11 -> pr/qtset.12, compare) after #15935 merge Rebased 8aa59dbd667883836fcdaad284fcd7f1fc1b4a7f -> 6634f860f1ff57dffc1c608f427398e95914b5dc (pr/qtset.12 -> pr/qtset.13, compare) due to conflict with https://github.com/bitcoin-core/gui/pull/35 Updated 6634f860f1ff57dffc1c608f427398e95914b5dc -> 1dd17b4f0ae97a756b4afd3fc5560dc86da92f17 (pr/qtset.13 -> pr/qtset.14, compare) fixing missing #include and silent conflict with #15937 Updated 1dd17b4f0ae97a756b4afd3fc5560dc86da92f17 -> 15f341691b801caf10d353cd84206b1397711071 (pr/qtset.14 -> pr/qtset.15, compare) fixing unit test error Rebased 15f341691b801caf10d353cd84206b1397711071 -> 66ab29d052e0fdb4e5771908f2a46fa753d0ecb1 (pr/qtset.15 -> pr/qtset.16, compare) due to conflicts with #18077, #20494, and #21531 Rebased 66ab29d052e0fdb4e5771908f2a46fa753d0ecb1 -> 9d4ff45ce5704a1e29bc328eb2d46d28c0f411e5 (pr/qtset.16 -> pr/qtset.17, compare) due to conflicts with #21727 and #21850 (silent) Rebased 9d4ff45ce5704a1e29bc328eb2d46d28c0f411e5 -> 46cef157aa50e1a5e25bfc8fc034a1151be57c93 (pr/qtset.17 -> pr/qtset.18, compare) due to conflict with bitcoin-core/gui#313 Updated 46cef157aa50e1a5e25bfc8fc034a1151be57c93 -> ca1c704ac2dd6ba8cec4b2c42912211449d1aab9 (pr/qtset.18 -> pr/qtset.19, compare) with a compile fix to fix the same conflict Rebased ca1c704ac2dd6ba8cec4b2c42912211449d1aab9 -> c026213dda41e834b9883760d4d6b313c12eb683 (pr/qtset.19 -> pr/qtset.20, compare) due to conflict with bitcoin-core/gui#4 Rebased c026213dda41e834b9883760d4d6b313c12eb683 -> 73b31c13d0ad6c6447a7ef43f275a163bf1a9c94 (pr/qtset.20 -> pr/qtset.21, compare) due to conflict with bitcoin-core/gui#390 Rebased 73b31c13d0ad6c6447a7ef43f275a163bf1a9c94 -> 17fcdf51ab570eb55b46a7c44a2a631739462612 (pr/qtset.21 -> pr/qtset.22, compare) due to conflict with #22219

  18. ryanofsky referenced this in commit 6c6846cd58 on Jun 4, 2020
  19. ryanofsky referenced this in commit 44849d047f on Jun 4, 2020
  20. ryanofsky referenced this in commit 73b489863e on Jun 4, 2020
  21. ryanofsky renamed this:
    WIP: Unify bitcoin-qt and bitcoind persistent settings
    Unify bitcoin-qt and bitcoind persistent settings
    on Jun 4, 2020
  22. ryanofsky force-pushed on Jun 4, 2020
  23. ryanofsky marked this as ready for review on Jun 4, 2020
  24. ryanofsky force-pushed on Jun 5, 2020
  25. ryanofsky referenced this in commit 14849d8b24 on Jun 5, 2020
  26. ryanofsky referenced this in commit eb966f421c on Jun 5, 2020
  27. DrahtBot added the label Needs rebase on Jun 10, 2020
  28. ryanofsky referenced this in commit 8f099645ac on Jun 11, 2020
  29. ryanofsky referenced this in commit c6e86083ce on Jun 11, 2020
  30. ryanofsky referenced this in commit 81c2e91ca9 on Jun 11, 2020
  31. ryanofsky force-pushed on Jun 11, 2020
  32. DrahtBot removed the label Needs rebase on Jun 11, 2020
  33. ryanofsky referenced this in commit 15b93eeea3 on Jun 16, 2020
  34. DrahtBot added the label Needs rebase on Jun 21, 2020
  35. achow101 referenced this in commit a891f82ae4 on Jun 22, 2020
  36. ryanofsky referenced this in commit 6ec69d5e65 on Jun 25, 2020
  37. ryanofsky referenced this in commit 3e4f2b2c28 on Jun 25, 2020
  38. ryanofsky referenced this in commit a91fdd7ae5 on Jun 25, 2020
  39. ryanofsky force-pushed on Jun 29, 2020
  40. DrahtBot removed the label Needs rebase on Jun 29, 2020
  41. achow101 referenced this in commit 5c9231c87a on Jul 6, 2020
  42. ryanofsky force-pushed on Jul 10, 2020
  43. DrahtBot added the label Needs rebase on Jul 11, 2020
  44. ryanofsky referenced this in commit dfe5964723 on Jul 11, 2020
  45. ryanofsky referenced this in commit a9ba460906 on Jul 11, 2020
  46. ryanofsky force-pushed on Jul 11, 2020
  47. DrahtBot removed the label Needs rebase on Jul 11, 2020
  48. ryanofsky referenced this in commit 7b129c849b on Jul 13, 2020
  49. ryanofsky referenced this in commit b25ed47202 on Jul 21, 2020
  50. ryanofsky referenced this in commit 9c69cfe4c5 on Jul 22, 2020
  51. MarcoFalke referenced this in commit f4cfa6d019 on Jul 23, 2020
  52. DrahtBot added the label Needs rebase on Jul 23, 2020
  53. sidhujag referenced this in commit bcd2ed79e3 on Jul 24, 2020
  54. ryanofsky force-pushed on Jul 30, 2020
  55. DrahtBot removed the label Needs rebase on Jul 30, 2020
  56. Warchant referenced this in commit 451c272143 on Aug 6, 2020
  57. DrahtBot added the label Needs rebase on Aug 26, 2020
  58. ryanofsky force-pushed on Aug 28, 2020
  59. DrahtBot removed the label Needs rebase on Aug 28, 2020
  60. ryanofsky force-pushed on Sep 1, 2020
  61. ryanofsky force-pushed on Sep 2, 2020
  62. DrahtBot added the label Needs rebase on Nov 19, 2020
  63. ryanofsky force-pushed on Apr 10, 2021
  64. DrahtBot removed the label Needs rebase on Apr 10, 2021
  65. DrahtBot added the label Needs rebase on May 5, 2021
  66. ryanofsky force-pushed on May 25, 2021
  67. DrahtBot removed the label Needs rebase on May 25, 2021
  68. DrahtBot added the label Needs rebase on May 26, 2021
  69. ryanofsky force-pushed on Jun 2, 2021
  70. ryanofsky force-pushed on Jun 2, 2021
  71. DrahtBot removed the label Needs rebase on Jun 2, 2021
  72. DrahtBot added the label Needs rebase on Jun 9, 2021
  73. ryanofsky force-pushed on Jun 16, 2021
  74. DrahtBot removed the label Needs rebase on Jun 16, 2021
  75. DrahtBot added the label Needs rebase on Aug 12, 2021
  76. ryanofsky force-pushed on Aug 18, 2021
  77. DrahtBot removed the label Needs rebase on Aug 18, 2021
  78. DrahtBot added the label Needs rebase on Sep 16, 2021
  79. ryanofsky force-pushed on Sep 16, 2021
  80. DrahtBot removed the label Needs rebase on Sep 16, 2021
  81. DrahtBot added the label Needs rebase on Sep 29, 2021
  82. ryanofsky force-pushed on Sep 30, 2021
  83. ryanofsky commented at 6:20 pm on September 30, 2021: member
    Rebased 17fcdf51ab570eb55b46a7c44a2a631739462612 -> ec7cc41c00ca93a8bbf92ec13101358f7472cd84 (pr/qtset.22 -> pr/qtset.23, compare) due to conflict with bitcoin-core/gui#416
  84. DrahtBot removed the label Needs rebase on Sep 30, 2021
  85. ghost commented at 2:04 am on October 1, 2021: none
    Concept ACK
  86. DrahtBot added the label Needs rebase on Oct 4, 2021
  87. ryanofsky force-pushed on Oct 4, 2021
  88. ryanofsky commented at 3:12 pm on October 4, 2021: member
    Rebased ec7cc41c00ca93a8bbf92ec13101358f7472cd84 -> 4acc7fcbbcc63a25ac1e5368141dc9612a73c0d1 (pr/qtset.23 -> pr/qtset.24, compare) due to conflict with #20452
  89. in src/qt/optionsmodel.cpp:650 in 4acc7fcbbc outdated
    653+    migrate_setting(ExternalSignerPath, "external_signer_path", "signer");
    654+#endif
    655+    migrate_setting(MapPortUPnP, "fUseUPnP", "upnp");
    656+    migrate_setting(MapPortNatpmp, "fUseNatpmp", "natpmp");
    657+    migrate_setting(Listen, "fListen", "listen");
    658+    migrate_setting(Server, "server", "server");
    


    MarcoFalke commented at 4:08 pm on October 4, 2021:
    Is this needed, given that no version was released with this setting?

    ryanofsky commented at 6:15 am on October 5, 2021:

    Is this needed, given that no version was released with this setting?

    Not strictly needed, but it would be strange to remove this because removing it would treat this setting differently than all the other settings, it causes no harm, it is one line of code, removing it would introduce strange behaviors trying to revert and test this PR, and removing it would introduce a bug in the PR if there is any release before this PR is merged.

  90. DrahtBot removed the label Needs rebase on Oct 4, 2021
  91. ghost commented at 7:17 pm on October 4, 2021: none

    Tried on Fedora and it doesn’t work as expected.

    0[prayank@fedora bin]$ ./bitcoin-qt
    1QSocketNotifier: Can only be used with threads started with QThread
    2Segmentation fault (core dumped)
    

    I have txindex=1 in bitcoin.conf, not a pruned node which works fine with bitcoind. It created a settings file on first launch of bitcoin-qt which failed with error that txindex doesn’t work with pruning. Tried running with prune=0 and it still doesn’t work.

    I expect bitcoin-qt should use prune=0 by default if nothing is mentioned in config and also fix this segfault error.

  92. ryanofsky force-pushed on Oct 5, 2021
  93. ryanofsky commented at 6:31 am on October 5, 2021: member

    Updated 4acc7fcbbcc63a25ac1e5368141dc9612a73c0d1 -> 6e1c1ea20b8cf0bb6c24c81cda92e79dc14c31d5 (pr/qtset.24 -> pr/qtset.25, compare) to fix segfault caused by bad rebase.


    Tried on Fedora and it doesn’t work as expected.

    Thanks, segfault was caused by a conflict in one of the rebases and should be fixed in the newest update of this PR.

    I expect bitcoin-qt should use prune=0 by default if nothing is mentioned in config and also fix this segfault error.

    The segfault error shouldn’t be related to the prune or txindex settings, and I couldn’t reproduce any expected behaviors experimenting with these settings myself. I think the segfault should disappear if you try the updated version of the PR. And if you continue seeing prune/txindex errors, it’d be helpful to see contents of ~/.config/Bitcoin/Bitcoin-Qt.conf and ~/.bitcoin/settings.json files. (if you are using regtest the files are ~/.config/Bitcoin/Bitcoin-Qt-regtest.conf and ~/.bitcoin/regtest/settings.json)


    CI failure https://cirrus-ci.com/task/4987964057976832 Insufficient funds in rpc_fundrawtransaction.py was probably spurious and might be related to #22949.

  94. DrahtBot added the label Needs rebase on Oct 5, 2021
  95. ryanofsky force-pushed on Oct 5, 2021
  96. ryanofsky commented at 4:16 pm on October 5, 2021: member
    Rebased 6e1c1ea20b8cf0bb6c24c81cda92e79dc14c31d5 -> a4111bdc448af8f2b5a7126164fb7e5bb6c7f2b0 (pr/qtset.25 -> pr/qtset.26, compare) due to conflict with #22951
  97. DrahtBot removed the label Needs rebase on Oct 5, 2021
  98. ghost commented at 7:09 am on October 8, 2021: none

    Thanks for rebase. It compiled successfully on Fedora. I have few questions based on steps that I followed:

    1. bitcoin-qt had prune option unchecked in GUI. Relaunched bitcoin-qt with a data directory that has pruned node. Everything works fine and it automatically checked the prune option. Although GB mentioned in GUI was incorrect. I had saved prune=1024 in bitcoin.conf and GUI had 2 GB.

    2. bitcoin-qt had prune option checked in GUI from 1. Used data directory that has all blocks saved on disk. Everything works fine and it automatically unchecked the prune option in GUI.

    3. I wanted to check what happens if qt and bitcoin.conf are different. Restarted bitcoin-qt with data directory used in 1. Unchecked the prune option manually in GUI. This saved "prune": 0 in settings.json. While bitcoin.conf for 1 still has prune=1024, started bitcoin-qt and I see this error:

    image

    1. Saved below things in settings.json for non-pruned node:
      0{
      1    "prune": 1024,
      2    "wallet": [
      3    ]
      4   }
      
      bitcoin.conf had txindex=1

    and this is the error I get:

    image

    1. There is one more case which I wanted to reproduce but couldn’t and also don’t want to risk deleting my blocks for non-pruned node which is explained in https://github.com/bitcoin-core/gui/issues/245
  99. ryanofsky commented at 7:35 pm on October 8, 2021: member

    Thanks for the testing! In summary, I think all behavior described is expected (and improves on current behavior, even if could be improved more later).

    1. bitcoin-qt had prune option unchecked in GUI. Relaunched bitcoin-qt with a data directory that has pruned node. Everything works fine and it automatically checked the prune option. Although GB mentioned in GUI was incorrect. I had saved prune=1024 in bitcoin.conf and GUI had 2 GB.

    The GUI prune setting is a whole number of GB so it’s easier to change and understand than if it were MiB, and to avoid mistakes editing large numbers. 1024MiB is rounded up to 2GB in the display, even though 1024MiB should still be the effective pruning size until the user changes it again. The idea behind rounding up is that it would be bad if node used more disk space than the displayed amount, but ok if it’s using less space than the displayed amount.

    1. bitcoin-qt had prune option checked in GUI from 1. Used data directory that has all blocks saved on disk. Everything works fine and it automatically unchecked the prune option in GUI.

    Nice test. It’s good to have confirmation that bitcoin.conf still takes precedence over QSettings so upgrading does not cause changed settings to be used. (Implementation note: the precedence for settings sources is settings.json > bitcoin.conf > QSettings)

    1. I wanted to check what happens if qt and bitcoin.conf are different. Restarted bitcoin-qt with data directory used in 1. Unchecked the prune option manually in GUI. This saved "prune": 0 in settings.json. While bitcoin.conf for 1 still has prune=1024, started bitcoin-qt and I see this error: [Do you want to rebuild the block database now?]

    Ideally this would be shown as a question not an error, but the benefit of this PR is that when you uncheck the pruning option it now actually disables pruning. Disabling pruning does require reindexing, which is why it asks to reindex.

    Speaking more generally, the idea behind settings precedence is that settings.json is intended to hold live, dynamic settings chosen by the user, and bitcoin.conf is supposed to hold static settings chosen by the packager or installer (who can disable live settings with nosettings=1). The cases where different settings sources provide different values are intended to be well defined, but also rare. There should be few use cases that require controlling the same setting from different places. In the most common cases, GUI users should not need any bitcoin.conf file at all. GUI users should have better options than creating a text file, learning a configuration syntax, and restarting their node to apply settings. Also, ideally more settings will be able to be applied live without restarts, and there will be a config RPC method to get and set arbitrary settings.json settings.

    1. Saved below things in settings.json for non-pruned node:

      0{
      1    "prune": 1024,
      2    "wallet": [
      3    ]
      4   }
      

      bitcoin.conf had txindex=1

    and this is the error I get: [Prune mode is incompatible with -txindex]

    This is another good test, and I think it is straightforward that if you enable pruning and enable txindex you will see this error. Ideally this could show options for disabling pruning or disabling txindex, though.

    1. There is one more case which I wanted to reproduce but couldn’t and also don’t want to risk deleting my blocks for non-pruned node which is explained in Pruning should be based on bitcoin.conf bitcoin-core/gui#245

    I don’t think there should be any direct interaction between this PR and what’s described in #245. With this PR the node will still prune if you enable pruning in the GUI, and still not prune if you disable pruning in the GUI. The other issue #245 seems like it is requesting that the node avoids pruning even if pruning was requested, which does not make sense to me even though I agree we should have safeguards to prevent pruning from happening unintentionally. If you can describe in more detail how #245 happened (how pruning got enabled in the GUI), maybe we could add some safeguard to prevent this.

  100. ryanofsky commented at 7:59 pm on October 8, 2021: member

    If you can describe in more detail how #245 happened (how pruning got enabled in the GUI), maybe we could add some safeguard to prevent this.

    Maybe the GUI should have an extra prompt at startup if pruning is changing from disabled to enabled and blocks exist. In the opposite case we already have “You need to rebuild the database using -reindex to go back to unpruned mode. […] Do you want to rebuild the block database now?”. In this case GUI could prompt “Pruning setting has changed from disabled to enabled, which may discard previously downloaded blocks. Are you sure you want to enable pruning?” Buttons could be [Enable pruning] [Disable pruning] [Abort]." If this is a good idea to implement, probably it should be a separate GUI-only PR.

  101. ghost commented at 0:59 am on October 9, 2021: none

    If you can describe in more detail how #245 happened (how pruning got enabled in the GUI)

    It was enabled when I first installed Bitcoin Core. Did not use GUI for months with non-pruned data directory. Never had issues with CLI. So restarting bitcoin-qt after a long time unaware of settings being different, it deleted all my blocks without any prompt.

    In this case GUI could prompt “Pruning setting has changed from disabled to enabled, which may discard previously downloaded blocks. Are you sure you want to enable pruning?” Buttons could be [Enable pruning] [Disable pruning] [Abort]." If this is a good idea to implement, probably it should be a separate GUI-only PR.

    Agree

  102. unknown approved
  103. DrahtBot added the label Needs rebase on Nov 15, 2021
  104. ryanofsky commented at 10:41 pm on November 29, 2021: member
    Rebased a4111bdc448af8f2b5a7126164fb7e5bb6c7f2b0 -> 32ef6cfa521b8a0615de3259d7b81383608ab8f3 (pr/qtset.26 -> pr/qtset.27, compare) due to conflict with #23004.
  105. ryanofsky force-pushed on Nov 29, 2021
  106. DrahtBot removed the label Needs rebase on Nov 30, 2021
  107. DrahtBot added the label Needs rebase on Jan 9, 2022
  108. ryanofsky force-pushed on Jan 10, 2022
  109. ryanofsky commented at 4:42 pm on January 10, 2022: member
    Rebased 32ef6cfa521b8a0615de3259d7b81383608ab8f3 -> 91d3b48508440a16818ee9606bf5bbdca82edf8a (pr/qtset.27 -> pr/qtset.28, compare) due to conflict with bitcoin-core/gui#441
  110. DrahtBot removed the label Needs rebase on Jan 10, 2022
  111. unknown approved
  112. unknown commented at 7:57 pm on January 10, 2022: none
  113. MarcoFalke removed the label Feature on Jan 11, 2022
  114. MarcoFalke removed the label Build system on Jan 11, 2022
  115. MarcoFalke removed the label Tests on Jan 11, 2022
  116. hebasto commented at 8:16 pm on January 12, 2022: member
    Concept ACK.
  117. hebasto commented at 8:23 pm on January 13, 2022: member

    Approach ACK 91d3b48508440a16818ee9606bf5bbdca82edf8a.

    In here

    0$ cat settings.json 
    1{
    2    "fUseNatpmp": false,
    3    "listen": false,
    4    "upnp": false,
    5    "wallet": [
    6     ""
    7    ]
    8   }
    

    I was expecting to see natpmp instead of fUseNatpmp.

  118. ryanofsky force-pushed on Jan 13, 2022
  119. ryanofsky commented at 10:50 pm on January 13, 2022: member

    I was expecting to see natpmp instead of fUseNatpmp.

    Thanks for the review, and good catch. I think this was a bug introduced during a rebase. I also fixed a similar problem with -lang flag / language setting, and split off a separate commit introducing the OptionsModel getOption/setOption methods to make the individual settings changes easier to see.

    Updated 91d3b48508440a16818ee9606bf5bbdca82edf8a -> 79a0399c696b8212c11c868e1f45f9887aa71993 (pr/qtset.28 -> pr/qtset.29, compare) fixing natpmp and language bugs and splitting the commit

  120. Rspigler commented at 4:49 am on January 14, 2022: contributor

    Testing 79a0399c696b8212c11c868e1f45f9887aa71993

    Opening settings.json with a fresh Bitcoin-qt (I have some wallets in the directory).

    { “wallet”: [ “1”, “2”, “Config”, “1.6.22” ] }

    Open Bitcoin-qt, through the GUI set prune to 4GB. Close Bitcoin-qt. Open settings.json again:

    { “prune”: 3814, “upnp”: false, “wallet”: [ “1”, “2”, “Config”, “1.6.22” ] }

    UpnP is included because it is by default unselected in the GUI? I think that makes sense.

    I create a bitcoin.conf and set blockfilterindex=1. I get an alert:

    Error: basic block filter index best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)

    This makes sense. So I run bitcoin-qt -reindex

    However, I open settings.json, and it doesn’t show blockfilterindex:

    { “prune”: 3814, “upnp”: false, “wallet”: [ “1”, “2”, “Config”, “1.6.22” ] }

    And I open bitcoin.conf and it doesn’t show any other settings besides blockfilterindex=1

  121. hebasto commented at 9:55 am on January 14, 2022: member

    Tested 79a0399c696b8212c11c868e1f45f9887aa71993.

    Before running bitcoin-qt:

     0$ cat settings.json 
     1{
     2    "dbcache": 444,
     3    "lang": "en_GB",
     4    "listen": false,
     5    "natpmp": true,
     6    "onion": "127.0.0.1:9050",
     7    "par": -1,
     8    "proxy": "127.0.0.1:9050",
     9    "prune": 3814,
    10    "upnp": true,
    11    "wallet": [
    12     ""
    13    ]
    14   }
    

    Please note "natpmp": true and "upnp": true.

    Running bitcoin-qt, then Options shows:

    DeepinScreenshot_select-area_20220114115424

  122. ryanofsky commented at 2:01 pm on January 14, 2022: member

    Rspigler, all of that behavior except the upnp part is working as designed. The goal of the PR is for bitcoin-qt and bitcoind to share the same dynamic settings, and to store those settings in the settings.json file instead of QT settings storage. The software will never write or change bitcoin.conf because bitcoin.conf is for static settings, rather than dynamic ones. The ultimate goal (which is not fully realized here, but would be with a bitcoin-cli settings command) is that nobody should ever need to create or edit a bitcoin.conf file to change any setting. bitcoin.conf would be a way for distributions and packages to set configuration defaults, and for advanced users to be able switch between complicated configurations, or to track their configurations in git, or generate their configurations with deployment tools like docker, ansible, or nix. But everyday users would not know or care about bitcoin.conf and would just use the gui or command line to change settings dynamically (CLI would look like bitcoin-cli settings set prune 4000) with immediate feedback about invalid values, and not have to worry about creating a text file, or dealing with a configuration syntax, or stopping and restarting bitcoin to make sure the file is parsed and their settings are valid.

    Hebasto, it appears there’s another bug with natpmp/upnp settings, and I think I see what it is: the OptionsModel::getOption method is still returning settings.value("fUseUPnP") and settings.value("fUseNatpmp") for these settings instead of ToQVariant(node().getPersistentSetting("upnp"), DEFAULT_UPNP) and ToQVariant(node().getPersistentSetting("natpmp"), DEFAULT_NATPMP). There may be additional bugs around these settings as well. The implementation of the nat settings changed a lot after this PR was opened, and while I rebased it and fixed explicit conflicts, I never really went through the implementation updating all the upnp/natpmp references that needed to be updated or tested this feature.

  123. uvhw referenced this in commit 47d44ccc3e on Feb 14, 2022
  124. fanquake deleted a comment on Mar 7, 2022
  125. DrahtBot added the label Needs rebase on Mar 9, 2022
  126. ryanofsky force-pushed on Mar 16, 2022
  127. ryanofsky commented at 9:12 pm on March 16, 2022: member
    Rebased 79a0399c696b8212c11c868e1f45f9887aa71993 -> 7eb8fa3daf702d4f609ae0532dcfb61e4d26a173 (pr/qtset.29 -> pr/qtset.30, compare) due to conflicts with #24498 and ##20744. Also fixed upnp issue discussed above, and split PR into smaller commits.
  128. ryanofsky force-pushed on Mar 16, 2022
  129. ryanofsky commented at 9:27 pm on March 16, 2022: member
    Updated 7eb8fa3daf702d4f609ae0532dcfb61e4d26a173 -> 52438b033718afae375cea86ca349db3a878aef4 (pr/qtset.30 -> pr/qtset.31, compare) switching some default literals to constants
  130. DrahtBot removed the label Needs rebase on Mar 16, 2022
  131. hebasto commented at 11:59 am on March 23, 2022: member
    FWIW, this PR (52438b033718afae375cea86ca349db3a878aef4) fixes the bitcoin-core/gui#567 regression.
  132. jonatack commented at 12:20 pm on March 23, 2022: member
    Concept ACK
  133. vasild commented at 1:39 pm on March 23, 2022: member
    Concept ACK
  134. ryanofsky commented at 3:24 pm on March 23, 2022: member

    FWIW, this PR (52438b0) fixes the bitcoin-core/gui#567 regression.

    I could be wrong, but I’m guessing this PR only partially fixes https://github.com/bitcoin-core/gui/issues/567. It should prevent the bug if someone disables listening with this PR applied, and then restarts bitcoin-qt. But I’m guessing if they turn off listening without this PR, then restart with this PR applied, the same “Cannot set -listen=0 together with -listenonion=1” error will happen, because migrate_settings code apply the setting too late after the InitParameterInteraction code has already run, but before the AppInitParameterInteraction code runs and triggers the error. But the bug should be more temporary and go away after the next restart after the setting is migrated.

  135. DrahtBot added the label Needs rebase on Mar 23, 2022
  136. ryanofsky force-pushed on Mar 23, 2022
  137. ryanofsky commented at 8:24 pm on March 23, 2022: member
    Rebased 52438b033718afae375cea86ca349db3a878aef4 -> b81c22a2880a797ea86d9b793c58aa49c67b9cda (pr/qtset.31 -> pr/qtset.32, compare) due to conflict with bitcoin-core/gui#568. Also cleaned up messy previous conflict resolution with #17696. No change in behavior except for a minor bugfix when the -prune command line option is given and the intro dialog is shown. In previous version of this PR, the intro dialog prune value would only be written to settings.json and not take precedence over the command line value. Now it takes precedence over the command line value.
  138. DrahtBot removed the label Needs rebase on Mar 23, 2022
  139. DrahtBot added the label Needs rebase on Apr 4, 2022
  140. in doc/release-notes-15936.md:8 in b81c22a288 outdated
    0@@ -0,0 +1,8 @@
    1+GUI changes
    2+-----------
    3+
    4+Configuration changes made in the bitcoin GUI (such as the pruning setting,
    5+proxy settings, UPNP preferences) are now saved to <datadir>/settings.json file
    6+rather than to the Qt settings backend (windows registry or unix desktop config
    7+files), and the GUI settings will now be used if bitcoind is started in
    8+subsequently, rather than ignored.
    


    vasild commented at 11:19 am on April 5, 2022:

    nit:

    0files), and the GUI settings will now be used if bitcoind is started
    1subsequently, rather than ignored.
    

    ryanofsky commented at 5:45 pm on April 7, 2022:

    In commit “Unify bitcoin-qt and bitcoind persistent settings” (8d50aba09faafa2329751a30d5ce6f63afdc52d0)

    re: #15936 (review)

    nit:

    Thanks, updated


    vasild commented at 9:57 am on April 19, 2022:

    This can be marked as resolved. I cannot do that for some reason even though I opened it.

    Is not the author of a suggestion the best one to judge whether it is resolved or not, github ~!(@*(*~!=&/_*

  141. in src/qt/optionsmodel.cpp:41 in b81c22a288 outdated
    38+static int ToInt(const util::SettingsValue& value, int fallback = 0)
    39+{
    40+    if (value.isNull()) return fallback;
    41+    if (value.isBool()) return value.get_bool();
    42+    if (value.isNum()) return value.get_int();
    43+    return LocaleIndependentAtoi<int>(value.get_str().c_str());
    


    vasild commented at 11:34 am on April 5, 2022:

    The LocaleIndependentAtoi()’s argument is const std::string&, no need to get the C-string:

    0    return LocaleIndependentAtoi<int>(value.get_str());
    

    ryanofsky commented at 5:45 pm on April 7, 2022:

    In commit “Unify bitcoin-qt and bitcoind persistent settings” (8d50aba09faafa2329751a30d5ce6f63afdc52d0)

    re: #15936 (review)

    The LocaleIndependentAtoi()’s argument is const std::string&, no need to get the C-string:

    Thanks, updated


    vasild commented at 9:57 am on April 19, 2022:
    Can be marked as resolved.
  142. in src/qt/optionsmodel.cpp:56 in b81c22a288 outdated
    46+//! Convert bitcoin settings value to QString.
    47+static QString ToQString(const util::SettingsValue& value, const QString& fallback = {})
    48+{
    49+    if (value.isNull()) return fallback;
    50+    if (value.isFalse()) return "";
    51+    return QString::fromStdString(value.get_str());
    


    vasild commented at 12:14 pm on April 5, 2022:
    get_str() will throw if the value is not a string (typ != VSTR). I think it is strange to return "" for a boolean false value and throw for a boolean true. Will also throw for integers.

    ryanofsky commented at 5:56 pm on April 7, 2022:

    In commit “Unify bitcoin-qt and bitcoind persistent settings” (8d50aba09faafa2329751a30d5ce6f63afdc52d0)

    re: #15936 (review)

    get_str() will throw if the value is not a string (typ != VSTR). I think it is strange to return "" for a boolean false value and throw for a boolean true. Will also throw for integers.

    Added comment. In general, I want this function to throw if an setting is saved with the wrong type, because our code should write to settings.json file with proper types, and wrong types are an indication of a corrupt or invalid settings file.

    The isNull() and isFalse() cases are special just because ArgsManager treats them as special. Null values are used by ArgsManager to indicate unspecified settings values. False settings are settings that have been specified, but explicitly negated. There are some settings that don’t make sense to negate, which is why we have DISALLOW_NEGATION flag, but the general approach is allow negations, and treat a negated -nolist as [], treat -nostring as "", -noint as 0, -nobool as false.

    The ToQString method is used for -proxy -onion and -lang settings and returning empty string for these does make sense when they are negated. For example, if no -lang value was specified you might want to use operating system language for translation, where if -nolang were specified you might want to disable translation.


    vasild commented at 9:58 am on April 19, 2022:
    Can be marked as resolved.
  143. in src/qt/optionsmodel.cpp:67 in b81c22a288 outdated
    55+static QVariant ToQVariant(const util::SettingsValue& value, const QVariant& fallback = {})
    56+{
    57+    if (value.isNull()) return fallback;
    58+    if (value.isBool()) return value.get_bool();
    59+    if (value.isNum()) return value.get_int();
    60+    return QString::fromStdString(value.get_str());
    


    vasild commented at 12:19 pm on April 5, 2022:
    0    return QVariant::fromValue(value.get_str());
    

    ryanofsky commented at 6:09 pm on April 7, 2022:

    In commit “Unify bitcoin-qt and bitcoind persistent settings” (8d50aba09faafa2329751a30d5ce6f63afdc52d0)

    re: #15936 (review)

    Using QVariant::fromValue instead of QString::fromStdString would make this less clear, I think. Or I am not seeing the benefit. fromValue is a template method that doesn’t have clearly documented behavior, while fromStdString is clearly documented to accept the UTF8 strings that get_str returns, and is already very commonly used in our Qt code.


    vasild commented at 1:44 pm on April 8, 2022:

    Ok, leave it as is then.

    I mentioned it because this function has a return type QVariant and now it returns QString. This, I guess, implicitly calls the QVariant(const QString &string) contructor. Where is QString::fromStdString() documented? Is the constructor QVariant(const QString &string) documented too? I do not see any comments in Qt headers.


    ryanofsky commented at 2:09 pm on April 8, 2022:

    re: #15936 (review)

    Where is QString::fromStdString() documented? Is the constructor QVariant(const QString &string) documented too? I do not see any comments in Qt headers.

    Thanks, to answer question I think I just googled “fromStdString” and was looking at https://doc.qt.io/qt-5/qstring.html#fromStdString which describes the locale conversion. There also seem to be around ~100 other uses of fromStdString in our codebase, so probably developers will be familiar with it.

  144. in src/qt/optionsmodel.cpp:66 in b81c22a288 outdated
    63+//! Convert QSettings QVariant value to bitcoin setting.
    64+static util::SettingsValue ToSetting(const QVariant& variant, QVariant::Type type, const util::SettingsValue& fallback = {})
    65+{
    66+    if (!variant.isValid()) return fallback;
    67+    if (type == QVariant::Bool) return variant.toBool();
    68+    if (type == QVariant::Int) return variant.toInt();
    


    vasild commented at 12:26 pm on April 5, 2022:
    Is it not possible to use variant.Type() and ditch the second argument to this function QVariant::Type type?

    ryanofsky commented at 6:14 pm on April 7, 2022:

    In commit “Unify bitcoin-qt and bitcoind persistent settings” (8d50aba09faafa2329751a30d5ce6f63afdc52d0)

    re: #15936 (review)

    Is it not possible to use variant.Type() and ditch the second argument to this function QVariant::Type type?

    I want to make sure settings are written to settings.json with correct types. I rearranged the functions and expanded the comment to make the design goals more clear.


    vasild commented at 9:59 am on April 19, 2022:
    Can be marked as resolved.
  145. in src/qt/optionsmodel.cpp:68 in b81c22a288 outdated
    65+{
    66+    if (!variant.isValid()) return fallback;
    67+    if (type == QVariant::Bool) return variant.toBool();
    68+    if (type == QVariant::Int) return variant.toInt();
    69+    std::string str = variant.toString().toStdString();
    70+    if (str.empty()) return false;
    


    vasild commented at 12:29 pm on April 5, 2022:
    Here is the reverse of the above false->empty-string conversion. This code converts empty string to boolean false. This looks strange. Maybe in some cases we would like to keep the empty string as an empty string?

    ryanofsky commented at 6:15 pm on April 7, 2022:

    In commit “Unify bitcoin-qt and bitcoind persistent settings” (8d50aba09faafa2329751a30d5ce6f63afdc52d0)

    re: #15936 (review)

    Here is the reverse of the above false->empty-string conversion. This code converts empty string to boolean false. This looks strange. Maybe in some cases we would like to keep the empty string as an empty string?

    You’re right this was just strange, and I don’t know what motivated it. This was only used for the ExternalSignerPath option which was a QLineEdit string and the Language option which was QValueComboBox also always set string values. There would no reason in either case to turn empty strings into booleans.


    vasild commented at 9:59 am on April 19, 2022:
    Can be marked as resolved.
  146. ryanofsky force-pushed on Apr 5, 2022
  147. ryanofsky commented at 8:17 pm on April 5, 2022: member
    Rebased b81c22a2880a797ea86d9b793c58aa49c67b9cda -> 8d50aba09faafa2329751a30d5ce6f63afdc52d0 (pr/qtset.32 -> pr/qtset.33, compare) fixing conflict and test failure after bitcoin-core/gui#569
  148. DrahtBot removed the label Needs rebase on Apr 5, 2022
  149. hebasto commented at 7:33 am on April 6, 2022: member

    https://api.cirrus-ci.com/v1/task/6080882288099328/logs/ci.log:

     0FAIL: qt/test/test_bitcoin-qt
     1=============================
     2
     3QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'
     4********* Start testing of AppTests *********
     5Config: Using QtTest library 5.15.3, Qt 5.15.3 (x86_64-little_endian-lp64 static release build; by Clang 8.0.0 (tags/RELEASE_800/final)), ubuntu 18.04
     6PASS   : AppTests::initTestCase()
     7QINFO  : AppTests::appTests() Backing up GUI settings to "/tmp/test_common_Bitcoin Core/95f88467c15a125c7116b7e203b7386cf60ef5f9ce394165bee770ab2655162d/regtest/guisettings.ini.bak"
     8QDEBUG : AppTests::appTests() requestInitialize : Requesting initialize
     9QDEBUG : AppTests::appTests() Running initialization in thread
    10QDEBUG : AppTests::appTests() initializeResult : Initialization result:  true
    11QINFO  : AppTests::appTests() Platform customization: "other"
    12QWARN  : AppTests::appTests() This plugin does not support propagateSizeHints()
    13QWARN  : AppTests::appTests() This plugin does not support raise()
    14QWARN  : AppTests::appTests() This plugin does not support grabbing the keyboard
    15QWARN  : AppTests::appTests() This plugin does not support propagateSizeHints()
    16QDEBUG : AppTests::appTests() requestShutdown : Requesting shutdown
    17QDEBUG : AppTests::appTests() Running Shutdown in thread
    18QDEBUG : AppTests::appTests() Shutdown finished
    19PASS   : AppTests::appTests()
    20PASS   : AppTests::cleanupTestCase()
    21Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 522ms
    22********* Finished testing of AppTests *********
    23********* Start testing of OptionTests *********
    24Config: Using QtTest library 5.15.3, Qt 5.15.3 (x86_64-little_endian-lp64 static release build; by Clang 8.0.0 (tags/RELEASE_800/final)), ubuntu 18.04
    25PASS   : OptionTests::initTestCase()
    26FAIL!  : OptionTests::migrateSettings() Caught unhandled exception
    27   Loc: [qtestcase.cpp(1939)]
    28Totals: 1 passed, 1 failed, 0 skipped, 0 blacklisted, 7ms
    29********* Finished testing of OptionTests *********
    30terminating with uncaught exception of type std::__1::__fs::filesystem::filesystem_error: filesystem error: in create_directory: Not a directory [/root/.bitcoin/regtest]
    31FAIL qt/test/test_bitcoin-qt (exit status: 134)
    
  150. ryanofsky force-pushed on Apr 6, 2022
  151. ryanofsky commented at 8:22 pm on April 6, 2022: member

    Thanks! I think the errors should be fixed by the last push.

    Updated 8d50aba09faafa2329751a30d5ce6f63afdc52d0 -> 73d7e74aa3201158a7f33daf07fc23a370d2b4b9 (pr/qtset.33 -> pr/qtset.34, compare) to fix create_directory errors after OptionsTest caused by OptionsTest clearing the -datadir option set by BasicTestingSetup (https://cirrus-ci.com/task/4954982381256704?logs=ci#L3402, https://cirrus-ci.com/task/5377194846322688?logs=ci#L2727, https://cirrus-ci.com/task/4814244892901376?logs=ci#L3122, https://cirrus-ci.com/task/5236457357967360?logs=ci#L4040, https://cirrus-ci.com/task/4673507404546048?logs=ci#L3145, https://cirrus-ci.com/task/4954982381256704?logs=ci#L3402, https://cirrus-ci.com/task/6080882288099328?logs=ci#L2910)

  152. in src/qt/optionsmodel.cpp:344 in 73d7e74aa3 outdated
    344 }
    345 
    346-// read QSettings values and return them
    347-QVariant OptionsModel::data(const QModelIndex & index, int role) const
    348+// write QSettings values
    349+bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, int role)
    


    vasild commented at 12:22 pm on April 7, 2022:

    style:

    0bool OptionsModel::setData(const QModelIndex& index, const QVariant& value, int role)
    

    ryanofsky commented at 4:35 pm on April 7, 2022:

    In commit “refactor: Add OptionsModel getOption/setOption methods” (87c655ab07b2bddf50bfdc3fcceabd3ef46e436a)

    re: #15936 (review)

    style:

    This line is actually just moving and I didn’t change it. Would prefer not to change it here to avoid interfering with git diff --color-moved


    vasild commented at 1:44 pm on April 8, 2022:
    ok
  153. in src/qt/optionsmodel.h:83 in 73d7e74aa3 outdated
    78@@ -79,6 +79,8 @@ class OptionsModel : public QAbstractListModel
    79     int rowCount(const QModelIndex & parent = QModelIndex()) const override;
    80     QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
    81     bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole) override;
    82+    QVariant getOption(OptionID option) const;
    83+    bool setOption(OptionID option, const QVariant &value);
    


    vasild commented at 12:54 pm on April 7, 2022:

    style:

    0    bool setOption(OptionID option, const QVariant& value);
    

    ryanofsky commented at 4:38 pm on April 7, 2022:

    In commit “refactor: Add OptionsModel getOption/setOption methods” (87c655ab07b2bddf50bfdc3fcceabd3ef46e436a)

    re: #15936 (review)

    style:

    Thanks, updated


    vasild commented at 9:59 am on April 19, 2022:
    Can be marked as resolved.
  154. in src/qt/bitcoin.cpp:262 in 73d7e74aa3 outdated
    258@@ -259,7 +259,7 @@ void BitcoinApplication::createPaymentServer()
    259 
    260 void BitcoinApplication::createOptionsModel(bool resetSettings)
    261 {
    262-    optionsModel = new OptionsModel(this, resetSettings);
    263+    optionsModel = new OptionsModel(node(), this, resetSettings);
    


    vasild commented at 1:07 pm on April 7, 2022:

    node() would assert if the node is not created. This adds an implicit ordering dependency of these methods in src/qt/bitcoin.cpp:

    0    app.createNode(*init);
    1    app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false));
    

    Not so nice, but I guess it is ok. It will crash immediately if the order if violated, can’t remain unnoticed if somebody bricks it in the future.

    PS what about calling createNode() at the beginning of createOptionsModel()? The above is actually the only place where either method is called (ignoring tests).


    ryanofsky commented at 4:51 pm on April 7, 2022:

    In commit “refactor: Pass interfaces::Node references to OptionsModel constructor” (ae9a0987317e23d54c72d82787ef9690a2736595)

    re: #15936 (review)

    node() would assert if the node is not created.

    It doesn’t seem like a problem to me that app.createOptionsModel() and app.createSpashScreen() methods will fail if app.createNode() is not called before them. These are just normal function preconditions which are checked by asserts. If it is a problem, it’s not a new one: the existing app.createWindow() and app.baseInitialize() functions both fail in exactly the same way as app.createOptionsModel() does if m_node is null.

    If you have ideas about how to clean up this code generally, I’d be happy to review a PR. But I wouldn’t want to make createOptionsModel a special case here different from the other create methods.


    vasild commented at 1:47 pm on April 8, 2022:

    Ok, leave it as is for the purposes of this PR.

    There was some subtle bug recently caused by some not-obvious dependency during startup, but the difference with this code here is that here we have an assert(), so it will not remain unnoticed.

  155. in src/qt/bitcoin.cpp:636 in 73d7e74aa3 outdated
    631@@ -632,6 +632,7 @@ int GuiMain(int argc, char* argv[])
    632     app.parameterSetup();
    633     GUIUtil::LogQtInfo();
    634     // Load GUI settings from QSettings
    


    vasild commented at 1:08 pm on April 7, 2022:
    I think this comment is not correct anymore? The settings are no more in QSettings, right?

    ryanofsky commented at 4:53 pm on April 7, 2022:

    In commit “refactor: Pass interfaces::Node references to OptionsModel constructor” (ae9a0987317e23d54c72d82787ef9690a2736595)

    re: #15936 (review)

    I think this comment is not correct anymore? The settings are no more in QSettings, right?

    Expanded comment in later commit. GUI-only settings are still stored in QSettings, but shared bitcoind/bitcoin-qt settings will come from ArgsManager after this.


    vasild commented at 1:48 pm on April 8, 2022:
    ok

    vasild commented at 10:00 am on April 19, 2022:
    Can be marked as resolved.
  156. in src/qt/bitcoin.cpp:283 in 73d7e74aa3 outdated
    277@@ -278,7 +278,9 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
    278 void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
    279 {
    280     assert(!m_splash);
    281+    assert(m_node);
    282     m_splash = new SplashScreen(networkStyle);
    283+    m_splash->setNode(*m_node);
    


    vasild commented at 2:04 pm on April 7, 2022:

    equivalent, but shorter/simpler:

    0    m_splash = new SplashScreen(networkStyle);
    1    m_splash->setNode(node());
    

    ryanofsky commented at 4:52 pm on April 7, 2022:

    In commit “refactor: Pass interfaces::Node references to OptionsModel constructor” (ae9a0987317e23d54c72d82787ef9690a2736595)

    re: #15936 (review)

    equivalent, but shorter/simpler:

    Thanks! Updated this


    vasild commented at 10:00 am on April 19, 2022:
    Can be marked as resolved.
  157. in src/util/system.cpp:599 in 73d7e74aa3 outdated
    591@@ -592,6 +592,13 @@ bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors) const
    592     return true;
    593 }
    594 
    595+util::SettingsValue ArgsManager::GetPersistentSetting(const std::string& name) const
    596+{
    597+    LOCK(cs_args);
    598+    return util::GetSetting(m_settings, m_network, name, !UseDefaultSection("-" + name),
    599+        /* ignore_nonpersistent = */ true, /* get_chain_name= */ false);
    


    vasild commented at 2:36 pm on April 7, 2022:

    style, here and elsewhere, it must be without spaces for some automated tool to pick it up:

    0        /*ignore_nonpersistent=*/true, /*get_chain_name=*/false);
    

    ryanofsky commented at 5:44 pm on April 7, 2022:

    In commit “settings: Add update/getPersistent/isIgnored methods” (ea8c5cb67ac2aef7b24a4d5765edaca2fa84207a)

    re: #15936 (review)

    style, here and elsewhere, it must be without spaces for some automated tool to pick it up:

    Thanks, updated new & changed lines


    vasild commented at 10:00 am on April 19, 2022:
    Can be marked as resolved.
  158. vasild commented at 2:42 pm on April 7, 2022: member
    Posting mid-review, still need to review the last commit and test. Looks good so far.
  159. ryanofsky commented at 4:18 pm on April 7, 2022: member

    Thanks for review vasild! I’ll respond and push an update soon.

    I’m also looking into new MacOS test failure https://cirrus-ci.com/task/5754532419338240. Using cirrus’s nice “Re-run with Terminal Access”” access feature I was able to get the following stack trace:

     0find . -name test_bitcoin-qt
     1lldb -- ci/scratch/out/x86_64-apple-darwin/bin/test_bitcoin-qt
     2(lldb) run
     3(lldb) bt
     4* thread [#1](/bitcoin-bitcoin/1/), name = 'b-test', queue = 'com.apple.main-thread', stop reason = hit program assert
     5    frame [#0](/bitcoin-bitcoin/0/): 0x00007ff819f6800e libsystem_kernel.dylib`__pthread_kill + 10
     6    frame [#1](/bitcoin-bitcoin/1/): 0x00007ff819f9e1ff libsystem_pthread.dylib`pthread_kill + 263
     7    frame [#2](/bitcoin-bitcoin/2/): 0x00007ff819ee9d24 libsystem_c.dylib`abort + 123
     8    frame [#3](/bitcoin-bitcoin/3/): 0x00007ff819ee90cb libsystem_c.dylib`__assert_rtn + 314
     9  * frame [#4](/bitcoin-bitcoin/4/): 0x00000001007db0c1 test_bitcoin-qt`fsbridge::AbsPathJoin(fs::path const&, fs::path const&) (.cold.1) at fs.cpp:39:5 [opt]
    10    frame [#5](/bitcoin-bitcoin/5/): 0x0000000100518efa test_bitcoin-qt`fsbridge::AbsPathJoin(base=0x0000000100e137d8, path=<unavailable>) at fs.cpp:39:5 [opt]
    11    frame [#6](/bitcoin-bitcoin/6/): 0x0000000100534734 test_bitcoin-qt`ArgsManager::GetSettingsPath(this=<unavailable>, filepath=0x00007ff7bfefd740, temp=false) const at system.cpp:536:21 [opt]
    12    frame [#7](/bitcoin-bitcoin/7/): 0x00000001005348e3 test_bitcoin-qt`ArgsManager::WriteSettingsFile(this=0x0000000100e13688, errors=0x0000000000000000) const at system.cpp:578:10 [opt]
    13    frame [#8](/bitcoin-bitcoin/8/): 0x00000001002627cf test_bitcoin-qt`node::(anonymous namespace)::NodeImpl::updateSetting(this=<unavailable>, name="dbcache", value=0x00007ff7bfefd920) at interfaces.cpp:135:15 [opt]
    14    frame [#9](/bitcoin-bitcoin/9/): 0x000000010007b941 test_bitcoin-qt`OptionsModel::setOption(this=0x00007ff7bfefdc68, option=<unavailable>, value=0x00007ff7bfefda20) at optionsmodel.cpp:564:20 [opt]
    15    frame [#10](/bitcoin-bitcoin/10/): 0x000000010007f662 test_bitcoin-qt`OptionsModel::checkAndMigrate(this=0x00007ff7bfefdac0, option=DatabaseCache, qt_name=0x00007ff7bfefda90, name="dbcache")::$_1::operator()(OptionsModel::OptionID, QString const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const at optionsmodel.cpp:661:17 [opt]
    16    frame [#11](/bitcoin-bitcoin/11/): 0x00000001000783e6 test_bitcoin-qt`OptionsModel::checkAndMigrate(this=0x00007ff7bfefdc68) at optionsmodel.cpp:667:5 [opt]
    17    frame [#12](/bitcoin-bitcoin/12/): 0x0000000100074bc6 test_bitcoin-qt`OptionsModel::Init(this=0x00007ff7bfefdc68, resetSettings=<unavailable>) at optionsmodel.cpp:134:5 [opt]
    18    frame [#13](/bitcoin-bitcoin/13/): 0x000000010007449d test_bitcoin-qt`OptionsModel::OptionsModel(this=0x00007ff7bfefdc68, node=0x00006000000084b0, parent=<unavailable>, resetSettings=<unavailable>) at optionsmodel.cpp:110:5 [opt]
    19    frame [#14](/bitcoin-bitcoin/14/): 0x000000010000e0cc test_bitcoin-qt`OptionTests::migrateSettings(this=0x00007ff7bfefe9b0) at optiontests.cpp:50:18 [opt]
    20    frame [#15](/bitcoin-bitcoin/15/): 0x000000010218eda0 QtCore`QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const + 1472
    21    frame [#16](/bitcoin-bitcoin/16/): 0x0000000101769ff3 QtTest`___lldb_unnamed_symbol12$$QtTest + 819
    22    frame [#17](/bitcoin-bitcoin/17/): 0x000000010176ac02 QtTest`___lldb_unnamed_symbol14$$QtTest + 914
    23    frame [#18](/bitcoin-bitcoin/18/): 0x000000010176bacb QtTest`___lldb_unnamed_symbol17$$QtTest + 971
    24    frame [#19](/bitcoin-bitcoin/19/): 0x000000010176c027 QtTest`QTest::qRun() + 263
    25    frame [#20](/bitcoin-bitcoin/20/): 0x000000010176bcf4 QtTest`QTest::qExec(QObject*, int, char**) + 20
    26    frame [#21](/bitcoin-bitcoin/21/): 0x000000010001e282 test_bitcoin-qt`main(argc=<unavailable>, argv=<unavailable>) at test_main.cpp:94:9 [opt]
    27    frame [#22](/bitcoin-bitcoin/22/): 0x000000010140951e dyld`start + 462
    
  160. ryanofsky force-pushed on Apr 7, 2022
  161. ryanofsky commented at 9:32 pm on April 7, 2022: member
    Updated 73d7e74aa3201158a7f33daf07fc23a370d2b4b9 -> 88ead7707dea2e31ce1245daee7d23be3f72e041 (pr/qtset.34 -> pr/qtset.35, compare) with fix for macos test failure. The failure just happened because optionsTest code dependended on appTests testing setup, and appTests are skipped by default on mac. Problem could be reproduced on linux skipping appTests there.
  162. in src/qt/optionsmodel.cpp:305 in 88ead7707d outdated
    322+
    323+    // Force setting to take effect. It is still safe to change the value at
    324+    // this point because this function is only called after the intro screen is
    325+    // shown, before the node starts.
    326+    node().forceSetting("prune", new_value);
    327+    m_prune_size_gb = PruneSizeGB(new_value);
    


    vasild commented at 11:19 am on April 8, 2022:

    this is the same as:

    0    m_prune_size_gb = prune_target_gb;
    

    since new_value is derived from prune_target_gb. I think there is no point to convert the GB (prune_target_gb) to MB (new_value) only to convert back to GB for m_prune_size_gb?


    ryanofsky commented at 8:09 pm on April 11, 2022:

    re: #15936 (review)

    In commit “Unify bitcoin-qt and bitcoind persistent settings” (8d50aba09faafa2329751a30d5ce6f63afdc52d0)

    I think there is no point to convert the GB (prune_target_gb) to MB (new_value) only to convert back to GB for m_prune_size_gb?

    Nice suggestion, updated


    vasild commented at 10:02 am on April 19, 2022:
    Can be marked as resolved.
  163. in src/qt/optionsmodel.cpp:85 in 88ead7707d outdated
    83+
    84+//! Get pruning enabled value to show in GUI from bitcoin -prune setting.
    85+static bool PruneEnabled(const util::SettingsValue& prune_setting)
    86+{
    87+    // -prune=1 setting is manual pruning mode, so disabled for purposes of the gui
    88+    return ToInt(prune_setting) > 1;
    


    vasild commented at 1:10 pm on April 8, 2022:

    This, in isolation, is (wrongly) ignoring the fact that values in [2, 550) are not allowed (MIN_DISK_SPACE_FOR_BLOCK_FILES – 550 MiB). init.cpp would refuse to start with such a value.

    In context, this is only called with values entered in the GUI which is accepting integer GB only, so it is impossible to enter e.g. 100 MiB. Or it could come from settings.json where the value is stored in MiB and the user may have edited it (they are not supposed to). I think it is ok because even if <550 is entered in settings.json the startup would gracefully fail with the proper message from init.cpp.


    ryanofsky commented at 7:40 pm on April 11, 2022:

    re: #15936 (review)

    This, in isolation, is (wrongly) ignoring the fact that values in [2, 550) are not allowed

    This is all technically correct, and I agree with everything you wrote except for the word “wrongly”. I would say this is rightly not depending on details of the pruning implementation, and only commenting on the one special manual pruning case that does need to be handled here. Still would be open to suggestions to clarify this or maybe point to the -prune argument documentation for more background.


    vasild commented at 10:02 am on April 19, 2022:
    Can be marked as resolved.
  164. vasild commented at 1:37 pm on April 8, 2022: member

    Review still ongoing, posting two minor comments coz I am afraid github may lose them, feel free to ignore.

    This would be easier to review if the last commit Unify bitcoin-qt and bitcoind persistent settings is split so that there is one commit per config option migrated from ~/.config/Bitcoin/Bitcoin-Qt.conf to settings.json.

  165. in src/qt/optionsmodel.cpp:63 in 88ead7707d outdated
    60+    return QString::fromStdString(value.get_str());
    61+}
    62+
    63+//! Convert bitcoin setting to QString. The setting must already be a string, or
    64+//! it must be negated or unset. If it has another type like integer, bool,
    65+//! array, or object, this will raise an exception.
    


    vasild commented at 9:02 am on April 11, 2022:

    nit: use doxygen’s @throws

    0//! [@throws](/bitcoin-bitcoin/contributor/throws/) std::runtime_error if it has non-string type like integer, bool, array, or object.
    

    ryanofsky commented at 7:20 pm on April 11, 2022:

    In commit “Unify bitcoin-qt and bitcoind persistent settings” (8d50aba09faafa2329751a30d5ce6f63afdc52d0)

    re: #15936 (review)

    nit: use doxygen’s @throws

    Thanks, changed.

  166. in src/qt/optionsmodel.cpp:113 in 88ead7707d outdated
    111+struct ProxySetting {
    112+    bool is_set;
    113+    QString ip;
    114+    QString port;
    115+};
    116+static ProxySetting ParseProxyString(const QString& proxy);
    


    vasild commented at 9:15 am on April 11, 2022:

    I was about to suggest to remove the is_set member and use std::optional, but I noticed that none of the callers of ParseProxyString() bothers to check the is_set member, so it is set-but-never-used. Thus it can be removed:

    0struct ProxySetting {
    1    QString ip;
    2    QString port;
    3};
    4static ProxySetting ParseProxyString(const QString& proxy);
    

    ryanofsky commented at 7:49 pm on April 11, 2022:

    In commit “Unify bitcoin-qt and bitcoind persistent settings” (8d50aba09faafa2329751a30d5ce6f63afdc52d0)

    re: #15936 (review)

    I was about to suggest to remove the is_set member and use std::optional, but I noticed that none of the callers of ParseProxyString() bothers to check the is_set member, so it is set-but-never-used. Thus it can be removed.

    Nice catch. This struct definition is just moving not changing, but you’re right I wasn’t taking advantage of the is_used member in getOption code, and it is nicer to do that.

  167. in src/qt/optionsmodel.cpp:284 in 88ead7707d outdated
    273-};
    274-
    275-static ProxySetting GetProxySetting(QSettings &settings, const QString &name)
    276+static ProxySetting ParseProxyString(const QString& proxy)
    277 {
    278     static const ProxySetting default_val = {false, DEFAULT_GUI_PROXY_HOST, QString("%1").arg(DEFAULT_GUI_PROXY_PORT)};
    


    vasild commented at 9:17 am on April 11, 2022:

    If the is_set member is removed, then this becomes:

    0    static const ProxySetting default_val = {DEFAULT_GUI_PROXY_HOST, QString("%1").arg(DEFAULT_GUI_PROXY_PORT)};
    

    and also, a few lines below:

    0-return {true, ip_port.at(0), ip_port.at(1)};
    1+return {ip_port.at(0), ip_port.at(1)};
    

    ryanofsky commented at 8:08 pm on April 11, 2022:

    In commit “Unify bitcoin-qt and bitcoind persistent settings” (8d50aba09faafa2329751a30d5ce6f63afdc52d0)

    re: #15936 (review)

    If the is_set member is removed, then this becomes:

    Thanks, now make better use of the is_set member and ParseProxyString function.

  168. vasild commented at 10:18 am on April 11, 2022: member

    The ip address and port of the proxy would be lost if the user unchecks the “Connect through proxy…” in the network settings. Further, bitcoin-qt refuses to start with the error message:

    0Error: No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>.
    

    To reproduce:

    1. In the “GUI settings -> options -> network” click “Connect through SOCKS5 proxy” and input some values for “Proxy IP” and “Port”, l used 127.0.0.2 and 19050. Shut down.

    2. Confirm that ~/.bitcoin/settings.json contains "proxy": "127.0.0.2:19050". The use-proxy checkbox is not saved explicitly. Rather the presence of "proxy" implies that it is checked.

    3. Start and uncheck the “Connect through SOCKS5 proxy” box in the GUI. Notice that the address and port of the proxy are still displayed but greyed out / disabled. This is ok. In order to re-enable the proxy the user has to only check the box later and the previous addr/port from before are already filled in. Shut down.

    4. Notice that ~/.bitcoin/settings.json contains "proxy": "". At this point the user’s values for proxy address and port have been lost.

    5. Try to start bitcoin-qt, it refuses to start with an error Error: No proxy server specified. This is like trying to start bitcoind with -proxy="".

    I guess it would be better to explicitly save a “use proxy” boolean in settings.json that corresponds to the “Connect through SOCKS5 proxy” checkbox. This way the user can temporarily disable the proxy and re-enable it later, through restart, without having to re-enter its address and port. Also, if that “use proxy” boolean is false then we should avoid setting the proxy config which should allow bitcoin-qt to start.

    In this case my comments below about removing is_set from ProxySettings below should be ignored.

  169. ryanofsky referenced this in commit 6a51a91932 on Apr 12, 2022
  170. ryanofsky referenced this in commit 93e83a41fa on Apr 12, 2022
  171. ryanofsky referenced this in commit c241778582 on Apr 12, 2022
  172. ryanofsky force-pushed on Apr 12, 2022
  173. ryanofsky commented at 8:47 pm on April 12, 2022: member

    Thanks @vasild for the review and bug report and very helpful suggestions!

    Updated 88ead7707dea2e31ce1245daee7d23be3f72e041 -> 1a8ac5bb1baf555003580db96d619f4a9c23089a (pr/qtset.35 -> pr/qtset.36, compare) with suggested changes

    re: #15936#pullrequestreview-936298972

    This would be easier to review if the last commit Unify bitcoin-qt and bitcoind persistent settings is split so that there is one commit per config option migrated from ~/.config/Bitcoin/Bitcoin-Qt.conf to settings.json.

    Thanks, I agree and split this up into multiple commits.

    re: #15936#pullrequestreview-937685759

    The ip address and port of the proxy would be lost if the user unchecks the “Connect through proxy…” in the network settings. Further, bitcoin-qt refuses to start with the error message:

    It seems ok to me (and perhaps better) for the old proxy string to be cleared if the proxy is disabled and bitcoin-qt is restarted. I could think of various approaches to saving the unused proxy value, though, if it is important to change this.

    The “No proxy server specified” error message is definitely a bug. I could think of various ways to fix it, but the approach I like best is #24830, because it tones down the overeager error message more generally and doesn’t require changes here.

  174. ryanofsky force-pushed on Apr 14, 2022
  175. ryanofsky commented at 4:04 am on April 14, 2022: member

    I updated this to drop all the ToSetting/ToQVariant/ToQString/ToInt functions. These were supposed to help make optionsmodel code simpler, but I think in practice I think they were only obfuscating it. They were also duplicating type conversion logic in ArgsManager, which I think is just better to expose directly.

    Updated 1a8ac5bb1baf555003580db96d619f4a9c23089a -> 9b78c241e5e3af50eec732fb044183331fd0c756 (pr/qtset.36 -> pr/qtset.37, compare) fixing missing univalue include. Updated 9b78c241e5e3af50eec732fb044183331fd0c756 -> 7966254822e179798d6a375ac3183321ee541733 (pr/qtset.37 -> pr/qtset.38, compare) dropping setting conversion functions and cleaning up implementation and tests in other small ways.

  176. in src/util/system.cpp:641 in 7966254822 outdated
    633+}
    634+
    635+bool SettingToBool(const util::SettingsValue& value, bool fDefault)
    636+{
    637     return value.isNull() ? fDefault : value.isBool() ? value.get_bool() : InterpretBool(value.get_str());
    638 }
    


    vasild commented at 8:05 am on April 14, 2022:

    This was ok before because the supplied SettingsValue to GetBoolArg() was always of type string (VSTR) (right?). But now this code may be called with values coming from settings.json and thus it could be number as well which would trigger get_str() to throw.

    For example, if "listen": false in settings.json is changed to "listen": 0, then bitcoin-qt crashes at startup:

    0$ bitcoin-qt
    1Abort trap (core dumped)
    2$
    

    This looks easy to overcome:

    0-    return value.isNull() ? fDefault : value.isBool() ? value.get_bool() : InterpretBool(value.get_str());
    1+    return value.isNull() ? fDefault : value.isBool() ? value.get_bool() : InterpretBool(value.getValStr());
    

    (putting many things in one line makes a diff harder to read)


    ryanofsky commented at 5:17 pm on April 14, 2022:

    re: #15936 (review)

    This was ok before because the supplied SettingsValue to GetBoolArg() was always of type string (VSTR) (right?). But now this code may be called with values coming from settings.json and thus it could be number as well which would trigger get_str() to throw.

    You are right and the problem is even broader than described, because in general settings.json file is supposed to be strongly typed. If a settings.json file ever has string for an int value, or a int for a bool value, or vice versa, etc it means the file is corrupt and bitcoin should not continue running using a configuration that may be buggy or incomplete.

    But of course it shouldn’t abort with an uncaught exception either, so I added code to handle this with more clarity.

    Related: There are tests for what’s expected to happen when you set an integer in the settings.json file here:

    https://github.com/bitcoin/bitcoin/blob/cf0a8b9c4870cc88254a757286140d9632e7b70c/src/test/getarg_tests.cpp#L99-L104


    vasild commented at 10:05 am on April 19, 2022:
    Can be marked as resolved.
  177. in src/qt/optionsmodel.cpp:538 in 7966254822 outdated
    776-            break;
    777         }
    778+        break;
    779+    case DatabaseCache:
    780+        if (changed()) {
    781+            node().updateSetting("dbcache", value.toInt());
    


    vasild commented at 8:25 am on April 14, 2022:

    nit: toInt() returns int, thus this would limit dbcache to max 2^31. It is in megabytes, but still, int64_t is used for it elsewhere:

    0            node().updateSetting("dbcache", static_cast<int64_t>(value.toLongLong()));
    

    ryanofsky commented at 5:18 pm on April 14, 2022:

    re: #15936 (review)

    nit: toInt() returns int, thus this would limit dbcache to max 2^31. It is in megabytes, but still, int64_t is used for it elsewhere:

    Good catch. I’ve cleaned up the integer conversions here and elsewhere.


    vasild commented at 10:05 am on April 19, 2022:
    Can be marked as resolved.
  178. in src/qt/optionsmodel.cpp:469 in 7966254822 outdated
    549+    case MapPortNatpmp: // core option - can be changed on-the-fly
    550+        if (changed()) {
    551+            node().updateSetting("natpmp", value.toBool());
    552+            node().mapPort(getOption(MapPortUPnP).toBool(), value.toBool());
    553+        }
    554+        break;
    


    vasild commented at 12:47 pm on April 14, 2022:
    Why is it necessary to call mapPort() from here? In the previous code it was not called from here.

    ryanofsky commented at 5:18 pm on April 14, 2022:

    re: #15936 (review)

    Why is it necessary to call mapPort() from here? In the previous code it was not called from here.

    Added a commit message comment about this, and also removed other mapPort call this is supposed to replace. When this PR was first opened, mapPort() was called here, but 58e8364dcdc4e57b0caac09f8402e6535301de9b from #18077 removed it, adding an external call in OptionsDialog. I think it’s a good thing to move the mapPort() call back here, because for all other options, calling setOption completely applies the setting (either updating state immediately or calling restartRequired) instead of half-applying it.


    vasild commented at 10:08 am on April 19, 2022:
    The commit message of 58e8364dcdc4e57b0caac09f8402e6535301de9b says “It is a prerequisite for NAT-PMP support” but it does not explain why is it a prerequisite. Here we revert it. I don’t see what could go wrong, but maybe better to have @hebasto confirm that this change/reversal is ok.
  179. in src/qt/optionsmodel.cpp:654 in 7966254822 outdated
    649+    migrate_setting(Listen, "fListen", "listen");
    650+    migrate_setting(Server, "server", "server");
    651+    migrate_setting(PruneSize, "nPruneSize", "prune");
    652+    migrate_setting(Prune, "bPrune", "prune");
    653+    migrate_setting(ProxyIP, "addrProxy", "proxy");
    654+    migrate_setting(ProxyUse, "fUseProxy", "proxy");
    


    vasild commented at 1:23 pm on April 14, 2022:

    It is strange to migrate two different options (ProxyIP and ProxyUse) into the same option (proxy). What happens under the hood is that node().updateSetting("proxy", ...) is called 3 times (when it can/should be called 1 time) with the last call relying on m_proxy_ip and m_proxy_port being set already, so the order in which migrate_setting() is called matters. This is not obvious.

    This would resolve itself if the “use proxy” GUI option is stored explicitly in settings.json.


    ryanofsky commented at 5:20 pm on April 14, 2022:

    re : #15936 (review)

    It is strange to migrate two different options (ProxyIP and ProxyUse) into the same option (proxy). What happens under the hood is that node().updateSetting("proxy", ...) is called 3 times (when it can/should be called 1 time) with the last call relying on m_proxy_ip and m_proxy_port being set already, so the order in which migrate_setting() is called matters. This is not obvious.

    This would resolve itself if the “use proxy” GUI option is stored explicitly in settings.json.

    This is all true, but intentional. The migration code is pretty dumb and inefficient like you described, but it is also brief and self-contained. The PR is intentionally not adding any new settings fields to settings.json that current versions of bitcoind and bitcoin-qt don’t understand, and intentionally not making any behavior changes to bitcoind, only bitcoin-qt. It’s only trying to migrate existing settings values, so node and wallet settings are stored completely within the datadir, and current and new versions of bitcoind and bitcoin-qt all share the same configurations instead of seeing different realities.

    I could probably add some comments to the migration code if it’s not clear enough, but I think it’s ok for the code to be inefficient, and even ok for it to have a bit of extra complexity, if that is the tradeoff for keeping the settings format unchanged, and keeping bitcoind unchanged here.


    vasild commented at 11:21 am on April 19, 2022:

    Alright, if this PR settles as it is (to store “use proxy” implicitly), then this is ok IMO. If it is decided to store “use proxy” explicitly then this will be changed anyway.

    Can be marked as resolved.

  180. in src/qt/optionsmodel.cpp:672 in 7966254822 outdated
    616@@ -637,4 +617,49 @@ void OptionsModel::checkAndMigrate()
    617     if (settings.contains("addrSeparateProxyTor") && settings.value("addrSeparateProxyTor").toString().endsWith("%2")) {
    618         settings.setValue("addrSeparateProxyTor", GetDefaultProxyAddress());
    619     }
    620+
    621+    // Migrate and delete legacy GUI settings that have now moved to <datadir>/settings.json.
    


    vasild commented at 3:14 pm on April 14, 2022:

    This migration may silently drop configs from .config/Bitcoin/Bitcoin-Qt.conf with unexpected effects. Before this PR, values in Bitcoin-Qt.conf were overriding values from bitcoin.conf. So, for example, if one had:

    bitcoin.conf: listen=1 Bitcoin-Qt.conf : fListen=false

    then bitcoin-qt would not be listening and “Allow incoming connections” will be unchecked in the GUI (correct).

    However, once the migration happens, it would leave the configs in this state:

    bitcoin.conf: listen=1 Bitcoin-Qt.conf : (no fListen is present) settings.json: (no listen is present)

    which will cause bitcoin-qt to start listening, silently, when it was not listening before.


    ryanofsky commented at 5:19 pm on April 14, 2022:

    re: #15936 (review)

    This migration may silently drop configs from .config/Bitcoin/Bitcoin-Qt.conf with unexpected effects. Before this PR, values in Bitcoin-Qt.conf were overriding values from bitcoin.conf. So, for example, if one had:

    bitcoin.conf: listen=1 Bitcoin-Qt.conf : fListen=false

    then bitcoin-qt would not be listening and “Allow incoming connections” will be unchecked in the GUI (correct).

    However, once the migration happens, it would leave the configs in this state:

    bitcoin.conf: listen=1 Bitcoin-Qt.conf : (no fListen is present) settings.json: (no listen is present)

    which will cause bitcoin-qt to start listening, silently, when it was not listening before.

    I don’t think this is describing the previous behavior accurately. With listen=1 in bitcoin.conf it should be listening before and after this PR, no matter what is in Bitcoin-Qt.conf , because QSettings have lower priority than bitcoin.conf (now and previously).

    If you try setting fListen=false before this PR, you should see that bitcoin is listening, and there is an “Options set in this dialog are overridden by the command line or in the configuration file: -listen=1”

    If you try setting fListen=false after this PR, you should see that bitcoin is still listening and the setting is “migrated” by being deleted, since it was already being ignored anyway.

    This PR does add the ability for new GUI setting changes to override bitcoin.conf settings, (because by design settings.json has a higher priority than bitcoin.conf), but migration is one-time occurrence, and existing migrated settings are interpreted with the same lower priority before and after this PR.

    The goal for this PR, assuming this PR is merged before 0.24, is that if you switch back and forth between 0.23 and 0.24 you should never see settings changed or interpreted differently unless you actually intervene and edit something to change them.


    vasild commented at 12:01 pm on April 19, 2022:

    Thanks for the elaborate explanation! I was wrong, sorry for the noise.

    Can be marked as resolved.

  181. in src/qt/optionsmodel.cpp:108 in 7966254822 outdated
    63+{
    64+    return std::max(1, prune_size.toInt());
    65+}
    66+
    67+struct ProxySetting {
    68+    bool is_set;
    


    vasild commented at 3:36 pm on April 14, 2022:

    (continuing the proxy discussion here so that it is in its own thread, not in the main PR comments and so that it can be closed when resolved eventually)

    This applies to the options that have a user-input value and an additional checkbox to disable them: prune, proxy and onion. Naturally there are two things per option - the value typed by the user and the boolean checkbox (denoting enabled/disabled).

    This PR uses a dummy value in settings.json to denote the “disabled” state: 0 for prune and "" for proxy. The problem with this approach is that this loses the value typed by the user. This is surprising and annoying (having to re-enter it after temporary disabling it). Also, it is not consistent behavior:

    • closing the config window and re-opening it => the values are still there, greyed out
    • restarting bitcoin-qt => the values are deleted

    Firefox for example has a proxy-config and it acts in a consistent way - the values, when disabled, are preserved (greyed out) even after restart. IMO this is less surprising.

    I would suggest to save the “use prune”, “use proxy” and “use proxy for tor” as explicit boolean entities in settings.json and preserve the user-entered values in prune, proxy and onion.

    Actually, for prune the behavior is even a bit more confusing:

    • enter 5 in the GUI config (some arbitrary value)
    • disable the checkbox (5 remains in the box, greyed out)
    • restart
    • enable the checkbox
    • surprise! the value is not 5, but 2

    ryanofsky commented at 5:17 pm on April 14, 2022:

    re: #15936 (review)

    (continuing the proxy discussion here so that it is in its own thread, not in the main PR comments and so that it can be closed when resolved eventually)

    I’ll try to implement a patch which implements the previous behavior you seem to like. But honestly, I think storing unused settings values after a restart is just as likely to harm users as to help them. And even if it does help some users I think it make application behavior more opaque and settings format more complicated to keep around unused settings.

    I think it’s ok to clear pruning or proxy values after a users disables pruning or proxying and then restarts. I agree with you that if the user frequently toggles pruning or proxying off and on through the GUI, this may be less convenient. But probably in the more common case, when a user is turning pruning or proxying on for the first time, or turning it on after a long interval, the default values provided by the GUI (2GB for pruning and tor for the proxy), are more likely to be useful and actually work than previous values which may be old or completely invalid or never worked. Our proxy setting is different from firefox’s proxy setting because we actually do provide a default working value using tor, where firefox just has a blank default value that would never be worth resetting to.

    Also our UI is very simple, and the default values that will be applied when pruning or proxying are enabled are clearly visible, so I feel like your description exaggerates the amount of surprise or confusion they could cause. I’d agree that that it would be bad and confusing behavior to reset the proxy and values to defaults if a user only toggled the settings off and without restarting to apply the settings. But once you’re restarted with pruning or proxying disabled, I don’t think it’s essential to show old pruning and proxy values the next time you want to enable them. Especially since we have good defaults and don’t have a good way of knowing if the old values are currently valid or were ever valid.


    vasild commented at 12:26 pm on April 19, 2022:

    I’ll try to implement a patch which implements the previous behavior you seem to like.

    Hmm, I shouldn’t be forcing my view here. I could be nuts and totally disconnected from realit:space_invader: Maybe at this point it makes sense to poke other reviewers for opinion. Anyone?

    I think it’s ok to clear pruning or proxy values after a users disables pruning or proxying and then restarts.

    I think it would be less surprising and more obvious what is going on if we clear the values after the user disables the option. Like, immediately after the click on the checkbox. Then the behavior will be consistent between “close & re-open the config dialog box” and “close & re-open the app”.

    To summarize, there are 3 approaches for when an option is disabled (sorted in order of my preference):

    1. (this is how it works in master, before this PR) Preserve the value (greyed out) through config dialog re-open and through app restart. To achieve this, store an explicit use_proxy: false in settings.json and keep the proxy address in proxy: "...". This means that a config which bitcoind does not recognize will appear in settings.json which will require a tweak here: https://github.com/bitcoin/bitcoin/blob/b297b945f7610772434817181ad12067b2832565/src/util/system.cpp#L569

    2. Delete the value immediately after the checkbox is unchecked. This will make it obvious that the value is gone and will be consistent wrt open/close config dialog and open/close app.

    3. (this is how this PR works (99b4ce266f62afc8a37575527d82ac6048f50f75)) Preserve the value (greyed out) through config dialog re-open, but delete it through an app restart.


    ryanofsky commented at 10:41 pm on April 22, 2022:

    re: #15936 (review)

    I’ll try to implement a patch which implements the previous behavior you seem to like.

    Hmm, I shouldn’t be forcing my view here. I could be nuts and totally disconnected from realitspace_invader Maybe at this point it makes sense to poke other reviewers for opinion. Anyone?

    As a proof of concept I implemented the behavior you requested here: ~https://github.com/ryanofsky/bitcoin/commit/0f29583a903fd8ffa69abe7ae005acac340faa5c~. UPDATE: 4e86ab5dfc9bf40502aca0f9e3a4690f6f5dfc19 is a better version that incorporates #24830 bugfix.

    I don’t think that behavior is nuts but I think the alternative is perfectly fine and each behavior has advantages and disadvantages. For purpose of this PR I’m preferring behavior that has simplest possible implementation, and is completely backwards compatible (i.e, existing bitcoin-qt and bitcoind versions will correctly interpret settings.json files written by new bitcoin-qt versions). As commit https://github.com/ryanofsky/bitcoin/commit/4e86ab5dfc9bf40502aca0f9e3a4690f6f5dfc19 demonstrates, our options for the future are open here. We don’t need to fixate on this one minor behavior. We can start off with the simplest behavior, and change it if there is any desire for more complicated solutions in the future.

    I think it would be less surprising and more obvious what is going on if we clear the values after the user disables the option. Like, immediately after the click on the checkbox. Then the behavior will be consistent between “close & re-open the config dialog box” and “close & re-open the app”.

    IIUC this will require modifying OptionsDialog as well as OptionsModel, and will make interactions between the classes more involved. It may be also be worse for the user if it clears settings before restart while they are still in use. But again, the differences between all these behaviors are small and I don’t think any actual user will have much reason to care about them. I’m just trying to start off with the simplest possible implementation and mental model.

    To achieve this, store an explicit use_proxy: false in settings.json and keep the proxy address in proxy: "...". This means that a config which bitcoind does not recognize will appear in settings.json which will require a tweak

    I’m opposed to changing the setting.json format in this way, or any way that will cause previous versions of bitcoin-qt and bitcoind to not interpret settings correctly. Doing this is not necessary to get the behavior you are requesting with the storing previous values (as https://github.com/ryanofsky/bitcoin/commit/4e86ab5dfc9bf40502aca0f9e3a4690f6f5dfc19 demonstrates). If we do want to change the settnngs.json in a backwards incompatible way in the future, I think we can do that, but it’s not a line I want to be cross here in this PR.


    ryanofsky commented at 3:03 pm on April 29, 2022:

    re: #15936 (review)

    I opened https://github.com/bitcoin-core/gui/issues/596 to continue discussion from this thread and try to resolve this

  182. vasild commented at 3:45 pm on April 14, 2022: member
    Reviewed all as of 7966254822e179798d6a375ac3183321ee541733. Thanks for splitting the last commit, much easier to review now. Hopefully it will be easier for other reviewers too.
  183. DrahtBot added the label Needs rebase on Apr 15, 2022
  184. ryanofsky force-pushed on Apr 19, 2022
  185. ryanofsky commented at 1:15 am on April 19, 2022: member

    Thanks again vasild for the thorough review and testing! I made some updates and fixes in response to you comments, and also replied to everything below.

    Rebased 7966254822e179798d6a375ac3183321ee541733 -> 99b4ce266f62afc8a37575527d82ac6048f50f75 (pr/qtset.38 -> pr/qtset.39, compare) due to conflict with bitcoin-core/gui#556, also fixing uncaught startup exception on setting.json pointed out by vasild, and adding an options id to setting name helper function to reduce code duplication.

  186. DrahtBot removed the label Needs rebase on Apr 19, 2022
  187. in src/qt/optionsmodel.cpp:386 in 99b4ce266f outdated
    420+    case MinimizeOnClose:
    421+        return fMinimizeOnClose;
    422+
    423+    // default proxy
    424+    case ProxyUse:
    425+        return ParseProxyString(SettingToString(setting(), "")).is_set;
    


    vasild commented at 9:01 am on April 19, 2022:

    This diff is now in commit ce530d566f Migrate -prune setting from QSettings to settings.json, but it has to be amended to commit dd3d146f72 Migrate -proxy and -onion settings from QSettings to settings.json

     0--- a/src/qt/optionsmodel.cpp
     1+++ b/src/qt/optionsmodel.cpp
     2@@ -338,21 +364,21 @@ QVariant OptionsModel::getOption(OptionID option) const
     3 #endif // USE_NATPMP
     4     case MinimizeOnClose:
     5         return fMinimizeOnClose;
     6 
     7     // default proxy
     8     case ProxyUse:
     9-        return ParseProxyString(SettingToString(node().getPersistentSetting("proxy"), "")).is_set;
    10+        return ParseProxyString(SettingToString(setting(), "")).is_set;
    11     case ProxyIP:
    12         return m_proxy_ip;
    13     case ProxyPort:
    14         return m_proxy_port;
    15 
    16     // separate Tor proxy
    17     case ProxyUseTor:
    18-        return ParseProxyString(SettingToString(node().getPersistentSetting("onion"), "")).is_set;
    19+        return ParseProxyString(SettingToString(setting(), "")).is_set;
    20     case ProxyIPTor:
    21         return m_onion_ip;
    22     case ProxyPortTor:
    23         return m_onion_port;
    24 
    25 #ifdef ENABLE_WALLET
    26@@ -430,56 +456,56 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value)
    27         settings.setValue("fMinimizeOnClose", fMinimizeOnClose);
    28         break;
    29 
    30     // default proxy
    31     case ProxyUse:
    32         if (changed()) {
    33-            node().updateSetting("proxy", ProxyString(value.toBool(), m_proxy_ip, m_proxy_port));
    34+            update(ProxyString(value.toBool(), m_proxy_ip, m_proxy_port));
    35             setRestartRequired(true);
    36         }
    37         break;
    38     case ProxyIP:
    39         if (changed()) {
    40             m_proxy_ip = value.toString();
    41             if (getOption(ProxyUse).toBool()) {
    42-                node().updateSetting("proxy", ProxyString(true, m_proxy_ip, m_proxy_port));
    43+                update(ProxyString(true, m_proxy_ip, m_proxy_port));
    44                 setRestartRequired(true);
    45             }
    46         }
    47         break;
    48     case ProxyPort:
    49         if (changed()) {
    50             m_proxy_port = value.toString();
    51             if (getOption(ProxyUse).toBool()) {
    52-                node().updateSetting("proxy", ProxyString(true, m_proxy_ip, m_proxy_port));
    53+                update(ProxyString(true, m_proxy_ip, m_proxy_port));
    54                 setRestartRequired(true);
    55             }
    56         }
    57         break;
    58 
    59     // separate Tor proxy
    60     case ProxyUseTor:
    61         if (changed()) {
    62-            node().updateSetting("onion", ProxyString(value.toBool(), m_onion_ip, m_onion_port));
    63+            update(ProxyString(value.toBool(), m_onion_ip, m_onion_port));
    64             setRestartRequired(true);
    65         }
    66         break;
    67     case ProxyIPTor:
    68         if (changed()) {
    69             m_onion_ip = value.toString();
    70             if (getOption(ProxyUseTor).toBool()) {
    71-                node().updateSetting("onion", ProxyString(true, m_onion_ip, m_onion_port));
    72+                update(ProxyString(true, m_onion_ip, m_onion_port));
    73                 setRestartRequired(true);
    74             }
    75         }
    76         break;
    77     case ProxyPortTor:
    78         if (changed()) {
    79             m_onion_port = value.toString();
    80             if (getOption(ProxyUseTor).toBool()) {
    81-                node().updateSetting("onion", ProxyString(true, m_onion_ip, m_onion_port));
    82+                update(ProxyString(true, m_onion_ip, m_onion_port));
    83                 setRestartRequired(true);
    84             }
    85         }
    86         break;
    87 
    88 #ifdef ENABLE_WALLET
    

    ryanofsky commented at 10:42 pm on April 22, 2022:

    re: #15936 (review)

    This diff is now in commit ce530d5 Migrate -prune setting from QSettings to settings.json, but it has to be amended to commit dd3d146 Migrate -proxy and -onion settings from QSettings to settings.json diff

    Good catch. Now moved changes to the right commit.

  188. vasild commented at 1:31 pm on April 21, 2022: member
    Coverage report for modified lines by this PR and not covered by tests (test_bitcoin, test_bitcoin-qt, functional tests).
  189. in src/qt/optionsmodel.h:110 in 99b4ce266f outdated
    109 
    110     interfaces::Node& node() const { assert(m_node); return *m_node; }
    111-    void setNode(interfaces::Node& node) { assert(!m_node); m_node = &node; }
    112 
    113 private:
    114     interfaces::Node* m_node = nullptr;
    


    vasild commented at 7:41 am on April 22, 2022:

    Given that m_node is always initialized in the constructor, it can never be nullptr/uninitialized. It is better to make this explicit by changing the type of the member variable from pointer to reference. Here is a patch to amend into f384d4d935 refactor: Pass interfaces::Node references to OptionsModel constructor:

     0diff --git i/src/qt/optionsmodel.cpp w/src/qt/optionsmodel.cpp
     1index a83c61ffcc..0bde4407ca 100644
     2--- i/src/qt/optionsmodel.cpp
     3+++ w/src/qt/optionsmodel.cpp
     4@@ -91,13 +91,13 @@ struct ProxySetting {
     5     QString port;
     6 };
     7 static ProxySetting ParseProxyString(const std::string& proxy);
     8 static std::string ProxyString(bool is_set, QString ip, QString port);
     9 
    10 OptionsModel::OptionsModel(interfaces::Node& node, QObject *parent) :
    11-    QAbstractListModel(parent), m_node(&node)
    12+    QAbstractListModel(parent), m_node{node}
    13 {
    14 }
    15 
    16 void OptionsModel::addOverriddenOption(const std::string &option)
    17 {
    18     strOverriddenByCommandLine += QString::fromStdString(option) + "=" + QString::fromStdString(gArgs.GetArg(option, "")) + " ";
    19diff --git i/src/qt/optionsmodel.h w/src/qt/optionsmodel.h
    20index 4ee0d77a8e..5a4da8a72d 100644
    21--- i/src/qt/optionsmodel.h
    22+++ w/src/qt/optionsmodel.h
    23@@ -102,16 +102,16 @@ public:
    24     void SetPruneTargetGB(int prune_target_gb);
    25 
    26     /* Restart flag helper */
    27     void setRestartRequired(bool fRequired);
    28     bool isRestartRequired() const;
    29 
    30-    interfaces::Node& node() const { assert(m_node); return *m_node; }
    31+    interfaces::Node& node() const { return m_node; }
    32 
    33 private:
    34-    interfaces::Node* m_node = nullptr;
    35+    interfaces::Node& m_node;
    36     /* Qt-only settings */
    37     bool m_show_tray_icon;
    38     bool fMinimizeToTray;
    39     bool fMinimizeOnClose;
    40     QString language;
    41     BitcoinUnit m_display_bitcoin_unit;
    

    ryanofsky commented at 10:38 pm on April 22, 2022:

    re: #15936 (review)

    Given that m_node is always initialized in the constructor, it can never be nullptr/uninitialized. It is better to make this explicit by changing the type of the member variable from pointer to reference. Here is a patch to amend into f384d4d refactor: Pass interfaces::Node references to OptionsModel constructor:

    Makes sense. Added this change.

  190. in src/qt/bitcoin.cpp:299 in 99b4ce266f outdated
    295@@ -281,6 +296,7 @@ void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
    296 {
    297     assert(!m_splash);
    298     m_splash = new SplashScreen(networkStyle);
    299+    m_splash->setNode(node());
    


    vasild commented at 7:58 am on April 22, 2022:

    It turns out that now this is the only place where the constructor of SplashScreen is called and it is immediately followed by an unconditional call to setNode(). So it would be better to pass the node to the constructor and ditch the setNode() method. This also allows to make the SplashSceen::m_node member a reference, so that it is obvious that it will always be initialized.

    Here is a diff to amend into f384d4d9350f94043518d1cba98f4054cd54b325 refactor: Pass interfaces::Node references to OptionsModel constructor or maybe that deserves a separate commit or maybe even a followup PR:

      0diff --git i/src/qt/bitcoin.cpp w/src/qt/bitcoin.cpp
      1index 324f1c7ce0..ad6a7a129d 100644
      2--- i/src/qt/bitcoin.cpp
      3+++ w/src/qt/bitcoin.cpp
      4@@ -292,14 +292,13 @@ void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
      5     });
      6 }
      7 
      8 void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
      9 {
     10     assert(!m_splash);
     11-    m_splash = new SplashScreen(networkStyle);
     12-    m_splash->setNode(node());
     13+    m_splash = new SplashScreen(node(), networkStyle);
     14     // We don't hold a direct pointer to the splash screen after creation, but the splash
     15     // screen will take care of deleting itself when finish() happens.
     16     m_splash->show();
     17     connect(this, &BitcoinApplication::splashFinished, m_splash, &SplashScreen::finish);
     18     connect(this, &BitcoinApplication::requestedShutdown, m_splash, &QWidget::close);
     19 }
     20diff --git i/src/qt/splashscreen.cpp w/src/qt/splashscreen.cpp
     21index a4dfffa387..de99e36ad0 100644
     22--- i/src/qt/splashscreen.cpp
     23+++ w/src/qt/splashscreen.cpp
     24@@ -24,14 +24,14 @@
     25 #include <QCloseEvent>
     26 #include <QPainter>
     27 #include <QRadialGradient>
     28 #include <QScreen>
     29 
     30 
     31-SplashScreen::SplashScreen(const NetworkStyle* networkStyle)
     32-    : QWidget(), curAlignment(0)
     33+SplashScreen::SplashScreen(interfaces::Node& node, const NetworkStyle* networkStyle)
     34+    : QWidget(), curAlignment(0), m_node{node}
     35 {
     36     // set reference point, paddings
     37     int paddingRight            = 50;
     38     int paddingTop              = 50;
     39     int titleVersionVSpace      = 17;
     40     int titleCopyrightVSpace    = 40;
     41@@ -127,31 +127,25 @@ SplashScreen::SplashScreen(const NetworkStyle* networkStyle)
     42     setFixedSize(r.size());
     43     move(QGuiApplication::primaryScreen()->geometry().center() - r.center());
     44 
     45     installEventFilter(this);
     46 
     47     GUIUtil::handleCloseWindowShortcut(this);
     48-}
     49 
     50-SplashScreen::~SplashScreen()
     51-{
     52-    if (m_node) unsubscribeFromCoreSignals();
     53+    subscribeToCoreSignals();
     54 }
     55 
     56-void SplashScreen::setNode(interfaces::Node& node)
     57+SplashScreen::~SplashScreen()
     58 {
     59-    assert(!m_node);
     60-    m_node = &node;
     61-    subscribeToCoreSignals();
     62-    if (m_shutdown) m_node->startShutdown();
     63+    unsubscribeFromCoreSignals();
     64 }
     65 
     66 void SplashScreen::shutdown()
     67 {
     68     m_shutdown = true;
     69-    if (m_node) m_node->startShutdown();
     70+    m_node.startShutdown();
     71 }
     72 
     73 bool SplashScreen::eventFilter(QObject * obj, QEvent * ev) {
     74     if (ev->type() == QEvent::KeyPress) {
     75         QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
     76         if (keyEvent->key() == Qt::Key_Q) {
     77@@ -189,22 +183,22 @@ static void ShowProgress(SplashScreen *splash, const std::string &title, int nPr
     78             strprintf("\n%d", nProgress) + "%");
     79 }
     80 
     81 void SplashScreen::subscribeToCoreSignals()
     82 {
     83     // Connect signals to client
     84-    m_handler_init_message = m_node->handleInitMessage(std::bind(InitMessage, this, std::placeholders::_1));
     85-    m_handler_show_progress = m_node->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
     86-    m_handler_init_wallet = m_node->handleInitWallet([this]() { handleLoadWallet(); });
     87+    m_handler_init_message = m_node.handleInitMessage(std::bind(InitMessage, this, std::placeholders::_1));
     88+    m_handler_show_progress = m_node.handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
     89+    m_handler_init_wallet = m_node.handleInitWallet([this]() { handleLoadWallet(); });
     90 }
     91 
     92 void SplashScreen::handleLoadWallet()
     93 {
     94 #ifdef ENABLE_WALLET
     95     if (!WalletModel::isWalletEnabled()) return;
     96-    m_handler_load_wallet = m_node->walletLoader().handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
     97+    m_handler_load_wallet = m_node.walletLoader().handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
     98         m_connected_wallet_handlers.emplace_back(wallet->handleShowProgress(std::bind(ShowProgress, this, std::placeholders::_1, std::placeholders::_2, false)));
     99         m_connected_wallets.emplace_back(std::move(wallet));
    100     });
    101 #endif
    102 }
    103 
    104diff --git i/src/qt/splashscreen.h w/src/qt/splashscreen.h
    105index c14fc521a7..e9879e835b 100644
    106--- i/src/qt/splashscreen.h
    107+++ w/src/qt/splashscreen.h
    108@@ -25,15 +25,14 @@ class Wallet;
    109  */
    110 class SplashScreen : public QWidget
    111 {
    112     Q_OBJECT
    113 
    114 public:
    115-    explicit SplashScreen(const NetworkStyle *networkStyle);
    116+    explicit SplashScreen(interfaces::Node& node, const NetworkStyle* networkStyle);
    117     ~SplashScreen();
    118-    void setNode(interfaces::Node& node);
    119 
    120 protected:
    121     void paintEvent(QPaintEvent *event) override;
    122     void closeEvent(QCloseEvent *event) override;
    123 
    124 public Q_SLOTS:
    125@@ -59,13 +58,13 @@ private:
    126 
    127     QPixmap pixmap;
    128     QString curMessage;
    129     QColor curColor;
    130     int curAlignment;
    131 
    132-    interfaces::Node* m_node = nullptr;
    133+    interfaces::Node& m_node;
    134     bool m_shutdown = false;
    135     std::unique_ptr<interfaces::Handler> m_handler_init_message;
    136     std::unique_ptr<interfaces::Handler> m_handler_show_progress;
    137     std::unique_ptr<interfaces::Handler> m_handler_init_wallet;
    138     std::unique_ptr<interfaces::Handler> m_handler_load_wallet;
    139     std::list<std::unique_ptr<interfaces::Wallet>> m_connected_wallets;
    

    ryanofsky commented at 10:37 pm on April 22, 2022:

    re: #15936 (review)

    It turns out that now this is the only place where the constructor of SplashScreen is called and it is immediately followed by an unconditional call to setNode(). So it would be better to pass the node to the constructor and ditch the setNode() method. This also allows to make the SplashSceen::m_node member a reference, so that it is obvious that it will always be initialized.

    Thanks, applied this change

  191. ryanofsky referenced this in commit 2dd933be17 on Apr 23, 2022
  192. ryanofsky force-pushed on Apr 23, 2022
  193. ryanofsky commented at 0:48 am on April 23, 2022: member

    Thanks vasild for the more thorough reviews! I implmented all your suggestions, including the one that retains disabled proxy and prune setting across restarts, except that one is a separate commit not currently included in the PR because of the complexity it adds (see comments below).

    Updated 99b4ce266f62afc8a37575527d82ac6048f50f75 -> 633596af152ddc893269787b227d2ea3f9c1c899 (pr/qtset.39 -> pr/qtset.40, compare) with various suggestions and fixes from vasild, also fixing an fs::quoted windows build error https://cirrus-ci.com/task/5838702671822848

    re: #15936 (review)

    Probably Hennadii could confirm, but I think the only reason the commit was called a prerequisite was that at the time, getOption() method did not exist, so OptionsModel didn’t provide a convenient way to get the current UPNP value, while setting a new NATPMP value, or vice versa. So the mapPort call was moved out of OptionsModel to OptionsDialog, where the call didn’t really belong, but both option values are easily available. However, OptionsModel always made more sense than for the call than OptionsDialog, because OptionsModel is the place where every other setting is applied (also the place that makes sense conceptually, for model/view separation).

  194. ryanofsky referenced this in commit fdbdcd744d on Apr 26, 2022
  195. ryanofsky referenced this in commit c657f005eb on Apr 26, 2022
  196. ryanofsky referenced this in commit 1d4122dfef on Apr 26, 2022
  197. vasild commented at 10:04 am on April 27, 2022: member
    633596af152ddc893269787b227d2ea3f9c1c899 looks ok, modulo the vanishing proxy values, I have to think more about this. I will also test a bit further. Thanks!
  198. ryanofsky commented at 3:12 pm on April 29, 2022: member

    re: #15936 (comment)

    633596a looks ok, modulo the vanishing proxy values, I have to think more about this. I will also test a bit further. Thanks!

    Thanks again for the reviews! I would probably qualify them “vanishing disabled values after restarting” instead of “vanishing values” but I opened https://github.com/bitcoin-core/gui/issues/596 to think about this more and get more feedback

  199. in src/qt/optionsmodel.cpp:198 in 68a4f322e9 outdated
    109+        std::string setting = SettingName(option);
    110+        if (node().isSettingIgnored(setting)) addOverriddenOption("-" + setting);
    111+        try {
    112+            getOption(option);
    113+        } catch (const std::runtime_error& e) {
    114+            error = strprintf(_("Could not read setting \"%s\", %s."), setting, e.what());
    


    Sjors commented at 5:03 pm on April 29, 2022:
    68a4f322e93e413cb8f1f1b998a2b2ee63df9b9d: how can you trigger this error?

    vasild commented at 8:00 am on May 2, 2022:

    The only way to throw from getOption() is if SettingName() (called from getOption()) throws. However, SettingName(option) (same argument) is also called just before this try/catch without try/catch. So, if SettingName() is going to throw it will do so before this try/catch and so this code will never be reached.

    To trigger that SettingName() to throw the source code must be modified. Cannot be triggered by wrong user input or corrupted config file.


    ryanofsky commented at 3:39 pm on May 2, 2022:

    re: #15936 (review)

    To trigger that SettingName() to throw the source code must be modified. Cannot be triggered by wrong user input or corrupted config file.

    I added a comment to clarify, but this is not the case! The catch is supposed to deal with runtime_error exceptions thrown by univalue, related to the ones you reported #15936 (review). You can trigger it by adding a nonsense line like "upnp": 37 to the settings file.

  200. Sjors commented at 5:46 pm on April 29, 2022: member

    Did some code review up to 1e1ccabf0d38201e1c37164c7ec02ff8036af820.

    Lightly tested some of the settings migrations. This should be thoroughly tested though, especially the Tor proxy, since a mistake there could have privacy consequences.

    Once all settings are migrated, the following text needs to be adjusted: “Options set in this dialog are overridden by the command line ~or in the configuration file~”. The way it seems to work now (which is fine by me) is that that settings.json takes precedent over bitcoin.conf, whereas previously bitcoin.conf would take precedence over GUI settings.

    The above change has some subtle consequences, that are probably fine. If before this PR you set dbcache=1000 in bitcoin.conf and 999 in the GUI settings, it would use 1000. This PR wipes 999 from QT’s settings and sets the field to 1000. This is definitely safer than the alternative of migrating the GUI setting and suddenly starting to use it. It may be good to point this behaviour out in the release notes.

  201. ryanofsky force-pushed on May 2, 2022
  202. ryanofsky commented at 6:20 pm on May 2, 2022: member

    re: #15936#pullrequestreview-958013757

    Once all settings are migrated, the following text needs to be adjusted: “Options set in this dialog are overridden by the command line ~or in the configuration file~”.

    This change is made in the commit migrating the last setting which would be overridden by the configuration file (commit “Migrate -lang setting from QSettings to settings.json” af8ac293addda5778a52cc39bc270a0c9179bafb). I think this is after the commits you looked at.

    It may be good to point this behaviour out in the release notes.

    Thanks, updated to mention the bitcoin.conf interaction. All the behavior you described is intentional. Applying this PR or reverting it should keep applied settings values the same.


    Updated 633596af152ddc893269787b227d2ea3f9c1c899 -> 2f77c49174ca3932988f74faf75c8838dd95ec82 (pr/qtset.40 -> pr/qtset.41, compare) adding comment and more release notes.

  203. vasild commented at 11:28 am on May 3, 2022: member
    While testing this, 22.x crashes if settings.json contains "prune": 1234 due to #24498 which was fixed in 23.0. So, if this PR is included in 24.x and a user upgrades to 24.x and then downgrades to 22.x his 22.x would crash at startup. Is that acceptable?
  204. ryanofsky commented at 12:02 pm on May 3, 2022: member

    While testing this, 22.x crashes if settings.json contains "prune": 1234 due to #24498 which was fixed in 23.0. So, if this PR is included in 24.x and a user upgrades to 24.x and then downgrades to 22.x his 22.x would crash at startup. Is that acceptable?

    What a mess. I guess I’ll just write a string instead of an int to avoid this. Maybe will try to backport #24498, too, since it’s a one-line fix and would make 22.x less fragile in general. Thanks for testing this! It is pretty important for this PR to be backwards compatible.

    UPDATE: Same issue will probably happen with the “dbcache” and “par” int settings, so I will address these too. But the “prune” setting is most likely to trigger this since that is most likely to be changed from the default.

  205. ryanofsky force-pushed on May 16, 2022
  206. ryanofsky commented at 7:14 pm on May 16, 2022: member

    re: #15936 (comment)

    What a mess. I guess I’ll just write a string instead of an int to avoid this

    Updated so this now writes 22.x int settings as strings to avoid triggering uncaught exceptions if there is a downgrade. I also added a new commit to clear settings.json file when the reset button is pressed, after @Rspigler’s comment https://github.com/bitcoin-core/gui/issues/596#issuecomment-1115233031

    Updated 2f77c49174ca3932988f74faf75c8838dd95ec82 -> 616b95a061ae4b9de171277da1e97d3d6543b0b0 (pr/qtset.41 -> pr/qtset.42, compare) with 22.x compatibility and reset button fixes

  207. ryanofsky force-pushed on May 17, 2022
  208. ryanofsky commented at 3:58 pm on May 17, 2022: member

    This PR needs more ACKs, but it has been reviewed extensively and tested to death. I’d really appreciate any new review and testing, but also updates from people who commented previously. Summary of feedback so far:

  209. settings: Add update/getPersistent/isIgnored methods
    Add interfaces::Node methods to give GUI finer grained control over
    settings.json file. Update method is used to write settings to the file,
    getPersistent and isIgnored methods are used to find out about settings
    file and command line option interactions.
    0e55bc6e7f
  210. init: Remove Shutdown() node.args reset
    This commit removes the `node.args = nullptr` assignment in the Shutdown()
    function.
    
    Clearing node.args there never made sense because it made the
    Shutdown() function not idempotent, making it fragile and causing issues like
    https://github.com/bitcoin/bitcoin/issues/23186.
    
    The assignment also causes segfaults in GUI unit tests when a new
    node().initParameterInteraction() call is added in OptionsModel to apply to Qt
    settings (happens because AppTests calls Shutdown() which sets node.args to
    null, and OptionTests runs after AppTests and then needs node.args not to be
    null.)
    77fabffef4
  211. settings: Add resetSettings() method
    Allows the GUI to clear settings.json file and save settings.json.bak file when
    GUI "Reset Options" button is pressed or -resetguisettings command line option
    is used. (GUI code already backs up and resets the "guisettings.ini" file this
    way, so this just makes the same behavior possible for "settings.json")
    f9fdcec7e9
  212. DrahtBot added the label Needs rebase on May 19, 2022
  213. ryanofsky referenced this in commit f2b20bb65f on May 19, 2022
  214. ryanofsky referenced this in commit 685aab235c on May 19, 2022
  215. ryanofsky force-pushed on May 19, 2022
  216. ryanofsky commented at 6:51 pm on May 19, 2022: member
    Rebased e4ef0b6f78cc7c6ac148674b9c8ac40bd7e5f30d -> 084b888ef1934f4ef88da33f72ffdd321af7c6b7 (pr/qtset.43 -> pr/qtset.44, compare) due to conflict with #25153
  217. ryanofsky referenced this in commit 945e4676dd on May 19, 2022
  218. ryanofsky force-pushed on May 19, 2022
  219. ryanofsky renamed this:
    Unify bitcoin-qt and bitcoind persistent settings
    interfaces: Expose settings.json methods to GUI
    on May 19, 2022
  220. ryanofsky commented at 8:29 pm on May 19, 2022: member
    Updated 084b888ef1934f4ef88da33f72ffdd321af7c6b7 -> 02ce0badbe3fd50a508b1c189082c91bff420c60 (pr/qtset.44 -> pr/qtset.45, compare) dropping the GUI changes from this PR and moving them to https://github.com/bitcoin-core/gui/pull/602. This should make the node changes here, and the GUI changes over there both easier to review
  221. DrahtBot removed the label Needs rebase on May 19, 2022
  222. in src/util/system.cpp:581 in 02ce0badbe outdated
    574@@ -572,10 +575,10 @@ bool ArgsManager::ReadSettingsFile(std::vector<std::string>* errors)
    575     return true;
    576 }
    577 
    578-bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors) const
    579+bool ArgsManager::WriteSettingsFile(std::vector<std::string>* errors, bool backup) const
    580 {
    581     fs::path path, path_tmp;
    582-    if (!GetSettingsPath(&path, /* temp= */ false) || !GetSettingsPath(&path_tmp, /* temp= */ true)) {
    583+    if (!GetSettingsPath(&path, /* temp= */ false, backup) || !GetSettingsPath(&path_tmp, /* temp= */ true, backup)) {
    


    hebasto commented at 9:12 pm on May 19, 2022:

    02ce0badbe3fd50a508b1c189082c91bff420c60, style nit

    0    if (!GetSettingsPath(&path, /*temp=*/false, backup) || !GetSettingsPath(&path_tmp, /*temp=*/true, backup)) {
    
  223. hebasto approved
  224. hebasto commented at 9:16 pm on May 19, 2022: member

    ACK 02ce0badbe3fd50a508b1c189082c91bff420c60, I have reviewed the code and it looks OK, I agree it can be merged.

    Thanks for 9dd3817ee2f67d021aad7a809daa136300a8d8e1 “init: Remove Shutdown() node.args reset” commit!

    Only style nits, including following parameter naming convention in new SettingTo{String,Int,Bool} functions. Anyway, feel free to ignore :)

  225. ryanofsky force-pushed on May 19, 2022
  226. ryanofsky commented at 9:51 pm on May 19, 2022: member

    Thanks for the review!

    Updated 02ce0badbe3fd50a508b1c189082c91bff420c60 -> 3340286c752d2b8ace594f7ae179c290b3687a37 (pr/qtset.45 -> pr/qtset.46, compare) just tweaking some comments, including the parameter name one that was suggested.

  227. hebasto approved
  228. hebasto commented at 10:14 pm on May 19, 2022: member
    re-ACK 3340286c752d2b8ace594f7ae179c290b3687a37
  229. Rspigler commented at 3:32 am on May 20, 2022: contributor
    I will re-test tomorrow. Thanks for keeping this up!
  230. MarcoFalke referenced this in commit 4a8709821e on May 20, 2022
  231. vasild approved
  232. vasild commented at 9:26 am on May 20, 2022: member
    ACK 3340286c752d2b8ace594f7ae179c290b3687a37
  233. ryanofsky referenced this in commit c2051b35f4 on May 20, 2022
  234. Rspigler commented at 4:19 am on May 21, 2022: contributor

    tACK 3340286c752d2b8ace594f7ae179c290b3687a37

    Tested with various changes to settings.json, bitcoin.conf, and the GUI. Everything behaved as it should.

    Previous issues people reported are resolved (including #24457).

    Only other issue is solved by https://github.com/bitcoin-core/gui/pull/603

  235. in src/node/interfaces.cpp:128 in e58b932f58 outdated
    123+        return ignored;
    124+    }
    125+    util::SettingsValue getPersistentSetting(const std::string& name) override { return gArgs.GetPersistentSetting(name); }
    126+    void updateSetting(const std::string& name, const util::SettingsValue& value) override
    127+    {
    128+        gArgs.LockSettings([&](util::Settings& settings) {
    


    promag commented at 11:37 am on May 21, 2022:

    Could be?

    0updateRwSetting(name, value, /* write = */ true)
    

    ryanofsky commented at 3:32 pm on May 23, 2022:

    re: #15936 (review)

    0updateRwSetting(name, value, /* write = */ true)
    

    Thanks renamed to updateRwSetting to be consistent with the Chain interface

  236. promag commented at 11:40 am on May 21, 2022: member
    Concept ACK, unifying persistent node settings across apps makes sense to me.
  237. Rspigler commented at 1:11 am on May 22, 2022: contributor
  238. naumenkogs referenced this in commit 614afa5c42 on May 23, 2022
  239. ryanofsky force-pushed on May 23, 2022
  240. ryanofsky commented at 3:35 pm on May 23, 2022: member
    Updated 3340286c752d2b8ace594f7ae179c290b3687a37 -> f9fdcec7e932843a91ddf7f377e00bd2a6efb82a (pr/qtset.46 -> pr/qtset.47, compare) just renaming updateSetting to updateRwSetting;
  241. hebasto referenced this in commit 1368634433 on May 24, 2022
  242. vasild approved
  243. vasild commented at 1:43 pm on May 24, 2022: member
    ACK f9fdcec7e932843a91ddf7f377e00bd2a6efb82a
  244. laanwj referenced this in commit 04fdd644b4 on May 25, 2022
  245. hebasto approved
  246. hebasto commented at 12:45 pm on May 25, 2022: member
    re-ACK f9fdcec7e932843a91ddf7f377e00bd2a6efb82a, only a function renamed since my recent review.
  247. ryanofsky commented at 2:05 pm on May 26, 2022: member
    This is probably ready for merge (sorry for the confusing history, it was originally a lot bigger PR before I removed the GUI parts)
  248. MarcoFalke merged this on May 26, 2022
  249. MarcoFalke closed this on May 26, 2022

  250. sidhujag referenced this in commit c58ab277af on May 28, 2022
  251. sidhujag referenced this in commit e191780261 on May 28, 2022
  252. PastaPastaPasta referenced this in commit ebe4525780 on Jun 7, 2022
  253. PastaPastaPasta referenced this in commit 483d04fc12 on Jun 7, 2022
  254. PastaPastaPasta referenced this in commit 28f6701907 on Jun 10, 2022
  255. hebasto referenced this in commit 37633d2f61 on Jun 12, 2022
  256. PastaPastaPasta referenced this in commit 893835826a on Jun 14, 2022
  257. janus referenced this in commit 8b785de388 on Aug 4, 2022
  258. ryanofsky referenced this in commit bd354d6fdc on Sep 21, 2022
  259. ryanofsky referenced this in commit 9d3127b11e on Sep 21, 2022
  260. josibake referenced this in commit ae35f65df3 on Apr 5, 2023
  261. DrahtBot locked this on May 26, 2023

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: 2024-11-23 21:12 UTC

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