furszy
commented at 1:05 pm on January 6, 2023:
member
Commits decoupled from #28574, focused on the address book cloning process
Includes:
DB batch operations and flow simplification for the address book migration process.
Code improvements to CWallet::DelAddressBook and Wallet::SetAddrBookWithDB methods.
These changes will let us consolidate all individual write operations that take place during the wallet migration process into a single db txn in the future.
DrahtBot
commented at 1:05 pm on January 6, 2023:
contributor
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
Conflicts
Reviewers, this pull request conflicts with the following ones:
#29403 (wallet: batch erase procedures and improve ‘EraseRecords’ performance by furszy)
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 Jan 6, 2023
w0xlt
commented at 12:38 pm on January 9, 2023:
contributor
Approach ACK.
I will review soon.
in
src/wallet/wallet.h:484
in
093203ecc2outdated
479@@ -480,6 +480,12 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
480481 //! Adds a destination data tuple to the store, without saving it to disk
482 void LoadDestData(const CTxDestination& dest, const std::string& key, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
483+ //! Adds destination label to the store, without saving it to disk
484+ void LoadAddrbookEntryLabel(const CTxDestination& dest, const std::string& label) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
rserranon
commented at 8:12 pm on February 24, 2023:
Nit: Shouldn’t be better to use the capital B in LoadAddrBookEntryLablel and LoadAddrBookEntryPurpose as in GetAddrBookSize and ListAddrBookAddreses ?
why not encapsulate the other calls to wallet->m_address_book[addr_pair.first].purpose = purpose ?
Good catch. I did this changes prior the wallet migration PR merge. Will add those too and make the addressbook member private so we don’t keep adding more in the future.
furszy force-pushed
on Feb 27, 2023
furszy force-pushed
on Feb 27, 2023
furszy
commented at 2:13 pm on February 27, 2023:
member
Updated per feedback. Now we no longer access the wallet’s addressbook member externally.
Plus, improvements to the address book migration process:
Fixed a bug where we don’t copy the “send” records to all the wallets.
Have re-written the process with no code duplication.
Batched db writes so the disk dump is done all at once.
furszy requested review from rserranon
on Mar 6, 2023
rserranon approved
rserranon
commented at 1:13 am on March 7, 2023:
none
tAck
unit tests
functional tests
qt & bitcoin-cli manual tests
furszy requested review from w0xlt
on Mar 12, 2023
hernanmarino approved
hernanmarino
commented at 11:31 pm on March 26, 2023:
contributor
tested ACK, both unit and functional tests.
in
src/wallet/wallet.cpp:4045
in
0053949919outdated
4058- data.solvable_wallet->m_address_book[addr_pair.first].SetLabel(label);
4059+ for (const auto& [dest, record] : m_address_book) {
4060+ // Append "receive" data to other wallets only if not mine.
4061+ // Labels for everything else ("send") should be cloned to all.
4062+ bool require_is_mine = record.purpose == "receive" && !IsMine(dest);
4063+ bool copied = false;
I prefer the current code, it’s more readable.
The curly braces initializer is primarily useful to prevent narrowing (which is the implicit conversion of arithmetic values). Here, there is no loss of accuracy, we are simply initializing a boolean from a logical statement.
in
src/wallet/wallet.cpp:2462
in
0053949919outdated
furszy renamed this:
wallet: finish addressbook encapsulation
wallet: finish addressbook encapsulation and ApplyMigrationData code simplification
on May 1, 2023
furszy renamed this:
wallet: finish addressbook encapsulation and ApplyMigrationData code simplification
wallet: finish addressbook encapsulation and simplify addressbook migration
on May 4, 2023
DrahtBot added the label
Needs rebase
on May 27, 2023
furszy force-pushed
on May 31, 2023
furszy
commented at 3:37 pm on May 31, 2023:
member
rebased
DrahtBot removed the label
Needs rebase
on May 31, 2023
DrahtBot added the label
Needs rebase
on Jun 20, 2023
furszy force-pushed
on Jun 21, 2023
furszy renamed this:
wallet: finish addressbook encapsulation and simplify addressbook migration
wallet: simplify addressbook migration and encapsulate access
on Jun 21, 2023
DrahtBot removed the label
Needs rebase
on Jun 21, 2023
furszy
commented at 3:19 pm on June 21, 2023:
member
rebased, conflicts solved.
DrahtBot added the label
Needs rebase
on Jun 28, 2023
furszy renamed this:
wallet: simplify addressbook migration and encapsulate access
wallet: simplify and add coverage for addressbook migration
on Jun 28, 2023
furszy force-pushed
on Jun 28, 2023
DrahtBot removed the label
Needs rebase
on Jun 28, 2023
furszy force-pushed
on Jul 5, 2023
furszy renamed this:
wallet: simplify and add coverage for addressbook migration
wallet: fix bug, simplify and add coverage for addressbook migration
on Jul 5, 2023
DrahtBot added the label
CI failed
on Jul 5, 2023
achow101
commented at 3:42 pm on July 6, 2023:
member
This PR ends up doing a lot of different things that are only tangentially related. I think it could be split up into a few smaller PRs, e.g. one for the migration fix, one for the migration refactoring, and one for the other refactors.
furszy
commented at 3:52 pm on July 6, 2023:
member
This PR ends up doing a lot of different things that are only tangentially related. I think it could be split up into a few smaller PRs, e.g. one for the migration fix, one for the migration refactoring, and one for the other refactors.
sure, will work on it.
DrahtBot removed the label
CI failed
on Jul 6, 2023
DrahtBot added the label
Needs rebase
on Jul 7, 2023
furszy force-pushed
on Jul 12, 2023
furszy renamed this:
wallet: fix bug, simplify and add coverage for addressbook migration
wallet: simplify addressbook migration process
on Jul 12, 2023
DrahtBot removed the label
Needs rebase
on Jul 12, 2023
furszy force-pushed
on Jul 18, 2023
DrahtBot added the label
Needs rebase
on Sep 19, 2023
achow101 marked this as a draft
on Sep 20, 2023
furszy force-pushed
on Jan 21, 2024
furszy
commented at 4:12 pm on January 21, 2024:
member
In response to feedback, the PR scope has been shortened, omitting the address book encapsulation commits. The current version includes only the subset of commits related to the address book from #28574. Decoupling this PR into two is also possible upon request.
furszy marked this as ready for review
on Jan 21, 2024
DrahtBot removed the label
Needs rebase
on Jan 21, 2024
furszy renamed this:
wallet: simplify addressbook migration process
wallet: batch and simplify addressbook migration process
on Jan 24, 2024
in
src/wallet/wallet.cpp:2395
in
da3b8f927coutdated
Because I made this commit before e83babe (#27217), which removed the IsMine calls, and I forgot to update the commit description after the rebase. Will clean it, thanks.
in
src/wallet/wallet.cpp:2376
in
0b83c8691boutdated
As we will never merge a PR solely removing the extra parentheses, we can either clean them now while working on this function or we keep them for another decade. I prefer to clean them now, but np in reverting the line if it conflicts with the review process.
in
src/wallet/wallet.cpp:4058
in
8b331613bfoutdated
4038+
4039+ copied = true;
4040+ // Only delete 'receive' records that are no longer part of the original wallet
4041+ if (require_transfer) {
4042+ dests_to_delete.push_back(dest);
4043+ break;
josibake
commented at 8:45 pm on February 2, 2024:
This is a pretty thorny block of code with all of the booleans, let me summarize just to make sure I’m following:
If the destination requires_transfer but isn’t ours, go to the next wallet. If this happens for both wallets, copy will never be set and we will fail
If it requires transfer and does belong to the current wallet in the loop, continue and set copy = true, and add the destination to dests_to_delete. Do not check the next wallet. I’m assuming the assumption here is it can only belong to one of the wallets, and if it does end up happening to belong to both wallets this is not an issue?
If it does not require transfer, we always copy it, and copy is always set to true, so we are fine for the next block
Might be worth adding a comment explaining why its okay to break early? That’s the part that kinda threw me.
If the destination requires_transfer but isn’t ours, go to the next wallet. If this happens for both wallets, copy will never be set and we will fail
If the destination requires transfer (a “receive” addr that is no longer part of the main wallet), the process checks to which wallet the entry belongs to. And, when the entry does not belong to any of the created wallets, it means that the key/script-to-descriptor migration process failed. This is because “receive” entries must always be tracked by the wallet.
If it requires transfer and does belong to the current wallet in the loop, continue and set copy = true, and add the destination to dests_to_delete. Do not check the next wallet. I’m assuming the assumption here is it can only belong to one of the wallets, and if it does end up happening to belong to both wallets this is not an issue?
Yes, thats the existing assumption. If you check the previous code, will see that I did not change this part of the flow on purpose. This is what we had before:
0if (purpose =="RECEIVE"&& not_mine_anymore) {
1 2// check if it is part of the watch-only wallet
3if (watch_only_wallet.IsMine(dest)) {
4 store_address(watch_only_wallet, dest);
5 add_to_pending_to_delete(dest);
6continue; // --> this skips the next wallet.
7 }
8 9// check if it is part of the solvables wallet
10if (solvables_wallet.IsMine(dest)) {
11 store_address(solvables_wallet, dest);
12 add_to_pending_to_delete(dest);
13continue; // --> skips any following-up check
14 }
1516// We only reach here if the entry wasn't added to any wallet
17 error out...
18}
The only diff between the new code and the previous one is that we had a continue instead of a break statement.
Might be worth adding a comment explaining why it’s okay to break early? That’s the part that kinda threw me.
We should double-check if we could ever have the same no-longer ours “receive” entry in both wallets (the watch-only and the solvables ones). If we find a way to achieve this, then the bug predates this PR.
in
src/wallet/wallet.cpp:2401
in
3aff6d5b4foutdated
in
src/wallet/wallet.cpp:4068
in
8b331613bfoutdated
4068- if (data.solvable_wallet) {
4069- LOCK(data.solvable_wallet->cs_wallet);
4070- // Add to the solvable. Copy the entire address book entry
4071- data.solvable_wallet->m_address_book[addr_pair.first] = addr_pair.second;
4072+ // Skip invalid/non-watched scripts that will not be migrated
4073+ if (not_migrated_dests.count(dest) > 0) {
josibake
commented at 9:00 pm on February 2, 2024:
nit: C++20 has .contains(arg) for sets (yay!). No performance difference, but semantically I think it makes a lot more sense to use when testing for existence.
josibake approved
josibake
commented at 9:04 pm on February 2, 2024:
member
DrahtBot
commented at 2:17 pm on February 7, 2024:
contributor
🚧 At least one of the CI tasks failed. Make sure to run all tests locally, according to the
documentation.
Possibly this is 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.
Leave a comment here, if you need help tracking down a confusing failure.
DrahtBot removed review request from josibake
on Feb 7, 2024
DrahtBot removed review request from rserranon
on Feb 7, 2024
DrahtBot removed review request from hernanmarino
on Feb 7, 2024
DrahtBot removed review request from w0xlt
on Feb 7, 2024
DrahtBot requested review from w0xlt
on Feb 7, 2024
DrahtBot requested review from hernanmarino
on Feb 7, 2024
DrahtBot requested review from rserranon
on Feb 7, 2024
wallet: clean redundancies in DelAddressBook
1) Encode destination only once (instead of three).
2) Fail if the entry's linked data cannot be removed.
3) Don't remove entry from memory if db write fail.
4) Notify GUI only if removal succeeded
97b0753923
refactor: SetAddrBookWithDB, signal only if write succeededbba4f8dcb5
refactor: SetAddressBookWithDB, minimize number of map lookupsd0943315b1
refactor: wallet, simplify addressbook migration
Same process written in a cleaner manner.
Removing code duplication.
595bbe6e81
wallet: addressbook migration, batch db writes
Optimizing the process performance and consistency.
342c45f80e
wallet: migration, batch addressbook records removal
Instead of doing one db transaction per removed record,
we now batch all removals in a single db transaction.
Speeding up the process and preventing the wallet from entering
an inconsistent state when any of the intermediate writes fail.
86960cdb7f
furszy force-pushed
on Feb 7, 2024
furszy
commented at 9:23 pm on February 7, 2024:
member
in
src/wallet/wallet.cpp:4015
in
595bbe6e81outdated
4033- }
4034- }
4035+ for (const auto& [dest, record] : m_address_book) {
4036+ // Ensure "receive" entries that are no longer part of the original wallet are transferred to another wallet
4037+ // Entries for everything else ("send") will be cloned to all wallets.
4038+ bool require_transfer = record.purpose == AddressPurpose::RECEIVE && !IsMine(dest);
ryanofsky
commented at 3:04 pm on February 8, 2024:
In commit “refactor: wallet, simplify addressbook migration” (595bbe6e81885d35179aba6137dc63d0e652cc1f)
IMO, this would be less confusing if require_transfer bool was replaced by an copy_to_all bool with the opposite meaning, because the thing require_transfer is used for in the loop below is to determining whether the address book entry is copied to all wallets or is moved from the *this wallet to one of the other two.
The name require_transfer is also misleading because the transfer is not required if dest is in not_migrated_dests.
in
src/wallet/wallet.cpp:4024
in
342c45f80eoutdated
4019+ }
4020+ wallets_vec.emplace_back(ext_wallet, std::move(batch));
4021+ }
4022+
4023+ // Write address book entry to disk
4024+ auto func_store_addr = [](WalletBatch& batch, const CTxDestination& dest, const CAddressBookData& entry) {
ryanofsky
commented at 3:23 pm on February 8, 2024:
In commit “wallet: addressbook migration, batch db writes” (342c45f80e32b0320829ce380b5854844cd74bc8)
write_address_book would be a more descriptive name than func_store_addr and watchonly_wallets would be more descriptive than wallet_vec. The _vec suffix and and func_ prefix do not do anything to help a reader of the code, IMO.
ryanofsky
commented at 3:30 pm on February 8, 2024:
contributor
Post-merge code review ACK86960cdb7f75eaa2ae150914c54240d1d5ef96d1. Nice code cleanups, and use of batches to speed things up
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: 2024-12-18 15:12 UTC
This site is hosted by @0xB10C More mirrored repositories can be found on mirror.b10c.me