Skip to content

Commit c734c8a

Browse files
PastaPastaPastaknst
authored andcommitted
Merge dashpay#6570: feat: mnemonic support for descriptor wallets
42e80f1 refactor: add prefix crypted_ for arguments related to crypted mnemonic (Konstantin Akimov) c89e181 feat: improve wording for errors, RPC and logs (Konstantin Akimov) b3a7475 refactor: removed dead commented code from serialize.h (Konstantin Akimov) c8a6f69 refactor: use args instead gArgs in new mnemonic code (Konstantin Akimov) d093506 fix: compilation errors due to advancing develop branch (Konstantin Akimov) e636d19 test: multiple fixes in wallet_mnemonics to fix review comments (Konstantin Akimov) 3a8ab80 fix: intermittent error in wallet_mnemonic.py due to different order of descriptors (Konstantin Akimov) 4bd214e test: adjust commentary, ensure cb private key is "inactive" descriptor (Konstantin Akimov) 8eb5d4a fix: do not reset seed / mnemonic for descriptor wallets in case of encryption (Konstantin Akimov) e27f95c fix: text message for HD wallets (both descriptors and non-descriptors) (Konstantin Akimov) 4f6be3d test: make functional test wallet_mnemonicbits.py works for descriptor wallets (Konstantin Akimov) 979ed95 feat: implement mnemonic for descriptor wallets (Konstantin Akimov) 267693f fix: expand text commentary for RPC encryptwallet (Konstantin Akimov) d287f09 refactor: drop -usehd=1 from some functional tests so far as it is default option (Konstantin Akimov) Pull request description: ## Issue being fixed or feature implemented Descriptor wallets doesn't support yet mnemonics (BIP39), which are supported only by legacy (non-descriptor) wallet. ## What was done? This PR adds basic support BIP39 to descriptor wallets: - newly created descriptor wallets will have mnemonic - RPC `upgradetohd` now support descriptor wallets and let to set specifict mnemonic with passphrase to newly created wallet - mnemonic is shown when calling RPC `listdescriptors` if exists ## How Has This Been Tested? Functional test `wallet_mnemonicbits.py` support `--descriptors` now Functional test `wallet_upgradetohd.py` is updated also ## Breaking Changes N/A ## Checklist: - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK 42e80f1 kwvg: utACK 42e80f1 Tree-SHA512: 2f55dd291356da8bfca31bd270c1a22056e7d2977e5f91761970cfaa6ccf5038cc930d59b6a572a2fcc6198ac9031ab177ca86d63155a6b3bd86bd92d3dbb4ee
1 parent a2ba808 commit c734c8a

16 files changed

+396
-65
lines changed

src/serialize.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <utility>
2626
#include <vector>
2727

28+
#include <support/allocators/secure.h>
2829
#include <prevector.h>
2930
#include <span.h>
3031

@@ -816,8 +817,8 @@ struct VectorFormatter
816817
/**
817818
* string
818819
*/
819-
template<typename Stream, typename C> void Serialize(Stream& os, const std::basic_string<C>& str);
820-
template<typename Stream, typename C> void Unserialize(Stream& is, std::basic_string<C>& str);
820+
template<typename Stream, typename A, typename B, typename C> void Serialize(Stream& os, const std::basic_string<A, B, C>& str);
821+
template<typename Stream, typename A, typename B, typename C> void Unserialize(Stream& is, std::basic_string<A, B, C>& str);
821822

822823
/**
823824
* prevector
@@ -947,16 +948,16 @@ struct DefaultFormatter
947948
/**
948949
* string
949950
*/
950-
template<typename Stream, typename C>
951-
void Serialize(Stream& os, const std::basic_string<C>& str)
951+
template<typename Stream, typename A, typename B, typename C>
952+
void Serialize(Stream& os, const std::basic_string<A, B, C>& str)
952953
{
953954
WriteCompactSize(os, str.size());
954955
if (!str.empty())
955956
os.write(MakeByteSpan(str));
956957
}
957958

958-
template<typename Stream, typename C>
959-
void Unserialize(Stream& is, std::basic_string<C>& str)
959+
template<typename Stream, typename A, typename B, typename C>
960+
void Unserialize(Stream& is, std::basic_string<A, B, C>& str)
960961
{
961962
unsigned int nSize = ReadCompactSize(is);
962963
str.resize(nSize);

src/wallet/rpcdump.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -860,9 +860,9 @@ RPCHelpMan dumphdinfo()
860860
RPCResult{
861861
RPCResult::Type::OBJ, "", "",
862862
{
863-
{RPCResult::Type::STR_HEX, "hdseed", "The HD seed (bip32, in hex)"},
864-
{RPCResult::Type::STR, "mnemonic", "The mnemonic for this HD wallet (bip39, english words)"},
865-
{RPCResult::Type::STR, "mnemonicpassphrase", "The mnemonic passphrase for this HD wallet (bip39)"},
863+
{RPCResult::Type::STR_HEX, "hdseed", "The HD seed (BIP32, in hex)"},
864+
{RPCResult::Type::STR, "mnemonic", "The mnemonic for this HD wallet (BIP39, english words)"},
865+
{RPCResult::Type::STR, "mnemonicpassphrase", "The mnemonic passphrase for this HD wallet (BIP39)"},
866866
}
867867
},
868868
RPCExamples{
@@ -1951,6 +1951,8 @@ RPCHelpMan listdescriptors()
19511951
{
19521952
{RPCResult::Type::OBJ, "", "", {
19531953
{RPCResult::Type::STR, "desc", "Descriptor string representation"},
1954+
{RPCResult::Type::STR, "mnemonic", "The mnemonic for this descriptor wallet (BIP39, english words). Presented only if private=true and created with a mnemonic"},
1955+
{RPCResult::Type::STR, "mnemonicpassphrase", "The mnemonic passphrase for this descriptor wallet (BIP39). Presented only if private=true and created with a mnemonic"},
19541956
{RPCResult::Type::NUM, "timestamp", "The creation time of the descriptor"},
19551957
{RPCResult::Type::BOOL, "active", "Whether this descriptor is currently used to generate new addresses"},
19561958
{RPCResult::Type::BOOL, "internal", /*optional=*/true, "True if this descriptor is used to generate change addresses. False if this descriptor is used to generate receiving addresses; defined only for active descriptors"},
@@ -1997,6 +1999,14 @@ RPCHelpMan listdescriptors()
19971999
if (!desc_spk_man->GetDescriptorString(descriptor, priv)) {
19982000
throw JSONRPCError(RPC_WALLET_ERROR, "Can't get descriptor string.");
19992001
}
2002+
if (priv) {
2003+
SecureString mnemonic;
2004+
SecureString mnemonic_passphrase;
2005+
if (desc_spk_man->GetMnemonicString(mnemonic, mnemonic_passphrase) && !mnemonic.empty()) {
2006+
spk.pushKV("mnemonic", mnemonic.c_str());
2007+
spk.pushKV("mnemonicpassphrase", mnemonic_passphrase.c_str());
2008+
}
2009+
}
20002010
spk.pushKV("desc", descriptor);
20012011
spk.pushKV("timestamp", wallet_descriptor.creation_time);
20022012
const bool active = active_spk_mans.count(desc_spk_man) != 0;

src/wallet/scriptpubkeyman.cpp

Lines changed: 128 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <util/strencodings.h>
1414
#include <util/system.h>
1515
#include <util/translation.h>
16+
#include <wallet/bip39.h>
1617
#include <wallet/scriptpubkeyman.h>
1718

1819
bool LegacyScriptPubKeyMan::GetNewDestination(CTxDestination& dest, bilingual_str& error)
@@ -1844,6 +1845,7 @@ bool DescriptorScriptPubKeyMan::CheckDecryptionKey(const CKeyingMaterial& master
18441845
keyFail = true;
18451846
break;
18461847
}
1848+
// TODO: test for mnemonics
18471849
keyPass = true;
18481850
if (m_decryption_thoroughly_checked)
18491851
break;
@@ -1870,15 +1872,34 @@ bool DescriptorScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, Walle
18701872
{
18711873
const CKey &key = key_in.second;
18721874
CPubKey pubkey = key.GetPubKey();
1875+
assert(pubkey.GetID() == key_in.first);
1876+
const auto mnemonic_in = m_mnemonics.find(key_in.first);
18731877
CKeyingMaterial secret(key.begin(), key.end());
18741878
std::vector<unsigned char> crypted_secret;
18751879
if (!EncryptSecret(master_key, secret, pubkey.GetHash(), crypted_secret)) {
18761880
return false;
18771881
}
1882+
std::vector<unsigned char> crypted_mnemonic;
1883+
std::vector<unsigned char> crypted_mnemonic_passphrase;
1884+
if (mnemonic_in != m_mnemonics.end()) {
1885+
const Mnemonic mnemonic = mnemonic_in->second;
1886+
1887+
CKeyingMaterial mnemonic_secret(mnemonic.first.begin(), mnemonic.first.end());
1888+
CKeyingMaterial mnemonic_passphrase_secret(mnemonic.second.begin(), mnemonic.second.end());
1889+
if (!EncryptSecret(master_key, mnemonic_secret, pubkey.GetHash(), crypted_mnemonic)) {
1890+
return false;
1891+
}
1892+
if (!EncryptSecret(master_key, mnemonic_passphrase_secret, pubkey.GetHash(), crypted_mnemonic_passphrase)) {
1893+
return false;
1894+
}
1895+
}
1896+
18781897
m_map_crypted_keys[pubkey.GetID()] = make_pair(pubkey, crypted_secret);
1879-
batch->WriteCryptedDescriptorKey(GetID(), pubkey, crypted_secret);
1898+
m_crypted_mnemonics[pubkey.GetID()] = make_pair(crypted_mnemonic, crypted_mnemonic_passphrase);
1899+
batch->WriteCryptedDescriptorKey(GetID(), pubkey, crypted_secret, crypted_mnemonic, crypted_mnemonic_passphrase);
18801900
}
18811901
m_map_keys.clear();
1902+
m_mnemonics.clear();
18821903
return true;
18831904
}
18841905

@@ -2003,12 +2024,12 @@ void DescriptorScriptPubKeyMan::AddDescriptorKey(const CKey& key, const CPubKey
20032024
{
20042025
LOCK(cs_desc_man);
20052026
WalletBatch batch(m_storage.GetDatabase());
2006-
if (!AddDescriptorKeyWithDB(batch, key, pubkey)) {
2027+
if (!AddDescriptorKeyWithDB(batch, key, pubkey, "", "")) {
20072028
throw std::runtime_error(std::string(__func__) + ": writing descriptor private key failed");
20082029
}
20092030
}
20102031

2011-
bool DescriptorScriptPubKeyMan::AddDescriptorKeyWithDB(WalletBatch& batch, const CKey& key, const CPubKey &pubkey)
2032+
bool DescriptorScriptPubKeyMan::AddDescriptorKeyWithDB(WalletBatch& batch, const CKey& key, const CPubKey &pubkey, const SecureString& mnemonic, const SecureString& mnemonic_passphrase)
20122033
{
20132034
AssertLockHeld(cs_desc_man);
20142035
assert(!m_storage.IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS));
@@ -2025,22 +2046,37 @@ bool DescriptorScriptPubKeyMan::AddDescriptorKeyWithDB(WalletBatch& batch, const
20252046
}
20262047

20272048
std::vector<unsigned char> crypted_secret;
2049+
std::vector<unsigned char> crypted_mnemonic;
2050+
std::vector<unsigned char> crypted_mnemonic_passphrase;
20282051
CKeyingMaterial secret(key.begin(), key.end());
2052+
CKeyingMaterial mnemonic_secret(mnemonic.begin(), mnemonic.end());
2053+
CKeyingMaterial mnemonic_passphrase_secret(mnemonic_passphrase.begin(), mnemonic_passphrase.end());
20292054
if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
2030-
return EncryptSecret(encryption_key, secret, pubkey.GetHash(), crypted_secret);
2055+
if (!EncryptSecret(encryption_key, secret, pubkey.GetHash(), crypted_secret)) return false;
2056+
if (!mnemonic.empty()) {
2057+
if (!EncryptSecret(encryption_key, mnemonic_secret, pubkey.GetHash(), crypted_mnemonic)) {
2058+
return false;
2059+
}
2060+
if (!EncryptSecret(encryption_key, mnemonic_passphrase_secret, pubkey.GetHash(), crypted_mnemonic_passphrase)) {
2061+
return false;
2062+
}
2063+
}
2064+
return true;
20312065
})) {
20322066
return false;
20332067
}
20342068

20352069
m_map_crypted_keys[pubkey.GetID()] = make_pair(pubkey, crypted_secret);
2036-
return batch.WriteCryptedDescriptorKey(GetID(), pubkey, crypted_secret);
2070+
m_crypted_mnemonics[pubkey.GetID()] = make_pair(crypted_mnemonic, crypted_mnemonic_passphrase);
2071+
return batch.WriteCryptedDescriptorKey(GetID(), pubkey, crypted_secret, crypted_mnemonic, crypted_mnemonic_passphrase);
20372072
} else {
20382073
m_map_keys[pubkey.GetID()] = key;
2039-
return batch.WriteDescriptorKey(GetID(), pubkey, key.GetPrivKey());
2074+
m_mnemonics[pubkey.GetID()] = make_pair(mnemonic, mnemonic_passphrase);
2075+
return batch.WriteDescriptorKey(GetID(), pubkey, key.GetPrivKey(), mnemonic, mnemonic_passphrase);
20402076
}
20412077
}
20422078

2043-
bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_key, bool internal)
2079+
bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_key, const SecureString& secure_mnemonic, const SecureString& secure_mnemonic_passphrase, bool internal)
20442080
{
20452081
LOCK(cs_desc_man);
20462082
assert(m_storage.IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
@@ -2050,6 +2086,16 @@ bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_
20502086
return false;
20512087
}
20522088

2089+
if (!secure_mnemonic.empty()) {
2090+
// TODO: remove duplicated code with AddKey()
2091+
SecureVector seed_key_tmp;
2092+
CMnemonic::ToSeed(secure_mnemonic, secure_mnemonic_passphrase, seed_key_tmp);
2093+
2094+
CExtKey master_key_tmp;
2095+
master_key_tmp.SetSeed(MakeByteSpan(seed_key_tmp));
2096+
assert(master_key == master_key_tmp);
2097+
}
2098+
20532099
int64_t creation_time = GetTime();
20542100

20552101
std::string xpub = EncodeExtPubKey(master_key.Neuter());
@@ -2070,7 +2116,7 @@ bool DescriptorScriptPubKeyMan::SetupDescriptorGeneration(const CExtKey& master_
20702116

20712117
// Store the master private key, and descriptor
20722118
WalletBatch batch(m_storage.GetDatabase());
2073-
if (!AddDescriptorKeyWithDB(batch, master_key.key, master_key.key.GetPubKey())) {
2119+
if (!AddDescriptorKeyWithDB(batch, master_key.key, master_key.key.GetPubKey(), secure_mnemonic, secure_mnemonic_passphrase)) {
20742120
throw std::runtime_error(std::string(__func__) + ": writing descriptor master private key failed");
20752121
}
20762122
if (!batch.WriteDescriptor(GetID(), m_wallet_descriptor)) {
@@ -2354,21 +2400,34 @@ void DescriptorScriptPubKeyMan::SetCache(const DescriptorCache& cache)
23542400
}
23552401
}
23562402

2357-
bool DescriptorScriptPubKeyMan::AddKey(const CKeyID& key_id, const CKey& key)
2403+
bool DescriptorScriptPubKeyMan::AddKey(const CKeyID& key_id, const CKey& key, const SecureString& mnemonic, const SecureString& mnemonic_passphrase)
23582404
{
23592405
LOCK(cs_desc_man);
2406+
if (!mnemonic.empty()) {
2407+
// TODO: remove duplicated code with AddKey()
2408+
SecureVector seed_key_tmp;
2409+
CMnemonic::ToSeed(mnemonic, mnemonic_passphrase, seed_key_tmp);
2410+
2411+
CExtKey master_key_tmp;
2412+
master_key_tmp.SetSeed(MakeByteSpan(seed_key_tmp));
2413+
assert(key == master_key_tmp.key);
2414+
}
2415+
23602416
m_map_keys[key_id] = key;
2417+
m_mnemonics[key_id] = make_pair(mnemonic, mnemonic_passphrase);
2418+
23612419
return true;
23622420
}
23632421

2364-
bool DescriptorScriptPubKeyMan::AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key)
2422+
bool DescriptorScriptPubKeyMan::AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key, const std::vector<unsigned char>& crypted_mnemonic,const std::vector<unsigned char>& crypted_mnemonic_passphrase)
23652423
{
23662424
LOCK(cs_desc_man);
23672425
if (!m_map_keys.empty()) {
23682426
return false;
23692427
}
23702428

23712429
m_map_crypted_keys[key_id] = make_pair(pubkey, crypted_key);
2430+
m_crypted_mnemonics[key_id] = make_pair(crypted_mnemonic, crypted_mnemonic_passphrase);
23722431
return true;
23732432
}
23742433

@@ -2410,7 +2469,6 @@ bool DescriptorScriptPubKeyMan::GetDescriptorString(std::string& out, const bool
24102469

24112470
FlatSigningProvider provider;
24122471
provider.keys = GetKeys();
2413-
24142472
if (priv) {
24152473
// For the private version, always return the master key to avoid
24162474
// exposing child private keys. The risk implications of exposing child
@@ -2421,6 +2479,65 @@ bool DescriptorScriptPubKeyMan::GetDescriptorString(std::string& out, const bool
24212479
return m_wallet_descriptor.descriptor->ToNormalizedString(provider, out, &m_wallet_descriptor.cache);
24222480
}
24232481

2482+
bool DescriptorScriptPubKeyMan::GetMnemonicString(SecureString& mnemonic_out, SecureString& mnemonic_passphrase_out) const
2483+
{
2484+
LOCK(cs_desc_man);
2485+
2486+
mnemonic_out.clear();
2487+
mnemonic_passphrase_out.clear();
2488+
2489+
if (m_mnemonics.empty() && m_crypted_mnemonics.empty()) {
2490+
WalletLogPrintf("%s: Descriptor wallet has no mnemonic defined\n", __func__);
2491+
return false;
2492+
}
2493+
if (m_storage.IsLocked(false)) return false;
2494+
2495+
if (m_mnemonics.size() + m_crypted_mnemonics.size() > 1) {
2496+
WalletLogPrintf("%s: ERROR: One descriptor has multiple mnemonics. Can't match it\n", __func__);
2497+
return false;
2498+
}
2499+
if (m_storage.HasEncryptionKeys() && !m_storage.IsLocked(true)) {
2500+
if (!m_crypted_mnemonics.empty() && m_map_crypted_keys.size() != 1) {
2501+
WalletLogPrintf("%s: ERROR: can't choose encryption key for mnemonic out of %lld\n", __func__, m_map_crypted_keys.size());
2502+
return false;
2503+
}
2504+
const CPubKey& pubkey = m_map_crypted_keys.begin()->second.first;
2505+
const auto mnemonic = m_crypted_mnemonics.begin()->second;
2506+
const std::vector<unsigned char>& crypted_mnemonic = mnemonic.first;
2507+
const std::vector<unsigned char>& crypted_mnemonic_passphrase = mnemonic.second;
2508+
2509+
SecureVector mnemonic_v;
2510+
SecureVector mnemonic_passphrase_v;
2511+
if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
2512+
return DecryptSecret(encryption_key, crypted_mnemonic, pubkey.GetHash(), mnemonic_v);
2513+
})) {
2514+
WalletLogPrintf("%s: ERROR: can't decrypt mnemonic pubkey %s crypted: %s\n", __func__, pubkey.GetHash().ToString(), HexStr(crypted_mnemonic));
2515+
return false;
2516+
}
2517+
if (!crypted_mnemonic_passphrase.empty()) {
2518+
if (!m_storage.WithEncryptionKey([&](const CKeyingMaterial& encryption_key) {
2519+
return DecryptSecret(encryption_key, crypted_mnemonic_passphrase, pubkey.GetHash(), mnemonic_passphrase_v);
2520+
})) {
2521+
WalletLogPrintf("%s: ERROR: can't decrypt mnemonic passphrase\n", __func__);
2522+
return false;
2523+
}
2524+
}
2525+
2526+
std::copy(mnemonic_v.begin(), mnemonic_v.end(), std::back_inserter(mnemonic_out));
2527+
std::copy(mnemonic_passphrase_v.begin(), mnemonic_passphrase_v.end(), std::back_inserter(mnemonic_passphrase_out));
2528+
2529+
return true;
2530+
}
2531+
if (m_mnemonics.empty()) return false;
2532+
2533+
const auto mnemonic_it = m_mnemonics.begin();
2534+
2535+
mnemonic_out = mnemonic_it->second.first;
2536+
mnemonic_passphrase_out = mnemonic_it->second.second;
2537+
2538+
return true;
2539+
}
2540+
24242541
void DescriptorScriptPubKeyMan::UpgradeDescriptorCache()
24252542
{
24262543
LOCK(cs_desc_man);

src/wallet/scriptpubkeyman.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,17 +510,25 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
510510
using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
511511
using KeyMap = std::map<CKeyID, CKey>;
512512

513+
using Mnemonic = std::pair<SecureString, SecureString>;
514+
using MnemonicMap = std::map<CKeyID, Mnemonic>;
515+
using CryptedMnemonic = std::pair<std::vector<unsigned char>, std::vector<unsigned char>>;
516+
using CryptedMnemonicMap = std::map<CKeyID, CryptedMnemonic>;
517+
513518
ScriptPubKeyMap m_map_script_pub_keys GUARDED_BY(cs_desc_man);
514519
PubKeyMap m_map_pubkeys GUARDED_BY(cs_desc_man);
515520
int32_t m_max_cached_index = -1;
516521

517522
KeyMap m_map_keys GUARDED_BY(cs_desc_man);
518523
CryptedKeyMap m_map_crypted_keys GUARDED_BY(cs_desc_man);
519524

525+
MnemonicMap m_mnemonics GUARDED_BY(cs_desc_man);
526+
CryptedMnemonicMap m_crypted_mnemonics GUARDED_BY(cs_desc_man);
527+
520528
//! keeps track of whether Unlock has run a thorough check before
521529
bool m_decryption_thoroughly_checked = false;
522530

523-
bool AddDescriptorKeyWithDB(WalletBatch& batch, const CKey& key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
531+
bool AddDescriptorKeyWithDB(WalletBatch& batch, const CKey& key, const CPubKey &pubkey, const SecureString& mnemonic, const SecureString& mnemonic_passphrase) EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
524532

525533
KeyMap GetKeys() const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
526534

@@ -562,7 +570,7 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
562570
bool IsHDEnabled() const override;
563571

564572
//! Setup descriptors based on the given CExtkey
565-
bool SetupDescriptorGeneration(const CExtKey& master_key, bool internal);
573+
bool SetupDescriptorGeneration(const CExtKey& master_key, const SecureString& secure_mnemonic, const SecureString& secure_mnemonic_passphrase, bool internal);
566574

567575
bool HavePrivateKeys() const override;
568576

@@ -588,8 +596,8 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
588596

589597
void SetCache(const DescriptorCache& cache);
590598

591-
bool AddKey(const CKeyID& key_id, const CKey& key);
592-
bool AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key);
599+
bool AddKey(const CKeyID& key_id, const CKey& key, const SecureString& mnemonic, const SecureString& mnemonic_passphrase);
600+
bool AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key, const std::vector<unsigned char>& crypted_mnemonic,const std::vector<unsigned char>& crypted_mnemonic_passphrase);
593601

594602
bool HasWalletDescriptor(const WalletDescriptor& desc) const;
595603
void UpdateWalletDescriptor(WalletDescriptor& descriptor);
@@ -601,6 +609,7 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
601609
const std::vector<CScript> GetScriptPubKeys() const;
602610

603611
bool GetDescriptorString(std::string& out, const bool priv) const;
612+
bool GetMnemonicString(SecureString& mnemonic_out, SecureString& mnemonic_passphrase_out) const;
604613

605614
void UpgradeDescriptorCache();
606615
};

0 commit comments

Comments
 (0)