Skip to content

Conversation

@kwvg
Copy link
Collaborator

@kwvg kwvg commented Aug 30, 2025

Additional Information

Breaking Changes

See release notes.

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@kwvg kwvg added this to the 23 milestone Aug 30, 2025
@github-actions
Copy link

github-actions bot commented Aug 30, 2025

✅ No Merge Conflicts Detected

This PR currently has no conflicts with other open PRs.

@kwvg
Copy link
Collaborator Author

kwvg commented Aug 30, 2025

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Aug 30, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Aug 30, 2025

Walkthrough

OptionsModel was refactored to be node-aware and deferred-initialized: its constructor now takes interfaces::Node& and Init(bilingual_str& error) returns bool. BitcoinApplication::createOptionsModel(bool) now returns bool and startup creates the splash and node earlier, aborting startup on options init failure. Settings persistence was migrated from QSettings to node-backed settings.json (including prune, proxy, font, mask values), many legacy QSettings keys are migrated/removed, and some QSettings-based behavior (e.g., UPnP persistence on accept) was removed. Tests and UI components were updated to construct OptionsModel with a node and call Init(error).

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant App as BitcoinApplication
    participant Splash as SplashScreen
    participant OM as OptionsModel
    participant Node as interfaces::Node
    participant FS as settings.json

    rect rgb(235,245,255)
    Note over App,Splash: Early startup: splash & node creation
    User->>App: Launch
    App->>Splash: create & show
    App->>Node: create node instance
    end

    rect rgb(245,255,235)
    Note over App,OM: Node-backed OptionsModel init (deferred constructor)
    App->>OM: new OptionsModel(node, parent)
    OM-->>App: constructed (Init deferred)
    App->>OM: Init(error)
    OM->>Node: read/migrate settings
    Node->>FS: read/write settings.json
    FS-->>Node: return settings
    Node-->>OM: settings values / ack writes
    alt Init success
        OM-->>App: true
        App->>App: continue startup -> show main window
    else Init failure
        OM-->>App: false + error
        App->>User: show critical error (settings path)
        App->>App: exit(EXIT_FAILURE)
    end
    end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.66% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: migrating QSettings to settings.json by backporting specific bitcoin-core/gui PRs.
Description check ✅ Passed The description is related to the changeset, providing context about dependencies, breaking changes, and completion of required checklist items.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4fb6c74 and 076ce3d.

📒 Files selected for processing (1)
  • src/qt/optionsmodel.cpp
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{cpp,h,hpp,cc}

📄 CodeRabbit inference engine (CLAUDE.md)

Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1

Files:

  • src/qt/optionsmodel.cpp
src/qt/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

GUI implementation in src/qt/ must use Qt 5

Files:

  • src/qt/optionsmodel.cpp
🧠 Learnings (14)
📓 Common learnings
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6786
File: ci/test/04_install.sh:99-101
Timestamp: 2025-08-01T07:46:37.840Z
Learning: In backport PRs like #6786, UdjinM6 prefers to defer non-critical fixes (such as shell command expansion issues) to separate commits/PRs to maintain focus on the primary backport objectives, consistent with the project's pattern of avoiding scope creep.
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 6804
File: src/qt/proposalwizard.cpp:40-42
Timestamp: 2025-08-11T17:16:36.654Z
Learning: In the Dash repository, when a PR adds new files that are not from Bitcoin backports, these files must be added to the list in test/util/data/non-backported.txt. This applies to newly created files like qt/proposalwizard.{h,cpp} and forms/proposalwizard.ui. Limited exemptions may exist for subtrees and similar cases.
Learnt from: kwvg
Repo: dashpay/dash PR: 7072
File: src/qt/walletcontroller.cpp:520-528
Timestamp: 2025-12-17T13:58:26.891Z
Learning: In Dash Qt wallet code, when leveraging upstream Bitcoin Core wallet capabilities (especially for operations like rescanning), prefer using the inherited signal-based mechanisms (e.g., ShowProgress signals) over adding explicit Qt progress dialogs to minimize upstream deviation and simplify future backports.
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: knst
Repo: dashpay/dash PR: 6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.
📚 Learning: 2025-12-17T13:58:19.813Z
Learnt from: kwvg
Repo: dashpay/dash PR: 7072
File: src/qt/walletcontroller.cpp:520-528
Timestamp: 2025-12-17T13:58:19.813Z
Learning: In Dash Qt wallet code, prefer using existing Qt signals/slots (e.g., ShowProgress signals) for long-running operations instead of adding explicit QProgressDialog dialogs. This minimizes upstream deviations and simplifies backports. Apply this pattern to wallet-related Qt components (e.g., operations like rescanning) and rely on signal-based progress updates rather than bespoke dialogs.

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-07-29T14:32:48.369Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-02-06T14:34:30.466Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-10-25T07:08:51.918Z
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-10-05T20:38:28.457Z
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-08-11T17:16:36.654Z
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 6804
File: src/qt/proposalwizard.cpp:40-42
Timestamp: 2025-08-11T17:16:36.654Z
Learning: In the Dash repository, when a PR adds new files that are not from Bitcoin backports, these files must be added to the list in test/util/data/non-backported.txt. This applies to newly created files like qt/proposalwizard.{h,cpp} and forms/proposalwizard.ui. Limited exemptions may exist for subtrees and similar cases.

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-07-29T14:33:01.040Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/wallet/wallet.cpp:0-0
Timestamp: 2025-07-29T14:33:01.040Z
Learning: In refactoring PRs like #6761, kwvg acknowledges code safety improvements (like null pointer checks and unused parameter warnings) but prefers to defer them to follow-up PRs to maintain focus on the primary refactoring objectives, avoiding scope creep.

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-10-13T12:37:12.357Z
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-11-04T18:24:27.241Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/wallet/**/*.{cpp,h} : Wallet implementation must use Berkeley DB and SQLite

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-12-22T15:42:51.679Z
Learnt from: kwvg
Repo: dashpay/dash PR: 7068
File: src/qt/guiutil_font.h:68-77
Timestamp: 2025-12-22T15:42:51.679Z
Learning: In the Dash Core Qt codebase (src/qt/guiutil_font.h), kwvg intentionally uses `assert()` in setter methods like `SetWeightBold` and `SetWeightNormal` to enforce invariants (e.g., `assert(m_weights.count(m_font))`). This fail-fast approach is preferred over defensive checks with fallbacks when an inconsistent state indicates a programming error that should be caught during development, rather than a runtime condition requiring graceful handling.

Applied to files:

  • src/qt/optionsmodel.cpp
🧬 Code graph analysis (1)
src/qt/optionsmodel.cpp (3)
src/util/system.cpp (8)
  • SettingName (190-193)
  • SettingName (190-190)
  • SettingToInt (656-659)
  • SettingToInt (656-656)
  • SettingToString (645-648)
  • SettingToString (645-645)
  • SettingToBool (667-670)
  • SettingToBool (667-667)
src/qt/optionsmodel.h (3)
  • PruneGBtoMiB (35-35)
  • PruneMiBtoGB (30-30)
  • isOptionOverridden (134-134)
src/qt/guiutil_font.cpp (4)
  • weightFromArg (173-181)
  • weightFromArg (173-173)
  • weightToArg (183-187)
  • weightToArg (183-183)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: mac-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_fuzz-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: Lint / Run linters
🔇 Additional comments (9)
src/qt/optionsmodel.cpp (9)

42-175: Well-structured helper functions for settings migration.

The helper functions provide clean abstractions for the settings migration:

  • SettingName() centralizes the mapping from GUI options to node setting names
  • UpdateRwSetting() properly documents the Bitcoin 22.x compatibility workaround
  • Prune and font weight helpers handle conversions and fallbacks correctly

215-217: Constructor signature updated for node-backed design.

The constructor now requires an interfaces::Node& reference, enabling the options model to read/write settings through the node interface rather than directly via QSettings.


226-410: Init() properly handles settings validation and error reporting.

The refactored Init() method introduces several improvements:

  • Returns bool to signal success/failure
  • Accepts bilingual_str& error for user-facing error messages
  • Lines 370-378 catch exceptions from univalue when settings have unexpected types
  • Font weight validation (lines 304-327) includes fallback logic when weights are invalid

The exception handling is particularly important since settings.json can be manually edited and may contain invalid types.


431-471: Reset() correctly backs up settings.json before clearing GUI settings.

The implementation addresses UdjinM6's concern by backing up settings.json at line 434 before clearing GUI-managed settings. The loop (lines 438-448) iterates through all GUI options and clears both the main setting and the "-prev" rollback value. Options without corresponding node settings are properly skipped via the try-catch block.


593-728: getOption() comprehensively migrated to node-backed settings.

The refactored getOption() properly handles:

  • Reading from node settings via the setting() lambda
  • Type conversions using SettingToBool, SettingToInt, SettingToString with safe defaults
  • The "-prev" suffix pattern for rollback scenarios (e.g., lines 630, 641 for proxy settings)
  • Wallet-specific options appropriately guarded by #ifdef ENABLE_WALLET

The recursive pattern for proxy settings (lines 624-633, 636-644) is bounded to one level and correctly falls back to defaults.


1065-1183: Migration logic comprehensively handles QSettings to settings.json transition.

The checkAndMigrate() method implements a thorough migration strategy:

  • Version-gated migrations (lines 1070-1100) ensure one-time execution
  • Lambda-based migration (lines 1121-1140) cleanly handles the common case with special-case logic for:
    • Proxy settings: parses host:port strings and migrates to separate IP/Port options
    • Font weights: converts old integer weights to new index-based format
  • Comprehensive coverage (lines 1142-1175) migrates all node-backed settings
  • Parameter interaction (line 1182): calling node().initParameterInteraction() is crucial—it ensures dependent settings (like -listen affecting -listenonion, -upnp) are recalculated after migration

The migration only writes to node settings if they're not already set (line 1124), preserving CLI overrides.


1-1183: Excellent refactoring of settings persistence to node-backed design.

This comprehensive refactor successfully migrates Qt GUI settings from QSettings to the node-backed settings.json approach. Key strengths:

Robust error handling: Init() catches univalue exceptions and provides bilingual error messages
Settings backup: Reset() properly backs up settings.json before clearing
Rollback support: The "-prev" suffix pattern enables toggling settings like proxy/prune
Migration completeness: checkAndMigrate() thoroughly migrates legacy QSettings with special-case handling
Type safety: Proper use of SettingToBool, SettingToInt, SettingToString with safe defaults

The only verification requested is confirming the Dash-specific behavior where pruning disables governance and txindex (line 521-522).


520-523: Governance and txindex constraints with pruning are correct and enforced.

The code correctly forces disablegovernance=1 and txindex=0 when pruning is enabled. This is a documented, network-wide incompatibility enforced in src/init.cpp (parameter interactions at lines 1033-1038 and validation at lines 1217-1219). The GUI implementation aligns with the daemon initialization logic, and the constraints are properly documented in the help text and error messages.


730-1037: setOption() comprehensively migrated to node-backed settings with correct rollback pattern.

The refactored setOption() implementation is sound:

  • "-prev" rollback pattern (lines 768–825, 991–1008): Proxy and prune options correctly save their previous value with a "-prev" suffix when disabled. Restoration is implicit: getOption() retrieves the "-prev" value when the main setting is disabled, enabling seamless value recovery when re-enabled.
  • Runtime synchronization: CoinJoin options (lines 877–912) correctly update both persistent settings via update() and runtime state via node().coinJoinOptions().setSessions/setRounds/setAmount/etc.
  • Type safety: Proper conversions (toLongLong() to int64_t, font weight index to weight argument).
  • Change detection and persistence: The changed() and update() lambdas (lines 732–733) provide clean abstractions for conditional updates and persistence.

The pattern works correctly via the model layer: UI changes trigger setOption() through QDataWidgetMapper, which persists changes; subsequent getOption() calls with the "-prev" suffix retrieve stored previous values when needed.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/qt/masternodelist.cpp (1)

5-13: Fix CI: clang-format include-order violation.

The pipeline failed due to include order changes. Please run the repo’s clang-format step (e.g., contrib/devtools/clang-format-diff.py -p1) or reorder the includes per project style to satisfy CI.

🧹 Nitpick comments (28)
src/qt/test/test_main.cpp (1)

63-66: Prefer explicit scope over IILE for BasicTestingSetup; also keep creation within the same lifetime as directory creation

This avoids subtle lifetime semantics and reads clearer. Functionally equivalent.

-    fs::create_directories([] {
-        BasicTestingSetup dummy{CBaseChainParams::REGTEST};
-        return gArgs.GetDataDirNet() / "blocks";
-    }());
+    {
+        BasicTestingSetup dummy{CBaseChainParams::REGTEST};
+        fs::create_directories(gArgs.GetDataDirNet() / "blocks");
+    }

Additionally, consider checking the return value or logging failures from create_directories.

src/qt/forms/optionsdialog.ui (1)

1058-1169: Monospaced font selector UI: looks good; add basic UX affordances

  • Add short tooltips to both radio buttons to clarify “embedded” vs “system” choice.
  • Optionally group them in a QButtonGroup for explicit exclusivity (not required, but future-proof if the layout changes).
-             <widget class="QRadioButton" name="embeddedFont_radioButton">
+             <widget class="QRadioButton" name="embeddedFont_radioButton">
               <property name="text">
                <string>embedded "%1"</string>
               </property>
+              <property name="toolTip">
+               <string>Use the bundled monospaced font for amounts.</string>
+              </property>
              </widget>
...
-             <widget class="QRadioButton" name="systemFont_radioButton">
+             <widget class="QRadioButton" name="systemFont_radioButton">
               <property name="text">
                <string>closest matching "%1"</string>
               </property>
+              <property name="toolTip">
+               <string>Use the closest system-installed monospaced font for amounts.</string>
+              </property>
              </widget>
src/qt/masternodelist.cpp (3)

233-240: Localize “UNKNOWN” next-payment text.

Untranslated literal leaks into UI; use tr() for i18n.

-        QString strNextPayment = "UNKNOWN";
+        QString strNextPayment = tr("UNKNOWN");

149-151: Typo: nMnListUpdateSecods → nMnListUpdateSeconds.

Minor readability fix; avoids propagating the misspelling.

-        int64_t nMnListUpdateSecods = clientModel->masternodeSync().isBlockchainSynced() ? MASTERNODELIST_UPDATE_SECONDS : MASTERNODELIST_UPDATE_SECONDS * 10;
-        int64_t nSecondsToWait = nTimeUpdatedDIP3 - GetTime() + nMnListUpdateSecods;
+        int64_t nMnListUpdateSeconds = clientModel->masternodeSync().isBlockchainSynced() ? MASTERNODELIST_UPDATE_SECONDS : MASTERNODELIST_UPDATE_SECONDS * 10;
+        int64_t nSecondsToWait = nTimeUpdatedDIP3 - GetTime() + nMnListUpdateSeconds;

141-147: Avoid briefly showing negative countdown.

Clamp the displayed value to 0 to prevent negative numbers flashing in the label.

-        ui->countLabelDIP3->setText(tr("Please wait…") + " " + QString::number(nSecondsToWait));
+        const auto displayWait = nSecondsToWait > 0 ? nSecondsToWait : 0;
+        ui->countLabelDIP3->setText(tr("Please wait…") + " " + QString::number(displayWait));
src/qt/coincontroldialog.cpp (1)

16-16: Good: proper dependency for GUIUtil::FontWeight.

One question: this file still persists UI prefs via QSettings (Lines 135–139, 153–157). If the PR goal is migrating settings to settings.json where feasible, consider whether these should be moved too, or explicitly documented as remaining UI-local prefs.

src/qt/appearancewidget.h (1)

12-12: Appropriate to include in a header due to member types/default initializers

prevFontFamily and weight members (with default initializers calling GUIUtil getters) require guiutil_font.h in this header. This is the right place to include it.

If compile time becomes a concern later, consider moving function-based default initializers (e.g., GUIUtil::getFontFamily()) into the .cpp constructor to reduce header coupling. Not required for this backport.

src/qt/rpcconsole.cpp (1)

68-71: Consider migrating console font size setting away from QSettings

Given the PR’s “migrate some QSettings to settings.json,” consider moving consoleFontSize to the new persistent settings path (via Node/ArgsManager helpers) for consistency and headless configurability. Low priority; can be follow-up.

src/qt/appearancewidget.cpp (1)

31-33: Populate font families from GUIUtil::AVAILABLE_FONTS — good step; add fallback and verify localization

  • Good: dynamic population with “selectable” filter.
  • Risks:
    • If the stored OptionsModel FontFamily is not selectable on the current platform, currentIndex may be -1 after mapper->toFirst(). Add a graceful fallback to the first available entry and apply it.
    • Ensure family_str strings are already localized in GUIUtil; otherwise, user-facing labels like “System default” should be translated.

Suggested fallback (in setModel(), after mapper->toFirst()):

@@ void AppearanceWidget::setModel(OptionsModel* _model)
-        mapper->toFirst();
+        mapper->toFirst();
+        // Fallback if stored value is not present (e.g., font now non-selectable)
+        if (ui->fontFamily->currentIndex() < 0 && ui->fontFamily->count() > 0) {
+            ui->fontFamily->setCurrentIndex(0);
+            updateFontFamily(0);
+        }

Also verify that guiutil_font.h is included indirectly via appearancewidget.h. If not, include it here:

+#include <qt/guiutil_font.h>
src/qt/bitcoin.h (1)

49-49: Call sites already handle [[nodiscard]] return; add a header comment for failure reasons and optionally inline‐initialize optionsModel.

--- a/src/qt/bitcoin.h
+++ b/src/qt/bitcoin.h
@@
-   /// Create options model
-   [[nodiscard]] bool createOptionsModel(bool resetSettings);
+   /// Create options model; returns false on Init() failure (e.g. settings load error)
+   [[nodiscard]] bool createOptionsModel(bool resetSettings);

@@
-    OptionsModel *optionsModel;
+    OptionsModel *optionsModel{nullptr};
src/qt/test/addressbooktests.cpp (1)

122-125: Prefer QVERIFY2 to surface Init() failure reason.

Improves debuggability without changing behavior.

-    bilingual_str error;
-    QVERIFY(optionsModel.Init(error));
+    bilingual_str error;
+    QVERIFY2(optionsModel.Init(error), error.translated.c_str());
src/qt/test/wallettests.cpp (1)

155-158: Use QVERIFY2 with message for OptionsModel::Init.

Shows the translated error on failure.

-    bilingual_str error;
-    QVERIFY(optionsModel.Init(error));
+    bilingual_str error;
+    QVERIFY2(optionsModel.Init(error), error.translated.c_str());
src/util/settings.cpp (1)

180-182: Nonpersistent filter logic looks correct; consider parity helpers and tests

Skipping COMMAND_LINE and FORCED when ignore_nonpersistent is true aligns with “persistent-only” reads. Two follow-ups:

  • Consider a parallel API for lists (e.g., GetPersistentSettingsList) if the GUI needs array semantics without CLI/forced influence.
  • Add tests covering forced and negated values when ignore_nonpersistent=true to prevent regressions.

I can draft tests mirroring existing settings_tests with forced/CLI sources. Want a patch?

src/node/interfaces.cpp (1)

479-486: Consider error handling during resetSettings

resetSettings() ignores the return of WriteSettingsFile(...). A failed backup or rewrite would be silent. Capture the boolean and log or surface an error to the caller/UI.

Apply:

 void resetSettings() override
 {
-    gArgs.WriteSettingsFile(/*errors=*/nullptr, /*backup=*/true);
+    if (!gArgs.WriteSettingsFile(/*errors=*/nullptr, /*backup=*/true)) {
+        LogPrintf("resetSettings: failed to write backup settings file\n");
+    }
     gArgs.LockSettings([&](util::Settings& settings) {
         settings.rw_settings.clear();
     });
-    gArgs.WriteSettingsFile();
+    if (!gArgs.WriteSettingsFile()) {
+        LogPrintf("resetSettings: failed to write cleared settings file\n");
+    }
 }
src/qt/optionsdialog.cpp (1)

376-376: Map the radio button’s checked property explicitly

Relying on the widget’s user property works, but making the mapping explicit avoids surprises if UI changes later.

Apply:

-    mapper->addMapping(ui->embeddedFont_radioButton, OptionsModel::UseEmbeddedMonospacedFont);
+    mapper->addMapping(ui->embeddedFont_radioButton, OptionsModel::UseEmbeddedMonospacedFont, "checked");
src/interfaces/node.h (1)

197-214: Clarify override semantics (CLI vs forced) and return contracts

Docs say “overridden by the command line,” but implementation likely should also consider forced_settings. Either:

  • Update isSettingIgnored docs to include “or forced settings,” or
  • Intentionally exclude forced and state that explicitly.

Also, updateRwSetting here is void while an existing overload returns bool. Consider harmonizing the contract in a follow-up (even if just by documenting error handling expectations).

src/test/settings_tests.cpp (1)

145-148: NullOverride assertions remain valid with new flag.

Using ignore_nonpersistent=false ensures forced null overrides are tested. Consider adding a complementary test with ignore_nonpersistent=true to lock in persistent-only semantics.

I can add a small test exercising GetPersistentSetting/ignore_nonpersistent=true if helpful.

src/util/system.h (3)

179-182: Avoid leaking helpers into global namespace.

Consider placing SettingToString/SettingToInt/SettingToBool into a namespace (e.g., util) to minimize global symbol surface.

-std::string SettingToString(const util::SettingsValue&, const std::string&);
-int64_t SettingToInt(const util::SettingsValue&, int64_t);
-bool SettingToBool(const util::SettingsValue&, bool);
+namespace util {
+std::string SettingToString(const util::SettingsValue&, const std::string&);
+int64_t SettingToInt(const util::SettingsValue&, int64_t);
+bool SettingToBool(const util::SettingsValue&, bool);
+} // namespace util

Note: adjust call sites accordingly.


477-477: Mark GetSettingsPath as nodiscard.

This is typically used for control flow; marking nodiscard avoids accidental ignoring of failure.

-    bool GetSettingsPath(fs::path* filepath = nullptr, bool temp = false, bool backup = false) const;
+    [[nodiscard]] bool GetSettingsPath(fs::path* filepath = nullptr, bool temp = false, bool backup = false) const;

490-495: New persistent accessor: verify thread-safety note.

The method is const and acquires cs_args in the impl—good. Consider noting in the comment that it acquires the internal lock.

src/qt/test/optiontests.cpp (1)

31-62: Clean up artifacts after migration test.

To avoid influencing subsequent tests, consider removing settings.json (and clearing QSettings) at the end of migrateSettings().

src/util/system.cpp (2)

563-577: Backup path suffix ordering: confirm intent.

GetSettingsPath builds "settings.json.bak.tmp" for temp backups. If tooling expects ".tmp" to be the final suffix, consider swapping the order:

-    if (backup) {
-        settings += ".bak";
-    }
-    if (filepath) {
-        *filepath = fsbridge::AbsPathJoin(GetDataDirNet(), temp ? settings + ".tmp" : settings);
-    }
+    if (filepath) {
+        fs::path base = settings;
+        if (temp) base += ".tmp";
+        if (backup) base += ".bak";
+        *filepath = fsbridge::AbsPathJoin(GetDataDirNet(), base);
+    }

Please verify no consumers depend on the current ordering.


632-638: Persistent-only accessor correctly ignores nonpersistent layers.

Lock + util::GetSetting(..., /ignore_nonpersistent=/true) is correct. Consider a unit test exercising this path.

Happy to add a small test demonstrating forced/CLI values being ignored.

src/qt/bitcoin.cpp (1)

509-512: Avoid duplicating the list of valid font families.

Consider deriving the “Possible values” string from the enum/registry used by GUIUtil::fontFamilyFromString to keep help text in sync.

src/qt/guiutil_font.h (2)

43-48: Unify macOS guard with .cpp for consistency.
.cpp uses Q_OS_MAC; header uses Q_OS_MACOS. Align to one macro to avoid confusion and divergent defaults.

-#ifdef Q_OS_MACOS
+#ifdef Q_OS_MAC
     QFont::ExtraLight
 #else
     QFont::Light
-#endif // Q_OS_MAC
+#endif // Q_OS_MAC

85-89: Typo in comment.
“appliciation” → “application”.

-/** Load dash specific appliciation fonts */
+/** Load Dash-specific application fonts */
src/qt/optionsmodel.cpp (2)

334-339: Store boolean default, not string, for UseEmbeddedMonospacedFont.
Avoid type drift in QSettings.

-    if (!settings.contains("UseEmbeddedMonospacedFont")) {
-        settings.setValue("UseEmbeddedMonospacedFont", "true");
-    }
+    if (!settings.contains("UseEmbeddedMonospacedFont")) {
+        settings.setValue("UseEmbeddedMonospacedFont", true);
+    }

755-760: Signal name may be misleading.
Changing sessions emits coinJoinRoundsChanged(). Consider a dedicated sessions-changed signal for clarity.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 873dee0 and 36795534ab4e314697b33cd6729585e82d856c17.

📒 Files selected for processing (52)
  • src/Makefile.qt.include (2 hunks)
  • src/init.cpp (0 hunks)
  • src/interfaces/node.h (2 hunks)
  • src/node/interfaces.cpp (1 hunks)
  • src/qt/addressbookpage.cpp (1 hunks)
  • src/qt/addresstablemodel.cpp (1 hunks)
  • src/qt/appearancewidget.cpp (1 hunks)
  • src/qt/appearancewidget.h (1 hunks)
  • src/qt/askpassphrasedialog.cpp (1 hunks)
  • src/qt/bitcoin.cpp (5 hunks)
  • src/qt/bitcoin.h (1 hunks)
  • src/qt/bitcoingui.cpp (2 hunks)
  • src/qt/coincontroldialog.cpp (1 hunks)
  • src/qt/forms/optionsdialog.ui (2 hunks)
  • src/qt/governancelist.cpp (1 hunks)
  • src/qt/guiutil.cpp (0 hunks)
  • src/qt/guiutil.h (0 hunks)
  • src/qt/guiutil_font.cpp (1 hunks)
  • src/qt/guiutil_font.h (1 hunks)
  • src/qt/masternodelist.cpp (1 hunks)
  • src/qt/modaloverlay.cpp (1 hunks)
  • src/qt/openuridialog.cpp (1 hunks)
  • src/qt/optionsdialog.cpp (3 hunks)
  • src/qt/optionsmodel.cpp (9 hunks)
  • src/qt/optionsmodel.h (8 hunks)
  • src/qt/overviewpage.cpp (4 hunks)
  • src/qt/overviewpage.h (1 hunks)
  • src/qt/proposalwizard.cpp (1 hunks)
  • src/qt/qrdialog.cpp (1 hunks)
  • src/qt/qrimagewidget.cpp (1 hunks)
  • src/qt/receivecoinsdialog.cpp (1 hunks)
  • src/qt/receiverequestdialog.cpp (1 hunks)
  • src/qt/rpcconsole.cpp (1 hunks)
  • src/qt/sendcoinsdialog.cpp (1 hunks)
  • src/qt/sendcoinsentry.cpp (1 hunks)
  • src/qt/signverifymessagedialog.cpp (1 hunks)
  • src/qt/splashscreen.cpp (1 hunks)
  • src/qt/test/addressbooktests.cpp (1 hunks)
  • src/qt/test/apptests.cpp (2 hunks)
  • src/qt/test/optiontests.cpp (3 hunks)
  • src/qt/test/optiontests.h (1 hunks)
  • src/qt/test/test_main.cpp (1 hunks)
  • src/qt/test/wallettests.cpp (1 hunks)
  • src/qt/trafficgraphwidget.cpp (1 hunks)
  • src/qt/transactiondescdialog.cpp (1 hunks)
  • src/qt/utilitydialog.cpp (1 hunks)
  • src/qt/walletview.cpp (1 hunks)
  • src/test/settings_tests.cpp (3 hunks)
  • src/util/settings.cpp (2 hunks)
  • src/util/settings.h (1 hunks)
  • src/util/system.cpp (6 hunks)
  • src/util/system.h (2 hunks)
💤 Files with no reviewable changes (3)
  • src/init.cpp
  • src/qt/guiutil.h
  • src/qt/guiutil.cpp
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: kwvg
PR: dashpay/dash#6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
PR: dashpay/dash#6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.

Applied to files:

  • src/qt/test/wallettests.cpp
📚 Learning: 2025-07-20T18:42:49.794Z
Learnt from: CR
PR: dashpay/dash#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T18:42:49.794Z
Learning: Applies to src/{test,wallet/test,qt/test}/**/*.{cpp,h,cc,cxx,hpp} : Unit tests for C++ code should be placed in src/test/, src/wallet/test/, or src/qt/test/ and use Boost::Test or Qt 5 for GUI tests

Applied to files:

  • src/qt/test/apptests.cpp
  • src/qt/test/optiontests.h
🪛 GitHub Actions: Clang Diff Format Check
src/qt/masternodelist.cpp

[error] 5-13: Clang format differences found in src/qt/masternodelist.cpp. The diff shows an include order change (added '#include <coins.h>' before 'evo/deterministicmns.h' and removed the previous '#include <coins.h>'). The check failed with exit code 1. Run 'clang-format-diff.py -p1' (or 'clang-format') to fix.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: x86_64-apple-darwin / Build depends
  • GitHub Check: x86_64-w64-mingw32 / Build depends
  • GitHub Check: x86_64-pc-linux-gnu_nowallet / Build depends
  • GitHub Check: x86_64-pc-linux-gnu_multiprocess / Build depends
  • GitHub Check: arm-linux-gnueabihf / Build depends
  • GitHub Check: x86_64-pc-linux-gnu / Build depends
🔇 Additional comments (55)
src/qt/forms/optionsdialog.ui (1)

1215-1215: String change: confirm translations are updated

The bottom info label text changed; please run lupdate / refresh .ts files so translators see the new string.

src/util/settings.h (1)

58-71: All GetSetting call sites and tests updated to 6-arg signature Verified no lingering 5-arg calls remain.

src/qt/utilitydialog.cpp (1)

15-15: Include aligns with font subsystem migration

Header inclusion matches the use of GUIUtil::updateFonts and the new split of font utilities. LGTM.

src/qt/transactiondescdialog.cpp (1)

9-9: Include aligns with font subsystem migration

Consistent with calling GUIUtil::updateFonts(). LGTM.

src/qt/masternodelist.cpp (1)

12-12: Header include looks correct.

Including qt/guiutil_font.h is required for GUIUtil::setFont/updateFonts. No issues.

src/qt/sendcoinsdialog.cpp (1)

18-18: Header include is appropriate.

qt/guiutil_font.h is needed for font helpers used in this file. Looks good.

src/qt/openuridialog.cpp (1)

10-10: Include addition is correct.

Required for GUIUtil::updateFonts usage. No further changes needed.

src/qt/addresstablemodel.cpp (1)

9-9: Include addition aligns with FontRole usage.

Bringing in qt/guiutil_font.h matches GUIUtil::getFontNormal() usage. All good.

src/qt/splashscreen.cpp (1)

19-19: Include addition is correct.

Needed for GUIUtil::getFontNormal/getFontBold; no issues.

src/qt/addressbookpage.cpp (1)

17-17: Include for font utilities is correct.

Matches the migration of font APIs out of guiutil.h; aligns with GUIUtil::updateFonts() usage later. No issues.

src/qt/qrimagewidget.cpp (1)

8-8: Header addition aligns with font API split.

Required for getFontNormal/calculateIdealFontSize. Looks good.

src/qt/sendcoinsentry.cpp (1)

16-16: Review OK; include needed for setFont(FontWeight)

  • <qt/guiutil_font.h> is required for GUIUtil::setFont(FontWeight) — LGTM.
  • labellLabel is defined in src/qt/forms/sendcoinsentry.ui (line 118); name matches the code, no typo.
src/qt/modaloverlay.cpp (1)

10-10: Correct header include for font utilities.

Consistent with GUIUtil::setFont usage below. No further action.

src/qt/signverifymessagedialog.cpp (1)

11-11: Approve: guiutil_font header integration verified
Makefile.qt.include lists guiutil_font.h/.cpp and all translation units using GUIUtil::FontWeight include <qt/guiutil_font.h>.

src/qt/receivecoinsdialog.cpp (1)

10-10: Header addition aligns with centralized font utilities

Including qt/guiutil_font.h here is consistent with using GUIUtil::setFont/updateFonts. No issues.

src/qt/qrdialog.cpp (1)

11-11: Good: pulls in FontWeight after font helpers moved out of guiutil.h

Keeps this TU compiling with the new font subsystem. Looks good.

src/qt/governancelist.cpp (1)

20-20: Correct dependency on guiutil_font.h

Needed for the GUIUtil::setFont calls used in this widget. Change is safe and scoped.

src/qt/askpassphrasedialog.cpp (1)

15-15: Include for font utilities looks correct

Unblocks usage of GUIUtil::FontWeight in this TU. No further action.

src/qt/rpcconsole.cpp (1)

21-21: Add guiutil_font include — OK

Matches usage of GUIUtil::setFont/updateFonts and font weights below.

src/qt/trafficgraphwidget.cpp (1)

9-9: Include addition is fine

Aligns this TU with GUI font helpers; no behavior change.

src/qt/walletview.cpp (1)

15-15: Include addition is fine

Enables explicit font weight usage in this TU. No issues.

src/qt/appearancewidget.cpp (1)

31-33: AVAILABLE_FONTS header inclusion verified
Declaration exists in src/qt/guiutil_font.h (line 26) and appearancewidget.h includes it (line 11) — no further changes needed.

src/qt/receiverequestdialog.cpp (1)

10-10: Include for moved font utilities looks correct.

This aligns with updateFonts() migration to guiutil_font.*. No further action.

src/qt/proposalwizard.cpp (1)

16-16: Correct header added for GUIUtil::setFont and FontWeight.

Header placement is fine and resolves the new font API usage.

src/qt/overviewpage.h (1)

74-74: No issues—slot implemented and signal connected.

OverviewPage::setMonospacedFont(bool) is defined in overviewpage.cpp (line 379) and wired to OptionsModel::useEmbeddedMonospacedFontChanged in overviewpage.cpp (line 305); no further action required.

src/Makefile.qt.include (1)

140-140: Confirmed no Q_OBJECT in guiutil_font.h; no moc entry needed.

src/qt/test/apptests.cpp (1)

11-11: LGTM on include and return-value assert.

The new guiutil_font include and the updated QVERIFY for createOptionsModel(bool) look correct and align with the API change.

Also applies to: 79-79

src/qt/bitcoingui.cpp (1)

13-13: LGTM: guiutil_font include.

Consistent with the new font utilities usage elsewhere.

src/qt/test/optiontests.h (3)

9-11: LGTM: adds required headers for settings/JSON use.


18-18: Constructor change acknowledged.

Node-injecting ctor is appropriate for node-backed settings tests.


21-26: Ensure settings backup/restore around tests.

Please verify that m_previous_settings is populated before mutation (e.g., in init()) and restored afterward (e.g., dedicated cleanup slot or destructor) to avoid cross-test contamination.

Also applies to: 29-29

src/util/settings.cpp (1)

144-146: All util::GetSetting call sites updated and docs accurate
Verified the three invocations in system.cpp (lines 635–637, 1113–1115, 1183–1185) now pass both ignore_nonpersistent and get_chain_name in the correct order, and the header comment already documents that ignore_nonpersistent filters out forced and command-line values.

src/node/interfaces.cpp (1)

1127-1154: All boolean-returning calls to updateRwSetting use the Chain::updateRwSetting 3-arg overload (explicit or via default write flag); the 2-arg Node::updateRwSetting is only used by Qt code where its void return is correctly ignored.

src/qt/overviewpage.cpp (2)

379-395: LGTM: focused, minimal font application

Using GUIUtil::setFont(..., RobotoMono|DefaultMonospace, Bold) and GUIUtil::updateFonts() is consistent with the new font subsystem and limited in scope to balance labels.


305-307: [awaiting_run_scripts]

src/qt/optionsdialog.cpp (1)

205-218: LGTM: clear font previews and sane default

Preview labels use the actual families via QFontInfo, and defaulting to system-monospaced is reasonable until the model mapping loads. No functional issues spotted.

src/interfaces/node.h (1)

8-16: Header include adjustments look fine

Adding util/settings.h for util::SettingsValue is correct, and other includes are appropriately ordered.

src/test/settings_tests.cpp (2)

109-116: API update applied correctly in helper.

Passing ignore_nonpersistent=false preserves previous behavior. LGTM.


228-229: Merge test call site aligns with new GetSetting signature.

Explicit comments for the two new booleans are helpful. LGTM.

src/util/system.h (1)

485-489: Docs sync with backup behavior.

Comment clarifies backup path behavior. LGTM.

src/qt/test/optiontests.cpp (3)

24-29: Fixture reset is sound.

Restoring m_previous_settings and clearing the path cache prevents cross-test contamination. LGTM.


74-86: Regression guard looks good.

Constructing OptionsModel with Node and calling Init(error) directly covers the reported regression. LGTM.


108-110: parametersInteraction now validates via OptionsModel::Init.

Good shift to Node-aware initialization. LGTM.

src/util/system.cpp (4)

612-631: WriteSettingsFile backup plumbing is correct.

Using the same backup flag for both tmp and final paths is consistent. LGTM.


644-675: Centralized conversions reduce duplication.

Refactoring GetArg/GetIntArg/GetBoolArg to use SettingTo* helpers improves consistency. LGTM.


1109-1118: Chain selection call updated with new GetSetting flags.

Explicit get_chain_name=true and ignore_nonpersistent=false maintain existing semantics. LGTM.


1184-1186: ArgsManager::GetSetting updated with new flag.

Explicit ignore_nonpersistent=false preserves prior behavior. LGTM.

src/qt/bitcoin.cpp (3)

350-353: Prune API change accounted for.

Dropping the extra boolean matches the new signature. LGTM.


691-700: Startup flow improvement: create splash and node earlier; gate on options init.

Great for UX and error handling. LGTM.


704-705: Default font family fallback is consistent.

Using GUIUtil::g_font_defaults.family for default arg is correct. LGTM.

src/qt/optionsmodel.h (3)

103-105: Public getOption/setOption and embedded-mono getter are a welcome simplification.
API surface reads clean and matches the data()/setData() rework.

Also applies to: 114-115


45-47: All OptionsModel instantiations updated and no setNode usage remains
Verified that OptionsModel is only constructed via the new OptionsModel(interfaces::Node&, …) constructor (e.g. in bitcoin.cpp:273) and no .setNode( calls remain.


123-124: Confirm downstream usage update
Grep shows only a single call site in bitcoin.cpp using the new one-parameter signature; no force parameter remains.

src/qt/guiutil_font.cpp (1)

367-381: Update loop is careful and two-phase; LGTM.
The cleanup of dead QPointers and deferred apply avoids inheritance glitches.

Also applies to: 383-392, 439-447, 449-463

src/qt/optionsmodel.cpp (1)

99-115: Back-compat workaround with 22.x numerics: solid approach.
Writing specific numeric settings as strings to dodge UniValue exceptions is pragmatic and isolated.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Also treat forced settings as “ignored” overrides

isSettingIgnored only checks command_line_options. If a setting is overridden via forced_settings, the GUI will not flag it as ignored. Either update the docstring in node.h or include forced settings here for consistency with ignore_nonpersistent.

Apply:

 bool isSettingIgnored(const std::string& name) override
 {
-    bool ignored = false;
-    gArgs.LockSettings([&](util::Settings& settings) {
-        if (auto* options = util::FindKey(settings.command_line_options, name)) {
-            ignored = !options->empty();
-        }
-    });
-    return ignored;
+    bool ignored = false;
+    gArgs.LockSettings([&](const util::Settings& settings) {
+        if (const auto* v = util::FindKey(settings.command_line_options, name)) {
+            ignored = !v->empty();
+        }
+        if (!ignored) {
+            if (const auto* f = util::FindKey(settings.forced_settings, name)) {
+                ignored = !f->empty();
+            }
+        }
+    });
+    return ignored;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bool isSettingIgnored(const std::string& name) override
{
bool ignored = false;
gArgs.LockSettings([&](util::Settings& settings) {
if (auto* options = util::FindKey(settings.command_line_options, name)) {
ignored = !options->empty();
}
});
return ignored;
}
bool isSettingIgnored(const std::string& name) override
{
bool ignored = false;
gArgs.LockSettings([&](const util::Settings& settings) {
if (const auto* v = util::FindKey(settings.command_line_options, name)) {
ignored = !v->empty();
}
if (!ignored) {
if (const auto* f = util::FindKey(settings.forced_settings, name)) {
ignored = !f->empty();
}
}
});
return ignored;
}
🤖 Prompt for AI Agents
In src/node/interfaces.cpp around lines 447 to 456, isSettingIgnored currently
only checks command_line_options and therefore misses settings present in
forced_settings; update the function to also check settings.forced_settings
(using util::FindKey or equivalent) and mark the setting as ignored if a
forced_settings entry exists or is non-empty, mirroring ignore_nonpersistent
behavior; keep the gArgs.LockSettings scope and combine the checks so that
ignored becomes true if either command_line_options or forced_settings indicates
an override.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Unify update path and handle write failures

This void updateRwSetting duplicates the logic of the existing bool updateRwSetting(name, value, write) and ignores the write result. Delegate to the boolean overload to centralize behavior and optionally log failures.

Apply:

 void updateRwSetting(const std::string& name, const util::SettingsValue& value) override
 {
-    gArgs.LockSettings([&](util::Settings& settings) {
-        if (value.isNull()) {
-            settings.rw_settings.erase(name);
-        } else {
-            settings.rw_settings[name] = value;
-        }
-    });
-    gArgs.WriteSettingsFile();
+    (void)updateRwSetting(name, value, /*write=*/true);
 }
🤖 Prompt for AI Agents
In src/node/interfaces.cpp around lines 458 to 468, this void updateRwSetting
duplicates logic of the existing bool updateRwSetting(name, value, write) and
ignores whether the write succeeded; replace the implementation to call the
boolean overload (e.g. updateRwSetting(name, value, /*write*/ true)) and if it
returns false, emit a failure log (use the existing logging facility in this
file) so write failures are not silently ignored, thereby centralizing behavior
and preserving the original semantics.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Null-deref risk if OptionsModel is null.

_setClientModel() unconditionally dereferences _clientModel->getOptionsModel() to set m_mask_values_action. This can crash when options model is not yet available. Guard it.

-        m_mask_values_action->setChecked(_clientModel->getOptionsModel()->getOption(OptionsModel::OptionID::MaskValues).toBool());
+        if (OptionsModel* opt = _clientModel->getOptionsModel()) {
+            m_mask_values_action->setChecked(opt->getOption(OptionsModel::OptionID::MaskValues).toBool());
+        } else {
+            m_mask_values_action->setChecked(false);
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
m_mask_values_action->setChecked(_clientModel->getOptionsModel()->getOption(OptionsModel::OptionID::MaskValues).toBool());
} else {
if (OptionsModel* opt = _clientModel->getOptionsModel()) {
m_mask_values_action->setChecked(opt->getOption(OptionsModel::OptionID::MaskValues).toBool());
} else {
m_mask_values_action->setChecked(false);
}
} else {
🤖 Prompt for AI Agents
In src/qt/bitcoingui.cpp around lines 893-894, the code unconditionally calls
_clientModel->getOptionsModel()->getOption(...), risking a null-deref if
getOptionsModel() returns nullptr; change the logic to first check that
_clientModel and _clientModel->getOptionsModel() are non-null before calling
getOption, and only call m_mask_values_action->setChecked(...) when the options
model exists (otherwise set a safe default or leave the action unchecked);
ensure any subsequent logic that assumes the options model exists is similarly
guarded or deferred until the model is available.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Null check before persisting privacy option

clientModel or its OptionsModel can be null during early lifecycle; this will dereference unconditionally.

Apply:

-    clientModel->getOptionsModel()->setOption(OptionsModel::OptionID::MaskValues, privacy);
+    if (clientModel && clientModel->getOptionsModel()) {
+        clientModel->getOptionsModel()->setOption(OptionsModel::OptionID::MaskValues, privacy);
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
clientModel->getOptionsModel()->setOption(OptionsModel::OptionID::MaskValues, privacy);
if (m_balances.balance != -1) {
setBalance(m_balances);
if (clientModel && clientModel->getOptionsModel()) {
clientModel->getOptionsModel()->setOption(OptionsModel::OptionID::MaskValues, privacy);
}
if (m_balances.balance != -1) {
setBalance(m_balances);
}
🤖 Prompt for AI Agents
In src/qt/overviewpage.cpp around lines 210 to 212, the code unconditionally
calls clientModel->getOptionsModel()->setOption(...), which can dereference a
null clientModel or a null OptionsModel during early lifecycle; guard this by
checking clientModel is non-null and that clientModel->getOptionsModel() returns
a non-null pointer before calling setOption (fetch the OptionsModel into a local
variable and only call setOption when both are valid); leave the existing
setBalance(m_balances) as-is since the comment targets persisting the privacy
option.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Make JSON verification robust; avoid comparing full file text and dangling c_str.

Comparing the whole serialized file string is brittle (ordering/whitespace) and uses c_str() on temporaries. Parse JSON and assert fields instead.

-    std::ifstream file(gArgs.GetDataDirNet() / "settings.json");
-    QCOMPARE(std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()).c_str(), "{\n"
-        "    \"dbcache\": \"600\",\n"
-        "    \"listen\": false,\n"
-        "    \"onion\": \"onion:234\",\n"
-        "    \"par\": \"12\",\n"
-        "    \"proxy\": \"proxy:123\",\n"
-        "    \"prune\": \"2861\"\n"
-        "}\n");
+    std::ifstream file(gArgs.GetDataDirNet() / "settings.json");
+    QVERIFY(file.is_open());
+    const std::string data((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
+    UniValue json;
+    QVERIFY(json.read(data));
+    QVERIFY(json.isObject());
+    QCOMPARE(QString::fromStdString(json["dbcache"].get_str()), QString("600"));
+    QCOMPARE(json["listen"].get_bool(), false);
+    QCOMPARE(QString::fromStdString(json["onion"].get_str()), QString("onion:234"));
+    QCOMPARE(QString::fromStdString(json["par"].get_str()), QString("12"));
+    QCOMPARE(QString::fromStdString(json["proxy"].get_str()), QString("proxy:123"));
+    QCOMPARE(QString::fromStdString(json["prune"].get_str()), QString("2861"));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
std::ifstream file(gArgs.GetDataDirNet() / "settings.json");
QCOMPARE(std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()).c_str(), "{\n"
" \"dbcache\": \"600\",\n"
" \"listen\": false,\n"
" \"onion\": \"onion:234\",\n"
" \"par\": \"12\",\n"
" \"proxy\": \"proxy:123\",\n"
" \"prune\": \"2861\"\n"
"}\n");
}
std::ifstream file(gArgs.GetDataDirNet() / "settings.json");
QVERIFY(file.is_open());
const std::string data((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
UniValue json;
QVERIFY(json.read(data));
QVERIFY(json.isObject());
QCOMPARE(QString::fromStdString(json["dbcache"].get_str()), QString("600"));
QCOMPARE(json["listen"].get_bool(), false);
QCOMPARE(QString::fromStdString(json["onion"].get_str()), QString("onion:234"));
QCOMPARE(QString::fromStdString(json["par"].get_str()), QString("12"));
QCOMPARE(QString::fromStdString(json["proxy"].get_str()), QString("proxy:123"));
QCOMPARE(QString::fromStdString(json["prune"].get_str()), QString("2861"));
}
🤖 Prompt for AI Agents
In src/qt/test/optiontests.cpp around lines 63 to 72, the test currently
compares the entire file text and calls c_str() on temporaries which is brittle
and unsafe; instead, read the file into a string or QByteArray, parse it as JSON
(e.g. QJsonDocument::fromJson or your project JSON parser), verify the parse
succeeded, and assert each expected key/value individually (dbcache as string or
number, listen as bool, onion/proxy as strings, par/prune as strings or numbers)
using QCOMPARE/QVERIFY; remove the direct full-string equality check and the
c_str() usage and add explicit error messages on parse failure.

@github-actions
Copy link

This pull request has conflicts, please rebase.

@kwvg kwvg changed the title backport: merge bitcoin-core/gui#600, #601, #602, #701, #603, merge bitcoin#15936 (migrate some QSettings to settings.json) backport: merge bitcoin-core/gui#600, #601, #602, #701, #603 (migrate some QSettings to settings.json) Oct 19, 2025
@kwvg kwvg modified the milestones: 23, 23.1 Oct 21, 2025
@github-actions
Copy link

This pull request has conflicts, please rebase.

PastaPastaPasta added a commit that referenced this pull request Dec 30, 2025
…to valid index

8bba1d2 fix: don't assume that successful `weightFromArg` links to valid index (Kittywhiskers Van Gogh)

Pull request description:

  ## Additional Information

  [dash#7068](#7068) introduced a regression where Qt clients with no GUI settings are unable to run at all due to failed weight to index conversion. This was covered in 9cd9d44 but made an incorrect assumption that earlier iterations of the fix (see ef34868) did not make.

  The assumption made that resulted in this regression was that if the argument to weight conversion is successful, then the weight to index conversion will also be successful.

  The earlier iteration of the fix checked the return value of the index conversion and set a sane default if it was invalid. The final iteration set the default weight value to the sane weight, expecting `weightFromArg()` to fail (hence using the sane weight), not `supportedWeightToIndex()` (which might not be able to process even a valid weight from argument).

  This was not caught in testing as over the course of working on [dash#6833](#6833), my GUI settings were migrated to `settings.json`, which has precedence over `QSettings` and therefore, the client always ran with known good Montserrat parameters.

  Fix can be verified by deleting your QSettings parameters and running the client anew.

  ## Breaking Changes

  None expected.

  ## Checklist

  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)**
  - [x] I have added or updated relevant unit/integration/functional/e2e tests **(note: N/A)**
  - [x] I have made corresponding changes to the documentation **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  UdjinM6:
    utACK 8bba1d2
  PastaPastaPasta:
    utACK 8bba1d2

Tree-SHA512: 6772d59a8cffb43427ea83b5ff2e725efbfc741e890c40e059ffe2fe3405fbe535f975f4ebbd78fbe44bdf671deaeb1a329b3c29530a8de4cceab02f5ce6009c
@github-actions
Copy link

github-actions bot commented Jan 1, 2026

This pull request has conflicts, please rebase.

PastaPastaPasta added a commit that referenced this pull request Jan 3, 2026
…nt font for overview page balances)

636e7a6 refactor: remove redundant preview and simplify font handling (UdjinM6)
b59b0f7 feat(qt): add live preview for monospace font in appearance settings (UdjinM6)
83af951 fix: set money font when setting wallet model instead of ctor (Kittywhiskers Van Gogh)
658905b qt: add non-monospace option and use it as default (Kittywhiskers Van Gogh)
e0513ff qt: add horizontal spacer for visual consistency (Kittywhiskers Van Gogh)
e5a8d05 refactor: move monospace font selector to appearance widget (Kittywhiskers Van Gogh)
41c69e9 merge bitcoin-core/gui#497: Enable users to configure their monospace font specifically (Kittywhiskers Van Gogh)
da5804e merge bitcoin-core/gui#79: Embed monospaced font (Kittywhiskers Van Gogh)
eac4f52 qt: adjust padding and font size of monospace font selector (Kittywhiskers Van Gogh)
9c315c3 qt: add monospaced font settings (Kittywhiskers Van Gogh)
34211b6 qt: apply monospace font to overview page balances and CoinJoin elements (Kittywhiskers Van Gogh)
6ed53d6 qt: allow overriding font registry for specific widgets (Kittywhiskers Van Gogh)
800cf66 qt: recognize system monospace font as non-selectable font (Kittywhiskers Van Gogh)
85b49b9 qt: add "Roboto Mono" as non-selectable font (Kittywhiskers Van Gogh)

Pull request description:

  ## Additional Information

  * Depends on #7068

  * Depends on #7084

  * Dependency for #6833

  | [dash#7084](#7084) (8bba1d2)  | This PR (636e7a6) |
  | ------------------- | ------------------- |
  | ![image](https://github.com/user-attachments/assets/0208ffb7-d511-4211-a304-6a0aa4d6c367) | ![image](https://github.com/user-attachments/assets/d1f42ec7-f1ee-4856-9c42-04b4c0b103aa) |
  | ![image](https://github.com/user-attachments/assets/1ce9c72b-d6a1-43ed-b86d-d76cbd52f2b8) | ![image](https://github.com/user-attachments/assets/e8e6bae2-1825-4132-9f78-385dbda31a61) |
  | ![image](https://github.com/user-attachments/assets/fac6e70f-1ebb-407b-bd16-85ea8ebef84f) | ![image](https://github.com/user-attachments/assets/b8f1d5f8-63a1-4e50-8314-0bc29000959a) |

  * Based on review suggestions given ([comment](#6831 (comment))), [bitcoin-core/gui#497](bitcoin-core/gui#497) was also backported to allow arbitrary font specification. This also allowed us to offer a "Use existing font" option that _doesn't_ use any monospace font but instead inherits whatever font is used in the rest of the application. This is set as the default ([source](https://github.com/kwvg/dash/blob/89aa2c4b2390ada504fd5b45e16d2cd379074138/src/qt/optionsmodel.cpp#L73)), rendering monospace balance counters opt-in.

  * Unlike Bitcoin, Dash has a dedicated appearance widget for managing font settings specifically. We have opted to deviate from upstream by moving the money font control from "Display" to "Appearance" for the sake of consistency.

  * We set the money font when setting the wallet model as client model updates happen after the UI is visible to the user while wallet model updates happen _before_, there is little point in setting them to any values in the constructor as during construction, we don't have access to the options model and thus don't know _what_ font is supposed to be used to begin with.

  * If a font is passed through the command line, it is considered "selectable" ([source](https://github.com/kwvg/dash/blob/89aa2c4b2390ada504fd5b45e16d2cd379074138/src/qt/bitcoin.cpp#L676-L679)) because we still need to populate that font in the drop-down menu so that we don't report stale data. Though, the font cannot be _set_ to that overridden value because command-line overridden controls are auto-disabled to prevent settings corruption (see 2f30002), which makes the "selectable" state more-or-less an internal detail.

    An example is that the user tries to run Dash Core, the embedded monospace font, Roboto Mono, is _not_ a selectable font (i.e. you cannot ordinarily set your client to use Roboto Mono, see below).

    <details>

    <summary>Screenshot:</summary>

    ![image](https://github.com/user-attachments/assets/cf005084-c184-4c61-8d37-4106102108f1)

    </details>

    But if an override is done, it will be respected, the client will start with Roboto Mono and the selectable status will be overwritten so that it is presented in the drop-down menu, albeit, with the menu disabled so it doesn't contaminate UI settings.

    <details>

    <summary>Screenshot:</summary>

    ![image](https://github.com/user-attachments/assets/a4479dc3-60e0-4c8b-bf41-f89ce2012539)

    </details>

  ## Breaking Changes

  None expected.

  ## Checklist

  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas
  - [x] I have added or updated relevant unit/integration/functional/e2e tests **(note: N/A)**
  - [x] I have made corresponding changes to the documentation **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  UdjinM6:
    ACK 636e7a6

Tree-SHA512: a8b23c14aec0ccac126bdc7a6db0a4583da3bda52e02f72d213431bbaa80c633a432ed02c4a33d71e3e4d2503d076624196c3e6e50c9bb7fd8e3b50ae4e9ec35
@github-actions
Copy link

github-actions bot commented Jan 3, 2026

This pull request has conflicts, please rebase.

kwvg added 4 commits January 3, 2026 23:25
Review with `git log -p -n1 --ignore-space-change --color-moved=dimmed_zebra`
The migration to CoinJoin was done in dash#4038, included in v0.17 and
there's more than a few major releases since then, we should be able to
safely assume that upgrading users are using more recent clients.
@kwvg kwvg marked this pull request as ready for review January 3, 2026 18:00
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/qt/optionsmodel.cpp (1)

464-488: Proxy parsing confirmed addressed.

The ParseProxyString() implementation uses simple ":" splitting. The IPv6 concern was raised in a previous review but marked as "✅ Addressed" in commits 6c9f1ae to 0c3b224. Since this is backported upstream code, maintaining fidelity is appropriate.

🧹 Nitpick comments (1)
doc/release-notes-6833.md (1)

6-6: Consider capitalizing operating system names.

In Line 6, "windows" and "unix" appear lowercase. When referring to operating systems (Microsoft Windows, Unix-like systems), these are typically capitalized: "Windows registry or Unix desktop config files."

🔎 Suggested capitalization fix
-file rather than to the Qt settings backend (windows registry or unix desktop
+file rather than to the Qt settings backend (Windows registry or Unix desktop
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36795534ab4e314697b33cd6729585e82d856c17 and 0c3b224.

📒 Files selected for processing (15)
  • doc/release-notes-6833.md
  • src/qt/bitcoin.cpp
  • src/qt/bitcoin.h
  • src/qt/bitcoingui.cpp
  • src/qt/forms/optionsdialog.ui
  • src/qt/optionsdialog.cpp
  • src/qt/optionsmodel.cpp
  • src/qt/optionsmodel.h
  • src/qt/overviewpage.cpp
  • src/qt/test/addressbooktests.cpp
  • src/qt/test/apptests.cpp
  • src/qt/test/optiontests.cpp
  • src/qt/test/optiontests.h
  • src/qt/test/test_main.cpp
  • src/qt/test/wallettests.cpp
💤 Files with no reviewable changes (1)
  • src/qt/optionsdialog.cpp
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/qt/forms/optionsdialog.ui
  • src/qt/overviewpage.cpp
  • src/qt/bitcoingui.cpp
🧰 Additional context used
📓 Path-based instructions (3)
{guix-build*,releases,**/guix-build*,releases/**,.github/**,depends/**,ci/**,contrib/**,doc/**}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not make changes to build system files (guix-build*), release artifacts, or avoid changes to .github, depends, ci, contrib, and doc directories unless specifically prompted

Files:

  • doc/release-notes-6833.md
src/**/*.{cpp,h,hpp,cc}

📄 CodeRabbit inference engine (CLAUDE.md)

Dash Core implementation must be written in C++20, requiring at least Clang 16 or GCC 11.1

Files:

  • src/qt/test/wallettests.cpp
  • src/qt/bitcoin.h
  • src/qt/test/apptests.cpp
  • src/qt/test/addressbooktests.cpp
  • src/qt/optionsmodel.h
  • src/qt/bitcoin.cpp
  • src/qt/test/test_main.cpp
  • src/qt/test/optiontests.cpp
  • src/qt/optionsmodel.cpp
  • src/qt/test/optiontests.h
src/qt/**/*.{cpp,h}

📄 CodeRabbit inference engine (CLAUDE.md)

GUI implementation in src/qt/ must use Qt 5

Files:

  • src/qt/test/wallettests.cpp
  • src/qt/bitcoin.h
  • src/qt/test/apptests.cpp
  • src/qt/test/addressbooktests.cpp
  • src/qt/optionsmodel.h
  • src/qt/bitcoin.cpp
  • src/qt/test/test_main.cpp
  • src/qt/test/optiontests.cpp
  • src/qt/optionsmodel.cpp
  • src/qt/test/optiontests.h
🧠 Learnings (22)
📓 Common learnings
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.
Learnt from: kwvg
Repo: dashpay/dash PR: 7072
File: src/qt/walletcontroller.cpp:520-528
Timestamp: 2025-12-17T13:58:26.891Z
Learning: In Dash Qt wallet code, when leveraging upstream Bitcoin Core wallet capabilities (especially for operations like rescanning), prefer using the inherited signal-based mechanisms (e.g., ShowProgress signals) over adding explicit Qt progress dialogs to minimize upstream deviation and simplify future backports.
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 6804
File: src/qt/proposalwizard.cpp:40-42
Timestamp: 2025-08-11T17:16:36.654Z
Learning: In the Dash repository, when a PR adds new files that are not from Bitcoin backports, these files must be added to the list in test/util/data/non-backported.txt. This applies to newly created files like qt/proposalwizard.{h,cpp} and forms/proposalwizard.ui. Limited exemptions may exist for subtrees and similar cases.
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6786
File: ci/test/04_install.sh:99-101
Timestamp: 2025-08-01T07:46:37.840Z
Learning: In backport PRs like #6786, UdjinM6 prefers to defer non-critical fixes (such as shell command expansion issues) to separate commits/PRs to maintain focus on the primary backport objectives, consistent with the project's pattern of avoiding scope creep.
📚 Learning: 2025-08-11T17:16:36.654Z
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 6804
File: src/qt/proposalwizard.cpp:40-42
Timestamp: 2025-08-11T17:16:36.654Z
Learning: In the Dash repository, when a PR adds new files that are not from Bitcoin backports, these files must be added to the list in test/util/data/non-backported.txt. This applies to newly created files like qt/proposalwizard.{h,cpp} and forms/proposalwizard.ui. Limited exemptions may exist for subtrees and similar cases.

Applied to files:

  • doc/release-notes-6833.md
  • src/qt/bitcoin.cpp
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-12-17T13:58:26.891Z
Learnt from: kwvg
Repo: dashpay/dash PR: 7072
File: src/qt/walletcontroller.cpp:520-528
Timestamp: 2025-12-17T13:58:26.891Z
Learning: In Dash Qt wallet code, when leveraging upstream Bitcoin Core wallet capabilities (especially for operations like rescanning), prefer using the inherited signal-based mechanisms (e.g., ShowProgress signals) over adding explicit Qt progress dialogs to minimize upstream deviation and simplify future backports.

Applied to files:

  • doc/release-notes-6833.md
  • src/qt/bitcoin.h
  • src/qt/optionsmodel.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{masternode,evo,llmq,governance,coinjoin}/**/*.{cpp,h} : Use Dash-specific database implementations: CFlatDB for persistent storage (MasternodeMetaStore, GovernanceStore, SporkStore, NetFulfilledRequestStore) and CDBWrapper extensions for Evolution/DKG/InstantSend/Quorum/RecoveredSigs data

Applied to files:

  • doc/release-notes-6833.md
📚 Learning: 2025-08-08T04:30:37.971Z
Learnt from: PastaPastaPasta
Repo: dashpay/dash PR: 6804
File: src/qt/proposalwizard.cpp:0-0
Timestamp: 2025-08-08T04:30:37.971Z
Learning: In the Dash codebase, direct RPC calling has been removed in recent commits, making suggestions about RPC command validation and error handling for direct RPC calls obsolete. The ProposalWizard and related components no longer use direct RPC calling patterns.

Applied to files:

  • doc/release-notes-6833.md
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
Repo: dashpay/dash PR: 6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.

Applied to files:

  • src/qt/test/wallettests.cpp
📚 Learning: 2025-12-17T13:58:19.813Z
Learnt from: kwvg
Repo: dashpay/dash PR: 7072
File: src/qt/walletcontroller.cpp:520-528
Timestamp: 2025-12-17T13:58:19.813Z
Learning: In Dash Qt wallet code, prefer using existing Qt signals/slots (e.g., ShowProgress signals) for long-running operations instead of adding explicit QProgressDialog dialogs. This minimizes upstream deviations and simplifies backports. Apply this pattern to wallet-related Qt components (e.g., operations like rescanning) and rely on signal-based progress updates rather than bespoke dialogs.

Applied to files:

  • src/qt/test/wallettests.cpp
  • src/qt/test/apptests.cpp
  • src/qt/test/addressbooktests.cpp
  • src/qt/bitcoin.cpp
  • src/qt/test/test_main.cpp
  • src/qt/test/optiontests.cpp
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-06-09T16:43:20.996Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6718
File: test/functional/test_framework/test_framework.py:2102-2102
Timestamp: 2025-06-09T16:43:20.996Z
Learning: In the test framework consolidation PR (#6718), user kwvg prefers to limit functional changes to those directly related to MasternodeInfo, avoiding scope creep even for minor improvements like error handling consistency.

Applied to files:

  • src/qt/test/wallettests.cpp
  • src/qt/bitcoin.cpp
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-12-22T15:42:48.595Z
Learnt from: kwvg
Repo: dashpay/dash PR: 7068
File: src/qt/guiutil_font.h:68-77
Timestamp: 2025-12-22T15:42:48.595Z
Learning: In C++/Qt codebases, use fail-fast asserts in setters to enforce invariants (e.g., ensuring internal maps contain necessary keys). Prefer assert() for programmer errors that should be caught in development and debugging, rather than defensive runtime checks with fallbacks. This helps catch invariant violations early during development. Apply to header and source files where invariant-driven state mutations occur, especially in setters like SetWeightBold/SetWeightNormal that assume established relationships or preconditions.

Applied to files:

  • src/qt/bitcoin.h
  • src/qt/optionsmodel.h
  • src/qt/test/optiontests.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/coinjoin/**/*.{cpp,h} : CoinJoin implementation must use masternode-coordinated mixing sessions with uniform denomination outputs

Applied to files:

  • src/qt/optionsmodel.h
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-10-05T20:38:28.457Z
Learnt from: knst
Repo: dashpay/dash PR: 6871
File: contrib/guix/libexec/build.sh:358-360
Timestamp: 2025-10-05T20:38:28.457Z
Learning: In the Dash repository, when backporting code from Bitcoin Core, typos and minor issues in comments should be kept as-is to reduce merge conflicts in future backports, even if they remain unfixed in Bitcoin Core's master branch.

Applied to files:

  • src/qt/bitcoin.cpp
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-10-25T07:08:51.918Z
Learnt from: knst
Repo: dashpay/dash PR: 6916
File: src/univalue/include/univalue.h:81-88
Timestamp: 2025-10-25T07:08:51.918Z
Learning: For backport PRs from bitcoin/bitcoin, bitcoin-core/gui, etc., backported changes should match the original upstream PRs even if they appear strange, modify vendored code, or seem to violate coding guidelines. Still flag genuine issues like bugs, undefined behavior, crashes, compilation errors, or linter failures.

Applied to files:

  • src/qt/bitcoin.cpp
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-10-13T12:37:12.357Z
Learnt from: knst
Repo: dashpay/dash PR: 6883
File: src/rpc/rawtransaction.cpp:1088-1125
Timestamp: 2025-10-13T12:37:12.357Z
Learning: In backport pull requests (especially from Bitcoin Core), treat "moved" or refactored code as out-of-scope for content-level review. Focus validation on verifying that code is moved correctly: no fields added, no fields removed, no fields reordered, and no unexpected changes beyond whitespace adjustments. Pre-existing issues in the upstream code should be preserved to maintain fidelity to the original implementation.

Applied to files:

  • src/qt/bitcoin.cpp
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-11-04T18:24:27.241Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6933
File: src/llmq/utils.cpp:284-298
Timestamp: 2025-11-04T18:24:27.241Z
Learning: In consensus-critical code (such as quorum formation, block validation, or deployment activation logic), do not suggest changes to the logic itself even if the implementation appears theoretically incorrect or off-by-one. Consensus rules, once deployed on the Dash network, must be preserved exactly to avoid network forks. Refactoring PRs should maintain perfect behavioral equivalence. Only suggest logic changes if explicitly accompanied by a DIP (Dash Improvement Proposal) or if the maintainer indicates the consensus rule needs to be changed with appropriate activation logic.

Applied to files:

  • src/qt/bitcoin.cpp
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-08-01T07:46:37.840Z
Learnt from: UdjinM6
Repo: dashpay/dash PR: 6786
File: ci/test/04_install.sh:99-101
Timestamp: 2025-08-01T07:46:37.840Z
Learning: In backport PRs like #6786, UdjinM6 prefers to defer non-critical fixes (such as shell command expansion issues) to separate commits/PRs to maintain focus on the primary backport objectives, consistent with the project's pattern of avoiding scope creep.

Applied to files:

  • src/qt/bitcoin.cpp
📚 Learning: 2025-07-29T14:32:48.369Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/chainlock/signing.cpp:247-250
Timestamp: 2025-07-29T14:32:48.369Z
Learning: In PR #6761, kwvg acknowledged a null pointer check issue in ChainLockSigner::Cleanup() method but deferred it to follow-up, consistent with the pattern of avoiding scope creep in refactoring PRs.

Applied to files:

  • src/qt/bitcoin.cpp
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-07-29T14:33:01.040Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6761
File: src/wallet/wallet.cpp:0-0
Timestamp: 2025-07-29T14:33:01.040Z
Learning: In refactoring PRs like #6761, kwvg acknowledges code safety improvements (like null pointer checks and unused parameter warnings) but prefers to defer them to follow-up PRs to maintain focus on the primary refactoring objectives, avoiding scope creep.

Applied to files:

  • src/qt/bitcoin.cpp
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-02-06T14:34:30.466Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6543
File: src/wallet/receive.cpp:240-251
Timestamp: 2025-02-06T14:34:30.466Z
Learning: Pull request #6543 is focused on move-only changes and refactoring, specifically backporting from Bitcoin. Behavior changes should be proposed in separate PRs.

Applied to files:

  • src/qt/bitcoin.cpp
  • src/qt/optionsmodel.cpp
📚 Learning: 2025-10-28T18:36:40.263Z
Learnt from: kwvg
Repo: dashpay/dash PR: 6923
File: src/test/util/setup_common.cpp:235-251
Timestamp: 2025-10-28T18:36:40.263Z
Learning: In `src/test/util/setup_common.cpp`, the `CEvoDB` instance in `BasicTestingSetup` is constructed with `.memory = true` flag (memory-only mode), so it does not create file handles on disk. This makes the destructor teardown order safe even if `fs::remove_all(m_path_root)` is called before `m_node.evodb.reset()`.

Applied to files:

  • src/qt/test/test_main.cpp
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/{test,wallet/test}/**/*.{cpp,h} : Unit tests in src/test/ and src/wallet/test/ must use Boost::Test framework

Applied to files:

  • src/qt/test/test_main.cpp
  • src/qt/test/optiontests.h
📚 Learning: 2025-11-24T16:41:22.457Z
Learnt from: CR
Repo: dashpay/dash PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:41:22.457Z
Learning: Applies to src/wallet/**/*.{cpp,h} : Wallet implementation must use Berkeley DB and SQLite

Applied to files:

  • src/qt/optionsmodel.cpp
📚 Learning: 2025-12-22T15:42:51.679Z
Learnt from: kwvg
Repo: dashpay/dash PR: 7068
File: src/qt/guiutil_font.h:68-77
Timestamp: 2025-12-22T15:42:51.679Z
Learning: In the Dash Core Qt codebase (src/qt/guiutil_font.h), kwvg intentionally uses `assert()` in setter methods like `SetWeightBold` and `SetWeightNormal` to enforce invariants (e.g., `assert(m_weights.count(m_font))`). This fail-fast approach is preferred over defensive checks with fallbacks when an inconsistent state indicates a programming error that should be caught during development, rather than a runtime condition requiring graceful handling.

Applied to files:

  • src/qt/optionsmodel.cpp
🧬 Code graph analysis (7)
src/qt/test/wallettests.cpp (1)
src/qt/test/addressbooktests.cpp (1)
  • optionsModel (125-125)
src/qt/bitcoin.h (1)
src/qt/bitcoin.cpp (2)
  • createOptionsModel (268-288)
  • createOptionsModel (268-268)
src/qt/test/addressbooktests.cpp (1)
src/qt/test/wallettests.cpp (1)
  • optionsModel (156-156)
src/qt/bitcoin.cpp (1)
src/qt/optionsmodel.h (1)
  • PruneMiBtoGB (30-30)
src/qt/test/optiontests.cpp (1)
src/qt/test/optiontests.h (1)
  • OptionTests (14-30)
src/qt/optionsmodel.cpp (3)
src/interfaces/node.h (2)
  • node (48-50)
  • node (481-481)
src/util/system.cpp (8)
  • SettingName (190-193)
  • SettingName (190-190)
  • SettingToInt (656-659)
  • SettingToInt (656-656)
  • SettingToString (645-648)
  • SettingToString (645-645)
  • SettingToBool (667-670)
  • SettingToBool (667-667)
src/wallet/wallet.cpp (1)
  • new_value (81-81)
src/qt/test/optiontests.h (1)
src/qt/test/optiontests.cpp (11)
  • OptionTests (19-22)
  • init (24-29)
  • init (24-24)
  • migrateSettings (31-72)
  • migrateSettings (31-31)
  • integerGetArgBug (74-90)
  • integerGetArgBug (74-74)
  • parametersInteraction (92-125)
  • parametersInteraction (92-92)
  • extractFilter (127-134)
  • extractFilter (127-127)
🪛 Cppcheck (2.19.0)
src/qt/test/optiontests.cpp

[error] 22-22: failed to evaluate #if condition, undefined function-like macro invocation

(syntaxError)


[error] 24-24: #error No known always_inline attribute for this platform.

(preprocessorErrorDirective)

🪛 LanguageTool
doc/release-notes-6833.md

[uncategorized] ~6-~6: “Windows” (operating system by Microsoft) is a proper noun and needs to be capitalized.
Context: ...rather than to the Qt settings backend (windows registry or unix desktop config files),...

(A_WINDOWS)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: linux64_multiprocess-build / Build source
  • GitHub Check: linux64_tsan-build / Build source
  • GitHub Check: mac-build / Build source
  • GitHub Check: arm-linux-build / Build source
  • GitHub Check: win64-build / Build source
  • GitHub Check: linux64-build / Build source
  • GitHub Check: linux64_nowallet-build / Build source
  • GitHub Check: linux64_sqlite-build / Build source
  • GitHub Check: linux64_ubsan-build / Build source
🔇 Additional comments (29)
src/qt/bitcoin.h (1)

49-49: LGTM! Error handling improvement.

The signature change from void to [[nodiscard]] bool properly enforces error checking, and the implementation correctly returns false when Init fails, with appropriate error messaging shown to the user.

src/qt/test/apptests.cpp (1)

79-79: LGTM! Test correctly validates initialization.

The test properly wraps createOptionsModel in QVERIFY to validate the boolean result, ensuring initialization failures are caught during testing.

src/qt/test/test_main.cpp (1)

61-64: LGTM! Ensures proper initialization order.

The lambda pattern correctly initializes BasicTestingSetup to configure gArgs before retrieving the data directory path. The scoped lifetime of the dummy setup ensures proper cleanup while allowing the blocks directory to be created with the correct path.

src/qt/test/wallettests.cpp (1)

156-158: LGTM! Correct adoption of two-phase initialization.

The test properly implements the new node-aware initialization pattern:

  1. Constructs OptionsModel with the node reference
  2. Declares bilingual_str error for error reporting
  3. Validates Init(error) success via QVERIFY

This aligns with the broader architectural change to node-backed settings persistence described in the release notes.

src/qt/test/addressbooktests.cpp (1)

125-128: LGTM!

The test correctly adapts to the new OptionsModel API by:

  1. Constructing with the node reference
  2. Declaring a bilingual_str error variable
  3. Verifying initialization succeeds via QVERIFY(optionsModel.Init(error))

This is consistent with the pattern used in wallettests.cpp and other test files.

src/qt/test/optiontests.h (2)

9-10: LGTM!

The added includes for univalue.h and util/settings.h are required to support the new util::Settings m_previous_settings member and JSON-based settings verification in the test implementation.


18-29: LGTM!

The header changes correctly declare:

  • Node-aware constructor matching the new OptionsModel initialization pattern
  • init() slot as a Qt Test lifecycle method for per-test setup
  • New test methods migrateSettings() and integerGetArgBug() for settings migration verification
  • m_previous_settings to capture/restore settings state between tests

The implementation in optiontests.cpp (lines 18-28) confirms proper usage of these declarations.

src/qt/bitcoin.cpp (3)

268-288: LGTM!

The createOptionsModel refactor correctly:

  1. Returns bool to indicate success/failure (aligning with [[nodiscard]] in header)
  2. Constructs OptionsModel with node() reference per new API
  3. Calls Reset() before Init() when resetSettings is true
  4. Handles Init failure by building a detailed bilingual error message with settings path context
  5. Shows a critical message box and returns false on failure

The use of fs::quoted is correct as it's defined in src/fs.h (confirmed in past review).


347-350: LGTM!

The InitPruneSetting update correctly matches the simplified SetPruneTargetGB(int) signature that no longer takes a force parameter.


687-696: LGTM!

The startup flow restructuring correctly ensures:

  1. Splash screen is created first (if enabled)
  2. Node is created via app.createNode(*init) before OptionsModel
  3. createOptionsModel result is checked, exiting with EXIT_FAILURE on initialization failure

This ordering is essential since OptionsModel now requires a valid node reference.

src/qt/optionsmodel.h (5)

19-22: LGTM!

Forward declarations for bilingual_str and interfaces::Node are correctly added to support the new constructor and Init signatures without requiring full header includes.


48-48: LGTM!

The constructor signature change from (QObject* parent, bool resetSettings) to (interfaces::Node& node, QObject* parent) correctly binds OptionsModel to a node reference at construction time, enabling node-backed settings persistence.


97-97: LGTM!

The MaskValues option is correctly added to the OptionID enum, positioned after Server to maintain logical grouping of boolean options.


110-117: LGTM!

The API surface changes correctly support the new architecture:

  • Init(bilingual_str& error) returns bool for explicit success/failure handling with error details
  • getOption(OptionID, suffix) and setOption(OptionID, value, suffix) provide generic access by option ID, supporting the -prev suffix pattern for storing previous values

138-148: LGTM!

The member and accessor changes correctly reflect the node-bound architecture:

  • SetPruneTargetGB(int) simplified signature (force behavior now handled internally)
  • node() returns a reference since m_node is always valid
  • m_node stored as reference rather than pointer, enforcing non-null invariant
src/qt/test/optiontests.cpp (4)

17-29: LGTM!

The test infrastructure correctly implements:

  • #include <fstream> for reading settings.json
  • Constructor captures m_previous_settings via gArgs.LockSettings() for isolation
  • init() lifecycle method restores settings before each test to ensure independence

31-72: Migration test matches upstream backport pattern.

The migrateSettings() test correctly verifies that:

  1. Legacy QSettings values are set and synced
  2. After OptionsModel::Init(), legacy keys are removed from QSettings
  3. Migrated values appear in settings.json

The full JSON string comparison at lines 63-71 was flagged in a previous review as brittle. However, since this is a backport from bitcoin-core/gui and the learning indicates backported changes should match upstream, this implementation should be preserved to maintain fidelity and simplify future backports. Based on learnings, typos and minor issues in backported code should be kept as-is.


74-90: LGTM!

The integerGetArgBug() test correctly verifies the regression fix from bitcoin/bitcoin#24457, ensuring that integer prune values in settings.json don't cause exceptions in OptionsModel::Init().


108-109: LGTM!

The parametersInteraction() test correctly updated to use the new OptionsModel initialization pattern with bilingual_str error and Init(error).

src/qt/optionsmodel.cpp (10)

43-77: LGTM!

The SettingName() function correctly maps GUI OptionID values to their corresponding node setting names. The mapping covers all node-backed options including:

  • Core options (dbcache, par, prune, proxy, listen, server)
  • CoinJoin options (coinjoinamount, coinjoinrounds, etc.)
  • Font settings (font-family, font-scale, font-weight-*)

The std::logic_error for unmapped options provides a fail-fast mechanism to catch programming errors.


79-115: LGTM!

The RequiresNumWorkaround() and UpdateRwSetting() functions correctly implement backward compatibility with Bitcoin 22.x:

  • Numeric settings that 22.x expects as strings are written via getValStr()
  • This prevents UniValue::get_str() exceptions in older releases
  • The comment clearly explains the rationale and references the upstream fix PR

This is inherited upstream behavior that should be preserved for backport fidelity.


117-145: LGTM!

The prune helper functions correctly implement the GUI-to-node prune value conversions:

  • PruneSetting() converts enabled/size to the node's -prune MiB value
  • PruneEnabled() correctly treats -prune=1 (manual mode) as disabled for GUI purposes
  • PruneSizeGB() converts MiB to GB for display, defaulting to DEFAULT_PRUNE_TARGET_GB
  • ParsePruneSizeGB() ensures minimum 1 GB to match GUI display constraints

The assert(!prune_enabled || prune_size_gb >= 1) enforces the invariant documented in the comment.


215-218: LGTM!

The constructor correctly stores the node reference in the initializer list. The body is intentionally empty since Init() must be called explicitly after construction, aligning with the new two-phase initialization pattern.


226-410: LGTM!

The Init() refactor correctly implements:

  1. Returns bool with error details via bilingual_str& error
  2. Initializes language from node persistent settings
  3. Calls checkAndMigrate() for legacy settings migration
  4. Handles font settings with fallback weights when values are invalid
  5. Iterates over node-backed options with try/catch for malformed settings.json values
  6. Returns false with descriptive error on settings parse failures
  7. Initializes m_mask_values from QSettings

The loop at lines 364-379 provides robust error handling for corrupt settings.


431-457: LGTM!

The Reset() function correctly:

  1. Calls node().resetSettings() to backup and clear settings.json
  2. Backs up QSettings to guisettings.ini.bak for troubleshooting
  3. Preserves strDataDir across reset
  4. Clears all QSettings and marks reset with fReset flag

495-525: LGTM!

The SetPruneTargetGB() refactor correctly:

  1. Compares current vs new prune settings using node persistent settings
  2. Forces the prune setting to take effect before node starts
  3. When pruning enabled, also forces disablegovernance=1 and txindex=0 (Dash-specific)
  4. Only writes to settings.json if values actually changed
  5. Preserves previous prune value with -prev suffix when disabling

579-714: LGTM!

The getOption() implementation correctly:

  1. Uses a lambda setting() to fetch node persistent settings with suffix support
  2. Returns values from node settings for node-backed options
  3. Returns values from QSettings or member variables for Qt-only options
  4. Implements the -prev suffix fallback pattern for proxy and prune options
  5. Uses SettingToString/Int/Bool helpers for type-safe conversions with defaults

716-1023: LGTM!

The setOption() implementation correctly:

  1. Uses changed() lambda to avoid unnecessary writes
  2. Uses update() lambda to route writes through UpdateRwSetting()
  3. Handles the -prev suffix pattern for preserving previous values
  4. Emits appropriate signals (e.g., coinControlFeaturesChanged, coinJoinEnabledChanged)
  5. Sets RestartRequired flag for options requiring restart
  6. Prune/PruneSize cases are correctly outside ENABLE_WALLET block (per resolved past review)

1051-1168: LGTM!

The checkAndMigrate() function correctly implements settings migration:

  1. Version-based migration for legacy settings cleanup (pre-230100 PrivateSend removal)
  2. Proxy address sanitization for the %2 bug (issue bitcoin#12623)
  3. Theme validation with fallback to default
  4. migrate_setting lambda that:
    • Checks if legacy QSettings key exists
    • Only migrates if node setting is null (no override)
    • Handles special cases (proxy parsing, font weight conversion)
    • Removes legacy key after migration
  5. Calls node().initParameterInteraction() to propagate dependent settings (e.g., -listen affecting -listenonion)

The migration covers all node-backed options including Dash-specific CoinJoin settings.

Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that -resetguisettings drops all settings from settings.json, not just gui related ones. I had 3 wallets listed there and after gui reset it's an empty file and I have to reopen them manually. Is it intentional or was it fixed in bitcoin later?

EDIT: Can't find any related fixes in bitcoin but it feels like an actual bug, not a feature. Pls consider 5c6a787.

@kwvg kwvg requested a review from UdjinM6 January 4, 2026 21:07
@UdjinM6
Copy link

UdjinM6 commented Jan 4, 2026

Hmm... My previous suggestion was incomplete I guess - settings.json is backed up in resetSettings() but we don't call it anymore so we should do that manually. Pls consider a7cb4d2 on top of it.

Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@kwvg kwvg requested review from UdjinM6 and removed request for UdjinM6 January 4, 2026 22:03
Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 076ce3d

@PastaPastaPasta PastaPastaPasta merged commit 7a2943e into dashpay:develop Jan 5, 2026
42 of 44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants