mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-08 10:31:50 -05:00
Be able to create new wallets with DescriptorScriptPubKeyMans as backing
This commit is contained in:
parent
b713baa75a
commit
82ae02b165
8 changed files with 87 additions and 11 deletions
|
@ -60,3 +60,8 @@ bool CreateWalletDialog::isMakeBlankWalletChecked() const
|
|||
{
|
||||
return ui->blank_wallet_checkbox->isChecked();
|
||||
}
|
||||
|
||||
bool CreateWalletDialog::isDescriptorWalletChecked() const
|
||||
{
|
||||
return ui->descriptor_checkbox->isChecked();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
bool isEncryptWalletChecked() const;
|
||||
bool isDisablePrivateKeysChecked() const;
|
||||
bool isMakeBlankWalletChecked() const;
|
||||
bool isDescriptorWalletChecked() const;
|
||||
|
||||
private:
|
||||
Ui::CreateWalletDialog *ui;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>364</width>
|
||||
<height>185</height>
|
||||
<height>213</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -17,7 +17,7 @@
|
|||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>140</y>
|
||||
<y>170</y>
|
||||
<width>341</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
|
@ -106,6 +106,22 @@
|
|||
<string>Make Blank Wallet</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="descriptor_checkbox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>140</y>
|
||||
<width>171</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Use descriptors for scriptPubKey management</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Descriptor Wallet</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>wallet_name_line_edit</tabstop>
|
||||
|
|
|
@ -226,6 +226,9 @@ void CreateWalletActivity::createWallet()
|
|||
if (m_create_wallet_dialog->isMakeBlankWalletChecked()) {
|
||||
flags |= WALLET_FLAG_BLANK_WALLET;
|
||||
}
|
||||
if (m_create_wallet_dialog->isDescriptorWalletChecked()) {
|
||||
flags |= WALLET_FLAG_DESCRIPTORS;
|
||||
}
|
||||
|
||||
QTimer::singleShot(500, worker(), [this, name, flags] {
|
||||
WalletCreationStatus status;
|
||||
|
|
|
@ -170,6 +170,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||
{ "createwallet", 1, "disable_private_keys"},
|
||||
{ "createwallet", 2, "blank"},
|
||||
{ "createwallet", 4, "avoid_reuse"},
|
||||
{ "createwallet", 5, "descriptors"},
|
||||
{ "getnodeaddresses", 0, "count"},
|
||||
{ "stop", 0, "wait" },
|
||||
};
|
||||
|
|
|
@ -2706,6 +2706,7 @@ static UniValue createwallet(const JSONRPCRequest& request)
|
|||
{"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."},
|
||||
{"passphrase", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Encrypt the wallet with this passphrase."},
|
||||
{"avoid_reuse", RPCArg::Type::BOOL, /* default */ "false", "Keep track of coin reuse, and treat dirty and clean coins differently with privacy considerations in mind."},
|
||||
{"descriptors", RPCArg::Type::BOOL, /* default */ "false", "Create a native descriptor wallet. The wallet will use descriptors internally to handle address creation"},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
|
@ -2742,6 +2743,9 @@ static UniValue createwallet(const JSONRPCRequest& request)
|
|||
if (!request.params[4].isNull() && request.params[4].get_bool()) {
|
||||
flags |= WALLET_FLAG_AVOID_REUSE;
|
||||
}
|
||||
if (!request.params[5].isNull() && request.params[5].get_bool()) {
|
||||
flags |= WALLET_FLAG_DESCRIPTORS;
|
||||
}
|
||||
|
||||
std::string error;
|
||||
std::shared_ptr<CWallet> wallet;
|
||||
|
@ -4298,7 +4302,7 @@ static const CRPCCommand commands[] =
|
|||
{ "wallet", "addmultisigaddress", &addmultisigaddress, {"nrequired","keys","label","address_type"} },
|
||||
{ "wallet", "backupwallet", &backupwallet, {"destination"} },
|
||||
{ "wallet", "bumpfee", &bumpfee, {"txid", "options"} },
|
||||
{ "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase", "avoid_reuse"} },
|
||||
{ "wallet", "createwallet", &createwallet, {"wallet_name", "disable_private_keys", "blank", "passphrase", "avoid_reuse", "descriptors"} },
|
||||
{ "wallet", "dumpprivkey", &dumpprivkey, {"address"} },
|
||||
{ "wallet", "dumpwallet", &dumpwallet, {"filename"} },
|
||||
{ "wallet", "encryptwallet", &encryptwallet, {"passphrase"} },
|
||||
|
|
|
@ -228,10 +228,14 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString&
|
|||
// Set a seed for the wallet
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
|
||||
if (!spk_man->SetupGeneration()) {
|
||||
error = "Unable to generate initial keys";
|
||||
return WalletCreationStatus::CREATION_FAILED;
|
||||
if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
|
||||
wallet->SetupDescriptorScriptPubKeyMans();
|
||||
} else {
|
||||
for (auto spk_man : wallet->GetActiveScriptPubKeyMans()) {
|
||||
if (!spk_man->SetupGeneration()) {
|
||||
error = "Unable to generate initial keys";
|
||||
return WalletCreationStatus::CREATION_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3783,10 +3787,16 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
|
|||
|
||||
if (!(wallet_creation_flags & (WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET))) {
|
||||
LOCK(walletInstance->cs_wallet);
|
||||
for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
|
||||
if (!spk_man->SetupGeneration()) {
|
||||
error = _("Unable to generate initial keys").translated;
|
||||
return nullptr;
|
||||
if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
|
||||
walletInstance->SetupDescriptorScriptPubKeyMans();
|
||||
// SetupDescriptorScriptPubKeyMans already calls SetupGeneration for us so we don't need to call SetupGeneration separately
|
||||
} else {
|
||||
// Legacy wallets need SetupGeneration here.
|
||||
for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
|
||||
if (!spk_man->SetupGeneration()) {
|
||||
error = _("Unable to generate initial keys").translated;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4351,6 +4361,39 @@ void CWallet::LoadDescriptorScriptPubKeyMan(uint256 id, WalletDescriptor& desc)
|
|||
m_spk_managers[id] = std::move(spk_manager);
|
||||
}
|
||||
|
||||
void CWallet::SetupDescriptorScriptPubKeyMans()
|
||||
{
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
// Make a seed
|
||||
CKey seed_key;
|
||||
seed_key.MakeNewKey(true);
|
||||
CPubKey seed = seed_key.GetPubKey();
|
||||
assert(seed_key.VerifyPubKey(seed));
|
||||
|
||||
// Get the extended key
|
||||
CExtKey master_key;
|
||||
master_key.SetSeed(seed_key.begin(), seed_key.size());
|
||||
|
||||
for (bool internal : {false, true}) {
|
||||
for (OutputType t : OUTPUT_TYPES) {
|
||||
auto spk_manager = std::unique_ptr<DescriptorScriptPubKeyMan>(new DescriptorScriptPubKeyMan(*this, t, internal));
|
||||
if (IsCrypted()) {
|
||||
if (IsLocked()) {
|
||||
throw std::runtime_error(std::string(__func__) + ": Wallet is locked, cannot setup new descriptors");
|
||||
}
|
||||
if (!spk_manager->CheckDecryptionKey(vMasterKey) && !spk_manager->Encrypt(vMasterKey, nullptr)) {
|
||||
throw std::runtime_error(std::string(__func__) + ": Could not encrypt new descriptors");
|
||||
}
|
||||
}
|
||||
spk_manager->SetupDescriptorGeneration(master_key);
|
||||
uint256 id = spk_manager->GetID();
|
||||
m_spk_managers[id] = std::move(spk_manager);
|
||||
SetActiveScriptPubKeyMan(id, t, internal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CWallet::SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly)
|
||||
{
|
||||
auto& spk_mans = internal ? m_internal_spk_managers : m_external_spk_managers;
|
||||
|
|
|
@ -1244,6 +1244,9 @@ public:
|
|||
//! @param[in] internal Whether this ScriptPubKeyMan provides change addresses
|
||||
//! @param[in] memonly Whether to record this update to the database. Set to true for wallet loading, normally false when actually updating the wallet.
|
||||
void SetActiveScriptPubKeyMan(uint256 id, OutputType type, bool internal, bool memonly = false);
|
||||
|
||||
//! Create new DescriptorScriptPubKeyMans and add them to the wallet
|
||||
void SetupDescriptorScriptPubKeyMans();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue