On a wallet with a very large shielded note set, the daemon re-decrypts all
notes under cs_main on every z_gettotalbalance / z_listunspent (GetFilteredNotes),
~15-33s per pass. The GUI issued these roughly every 15s and timed them out at
the 30s RPC limit, so the node looked permanently "busy" and per-address
balances read 0 (nothing to carry on a fresh session) while the total was fine.
Two wallet-side mitigations:
- A cost-proportional floor on VISIBLE balance polls (wallet_scan_governor): the
adaptive backoff previously applied only when the balance was off-screen. It
now also holds a visible poll until ~3x the measured scan cost has elapsed, so
a wallet whose sweep costs tens of seconds can't re-poll before the node
recovers. Negligible for small wallets (cost ~ms); forced / first-read bypass it.
- The heavy balance RPCs (z_gettotalbalance, z_listunspent) now use a 120s reply
timeout via the existing callLong path, so a slow pass completes and populates
per-address balances instead of aborting at 30s and leaving them at 0.
The root fix is daemon-side (cache decrypted notes so GetFilteredNotes isn't
O(notes x decrypt) per call); specced separately. Adds governor test coverage.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>