From f16aea4fa5e26c3a7ce92c0af829454675c03e1d Mon Sep 17 00:00:00 2001 From: pasta Date: Sun, 2 Aug 2026 13:36:06 -0500 Subject: [PATCH 1/2] fix: surface specific autobackup-failure tooltips in CoinJoin status guard The early guard in OverviewPage::coinJoinStatus() treated every non-positive nWalletBackups value the same, always showing the generic 'Automatic backups are disabled' tooltip. On every timer tick this overwrote the more specific messages for -1 (backup failed) and -2 (keypool not replenished, wallet locked), so the later per-status block only ever showed its text for the single tick in which autoBackupWallet() freshly failed. Move the status-specific tooltips into the guard, which now handles all three states persistently, and reduce the later block to what still matters in the same invocation: stopping mixing immediately on -1 (CCoinJoinClientManager::CheckAutomaticBackup() does not call stopMixing() for -1, and the modal at the failure site already tells the user mixing is disabled). Its tooltip assignments are dropped since they were overwritten by the guard within a second anyway. --- src/qt/overviewpage.cpp | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index c09ebd86c435..9ce945530a5b 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -526,8 +526,14 @@ void OverviewPage::coinJoinStatus(bool fForce) // Disable any PS UI for masternode or when autobackup is disabled or failed for whatever reason if (clientModel->node().isMasternode() || nWalletBackups <= 0) { DisableCoinJoinCompletely(); - if (nWalletBackups <= 0) { + if (nWalletBackups == 0) { ui->labelCoinJoinEnabled->setToolTip(tr("Automatic backups are disabled, no mixing available!")); + } else if (nWalletBackups == -1) { + ui->labelCoinJoinEnabled->setToolTip(tr("ERROR! Failed to create automatic backup") + ", " + + tr("see debug.log for details.") + "

" + + tr("Mixing is disabled, please close your wallet and fix the issue!")); + } else if (nWalletBackups == -2) { + ui->labelCoinJoinEnabled->setToolTip(tr("WARNING! Failed to replenish keypool, please unlock your wallet to do so.")); } return; } @@ -666,22 +672,11 @@ void OverviewPage::coinJoinStatus(bool fForce) if(fShowAdvancedCJUI && !strKeysLeftText.isEmpty()) strEnabled += ", " + strKeysLeftText; ui->labelCoinJoinEnabled->setText(strEnabled); - if (walletModel->wallet().isLegacy()) { - if(nWalletBackups == -1) { - // Automatic backup failed, nothing else we can do until user fixes the issue manually - DisableCoinJoinCompletely(); - - QString strError = tr("ERROR! Failed to create automatic backup") + ", " + - tr("see debug.log for details.") + "

" + - tr("Mixing is disabled, please close your wallet and fix the issue!"); - ui->labelCoinJoinEnabled->setToolTip(strError); - - return; - } else if(nWalletBackups == -2) { - // We were able to create automatic backup but keypool was not replenished because wallet is locked. - QString strWarning = tr("WARNING! Failed to replenish keypool, please unlock your wallet to do so."); - ui->labelCoinJoinEnabled->setToolTip(strWarning); - } + if (walletModel->wallet().isLegacy() && nWalletBackups == -1) { + // Automatic backup failed, nothing else we can do until user fixes the issue manually. + // Stop mixing right away; the guard above sets the matching tooltip on the next timer tick. + DisableCoinJoinCompletely(); + return; } // check coinjoin status and unlock if needed From 0d7a9d625981529aa3ee650dd22b4d441f1d986c Mon Sep 17 00:00:00 2001 From: pasta Date: Mon, 3 Aug 2026 09:54:26 -0500 Subject: [PATCH 2/2] test: add regression coverage for autobackup-failure CoinJoin tooltips Set nWalletBackups to 0, -1 and -2 in TestGUI and assert coinJoinStatus() selects the specific tooltip for each state, so the generic tooltip can no longer silently shadow the error/warning ones. Verified the new assertions fail against the pre-fix overviewpage.cpp. --- src/qt/test/wallettests.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index f051563a8532..1394ac1fdea1 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -193,6 +194,30 @@ void TestGUI(interfaces::Node& node) QString balanceComparison = BitcoinUnits::floorHtmlWithPrivacy(unit, balance, BitcoinUnits::SeparatorStyle::ALWAYS, false); QCOMPARE(balanceText, balanceComparison); + // Check that each autobackup failure state selects its specific tooltip on the CoinJoin status label + { + QLabel* coinJoinLabel = overviewPage.findChild("labelCoinJoinEnabled"); + QVERIFY(coinJoinLabel != nullptr); + const int nWalletBackupsOld = nWalletBackups; + + nWalletBackups = 0; + overviewPage.coinJoinStatus(/*fForce=*/true); + QCOMPARE(coinJoinLabel->toolTip(), QString("Automatic backups are disabled, no mixing available!")); + + nWalletBackups = -1; + overviewPage.coinJoinStatus(/*fForce=*/true); + QCOMPARE(coinJoinLabel->toolTip(), + QString("ERROR! Failed to create automatic backup, see debug.log for details.

Mixing is " + "disabled, please close your wallet and fix the issue!")); + + nWalletBackups = -2; + overviewPage.coinJoinStatus(/*fForce=*/true); + QCOMPARE(coinJoinLabel->toolTip(), + QString("WARNING! Failed to replenish keypool, please unlock your wallet to do so.")); + + nWalletBackups = nWalletBackupsOld; + } + // Check Request Payment button ReceiveCoinsDialog receiveCoinsDialog; receiveCoinsDialog.setModel(&walletModel);