Skip to content

Commit 82ae02b

Browse files
committed
Be able to create new wallets with DescriptorScriptPubKeyMans as backing
1 parent b713baa commit 82ae02b

File tree

8 files changed

+87
-11
lines changed

8 files changed

+87
-11
lines changed

src/qt/createwalletdialog.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,8 @@ bool CreateWalletDialog::isMakeBlankWalletChecked() const
6060
{
6161
return ui->blank_wallet_checkbox->isChecked();
6262
}
63+
64+
bool CreateWalletDialog::isDescriptorWalletChecked() const
65+
{
66+
return ui->descriptor_checkbox->isChecked();
67+
}

src/qt/createwalletdialog.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class CreateWalletDialog : public QDialog
2727
bool isEncryptWalletChecked() const;
2828
bool isDisablePrivateKeysChecked() const;
2929
bool isMakeBlankWalletChecked() const;
30+
bool isDescriptorWalletChecked() const;
3031

3132
private:
3233
Ui::CreateWalletDialog *ui;

src/qt/forms/createwalletdialog.ui

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<x>0</x>
88
<y>0</y>
99
<width>364</width>
10-
<height>185</height>
10+
<height>213</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
@@ -17,7 +17,7 @@
1717
<property name="geometry">
1818
<rect>
1919
<x>10</x>
20-
<y>140</y>
20+
<y>170</y>
2121
<width>341</width>
2222
<height>32</height>
2323
</rect>
@@ -106,6 +106,22 @@
106106
<string>Make Blank Wallet</string>
107107
</property>
108108
</widget>
109+
<widget class="QCheckBox" name="descriptor_checkbox">
110+
<property name="geometry">
111+
<rect>
112+
<x>20</x>
113+
<y>140</y>
114+
<width>171</width>
115+
<height>22</height>
116+
</rect>
117+
</property>
118+
<property name="toolTip">
119+
<string>Use descriptors for scriptPubKey management</string>
120+
</property>
121+
<property name="text">
122+
<string>Descriptor Wallet</string>
123+
</property>
124+
</widget>
109125
</widget>
110126
<tabstops>
111127
<tabstop>wallet_name_line_edit</tabstop>

src/qt/walletcontroller.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ void CreateWalletActivity::createWallet()
226226
if (m_create_wallet_dialog->isMakeBlankWalletChecked()) {
227227
flags |= WALLET_FLAG_BLANK_WALLET;
228228
}
229+
if (m_create_wallet_dialog->isDescriptorWalletChecked()) {
230+
flags |= WALLET_FLAG_DESCRIPTORS;
231+
}
229232

230233
QTimer::singleShot(500, worker(), [this, name, flags] {
231234
WalletCreationStatus status;

src/rpc/client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
170170
{ "createwallet", 1, "disable_private_keys"},
171171
{ "createwallet", 2, "blank"},
172172
{ "createwallet", 4, "avoid_reuse"},
173+
{ "createwallet", 5, "descriptors"},
173174
{ "getnodeaddresses", 0, "count"},
174175
{ "stop", 0, "wait" },
175176
};

src/wallet/rpcwallet.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2706,6 +2706,7 @@ static UniValue createwallet(const JSONRPCRequest& request)
27062706
{"blank", RPCArg::Type::BOOL, /* default */ "false", "Create a blank wallet. A blank wallet has no keys or HD seed. One can be set using sethdseed."},
27072707
{"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
27082708
{"avoid_reuse", RPCArg::Type::BOOL, /* default */ "false", "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."},
2709+
{"descriptors", RPCArg::Type::BOOL, /* default */ "false", "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation"},
27092710
},
27102711
RPCResult{
27112712
RPCResult::Type::OBJ, "", "",
@@ -2742,6 +2743,9 @@ static UniValue createwallet(const JSONRPCRequest& request)
27422743
if (!request.params[4].isNull() && request.params[4].get_bool()) {
27432744
flags |= WALLET_FLAG_AVOID_REUSE;
27442745
}
2746+
if (!request.params[5].isNull() && request.params[5].get_bool()) {
2747+
flags |= WALLET_FLAG_DESCRIPTORS;
2748+
}
27452749

27462750
std::string error;
27472751
std::shared_ptr<CWallet> wallet;
@@ -4298,7 +4302,7 @@ static const CRPCCommand commands[] =
42984302
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label","address_type"} },
42994303
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
43004304
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
4301-
{ "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase", "avoid_reuse"} },
4305+
{ "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase", "avoid_reuse", "descriptors"} },
43024306
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
43034307
{ "wallet", "dumpwallet", &dumpwallet, {"filename"} },
43044308
{ "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },

src/wallet/wallet.cpp

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,14 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString&
228228
// Set a seed for the wallet
229229
{
230230
LOCK(wallet->cs_wallet);
231-
for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
232-
if (!spk_man->SetupGeneration()) {
233-
error = "Unable to generate initial keys";
234-
return WalletCreationStatus::CREATION_FAILED;
231+
if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
232+
wallet->SetupDescriptorScriptPubKeyMans();
233+
} else {
234+
for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
235+
if (!spk_man->SetupGeneration()) {
236+
error = "Unable to generate initial keys";
237+
return WalletCreationStatus::CREATION_FAILED;
238+
}
235239
}
236240
}
237241
}
@@ -3783,10 +3787,16 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
37833787

37843788
if (!(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
37853789
LOCK(walletInstance->cs_wallet);
3786-
for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3787-
if (!spk_man->SetupGeneration()) {
3788-
error = _("Unable to generate initial keys").translated;
3789-
return nullptr;
3790+
if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
3791+
walletInstance->SetupDescriptorScriptPubKeyMans();
3792+
// SetupDescriptorScriptPubKeyMans already calls SetupGeneration for us so we don't need to call SetupGeneration separately
3793+
} else {
3794+
// Legacy wallets need SetupGeneration here.
3795+
for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
3796+
if (!spk_man->SetupGeneration()) {
3797+
error = _("Unable to generate initial keys").translated;
3798+
return nullptr;
3799+
}
37903800
}
37913801
}
37923802
}
@@ -4351,6 +4361,39 @@ void CWallet::LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc)
43514361
m_spk_managers[id] = std::move(spk_manager);
43524362
}
43534363

4364+
void CWallet::SetupDescriptorScriptPubKeyMans()
4365+
{
4366+
AssertLockHeld(cs_wallet);
4367+
4368+
// Make a seed
4369+
CKey seed_key;
4370+
seed_key.MakeNewKey(true);
4371+
CPubKey seed = seed_key.GetPubKey();
4372+
assert(seed_key.VerifyPubKey(seed));
4373+
4374+
// Get the extended key
4375+
CExtKey master_key;
4376+
master_key.SetSeed(seed_key.begin(), seed_key.size());
4377+
4378+
for (bool internal : {false, true}) {
4379+
for (OutputType t : OUTPUT_TYPES) {
4380+
auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, t, internal));
4381+
if (IsCrypted()) {
4382+
if (IsLocked()) {
4383+
throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
4384+
}
4385+
if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, nullptr)) {
4386+
throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
4387+
}
4388+
}
4389+
spk_manager->SetupDescriptorGeneration(master_key);
4390+
uint256 id = spk_manager->GetID();
4391+
m_spk_managers[id] = std::move(spk_manager);
4392+
SetActiveScriptPubKeyMan(id, t, internal);
4393+
}
4394+
}
4395+
}
4396+
43544397
void CWallet::SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly)
43554398
{
43564399
auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;

src/wallet/wallet.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,9 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
12441244
//! @param[in] internal Whether this ScriptPubKeyMan provides change addresses
12451245
//! @param[in] memonly Whether to record this update to the database. Set to true for wallet loading, normally false when actually updating the wallet.
12461246
void SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly = false);
1247+
1248+
//! Create new DescriptorScriptPubKeyMans and add them to the wallet
1249+
void SetupDescriptorScriptPubKeyMans();
12471250
};
12481251

12491252
/**

0 commit comments

Comments
 (0)