fix(security): reconcile the encryption-pending flag on every connect

The wizard persists an "encryption requested" flag so a quit or crash
before the wallet is actually encrypted is not silent. That flag was
only reconciled on the slow-path getwalletinfo refresh, so it could be
left stale, and the clear-and-warn logic lived inline in two places.

- A single reconcileEncryptionPending now runs on every connect and on
  every encryption-state refresh, keyed on the parsed getwalletinfo
  reply. It clears the flag whenever the wallet is encrypted, however it
  got there (deferred request, Settings, another client), and warns once
  per session when encryption was requested but the wallet is not
  encrypted and nothing is pending or in flight.
- A failed or warm-up (-28) RPC decides nothing, so a 15 s timeout that
  forces encrypted=false can no longer mis-clear or mis-warn.
- The flag is also cleared at encryptwallet success and when the user
  removes encryption, so neither path leaves a stale flag that would
  warn on the next connect. No settings format change.

Tests: the pure decision helper over the flag, RPC-ok, encrypted,
deferred-pending, in-flight and already-warned combinations (clear when
encrypted, warn once when lost, nothing on a failed RPC or no flag).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 21:42:23 -05:00
co-authored by Claude Opus 4.8
parent 0aaf33ecf0
commit 2fce9a7860
6 changed files with 82 additions and 19 deletions
+3
View File
@@ -2043,6 +2043,9 @@ private:
void refreshAddresses(); // Legacy: standalone address refresh
void refreshPrice();
void refreshWalletEncryptionState();
// C88: reconcile the persisted "encryption requested" flag against one parsed getwalletinfo result
// (connect-time ConnectionInit and every Encryption job). Main thread only.
void reconcileEncryptionPending(const services::NetworkRefreshService::WalletEncryptionResult& enc);
void applyRefreshPolicy(ui::NavPage page);
bool effectivelySyncing() const; // syncing, or within the post-sync settle window (hysteresis)
bool currentPageNeedsWalletDataRefresh() const;