fix(wallet): surface the real z_getnewaddress error; sweep coinbase in migrate-to-seed
From a legacy-wallet migration support case (mined T-funds, 3y-old Silent Dragon wallet.dat): the balance
shows but new-address and migrate both fail with unhelpful/silent results. Two fixes:
1) Real address-creation error. createNewAddress() swallowed the daemon's z_getnewaddress error and the UI
showed a generic "Failed to create shielded address". It now keeps the daemon's reason (friendly-mapped
via friendlyRpcError) in last_address_error_, which the Receive tab and request-payment dialog show
instead of the generic string — so a legacy/degraded wallet sees the actual "HD seed not found". And when
that specific error appears it flips wallet_degraded_ + warns once, even for an EXTERNAL daemon
(detectWalletDegraded() only scans the embedded daemon's log and would otherwise miss it).
2) Migrate-to-seed sweep skipped coinbase. beginSweepToSeedWallet()'s z_mergetoaddress ignores coinbase
UTXOs, so a miner's coinbase-only balance produced "Could not find any funds to merge", the legacy
balance never reached ~0, and the adopt gate stalled silently. The sweep now falls back to
z_shieldcoinbase("*", dest, fee, 50) to the SAME shielded destination when the merge reports no funds.
z_shieldcoinbase returns an opid just like the merge, so the single-opid adopt gate (opid -> txid ->
confirm -> balance ~0 -> adopt) is unchanged, and a batch limit / mixed wallet drains via the existing
"Sweep remaining" re-sweep.
Fund-path: the z_mergetoaddress call and its args are byte-identical; the fallback only ADDS a
z_shieldcoinbase to the same dest when merge finds nothing, and nothing is adopted until the swept funds
confirm and the legacy balance is ~0 (gate unchanged). Runtime-verified behavior (clean build + ctest; the
RPC paths are not pure-testable).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -453,6 +453,9 @@ public:
|
||||
// Address operations
|
||||
void createNewZAddress(std::function<void(const std::string&)> callback = nullptr);
|
||||
void createNewTAddress(std::function<void(const std::string&)> callback = nullptr);
|
||||
// The daemon's actual reason the last new-address RPC failed (friendly-mapped), or "" on success. Lets
|
||||
// the UI show e.g. "HD seed not found" (legacy/degraded wallet) instead of a generic "couldn't create".
|
||||
const std::string& lastAddressError() const { return last_address_error_; }
|
||||
|
||||
// Hide/unhide addresses from the address list (persisted in settings)
|
||||
void hideAddress(const std::string& addr);
|
||||
@@ -1350,6 +1353,7 @@ private:
|
||||
// so a possibly-incomplete salvaged wallet isn't mistaken for fund loss. Warned once per session.
|
||||
bool wallet_auto_recovered_ = false; // a salvage happened this session
|
||||
bool wallet_auto_recovered_warned_ = false; // guard: only surface it once per session
|
||||
std::string last_address_error_; // daemon reason the last z_getnewaddress/getnewaddress failed ("" = ok)
|
||||
bool wallet_degraded_ = false; // v1.3.0+ opened the wallet in DEGRADED mode (no new HD keys)
|
||||
bool wallet_degraded_warned_ = false; // guard: surface the degraded-mode notice once per session
|
||||
bool show_wallet_recovered_dialog_ = false; // auto-shown warning dialog
|
||||
|
||||
Reference in New Issue
Block a user