Skip to content

Commit 7f28e80

Browse files
committed
Merge bitcoin/bitcoin#32758: wallet: remove dead code in legacy wallet migration
150b5c9 wallet: replace `reload_wallet` with inline functionality (rkrux) 0f86da3 wallet: remove dead code in legacy wallet migration (rkrux) Pull request description: A discussion on a previous [PR 32481](bitcoin/bitcoin#32481 (comment)) related to legacy wallet dead code removal made me realize that checking if the legacy wallet was loaded prior to the start of the migration is not required ever since legacy wallets can't be loaded in the first place. I also verified that the `load_on_start` persistent setting can also not cause the legacy wallets to be loaded, which further makes the case for removal of the above mentioned checks during migration. The current test coverage also shows these lines uncovered. ACKs for top commit: achow101: ACK 150b5c9 furszy: ACK 150b5c9 Tree-SHA512: 9bc7043cac1f4051228557208895e43648de3c7ffae6860c0676d1aa2db3a8ed3a09d1f9defacd96ca50bbb9699ba86652ccb0c5e55cc88be248a1fe727c13d9
2 parents 5ef0d48 + 150b5c9 commit 7f28e80

File tree

3 files changed

+21
-49
lines changed

3 files changed

+21
-49
lines changed

src/bench/wallet_migration.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ static void WalletMigration(benchmark::Bench& bench)
6666

6767
bench.epochs(/*numEpochs=*/1).epochIterations(/*numIters=*/1) // run the migration exactly once
6868
.run([&] {
69-
auto res{MigrateLegacyToDescriptor(std::move(wallet), /*passphrase=*/"", *loader->context(), /*was_loaded=*/false)};
69+
auto res{MigrateLegacyToDescriptor(std::move(wallet), /*passphrase=*/"", *loader->context())};
7070
assert(res);
7171
assert(res->wallet);
7272
assert(res->watchonly_wallet);

src/wallet/wallet.cpp

Lines changed: 19 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4172,18 +4172,10 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
41724172
std::vector<bilingual_str> warnings;
41734173
bilingual_str error;
41744174

4175-
// If the wallet is still loaded, unload it so that nothing else tries to use it while we're changing it
4176-
bool was_loaded = false;
4175+
// The only kind of wallets that could be loaded are descriptor ones, which don't need to be migrated.
41774176
if (auto wallet = GetWallet(context, wallet_name)) {
4178-
if (wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4179-
return util::Error{_("Error: This wallet is already a descriptor wallet")};
4180-
}
4181-
4182-
if (!RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt, warnings)) {
4183-
return util::Error{_("Unable to unload the wallet before migrating")};
4184-
}
4185-
WaitForDeleteWallet(std::move(wallet));
4186-
was_loaded = true;
4177+
assert(wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
4178+
return util::Error{_("Error: This wallet is already a descriptor wallet")};
41874179
} else {
41884180
// Check if the wallet is BDB
41894181
const auto& wallet_path = GetWalletPath(wallet_name);
@@ -4217,10 +4209,10 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
42174209
return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
42184210
}
42194211

4220-
return MigrateLegacyToDescriptor(std::move(local_wallet), passphrase, context, was_loaded);
4212+
return MigrateLegacyToDescriptor(std::move(local_wallet), passphrase, context);
42214213
}
42224214

4223-
util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context, bool was_loaded)
4215+
util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context)
42244216
{
42254217
MigrationResult res;
42264218
bilingual_str error;
@@ -4232,20 +4224,8 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
42324224

42334225
const std::string wallet_name = local_wallet->GetName();
42344226

4235-
// Helper to reload as normal for some of our exit scenarios
4236-
const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4237-
assert(to_reload.use_count() == 1);
4238-
std::string name = to_reload->GetName();
4239-
to_reload.reset();
4240-
to_reload = LoadWallet(context, name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
4241-
return to_reload != nullptr;
4242-
};
4243-
42444227
// Before anything else, check if there is something to migrate.
42454228
if (local_wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4246-
if (was_loaded) {
4247-
reload_wallet(local_wallet);
4248-
}
42494229
return util::Error{_("Error: This wallet is already a descriptor wallet")};
42504230
}
42514231

@@ -4254,9 +4234,6 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
42544234
fs::path backup_filename = fs::PathFromString(strprintf("%s_%d.legacy.bak", (wallet_name.empty() ? "default_wallet" : wallet_name), GetTime()));
42554235
fs::path backup_path = this_wallet_dir / backup_filename;
42564236
if (!local_wallet->BackupWallet(fs::PathToString(backup_path))) {
4257-
if (was_loaded) {
4258-
reload_wallet(local_wallet);
4259-
}
42604237
return util::Error{_("Error: Unable to make a backup of your wallet")};
42614238
}
42624239
res.backup_path = backup_path;
@@ -4265,9 +4242,6 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
42654242

42664243
// Unlock the wallet if needed
42674244
if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4268-
if (was_loaded) {
4269-
reload_wallet(local_wallet);
4270-
}
42714245
if (passphrase.find('\0') == std::string::npos) {
42724246
return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
42734247
} else {
@@ -4304,10 +4278,10 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
43044278
}
43054279
}
43064280

4307-
// In case of reloading failure, we need to remember the wallet dirs to remove
4308-
// Set is used as it may be populated with the same wallet directory paths multiple times,
4309-
// both before and after reloading. This ensures the set is complete even if one of the wallets
4310-
// fails to reload.
4281+
// In case of loading failure, we need to remember the wallet dirs to remove.
4282+
// A `set` is used as it may be populated with the same wallet directory paths multiple times,
4283+
// both before and after loading. This ensures the set is complete even if one of the wallets
4284+
// fails to load.
43114285
std::set<fs::path> wallet_dirs;
43124286
if (success) {
43134287
Assume(!res.wallet); // We will set it here.
@@ -4319,15 +4293,17 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
43194293
for (const auto& path_to_remove : paths_to_remove) fs::remove_all(path_to_remove);
43204294
}
43214295

4322-
// Migration successful, unload all wallets locally, then reload them.
4323-
// Note: We use a pointer to the shared_ptr to avoid increasing its reference count,
4324-
// as 'reload_wallet' expects to be the sole owner (use_count == 1).
4296+
// Migration successful, load all the migrated wallets.
43254297
for (std::shared_ptr<CWallet>* wallet_ptr : {&local_wallet, &res.watchonly_wallet, &res.solvables_wallet}) {
43264298
if (success && *wallet_ptr) {
43274299
std::shared_ptr<CWallet>& wallet = *wallet_ptr;
4328-
// Save db path and reload wallet
4300+
// Save db path and load wallet
43294301
wallet_dirs.insert(fs::PathFromString(wallet->GetDatabase().Filename()).parent_path());
4330-
success = reload_wallet(wallet);
4302+
assert(wallet.use_count() == 1);
4303+
std::string wallet_name = wallet->GetName();
4304+
wallet.reset();
4305+
wallet = LoadWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
4306+
success = (wallet != nullptr);
43314307

43324308
// When no wallet is set, set the main wallet.
43334309
if (!res.wallet) {
@@ -4377,23 +4353,19 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
43774353

43784354
// Restore the backup
43794355
// Convert the backup file to the wallet db file by renaming it and moving it into the wallet's directory.
4380-
// Reload it into memory if the wallet was previously loaded.
43814356
bilingual_str restore_error;
4382-
const auto& ptr_wallet = RestoreWallet(context, temp_backup_location, wallet_name, /*load_on_start=*/std::nullopt, status, restore_error, warnings, /*load_after_restore=*/was_loaded);
4357+
const auto& ptr_wallet = RestoreWallet(context, temp_backup_location, wallet_name, /*load_on_start=*/std::nullopt, status, restore_error, warnings, /*load_after_restore=*/false);
43834358
if (!restore_error.empty()) {
43844359
error += restore_error + _("\nUnable to restore backup of wallet.");
43854360
return util::Error{error};
43864361
}
4362+
// Verify that the legacy wallet is not loaded after restoring from the backup.
4363+
assert(!ptr_wallet);
43874364

43884365
// The wallet directory has been restored, but just in case, copy the previously created backup to the wallet dir
43894366
fs::copy_file(temp_backup_location, backup_path, fs::copy_options::none);
43904367
fs::remove(temp_backup_location);
43914368

4392-
// Verify that there is no dangling wallet: when the wallet wasn't loaded before, expect null.
4393-
// This check is performed after restoration to avoid an early error before saving the backup.
4394-
bool wallet_reloaded = ptr_wallet != nullptr;
4395-
assert(was_loaded == wallet_reloaded);
4396-
43974369
return util::Error{error};
43984370
}
43994371
return res;

src/wallet/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ struct MigrationResult {
11371137
//! Do all steps to migrate a legacy wallet to a descriptor wallet
11381138
[[nodiscard]] util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& wallet_name, const SecureString& passphrase, WalletContext& context);
11391139
//! Requirement: The wallet provided to this function must be isolated, with no attachment to the node's context.
1140-
[[nodiscard]] util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context, bool was_loaded);
1140+
[[nodiscard]] util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context);
11411141
} // namespace wallet
11421142

11431143
#endif // BITCOIN_WALLET_WALLET_H

0 commit comments

Comments
 (0)