fix(security): follow the daemon's lock state on Set-PIN and expiry
Setting a PIN always unlocked the wallet with a 5 s probe and then re-locked it, even when the wallet was already unlocked, so a PIN check silently re-locked an unlocked wallet. And once the daemon's absolute unlock window ran out the GUI still showed "unlocked", so the next send failed with nothing on screen explaining it. - The Set-PIN check now decides on the main thread: an unlocked wallet is verified with the time it has left (capped at seven days) and is not re-locked, so the GUI and the daemon keep agreeing; a locked wallet still uses the 5 s probe and re-locks. Either way the daemon's lock state is re-read afterwards, which self-heals any drift. - When the daemon's unlock window has expired but the GUI still says "unlocked", a bounded reconcile (once per expiry, 30 s back-off) re-reads getwalletinfo so the lock screen and the transaction-cache lock follow the daemon. Lite wallets, which have no daemon timer, are left alone. Behaviour change: with auto-lock disabled the daemon still re-locks at its window, and the GUI now lands on the lock screen instead of appearing unlocked until a send fails. Tests: the Set-PIN verify plan (unlocked keeps its remaining time and skips the re-lock, locked or near-expiry falls back to the 5 s probe and re-lock, long windows are capped) and the unlock-expiry predicate across encrypted, locked, no-deadline and not-yet-expired cases. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1942,6 +1942,8 @@ private:
|
||||
// Auto-lock on idle. Fed by real input events (noteUserInput, from main.cpp's event ingest), NOT by
|
||||
// widget state: a focused-but-untouched text field must not keep the wallet unlocked (C21).
|
||||
util::IdleTracker idle_;
|
||||
// C90: back-off clock for the daemon-unlock-expiry reconcile (steady clock, wall-clock independent).
|
||||
std::chrono::steady_clock::time_point unlock_reconcile_retry_at_{};
|
||||
|
||||
// Wall-clock delta for logic timers (see logicDeltaTime()).
|
||||
std::chrono::steady_clock::time_point last_update_time_{};
|
||||
@@ -2052,6 +2054,9 @@ private:
|
||||
bool shouldRunWalletTransactionRefresh() const;
|
||||
bool shouldRefreshRecentTransactions() const;
|
||||
void checkAutoLock();
|
||||
// C90: the daemon's absolute unlock window ran out while the GUI still says "unlocked": re-read getwalletinfo
|
||||
// (once per expiry, backed off) so the lock screen / tx-cache lock follow the daemon.
|
||||
void reconcileUnlockExpiry();
|
||||
void checkIdleMining();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user