-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Split CWallet::Create()
into CreateNew
and LoadExisting
#32636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Split CWallet::Create()
into CreateNew
and LoadExisting
#32636
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/32636. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approach ACK
It'd be nice if the load or create intention could be propagated down to the DB level as well. In |
Any reason not to just pass a parameter to CWallet::Create, just to fix the bug in the simplest manner? Refactoring should ideally be separate from fixing. |
Because doing the bare minimum to fix a bug that is unreachable in production is how we end up with technical debt. IMO, this PR is primarily a refactor to split these 2 actions that should not be combined. The fact that it fixes those bugs, which are a result of the combining, is a bonus. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK
The current state of this code in master
adds confusion to flows like the legacy to descriptor wallet migration that's why I think it's an important work to be done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK 0f82224
I want to share my initial thoughts before I invest more time reviewing this.
I am in favour of such a refactor because from a reviewing POV I lose mental cycles every time I end up going through CWallet:Create
function that requires me to keep a mental context of whether this function was called from the creation flow or the load flow. Also, I feel this is a good time to get this done now that legacy wallets are no longer there.
However, I am slightly less inclined to review this PR in its current format because there are a few moving pieces here, and I'm afraid reviewing it thoroughly might be more time consuming and would induce less confidence in me finally a-c-king it.
Moreover, I feel the benefits of such a refactor would be more highlighted and appreciated if this can be broken down into smaller PRs in addition to ensuring data-correctness. Couple reasons I'm suggesting a breakdown are:
- I would like to give more attention to each of the commits by trying to understand their consequences on the wallet as a whole.
- I don't suppose all the commits are required to be present sequentially in a single PR based on my initial look, please feel free to correct me if I'm mistaken about their ability to be present in parallel.
PR breakdown suggestion
The first 3 can be done in parallel & the last one might be dependent on the previous ones:
- The
PopulateWalletFromDB
related changes can be 1 PR - the first 2 commits. - The
fBroadcastTransactions
change is independent, can be clubbed with the birth-time-update-removal optimisation - 3rd, 6th commits. - The argument parsing changes also seem independent to me and can be another PR - 4th, 5th commits.
- No strong opinion on the wallet stats logging commit, can go anywhere.
- The last 5 commits can be 1 PR that introduces and uses the
LoadExisting
&CreateNew
functions.
Also, I believe this is a good suggestion that might give dividends in the future and breaking down into smaller PRs might make it easy to incorporate it.
Having suggested all this, if you think the reward for breaking down the PR is not enough because the smaller refactoring PRs might not attract reviewers or might add rebase churn, I would still review this PR later but some kind of breakdown would aid review if not the one that I suggested.
Sorry if this got too long.
Shouldn't |
0f82224
to
349c9bc
Compare
349c9bc
to
353cfdd
Compare
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
Also fixes wallet stats being incorrectly logged. (bitcoin#32636 (comment))
353cfdd
to
05cbadf
Compare
Also fixes wallet stats being incorrectly logged. (bitcoin#32636 (comment))
5c33e05
to
a374f51
Compare
Thanks for catching this, fixed in acc0d3b
Agreed, I think it might be better to fix this in a follow-up as this PR is already quite large.
Thanks for the suggestion, despite the large number of commits in this PR, I've tried my best to make each one atomic and readable. I would prefer to not split into multiple PR's since most of the commits here are refactors that are setting-up for splitting wallet creation and loading, the first PR(s) in the series would have very little motivation, but if you insist I am open to splitting it up. Is there a particular commit or group of commits that are difficult to review? |
No insistence at the moment, I will do a full review of the PR soon. |
Previously creating an encrypted wallet would result in the keypool size incorrectly being reported as 0. See: bitcoin#32636 (comment)
a374f51
to
7b5fcb7
Compare
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
…FromDB There are too many functions in CWallet with names like "Load" and "Create", disambiguate what CWallet::LoadWallet does by renaming it to PopulateWalletFromDB. -BEGIN VERIFY SCRIPT- sed -i 's|\bLoadWallet()|PopulateWalletFromDB()|g' $(git grep -l 'LoadWallet()' -- ':(exclude)src/wallet/walletdb.cpp') -END VERIFY SCRIPT-
Co-authored-by: @w0xlt <w0xlt@users.noreply.github.com>
Modifying `fBroadcastTransactions` does not require any locks, initialization of this wallet parameter can be relocated with all of the other argument parsing in this function.
This section is necessarily repetitive, makes CWallet::Create() easier to read, and splits out functionality that will be useful when wallet creation and loading are separated.
`m_keypool_size` must be set before `CWallet::PopulateWalletFromDB()`, in order to move parsing of `-keypool` into `CWallet::LoadWalletArgs`, `LoadWalletArgs()` invocation in `CWallet::Create()` must be moved before `PopulateWalletFromDB()` is called.
Checking every SPKM in `CWallet::Create()` is not necessary, since the only way presently for an SPKM to get added to `m_spk_managers` (the return value of `GetAllScriptPubKeyMans()`) is through `AddScriptPubKeyMan()`, which already invokes `MaybeUpdateBirthTime()`.
This will avoid repetition when wallet creation and loading are separated.
Splits out logic relevant only to existing wallets in `CWallet::Create()` into `CWallet::LoadExisting()`
Writing the wallet version needs to be done on wallet creation, but WalletBatch::LoadWallet() does not, so factor this functionality out.
Previously creating an encrypted wallet would result in the keypool size incorrectly being reported as 0. See: bitcoin#32636 (comment)
Aside from being more legible, changing the name of `CWallet::Create()` also validates that every instance where a new wallet is `Create()`'ed is handled in this branch. -BEGIN VERIFY SCRIPT- sed -i 's|\bCreate(|CreateNew(|g' src/wallet/wallet.cpp src/wallet/wallet.h src/wallet/test/util.cpp src/wallet/test/wallet_tests.cpp -END VERIFY SCRIPT-
7b5fcb7
to
a6b43fa
Compare
This PR is mostly a refactor which splits out logic used for creating wallets and for loading wallets, both of which are presently contained in
CWallet::Create()
intoCWallet::CreateNew()
andCWallet::LoadExisting()
The real win of this PR is that
CWallet::Create()
uses a very bad heuristic for trying to guess whether or not it is supposed to be creating a new wallet or loading an existing wallet:bitcoin/src/wallet/wallet.cpp
Lines 2882 to 2885 in 370c592
This heuristic assumes that wallets with no
ScriptPubKeyMans
are being created, which sounds reasonable, but as demonstrated in #32112 and #32111, this can happen when the user tries to load a wallet file that is corrupted, both issues are fixed by this PR and any other misbehavior for wallet files which succeeded the broken heuristic's sniff test for new wallets.It was already the case that every caller of
CWallet::Create()
knows whether it is creating a wallet or loading one, so we can avoid replacing this bad heuristic with another one, and just shift the burden to the caller.