4cd5fab736
Three issues surfaced by testing the previous lock/unlock reconnect fix on Android with a large wallet: - The keep-alive ping had no timeout, so a "half-open" TCP connection (remote end gone with no FIN/RST ever delivered, the common outcome of Doze/mobile-radio suspend after a longer lock) left it awaiting a response that never arrives — the failure path that tears the dead client down was never reached. Bound the ping to 8s and added a re-entrancy guard so overlapping 20s ticks can't pile up concurrent reconnect attempts while one is stuck. - CheckConnectionOnResumeAsync bailed out whenever a sync was already in progress, so a lock/unlock during an active sync (which has no per-request timeout of its own) left it hung indefinitely instead of recovering. It now cancels the stuck sync and tears down the dead client, marking the interruption as self-inflicted (_resumeRecovering) so the UI shows "reconnecting" and restarts immediately instead of a transient error message. - WalletSynchronizer.ExportCaches persisted raw transaction bytes only for already-verified transactions, discarding anything downloaded but not yet through Merkle-proof verification when a sync was interrupted mid-way — forcing a full re-download of a large wallet's transactions on every resume instead of resuming straight into proof verification. Track confirmed txids at download time (_confirmedTxids), independent of verification status, and export/preload against that instead. Also unified the three sync progress messages onto one template reporting against the sync's total transaction/proof counts rather than this session's download count, so a resumed sync immediately shows "transactions n/n" instead of a misleading "0/0" before jumping into proof verification.