achow101
commented at 2:55 am on August 24, 2023:
member
Instead of constructing ScriptPubKeyMans with no data, and then loading data as we find it, we should gather everything first and then load it all on construction. If there actually is no data and we want to setup generation, then that should also occur in a constructor rather than afterwards.
This change is only applied to DescriptorScriptPubKeyMan and ExternalSignerScriptPubKeyMan, and should be done for any ScriptPubKeyMans added in the future. I don’t think it’s really worth it to do this for LegacyScriptPubKeyMan since it would make loading performance worse (or cause layer violations) and it’s (supposed to be) going away soon.
DrahtBot
commented at 2:55 am on August 24, 2023:
contributor
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
DrahtBot added the label
Wallet
on Aug 24, 2023
in
src/wallet/wallet.cpp:424
in
ca729a7d60outdated
390@@ -391,40 +391,18 @@ std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string&
391 return nullptr;
392 }
393394+ // Unset the blank flag if not specified by the user
395+ if (!create_blank) {
EncryptWallet does not end up calling the SetupGeneration functions when the blank flag is set. Previously, we would set those up manually after encrypting. While making this PR, I realized that we could just unset the blank flag before calling EncryptWallet so that it can do the setup for us and we don’t have to do it again afterwards.
unknown approved
DrahtBot added the label
CI failed
on Sep 3, 2023
DrahtBot removed the label
CI failed
on Sep 5, 2023
DrahtBot added the label
CI failed
on Nov 25, 2023
maflcko
commented at 1:35 pm on November 27, 2023:
member
0wallet/test/fuzz/scriptpubkeyman.cpp: In lambda function:
1wallet/test/fuzz/scriptpubkeyman.cpp:114:67: error: ‘void wallet::DescriptorScriptPubKeyMan::AddDescriptorKey(const CKey&, const CPubKey&)’ is private within this context
2114| spk_manager->AddDescriptorKey(key, key.GetPubKey());
3|
achow101 force-pushed
on Nov 27, 2023
DrahtBot removed the label
CI failed
on Nov 27, 2023
DrahtBot added the label
Needs rebase
on Nov 28, 2023
achow101 force-pushed
on Nov 28, 2023
DrahtBot removed the label
Needs rebase
on Nov 28, 2023
achow101 force-pushed
on Dec 7, 2023
DrahtBot added the label
Needs rebase
on Dec 8, 2023
achow101 force-pushed
on Dec 8, 2023
DrahtBot removed the label
Needs rebase
on Dec 8, 2023
DrahtBot added the label
CI failed
on Jan 12, 2024
DrahtBot added the label
Needs rebase
on Feb 20, 2024
achow101 force-pushed
on Feb 20, 2024
DrahtBot removed the label
Needs rebase
on Feb 20, 2024
DrahtBot added the label
Needs rebase
on Mar 29, 2024
achow101 force-pushed
on Mar 29, 2024
DrahtBot removed the label
Needs rebase
on Mar 29, 2024
achow101 force-pushed
on Apr 3, 2024
achow101
commented at 10:41 pm on April 3, 2024:
member
Added a commit so that the fuzzer will skip the type of inputs that was causing the previous failure. This should be safe as that failure is not reachable in normal usage. It can only be reached if the user’s wallet is corrupted, and in that case, the runtime error would propagate up to them so there would not be a crash.
DrahtBot removed the label
CI failed
on Apr 4, 2024
DrahtBot added the label
Needs rebase
on Jun 3, 2024
achow101 force-pushed
on Jun 4, 2024
DrahtBot removed the label
Needs rebase
on Jun 5, 2024
DrahtBot added the label
Needs rebase
on Jul 11, 2024
achow101 force-pushed
on Jul 22, 2024
DrahtBot removed the label
Needs rebase
on Jul 22, 2024
DrahtBot added the label
Needs rebase
on Aug 12, 2024
achow101 force-pushed
on Aug 29, 2024
DrahtBot removed the label
Needs rebase
on Aug 29, 2024
achow101 requested review from murchandamus
on Oct 15, 2024
DrahtBot added the label
Needs rebase
on Oct 24, 2024
achow101 force-pushed
on Oct 28, 2024
DrahtBot added the label
CI failed
on Oct 28, 2024
DrahtBot
commented at 7:24 pm on October 28, 2024:
contributor
Try to run the tests locally, according to the documentation. However, a CI failure may still
happen due to a number of reasons, for example:
Possibly due to a silent merge conflict (the changes in this pull request being
incompatible with the current code in the target branch). If so, make sure to rebase on the latest
commit of the target branch.
A sanitizer issue, which can only be found by compiling with the sanitizer and running the
affected test.
An intermittent issue.
Leave a comment here, if you need help tracking down a confusing failure.
achow101 force-pushed
on Oct 28, 2024
DrahtBot removed the label
Needs rebase
on Oct 28, 2024
DrahtBot removed the label
CI failed
on Oct 28, 2024
DrahtBot added the label
Needs rebase
on Apr 23, 2025
achow101 force-pushed
on Apr 24, 2025
DrahtBot removed the label
Needs rebase
on Apr 24, 2025
DrahtBot added the label
Needs rebase
on Apr 25, 2025
achow101 force-pushed
on Apr 25, 2025
DrahtBot removed the label
Needs rebase
on Apr 25, 2025
DrahtBot added the label
Needs rebase
on May 7, 2025
achow101 force-pushed
on May 7, 2025
DrahtBot removed the label
Needs rebase
on May 7, 2025
DrahtBot added the label
Needs rebase
on May 19, 2025
achow101 force-pushed
on May 20, 2025
DrahtBot removed the label
Needs rebase
on May 20, 2025
in
src/wallet/scriptpubkeyman.h:317
in
2cee4def97outdated
308@@ -317,22 +309,33 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
309 // Fetch the SigningProvider for a given index and optionally include private keys. Called by the above functions.
310 std::unique_ptr<FlatSigningProvider> GetSigningProvider(int32_t index, bool include_private = false) const EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
311312+ void SetCache(const DescriptorCache& cache);
313+
314+ void AddDescriptorKey(const CKey& key, const CPubKey &pubkey);
315+ void UpdateWithSigningProvider(WalletBatch& batch, const FlatSigningProvider& signing_provider) EXCLUSIVE_LOCKS_REQUIRED(cs_desc_man);
316+
317+ //! Setup descriptors based on the given CExtkey
CExtkey -> CExtKey [typographical error in type name]
DrahtBot added the label
Needs rebase
on May 21, 2025
achow101 force-pushed
on May 21, 2025
DrahtBot removed the label
Needs rebase
on May 21, 2025
DrahtBot added the label
Needs rebase
on Jun 14, 2025
achow101 force-pushed
on Jun 14, 2025
DrahtBot removed the label
Needs rebase
on Jun 14, 2025
rkrux
commented at 10:03 am on July 11, 2025:
contributor
I seem to be getting onboard with this idea as I can notice readability improvements on a cursory glance. Do you anticipate any performance improvements as well?
The last sentence related to legacy SPKMs of the last paragraph in the PR description can be removed now.
Will do full review soon.
in
src/wallet/wallet.cpp:429
in
32dd0e3525outdated
424+ if (!create_blank) {
425+ wallet->UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
426+ }
427+
428 // Encrypt the wallet
429 if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
In 32dd0e35251973f9bdc2114e70c800624894d489 “wallet: Consolidate generation setup callers into one function”
While this flow is being cleaned up. There is a check specially for this flag above on line 400 that forbids this situation and the secondary check seems redundant here now.
0- if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
1+ if (!passphrase.empty()) {
in
src/wallet/wallet.cpp:424
in
32dd0e3525outdated
419@@ -420,30 +420,18 @@ std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string&
420 return nullptr;
421 }
422423+ // Unset the blank flag if not specified by the user
424+ if (!create_blank) {
Fine as-is but perhaps this block can be put inside the if block below because from what I see if not set by the user, this flag can only be set in case of passphrase not being empty on line 388. This wrapped inside a tighter constraint such as the one below looks better to me.
The blank flag needs to be unset before EncryptWallet so that EncryptWallet can generate the new keys after encrypting. Otherwise, the newly created wallet will be encrypted but blank, which is not what we want in this scenario.
I had something like this in mind and I should have left a diff earlier for clarity. It seemed to me that only for encrypted wallets the blank flag was set by the code & hence, believed this flag unsetting could be nested inside the below condition.
0diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
1index bd1b36b4a9..5a3ecc1d19 100644
2--- a/src/wallet/wallet.cpp
3+++ b/src/wallet/wallet.cpp
4@@ -381,9 +381,6 @@ std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string&
5 Assert(wallet_creation_flags & WALLET_FLAG_DESCRIPTORS);
6 options.require_format = DatabaseFormat::SQLITE;
7 8- // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
9- bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
10-
11 // Born encrypted wallets need to be created blank first.
12 if (!passphrase.empty()) {
13 wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET;
14@@ -420,13 +417,10 @@ std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string&
15 return nullptr;
16 }
1718- // Unset the blank flag if not specified by the user
19- if (!create_blank) {
20- wallet->UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
21- }
22-
23 // Encrypt the wallet
24 if (!passphrase.empty()) {
25+ // Unset the blank flag that was purposefully set above for encrypted wallets
26+ wallet->UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
27 if (!wallet->EncryptWallet(passphrase)) {
28 error = Untranslated("Error: Wallet created but failed to encrypt.");
29 status = DatabaseStatus::FAILED_ENCRYPT;
But I check now that this fails the test for intentionally blank encrypted wallets. So, this suggestion is incorrect and need not be implemented.
This never seems to return false. Do we need to check for a falsy value while calling it like done above? Maybe not even return a bool? Just a thrown exception that is bubbled up.
in
src/wallet/walletdb.cpp:860
in
fdba094a67outdated
859- spk_man->SetCache(cache);
860+ // Set the cache to the WalletDescriptor
861+ desc.cache = cache;
862863 // Get unencrypted keys
864+ std::map<CKeyID, CKey> keys;
In fdba094a67906cc89918661e24c9c9a5e3f4cb0b “wallet: Load everything into DescSPKM on construction”
Some of them are now being used in wallet.cpp & external_signer_scriptpubkeyman.h and I suggested using couple in walletdb.cpp too. Maybe they can now go in a utility file like walletutil.h?
In 93c3729ad5adc02f6d87ec8daa1a1952d7c41009 “wallet: Setup new autogenerated descriptors on construction”
0- //! Create an automatically generated DescriptorScriptPubKeyMan
1+ //! Create an automatically generated DescriptorScriptPubKeyMan (i.e. during wallet or descriptor creation)
This PR makes DescriptorScriptPubKeyMan class RAII compliant by adding 4 constructors that are responsible for allocating all the resources (eg: memory) required by this class during initialisation itself. I feel that it improves the readability quite a lot as the reader can easily gauge what all is needed by this class at one place and there is no need for multiple scattered class-write function calls like the one below that used to appear before.
I noticed that this style now allows us to add more error checking that makes the code more robust imo.
0Error: Wallet contains both unencrypted and encrypted keys
Perhaps a Refactoring label is required in the PR?
wallet: Consolidate generation setup callers into one function23d60002a8
wallet: Load everything into DescSPKM on construction
Instead of creating a DescSPKM that is then progressively loaded, we
should instead create it all at once in a constructor when loading.
c94423fb71
fuzz: Skip adding descriptor to wallet if it cannot be expanded2c0c41f8c6
wallet: include keys when constructing DescriptorSPKM during import
When importing a descriptor, all of the descriptor data should be
provided at the same time in the constructor.
1e2113ca1a
wallet: Construct ExternalSignerSPKM with the new descriptor
Instead of constructing then setting the descriptor with
SetupDescriptor, just pass in that descriptor to the constructor.
a1a15bb4ac
wallet: Setup new autogenerated descriptors on construction
Instead of having a caller use SetupDescriptorGeneration, just have a
constructor that takes those arguments and sets up the descriptor with
the autogenerated key.
8e9de762f6
achow101 force-pushed
on Jul 24, 2025
rkrux approved
rkrux
commented at 7:48 am on July 25, 2025:
contributor
This is a metadata mirror of the GitHub repository
bitcoin/bitcoin.
This site is not affiliated with GitHub.
Content is generated from a GitHub metadata backup.
generated: 2025-07-26 09:13 UTC
This site is hosted by @0xB10C More mirrored repositories can be found on mirror.b10c.me