Skip to content

Commit 342c45f

Browse files
committed
wallet: addressbook migration, batch db writes
Optimizing the process performance and consistency.
1 parent 595bbe6 commit 342c45f

File tree

1 file changed

+33
-19
lines changed

1 file changed

+33
-19
lines changed

src/wallet/wallet.cpp

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4007,21 +4007,44 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
40074007
}
40084008
}
40094009

4010+
// Pair external wallets with their corresponding db handler
4011+
std::vector<std::pair<std::shared_ptr<CWallet>, std::unique_ptr<WalletBatch>>> wallets_vec;
4012+
for (const auto& ext_wallet : {data.watchonly_wallet, data.solvable_wallet}) {
4013+
if (!ext_wallet) continue;
4014+
4015+
std::unique_ptr<WalletBatch> batch = std::make_unique<WalletBatch>(ext_wallet->GetDatabase());
4016+
if (!batch->TxnBegin()) {
4017+
error = strprintf(_("Error: database transaction cannot be executed for wallet %s"), ext_wallet->GetName());
4018+
return false;
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) {
4025+
auto address{EncodeDestination(dest)};
4026+
if (entry.purpose) batch.WritePurpose(address, PurposeToString(*entry.purpose));
4027+
if (entry.label) batch.WriteName(address, *entry.label);
4028+
for (const auto& [id, request] : entry.receive_requests) {
4029+
batch.WriteAddressReceiveRequest(dest, id, request);
4030+
}
4031+
if (entry.previously_spent) batch.WriteAddressPreviouslySpent(dest, true);
4032+
};
4033+
40104034
// Check the address book data in the same way we did for transactions
40114035
std::vector<CTxDestination> dests_to_delete;
40124036
for (const auto& [dest, record] : m_address_book) {
40134037
// Ensure "receive" entries that are no longer part of the original wallet are transferred to another wallet
40144038
// Entries for everything else ("send") will be cloned to all wallets.
40154039
bool require_transfer = record.purpose == AddressPurpose::RECEIVE && !IsMine(dest);
40164040
bool copied = false;
4017-
for (auto& wallet : {data.watchonly_wallet, data.solvable_wallet}) {
4018-
if (!wallet) continue;
4019-
4041+
for (auto& [wallet, batch] : wallets_vec) {
40204042
LOCK(wallet->cs_wallet);
40214043
if (require_transfer && !wallet->IsMine(dest)) continue;
40224044

40234045
// Copy the entire address book entry
40244046
wallet->m_address_book[dest] = record;
4047+
func_store_addr(*batch, dest, record);
40254048

40264049
copied = true;
40274050
// 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)
40474070
}
40484071
}
40494072

4050-
// Persist added address book entries (labels, purpose) for watchonly and solvable wallets
4051-
auto persist_address_book = [](const CWallet& wallet) {
4052-
LOCK(wallet.cs_wallet);
4053-
WalletBatch batch{wallet.GetDatabase()};
4054-
for (const auto& [destination, addr_book_data] : wallet.m_address_book) {
4055-
auto address{EncodeDestination(destination)};
4056-
if (addr_book_data.purpose) batch.WritePurpose(address, PurposeToString(*addr_book_data.purpose));
4057-
if (addr_book_data.label) batch.WriteName(address, *addr_book_data.label);
4058-
for (const auto& [id, request] : addr_book_data.receive_requests) {
4059-
batch.WriteAddressReceiveRequest(destination, id, request);
4060-
}
4061-
if (addr_book_data.previously_spent) batch.WriteAddressPreviouslySpent(destination, true);
4073+
// Persist external wallets address book entries
4074+
for (auto& [wallet, batch] : wallets_vec) {
4075+
if (!batch->TxnCommit()) {
4076+
error = strprintf(_("Error: address book copy failed for wallet %s"), wallet->GetName());
4077+
return false;
40624078
}
4063-
};
4064-
if (data.watchonly_wallet) persist_address_book(*data.watchonly_wallet);
4065-
if (data.solvable_wallet) persist_address_book(*data.solvable_wallet);
4079+
}
40664080

4067-
// Remove the things to delete
4081+
// Remove the things to delete in this wallet
40684082
if (dests_to_delete.size() > 0) {
40694083
for (const auto& dest : dests_to_delete) {
40704084
if (!DelAddressBook(dest)) {

0 commit comments

Comments
 (0)