Skip to content

wallet: batch and simplify addressbook migration process#26836

Merged
achow101 merged 6 commits intobitcoin:masterfrom
furszy:2022_wallet_finish_addressbook_encapsulation
Feb 8, 2024
Merged

wallet: batch and simplify addressbook migration process#26836
achow101 merged 6 commits intobitcoin:masterfrom
furszy:2022_wallet_finish_addressbook_encapsulation

Conversation

@furszy
Copy link
Member

@furszy furszy commented Jan 6, 2023

Commits decoupled from #28574, focused on the address book cloning process

Includes:

  1. DB batch operations and flow simplification for the address book migration process.
  2. 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
Copy link
Contributor

DrahtBot commented Jan 6, 2023

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK achow101, josibake
Concept ACK rserranon, hernanmarino
Approach ACK w0xlt
Stale ACK pablomartin4btc

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.

Copy link
Contributor

@w0xlt w0xlt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach ACK.
I will review soon.

Copy link

@rserranon rserranon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK,

I understand this may become a separate commit, but why not encapsulate the other calls to wallet->m_address_book[addr_pair.first].purpose = purpose ?

src/wallet/wallet.cpp:3980:                            data.watchonly_wallet->m_address_book[addr_pair.first].purpose = purpose;
src/wallet/wallet.cpp:3996:                            data.solvable_wallet->m_address_book[addr_pair.first].purpose = purpose;
src/wallet/wallet.cpp:4017:                    data.watchonly_wallet->m_address_book[addr_pair.first].purpose = purpose;
src/wallet/wallet.cpp:4030:                    data.solvable_wallet->m_address_book[addr_pair.first].purpose = purpose;

If m_address_book has been encapsulated, why not make it private or protected?

@furszy
Copy link
Member Author

furszy commented Feb 27, 2023

Thanks @rserranon.

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 furszy force-pushed the 2022_wallet_finish_addressbook_encapsulation branch 2 times, most recently from cb82845 to 0053949 Compare February 27, 2023 14:06
@furszy
Copy link
Member Author

furszy commented Feb 27, 2023

Updated per feedback. Now we no longer access the wallet's addressbook member externally.

Plus, improvements to the address book migration process:

  1. Fixed a bug where we don't copy the "send" records to all the wallets.
  2. Have re-written the process with no code duplication.
  3. Batched db writes so the disk dump is done all at once.

Copy link

@rserranon rserranon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tAck

  • unit tests
  • functional tests
  • qt & bitcoin-cli manual tests

Copy link
Contributor

@hernanmarino hernanmarino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested ACK, both unit and functional tests.

Copy link
Member

@pablomartin4btc pablomartin4btc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach ACK.
I'll perform some testing soon.

Copy link
Member

@pablomartin4btc pablomartin4btc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested ACK.
On the code review, went thru the different commits of the PR.
Performed manual testing using bitcoin-qt.

@furszy furszy force-pushed the 2022_wallet_finish_addressbook_encapsulation branch from 0053949 to 819c0bc Compare April 12, 2023 14:00
@DrahtBot DrahtBot requested review from hernanmarino, rserranon and w0xlt and removed request for rserranon February 5, 2024 14:30
@furszy furszy force-pushed the 2022_wallet_finish_addressbook_encapsulation branch from 3aff6d5 to 238993e Compare February 5, 2024 14:33
@josibake
Copy link
Member

josibake commented Feb 5, 2024

reACK 238993e

verified the diff, thanks for taking the suggestions!

Copy link
Member Author

@furszy furszy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated per @maflcko review in #29403 (comment). Small diff.

@DrahtBot
Copy link
Contributor

DrahtBot commented Feb 7, 2024

🚧 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.

Debug: https://github.com/bitcoin/bitcoin/runs/21320950165

@furszy
Copy link
Member Author

furszy commented Feb 7, 2024

Green CI. Ready to go.

Copy link
Member

@achow101 achow101 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 1f177ff9a6ab229bd6486941e46daa92ab22b622

@josibake
Copy link
Member

josibake commented Feb 7, 2024

reACK 1f177ff

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
Same process written in a cleaner manner.
Removing code duplication.
Optimizing the process performance and consistency.
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.
Copy link
Member Author

@furszy furszy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated per feedback. Thanks achow!. Small diff.

Two changes:

  1. Removed __func__ usages in the logging messages (comment_1 and comment_2).
  2. Have divided the purpose and name erasing lines per request.

@achow101
Copy link
Member

achow101 commented Feb 7, 2024

ACK 86960cd

@josibake
Copy link
Member

josibake commented Feb 8, 2024

reACK 86960cd

Verified the diff, looks good.

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Post-merge code review ACK 86960cd. Nice code cleanups, and use of batches to speed things up

fUpdated = mi != m_address_book.end() && !mi->second.IsChange();

CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];
record.SetLabel(strName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "refactor: SetAddressBookWithDB, minimize number of map lookups" (d094331)

This isn't actually minimizing the number of lookups since it is doing two lookups in the insert case. Would replace:

std::map<CTxDestination, CAddressBookData>::iterator mi = m_address_book.find(address);
fUpdated = mi != m_address_book.end() && !mi->second.IsChange();
CAddressBookData& record = mi != m_address_book.end() ? mi->second : m_address_book[address];

with:

auto [it, inserted] = m_address_book.emplace(std::piecewise_construct, std::forward_as_tuple(address), std::tuple{});
fUpdated = !inserted && !it->second.IsChange();
CAddressBookData& record = it->second;

for (const auto& [dest, record] : m_address_book) {
// Ensure "receive" entries that are no longer part of the original wallet are transferred to another wallet
// Entries for everything else ("send") will be cloned to all wallets.
bool require_transfer = record.purpose == AddressPurpose::RECEIVE && !IsMine(dest);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "refactor: wallet, simplify addressbook migration" (595bbe6)

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.

}

// Write address book entry to disk
auto func_store_addr = [](WalletBatch& batch, const CTxDestination& dest, const CAddressBookData& entry) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In commit "wallet: addressbook migration, batch db writes" (342c45f)

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants