Bug-report fixes plus adversarial-audit follow-ups. Bumps full 2.0.1->2.0.2 and lite 1.1.0->1.1.1. i18n / fonts: - Rebuild the NotoSansCJK subset with the glyphs the FAQ back-fill introduced (什/么/门/做); Chinese FAQ titles rendered as "??" on zh (and ja/ko). Transaction history (enumeration gaps): - Surface outgoing shielded z->z sends via z_listsentbyaddress (listtransactions and z_listreceivedbyaddress never report them). - Surface z->t deshields by parsing z_listsentbyaddress transparentSends (which z_viewtransaction does not expose); dedupe t->t against listtransactions. - Key send-row dedup on address so equal-value multi-output sends aren't dropped. Lite wallet (key safety): - The async create/restore/open path the UI uses now applies the passphrase: encrypt a new/restored wallet, unlock an existing one. It previously discarded the passphrase, storing the seed/keys in PLAINTEXT (create/restore) or leaving an encrypted wallet locked (open). Migrate-to-seed (fund safety): - Persist a sweep-submitted marker at broadcast so a resumed migration can't treat a ~0 balance (an unconfirmed in-flight sweep) as an empty wallet and adopt (swap wallet.dat) before the sweep confirms; best-effort locate routes to the confirm gate. Sync / threading: - Gate isSynced() on a peer-derived tip (tip_known) so a peerless node isn't reported synced (Send against a stale balance); add a "no peers" status banner. - Guard daemon_status_ with a mutex (monitor-thread write vs UI-thread read). Tests: extends tests/test_phase4.cpp across all of the above; suite green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BwycPDQSfEKtrTS2uC4JeT
46 lines
2.6 KiB
C++
46 lines
2.6 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
|
|
// Pure routing decision for resuming a pending migrate-to-seed flow (finding W3-3). Kept free of
|
|
// App/UI/RPC state so the highest-risk branch — where a reopened migration lands — is unit-testable
|
|
// and reviewable in isolation. App::showSeedMigrationDialog feeds it the persisted state + live
|
|
// connectivity and switches on the result. See src/app_network.cpp.
|
|
namespace dragonx {
|
|
|
|
enum class MigrationResume {
|
|
Intro, // no pending migration → start fresh at the intro
|
|
Confirming, // a sweep txid is persisted → resume at the confirm/adopt gate (re-derived from chain)
|
|
RetrackOpid, // a sweep opid (but no txid yet) is persisted AND we're connected → re-poll it
|
|
SweepGate, // otherwise → the dismissable Sweep step (reload balance, offer re-sweep)
|
|
};
|
|
|
|
// Decide where reopening the migration dialog lands.
|
|
//
|
|
// Invariant: the txid outranks the opid — once a sweep resolves to a txid the opid is cleared in the
|
|
// same settings write, so a persisted txid always means "past the sweep". A persisted opid is only
|
|
// re-tracked when connected, because the buttonless "Sweeping" spinner relies on the opid poller
|
|
// (which needs an RPC connection) to ever exit; disconnected, we fall back to the dismissable Sweep
|
|
// gate (which reloads the balance and, if the earlier sweep already drained it, short-circuits to
|
|
// adopt) — never trapping the user.
|
|
inline MigrationResume decideSeedMigrationResume(bool pending,
|
|
bool haveDest,
|
|
const std::string& sweepTxid,
|
|
const std::string& sweepOpid,
|
|
bool connected) {
|
|
if (!pending || !haveDest) return MigrationResume::Intro;
|
|
if (!sweepTxid.empty()) return MigrationResume::Confirming;
|
|
if (!sweepOpid.empty() && connected) return MigrationResume::RetrackOpid;
|
|
return MigrationResume::SweepGate;
|
|
}
|
|
|
|
// At the Sweep step with a ~0 legacy balance, may we offer the direct "no funds -> adopt" short-cut
|
|
// (swap wallet.dat immediately)? Only when NO sweep has been submitted — a genuinely empty wallet.
|
|
// If a sweep WAS submitted, a ~0 balance is ambiguous: the sweep tx may be unconfirmed in the mempool
|
|
// and could revert on a drop/reorg, so adopting now can strand the funds in the moved-aside backup.
|
|
// In that case adopt must go through the confirmation-gated path (>=1 conf) instead — never swap
|
|
// wallet.dat on an unconfirmed sweep. (fund-safety: audit)
|
|
inline bool sweepGateMayAdoptEmptyWallet(bool sweepSubmitted) { return !sweepSubmitted; }
|
|
|
|
} // namespace dragonx
|