feat(wallet): migrate-to-seed, Phase 1 — isolated seed-wallet creation
First, fund-safe step of "migrate a legacy wallet to a seed wallet": mint a brand-new BIP39 mnemonic wallet in an ISOLATED throwaway datadir so the user can later sweep funds into it. No funds move and the real wallet.dat / main daemon are never touched — the isolated node runs concurrently on its own port. - EmbeddedDaemon: one-shot isolated-datadir override (setNextStartOverride) consumed on the next start(); a skip-default-port-check for an isolated instance beside the main daemon; and a tcpPortInUse() probe. The datadir's basename must be the assetchain name (DRAGONX) and the daemon reads <datadir>/DRAGONX.conf itself, so no -conf is passed (both learned from live testing against the hd-transparent-keys daemon). - SeedWalletCreator (src/daemon): picks a free port, writes a throwaway conf, starts an isolated dragonxd with -usemnemonic=1 -connect=0, waits for RPC, calls z_exportmnemonic + z_getnewaddress (the sweep target), stops it, and keeps/scrubs the temp datadir. Off-thread; the seed is wiped after use. - App: beginCreateSeedWallet (background) -> pumpSeedMigration (main-thread handoff) -> renderSeedMigrationDialog (Intro -> Working -> Show seed -> Error), reusing the seed_display grid + clipboard auto-clear. - Settings: "Migrate to seed…" button (full-node gated) + persisted pending migration state (dest address + temp datadir) for Phase 2 to adopt. Validated end-to-end against the hd-transparent-keys daemon: the isolated node comes up in ~4s and returns a 24-word mnemonic + a shielded z-address. Requires that daemon (the bundled Jun-28 build lacks z_exportmnemonic). The migration modal uses English literals for now (as renderBackupDialog does); the whole flow gets translated once Phase 2 finalizes it. Phase 2 (sweep + adopt) is next. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
32
src/daemon/seed_wallet_creator.h
Normal file
32
src/daemon/seed_wallet_creator.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace dragonx {
|
||||
namespace daemon {
|
||||
|
||||
struct SeedWalletResult {
|
||||
bool ok = false;
|
||||
std::string seedPhrase; // SECRET — the caller must wipe it after use
|
||||
std::string destAddress; // new shielded z-address (the Phase 2 sweep target)
|
||||
std::string tempDatadir; // datadir holding the new wallet.dat (kept iff keepDatadir + ok)
|
||||
std::string error;
|
||||
};
|
||||
|
||||
// Mint a fresh BIP39 mnemonic wallet in an ISOLATED throwaway datadir by running a second
|
||||
// dragonxd on its own port with no network, export its seed + a new z-address, then stop it.
|
||||
//
|
||||
// This is the safe first step of "migrate to a seed wallet": it moves no funds and never touches
|
||||
// the main daemon or the real wallet.dat. Blocking — call it on a background thread.
|
||||
//
|
||||
// keepDatadir: keep the temp datadir + its wallet.dat so a later sweep/adopt step can use it, or
|
||||
// delete it immediately (used when only the seed itself is wanted).
|
||||
class SeedWalletCreator {
|
||||
public:
|
||||
static SeedWalletResult create(bool keepDatadir,
|
||||
const std::function<void(const std::string&)>& progress = {});
|
||||
};
|
||||
|
||||
} // namespace daemon
|
||||
} // namespace dragonx
|
||||
Reference in New Issue
Block a user