wallet: create new wallets from a BIP39 seed phrase by default
New wallets now get an exportable 24-word phrase instead of a random seed that
no phrase can ever reproduce. Only wallets with no seed yet are affected;
GenerateNewSeed is reachable from one place, under !HaveHDSeed(), and all three
key stores refuse to replace an existing seed.
This is safe to default on now that the storage form is backwards compatible: the
expanded 64-byte BIP39 seed is what gets stored, so a binary predating any of
this reads it and derives the same keys.
Verified on an isolated chain before flipping:
- a new-format wallet reopened with the tagged v1.1.0 binary, which has no
knowledge of the entropy record, listed identical addresses;
- restoring only the 24 words into a fresh datadir recovered every address.
Note this changes what a new wallet is, not what an existing one is: the same
entropy yields a different key tree depending on which side of this commit
created the wallet. Nothing migrates, and nothing needs to.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -471,7 +471,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||||||
strUsage += HelpMessageOpt("-hdtransparent", strprintf(_("Derive transparent addresses from the HD seed so they can be recovered from it (default: %u)"), 1));
|
strUsage += HelpMessageOpt("-hdtransparent", strprintf(_("Derive transparent addresses from the HD seed so they can be recovered from it (default: %u)"), 1));
|
||||||
strUsage += HelpMessageOpt("-hdseed=<hex>", _("Restore a fresh/empty wallet from a 32- or 64-byte HD seed hex (the value shown in z_exportwallet's '# HDSeed=' line). WARNING: exposes the seed to your shell history and process list."));
|
strUsage += HelpMessageOpt("-hdseed=<hex>", _("Restore a fresh/empty wallet from a 32- or 64-byte HD seed hex (the value shown in z_exportwallet's '# HDSeed=' line). WARNING: exposes the seed to your shell history and process list."));
|
||||||
strUsage += HelpMessageOpt("-mnemonic=<words>", _("Restore/create a fresh/empty wallet from a BIP39 seed phrase, compatible with SilentDragonXLite (English, no passphrase; cross-wallet restore parity is mainnet-only -- testnet/regtest derive a different HD coin_type). WARNING: exposes the phrase to your shell history and process list; prefer DRAGONX.conf with tight permissions."));
|
strUsage += HelpMessageOpt("-mnemonic=<words>", _("Restore/create a fresh/empty wallet from a BIP39 seed phrase, compatible with SilentDragonXLite (English, no passphrase; cross-wallet restore parity is mainnet-only -- testnet/regtest derive a different HD coin_type). WARNING: exposes the phrase to your shell history and process list; prefer DRAGONX.conf with tight permissions."));
|
||||||
strUsage += HelpMessageOpt("-usemnemonic", strprintf(_("Create new wallets from a fresh BIP39 seed phrase so the 24 words can be exported (z_exportmnemonic) and used in SilentDragonXLite (default: %u)"), 0));
|
strUsage += HelpMessageOpt("-usemnemonic", strprintf(_("Create new wallets from a fresh BIP39 seed phrase so the 24 words can be exported (z_exportmnemonic) and used in SilentDragonXLite. Set to 0 for a raw random seed with no recovery phrase; existing wallets are never changed (default: %u)"), 1));
|
||||||
strUsage += HelpMessageOpt("-hdtransparentgaplimit=<n>", strprintf(_("On -mnemonic/-hdseed restore, pre-derive this many HD transparent keys so a rescan can find coinbase paid to them (default: %u)"), 1000));
|
strUsage += HelpMessageOpt("-hdtransparentgaplimit=<n>", strprintf(_("On -mnemonic/-hdseed restore, pre-derive this many HD transparent keys so a rescan can find coinbase paid to them (default: %u)"), 1000));
|
||||||
strUsage += HelpMessageOpt("-mnemonicsaplinggap=<n>", strprintf(_("On -mnemonic/-hdseed restore, pre-derive this many shielded (Sapling) addresses so a rescan can find notes sent to them (default: %u)"), 100));
|
strUsage += HelpMessageOpt("-mnemonicsaplinggap=<n>", strprintf(_("On -mnemonic/-hdseed restore, pre-derive this many shielded (Sapling) addresses so a rescan can find notes sent to them (default: %u)"), 100));
|
||||||
strUsage += HelpMessageOpt("-consolidation", _("Enable auto Sapling note consolidation (default: false)"));
|
strUsage += HelpMessageOpt("-consolidation", _("Enable auto Sapling note consolidation (default: false)"));
|
||||||
|
|||||||
@@ -1039,8 +1039,10 @@ UniValue z_exportmnemonic(const UniValue& params, bool fHelp, const CPubKey& myp
|
|||||||
"\nReveal the wallet's BIP39 seed phrase (24 words).\n"
|
"\nReveal the wallet's BIP39 seed phrase (24 words).\n"
|
||||||
"The phrase is byte-compatible with SilentDragonXLite: the same words\n"
|
"The phrase is byte-compatible with SilentDragonXLite: the same words\n"
|
||||||
"restore the same transparent and shielded addresses in either wallet.\n"
|
"restore the same transparent and shielded addresses in either wallet.\n"
|
||||||
"Only works for wallets created or restored from a mnemonic (see the\n"
|
"New wallets get a seed phrase by default (-usemnemonic=0 opts out);\n"
|
||||||
"-mnemonic and -usemnemonic options). Requires the wallet be unlocked.\n"
|
"wallets restored with -mnemonic have one too. Wallets created before\n"
|
||||||
|
"this feature, or from a raw -hdseed, have no phrase -- use\n"
|
||||||
|
"z_exportwallet for those. Requires the wallet be unlocked.\n"
|
||||||
"\nResult:\n"
|
"\nResult:\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" \"mnemonic\" : \"word1 ... word24\", (string) the BIP39 seed phrase\n"
|
" \"mnemonic\" : \"word1 ... word24\", (string) the BIP39 seed phrase\n"
|
||||||
|
|||||||
@@ -2476,7 +2476,7 @@ void CWallet::GenerateNewSeed()
|
|||||||
// (z_exportmnemonic refuses non-mnemonic wallets, rpcdump.cpp:1031+) and
|
// (z_exportmnemonic refuses non-mnemonic wallets, rpcdump.cpp:1031+) and
|
||||||
// that no seed phrase can restore. A user who asked for -usemnemonic must
|
// that no seed phrase can restore. A user who asked for -usemnemonic must
|
||||||
// get that or a hard failure.
|
// get that or a hard failure.
|
||||||
if (GetBoolArg("-usemnemonic", false)) {
|
if (GetBoolArg("-usemnemonic", true)) {
|
||||||
RawHDSeed entropy;
|
RawHDSeed entropy;
|
||||||
if (!GenerateMnemonicEntropy(256, entropy))
|
if (!GenerateMnemonicEntropy(256, entropy))
|
||||||
throw std::runtime_error(std::string(__func__) + ": -usemnemonic entropy generation failed");
|
throw std::runtime_error(std::string(__func__) + ": -usemnemonic entropy generation failed");
|
||||||
|
|||||||
Reference in New Issue
Block a user