aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet.cpp
diff options
context:
space:
mode:
authorfurszy <matiasfurszyfer@protonmail.com>2024-01-21 13:01:56 -0300
committerfurszy <matiasfurszyfer@protonmail.com>2024-02-07 18:15:38 -0300
commit342c45f80e32b0320829ce380b5854844cd74bc8 (patch)
tree58b79e64f897eebbb9392d106af72d71e2e815bb /src/wallet/wallet.cpp
parent595bbe6e81885d35179aba6137dc63d0e652cc1f (diff)
downloadbitcoin-342c45f80e32b0320829ce380b5854844cd74bc8.tar.xz
wallet: addressbook migration, batch db writes
Optimizing the process performance and consistency.
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r--src/wallet/wallet.cpp52
1 files changed, 33 insertions, 19 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index cebb7b3912..aae876a819 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -4007,6 +4007,30 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
}
}
+ // Pair external wallets with their corresponding db handler
+ std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
+ for (const auto& ext_wallet : {data.watchonly_wallet, data.solvable_wallet}) {
+ if (!ext_wallet) continue;
+
+ std::unique_ptr<WalletBatch> batch = std::make_unique<WalletBatch>(ext_wallet->GetDatabase());
+ if (!batch->TxnBegin()) {
+ error = strprintf(_("Error: database transaction cannot be executed for wallet %s"), ext_wallet->GetName());
+ return false;
+ }
+ wallets_vec.emplace_back(ext_wallet, std::move(batch));
+ }
+
+ // Write address book entry to disk
+ auto func_store_addr = [](WalletBatch& batch, const CTxDestination& dest, const CAddressBookData& entry) {
+ auto address{EncodeDestination(dest)};
+ if (entry.purpose) batch.WritePurpose(address, PurposeToString(*entry.purpose));
+ if (entry.label) batch.WriteName(address, *entry.label);
+ for (const auto& [id, request] : entry.receive_requests) {
+ batch.WriteAddressReceiveRequest(dest, id, request);
+ }
+ if (entry.previously_spent) batch.WriteAddressPreviouslySpent(dest, true);
+ };
+
// Check the address book data in the same way we did for transactions
std::vector<CTxDestination> dests_to_delete;
for (const auto& [dest, record] : m_address_book) {
@@ -4014,14 +4038,13 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
// Entries for everything else ("send") will be cloned to all wallets.
bool require_transfer = record.purpose == AddressPurpose::RECEIVE && !IsMine(dest);
bool copied = false;
- for (auto& wallet : {data.watchonly_wallet, data.solvable_wallet}) {
- if (!wallet) continue;
-
+ for (auto& [wallet, batch] : wallets_vec) {
LOCK(wallet->cs_wallet);
if (require_transfer && !wallet->IsMine(dest)) continue;
// Copy the entire address book entry
wallet->m_address_book[dest] = record;
+ func_store_addr(*batch, dest, record);
copied = true;
// Only delete 'receive' records that are no longer part of the original wallet
@@ -4047,24 +4070,15 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
}
}
- // Persist added address book entries (labels, purpose) for watchonly and solvable wallets
- auto persist_address_book = [](const CWallet& wallet) {
- LOCK(wallet.cs_wallet);
- WalletBatch batch{wallet.GetDatabase()};
- for (const auto& [destination, addr_book_data] : wallet.m_address_book) {
- auto address{EncodeDestination(destination)};
- if (addr_book_data.purpose) batch.WritePurpose(address, PurposeToString(*addr_book_data.purpose));
- if (addr_book_data.label) batch.WriteName(address, *addr_book_data.label);
- for (const auto& [id, request] : addr_book_data.receive_requests) {
- batch.WriteAddressReceiveRequest(destination, id, request);
- }
- if (addr_book_data.previously_spent) batch.WriteAddressPreviouslySpent(destination, true);
+ // Persist external wallets address book entries
+ for (auto& [wallet, batch] : wallets_vec) {
+ if (!batch->TxnCommit()) {
+ error = strprintf(_("Error: address book copy failed for wallet %s"), wallet->GetName());
+ return false;
}
- };
- if (data.watchonly_wallet) persist_address_book(*data.watchonly_wallet);
- if (data.solvable_wallet) persist_address_book(*data.solvable_wallet);
+ }
- // Remove the things to delete
+ // Remove the things to delete in this wallet
if (dests_to_delete.size() > 0) {
for (const auto& dest : dests_to_delete) {
if (!DelAddressBook(dest)) {