-
Notifications
You must be signed in to change notification settings - Fork 38.7k
refactor: Move many functions into LegacyScriptPubKeyMan and further separate it from CWallet #17304
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
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. 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. |
ryanofsky
left a comment
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.
Code review ACK e1b1702449a9172185d4bfb5e9043748328132ee. Left comments and suggestions which could be followed up later if we want to avoid losing momentum on #17261
src/wallet/rpcwallet.cpp
Outdated
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.
In commit "Refactor: Move GetMetadata code out of getaddressinfo" (bdb538d2fa8b171f1a96580a0f0a7395d52b336e)
It doesn't seem strictly true that this commit doesn't change behavior. Before the code was looking up key_id only in mapKeyMetadata and CScriptID(scriptPubKey) only in m_script_metadata. Now it is looking up both values in both maps, which I guess is fine, but maybe more confusing and less efficient.
I think it'd probably be clearer and more type-safe to have separate GetKeyMetadata and GetScriptMetadata methods.
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.
From the ScriptPubKeyMan design view, it doesn't make sense to have different metadata for keys and scripts, at least exposed publicly to the wallet. It should really be GetMetadata that takes a scriptPubKey, but it fit better to use uint160 for right now.
src/wallet/scriptpubkeyman.cpp
Outdated
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.
In commit "Refactor: Add new ScriptPubKeyMan virtual methods" (80a44800f35c3183edd8fc0914ed8edbd5c5887b)
Note for other reviewers: after future changes in #17261 there are some differences in functionality between the Reserve/Keep/Return destination methods and the Reserve/Keep/Return key methods, and they are called from different places, so there's some justification for keeping them separate, though I think ideally we could follow up by combining them, or at least making clear what the differences in behavior are supposed to be between the two sets of functions.
src/wallet/wallet.cpp
Outdated
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.
In commit "Refactor: Move SetupGeneration code out of CWallet" (f95750d52a21a69ad55db8422f10c563fb9e08ac)
Note for other reviews: Previous code was calling TopUp, while new code is calling SetupGeneration which calls NewKeyPool which calls TopUpKeyPool. I think the effect is basically the same because fFirstRun is true here so the additional ErasePool calls in NewKeyPool should have no effect.
e1b1702 to
5631c01
Compare
ryanofsky
left a comment
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.
Code review ACK 5631c01c845b1fb9a91e0b40709ceaac204fbb5d. Just a bunch of suggested changes made since the last review.
|
Not sure what your preference is @achow101, but it might be a good idea to replace #17261 with #17304 on the high priority review list https://github.com/bitcoin/bitcoin/projects/8, since #17261 builds on #17304. This PR is also just making small and mostly obvious changes, so it should be more approachable for reviewers. |
Yeah, it should replace that. #17261 was added to the list before I made this pr. |
|
mac build errors |
5631c01 to
b04a526
Compare
ryanofsky
left a comment
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.
Code review ACK b04a526aea91ba4caddbde1a1313a1dbf46bc5e5. Only change is adding back missing lock assert.
|
This PR has 18 commits, so it could be useful to get some Approach ACKS here on whether it's a reasonable size, or should be made smaller by dropping some number of commits, or dropping particular commits that seem more difficult to review. All of the commits should be small and straightforward, but it is also easily possible to scale back this PR if necessary. |
instagibbs
left a comment
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.
ACK with non-blocking nits
"Refactor: Move GetMetadata code out of getaddressinfo" more accurately: "Refactor: Remove direct accesses to key metadata code from getaddressinfo"
same type of message nit for "Refactor: Move HavePrivateKeys code out of CWallet::CreateWalletFromFile" and "Refactor: Move SetupGeneration code out of CWallet"
src/wallet/scriptpubkeyman.cpp
Outdated
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.
why the scope here?
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.
A lock is going to be added in the next step
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.
A lock is going to be added in the next step
The scope isn't needed even with the lock and all other changes from #17261:
But I don't think it's a big deal. Could clean this up later if reservekey and reservedestination methods are merged later (#17304 (comment))
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.
I'll just leave this as is so it can get merged sooner :)
src/wallet/wallet.cpp
Outdated
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.
I realize this is stopping mid-way, but this was slightly confusing. Add a comment saying this is temporarily going to always be true until a loop is introduced?
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.
That generally applies throughout this PR. So I guess a note to reviewers in the thread should be good enough?
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.
ok! Consider this your note, future reviewers
|
I'm going through these commits now. I've seen this code a few times before, but if others want to eject one or more commits to get it merged faster, that could make sense. |
src/wallet/wallet.cpp
Outdated
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.
In commit "Refactor: Move SetupGeneration code out of CWallet" (ef97f0b5451e4959c0d0bf649a71eec9b226210e)
No need to change now, but it seems like it'd probably be a good idea to check for an error from SetupGeneration here as well.
|
Code review ACK up to b04a526aea91ba4caddbde1a1313a1dbf46bc5e5. |
promag
left a comment
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.
Light code review ACK b04a526aea91ba4caddbde1a1313a1dbf46bc5e5 with some comments.
src/wallet/scriptpubkeyman.h
Outdated
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.
8bdac65e4c705f9f55c93b43792d036229cc9d5a
Sorry for nit picking here, but is this really necessary? What should be the rule of thumb?
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.
Is what necessary?
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.
The category comment.
src/wallet/wallet.cpp
Outdated
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.
bf5f6c5214706ef61f80c46063061a624c3d505b
This should be in the above if?
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.
Does it really matter?
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.
No, just that it looks like a leftover where before result could be changed in between.
Actually I think this would look better without the result variable.
You can resolve this.
src/wallet/wallet.cpp
Outdated
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.
2590266c193d27c979ad6287d72555ca3df630bc
What if IsLocked()?
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.
re: #17304 (comment)
What if
IsLocked()?
Nice catch! This seems like a bug. I think either the m_storage.IsLocked() || m_storage.IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA) check should move from LegacyScriptPubKeyMan::UpgradeKeyMetadata to
CWallet::UpgradeKeyMetadata, or preferably, theSetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA) call should move back in the other direction.
It's also unclear why UpgradeKeyMetadata shoud be a virtual method instead of being specific to the LegacyScriptPubKeyMan class. It doesn't seem like non-legacy keyman types should implement this upgrade function or be accessing this wallet flag.
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.
It seems like the CWallet::UpgradeKeyMetadata() and ScriptPubKeyMan::::UpgradeKeyMetadata() methods could both be dropped and walletdb.cpp could call pwallet->GetLegacyScriptPubKeyMan() and LegacyScriptPubKeyMan::UpgradeKeyMetadata directly for compatibility.
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.
Changed to be non-virtual and moved that check out to CWallet.
src/wallet/wallet.cpp
Outdated
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.
26fef3a525fd98f8205fd2f859f476fbf2cc6fcd
Just noting that there's actually a behavior change here - now if LegacyScriptPubKeyMan::ImportScriptPubKeys fails no label is applied.
Also, another change, which I think is harmless, is that now 2 batches are always used - easily "reverted" by passing the batch to LegacyScriptPubKeyMan::ImportScriptPubKeys from this method.
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.
Those are harmless. ImportScriptPubKeys only fails when writing to the database fails, so you'll have bigger problems if that happens.
b04a526 to
707a817
Compare
Can verify move-only with:
git log -p -n1 --color-moved
This commit is move-only and doesn't change code or affect behavior.
This commit does not change behavior.
This commit does not change behavior.
…ewDestination This commit does not change behavior.
…Metadata This commit does not change behavior.
SetWalletFlag is unused. Does not change any behavior
…HDSeed This commit does not change behavior.
…ScriptPubKeyMan ScriptPubKeyMan is only using UnsetWalletFlagWithDB to unset the blank wallet flag. Just make that it's own function and not expose the flag writing directly. This does not change behavior.
…::ImportScriptPubKeys This commit does not change behavior.
This commit does not change behavior.
Pass CTxDestination instead of more ambiguous uint160 hash value. This is more type safe and more efficient since it avoids doing map lookups that will always fail and were not done previously before a18edd7 from bitcoin#17304 Change suggested by Andrew Chow <[email protected]> in bitcoin#17304 (comment) and bitcoin#17381 (comment)
Suggested bitcoin#17304 (comment) by Gregory Sanders <[email protected]> Reason for keeping the `return true` `return false` verbosity is that more code will be added after the ReserveKeyFromKeyPool() call before returning.
Summary:
Can verify move-only with:
git log -p -n1 --color-moved
This commit is move-only and doesn't change code or affect behavior.
bitcoin/bitcoin@b4cb18b
---
Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]]
Test Plan:
ninja check
Reviewers: #bitcoin_abc, jasonbcox
Reviewed By: #bitcoin_abc, jasonbcox
Subscribers: jasonbcox
Differential Revision: https://reviews.bitcoinabc.org/D7147
… as virtual Summary: This commit does not change behavior. bitcoin/bitcoin@533d8b3 --- Depends on D7147 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Subscribers: jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7148
Summary: This commit does not change behavior. bitcoin/bitcoin@acedc5b --- Depends on D7148 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Subscribers: jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7149
…yScriptPubKeyMan::GetNewDestination Summary: This commit does not change behavior. bitcoin/bitcoin@769acef --- Depends on D7149 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7151
…tPubKeyMan::UpgradeKeyMetadata Summary: This commit does not change behavior. bitcoin/bitcoin@4c5491f --- Depends on D7151 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7152
Summary: SetWalletFlag is unused. Does not change any behavior bitcoin/bitcoin@0391aba --- Depends on D7152 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7153
…cyScriptPubKeyMan::SetHDSeed Summary: This commit does not change behavior. bitcoin/bitcoin@78e7cbc --- Depends on D7153 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7154
…setBlankWalletFlag in ScriptPubKeyMan Summary: ScriptPubKeyMan is only using UnsetWalletFlagWithDB to unset the blank wallet flag. Just make that it's own function and not expose the flag writing directly. This does not change behavior. bitcoin/bitcoin@fc2867f --- Depends on D7154 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7155
… LegacyScriptPubKeyMan::ImportScriptPubKeys Summary: This commit does not change behavior. bitcoin/bitcoin@67be6b9 --- Depends on D7155 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7156
…ethod definition Summary: This commit does not change behavior. bitcoin/bitcoin@9716bbe --- Depends on D7156 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7157
…essinfo
Summary:
Easier to review ignoring whitespace:
git log -p -n1 -w
This commit does not change behavior.
bitcoin/bitcoin@a18edd7
---
Depends on D7157
Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]]
Test Plan:
ninja check
Reviewers: #bitcoin_abc, jasonbcox
Reviewed By: #bitcoin_abc, jasonbcox
Differential Revision: https://reviews.bitcoinabc.org/D7158
… CWallet::AddToWalletIfInvolvingMe Summary: This commit does not change behavior. bitcoin/bitcoin@46865ec --- Depends on D7158 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7159
…eateWalletFromFile Summary: This commit does not change behavior. bitcoin/bitcoin@8b0d82b --- Depends on D7159 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7160
…llet::CreateWalletFromFile Summary: This commit does not change behavior. bitcoin/bitcoin@f45d12b --- Depends on D7160 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7161
…llet Summary: This commit does not change behavior. bitcoin/bitcoin@0eac708 --- Depends on D7161 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Subscribers: jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7162
Summary: This commit does not change behavior. bitcoin/bitcoin@089e17d --- Depends on D7162 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7163
Summary: This commit does not change behavior. bitcoin/bitcoin@7ef47b8 --- Depends on D7163 Partial backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7164
…Wallet Summary: This commit does not change behavior. bitcoin/bitcoin@152b0a0 --- Depends on D7164 Concludes backport of Core [[bitcoin/bitcoin#17304 | PR17304]] Test Plan: ninja check check-functional Reviewers: #bitcoin_abc, jasonbcox Reviewed By: #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D7165
Summary: Pass CTxDestination instead of more ambiguous uint160 hash value. This is more type safe and more efficient since it avoids doing map lookups that will always fail and were not done previously before bitcoin/bitcoin@a18edd7 Change suggested by Andrew Chow <[email protected]> in bitcoin/bitcoin#17304 (comment) and bitcoin/bitcoin#17381 (comment) --- bitcoin/bitcoin@4a0abf6 Depends on D7416 Partial backport of Core [[bitcoin/bitcoin#17381 | PR17381]] Test Plan: ninja check check-functional Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D7417
…pKeyPool method Summary: Previous discussion bitcoin/bitcoin#17304 (comment) --- bitcoin/bitcoin@491a599 Depends on D7417 Partial backport of Core [[bitcoin/bitcoin#17381 | PR17381]] Test Plan: ninja check check-functional Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D7418
Summary: Suggested bitcoin/bitcoin#17304 (comment) by Gregory Sanders <[email protected]> Reason for keeping the `return true` `return false` verbosity is that more code will be added after the ReserveKeyFromKeyPool() call before returning. --- bitcoin/bitcoin@bfd826a Depends on D7418 Partial backport of Core [[bitcoin/bitcoin#17381 | PR17381]] Test Plan: ninja check check-functional Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D7419
…cryptWallet Summary: Suggested bitcoin/bitcoin#17304 (comment) by me --- bitcoin/bitcoin@05b224a Depends on D7419 Concludes backport of Core [[bitcoin/bitcoin#17381 | PR17381]] Test Plan: ninja check check-functional Reviewers: #bitcoin_abc, deadalnix Reviewed By: #bitcoin_abc, deadalnix Differential Revision: https://reviews.bitcoinabc.org/D7420
05b224a Add missing SetupGeneration error handling in EncryptWallet (Russell Yanofsky) bfd826a Clean up nested scope in GetReservedDestination (Russell Yanofsky) 491a599 Get rid of confusing LegacyScriptPubKeyMan::TopUpKeyPool method (Russell Yanofsky) 4a0abf6 Pass CTxDestination to ScriptPubKeyMan::GetMetadata (Russell Yanofsky) b07b07c Add EnsureLegacyScriptPubKeyMan and use in rpcwallet.cpp (Russell Yanofsky) Pull request description: This PR implements suggested code cleanups from bitcoin#17300 and bitcoin#17304 review comments ACKs for top commit: Sjors: re-ACK 05b224a laanwj: Code review ACK 05b224a Tree-SHA512: 12fd86637088515b744c028e0501c5d21a9cf9ee9c9cfd70e9cb65d44611ea5643abd5f6f101105caa5aff015d74de606f074f08af7dae8429f929d21288ab45
Moves several more key management and metadata functions into LegacyScriptPubKeyMan from CWallet to further separate the two.
Note to reviewers: All of the
if (auto spk_man = walletInstance->m_spk_man.get()) {blocks will be replaced with for loops in the next PR so you may see some things in those blocks that don't necessarily make sense with anifbut will with afor.