Skip to content

Commit 78ba0e6

Browse files
committed
wallet: Reload the wallet if migration exited early
Migration will unload loaded wallets prior to beginning. It will then perform some checks which may exit early. Such unloaded wallets should be reloaded prior to exiting.
1 parent 9332c7e commit 78ba0e6

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed

src/wallet/wallet.cpp

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4213,11 +4213,13 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
42134213
std::vector<bilingual_str> warnings;
42144214

42154215
// If the wallet is still loaded, unload it so that nothing else tries to use it while we're changing it
4216+
bool was_loaded = false;
42164217
if (auto wallet = GetWallet(context, wallet_name)) {
42174218
if (!RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt, warnings)) {
42184219
return util::Error{_("Unable to unload the wallet before migrating")};
42194220
}
42204221
UnloadWallet(std::move(wallet));
4222+
was_loaded = true;
42214223
}
42224224

42234225
// Load the wallet but only in the context of this function.
@@ -4238,8 +4240,20 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
42384240
return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
42394241
}
42404242

4243+
// Helper to reload as normal for some of our exit scenarios
4244+
const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4245+
assert(to_reload.use_count() == 1);
4246+
std::string name = to_reload->GetName();
4247+
to_reload.reset();
4248+
to_reload = LoadWallet(context, name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
4249+
return to_reload != nullptr;
4250+
};
4251+
42414252
// Before anything else, check if there is something to migrate.
42424253
if (local_wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
4254+
if (was_loaded) {
4255+
reload_wallet(local_wallet);
4256+
}
42434257
return util::Error{_("Error: This wallet is already a descriptor wallet")};
42444258
}
42454259

@@ -4248,27 +4262,33 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
42484262
fs::path backup_filename = fs::PathFromString(strprintf("%s-%d.legacy.bak", wallet_name, GetTime()));
42494263
fs::path backup_path = this_wallet_dir / backup_filename;
42504264
if (!local_wallet->BackupWallet(fs::PathToString(backup_path))) {
4265+
if (was_loaded) {
4266+
reload_wallet(local_wallet);
4267+
}
42514268
return util::Error{_("Error: Unable to make a backup of your wallet")};
42524269
}
42534270
res.backup_path = backup_path;
42544271

42554272
bool success = false;
4256-
{
4257-
LOCK(local_wallet->cs_wallet);
42584273

4259-
// Unlock the wallet if needed
4260-
if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4261-
if (passphrase.find('\0') == std::string::npos) {
4262-
return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4263-
} else {
4264-
return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase entered was incorrect. "
4265-
"The passphrase contains a null character (ie - a zero byte). "
4266-
"If this passphrase was set with a version of this software prior to 25.0, "
4267-
"please try again with only the characters up to — but not including — "
4268-
"the first null character.")};
4269-
}
4274+
// Unlock the wallet if needed
4275+
if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
4276+
if (was_loaded) {
4277+
reload_wallet(local_wallet);
4278+
}
4279+
if (passphrase.find('\0') == std::string::npos) {
4280+
return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
4281+
} else {
4282+
return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase entered was incorrect. "
4283+
"The passphrase contains a null character (ie - a zero byte). "
4284+
"If this passphrase was set with a version of this software prior to 25.0, "
4285+
"please try again with only the characters up to — but not including — "
4286+
"the first null character.")};
42704287
}
4288+
}
42714289

4290+
{
4291+
LOCK(local_wallet->cs_wallet);
42724292
// First change to using SQLite
42734293
if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
42744294

@@ -4286,24 +4306,19 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
42864306
std::set<fs::path> wallet_dirs;
42874307
if (success) {
42884308
// Migration successful, unload all wallets locally, then reload them.
4289-
const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4290-
assert(to_reload.use_count() == 1);
4291-
std::string name = to_reload->GetName();
4292-
wallet_dirs.insert(fs::PathFromString(to_reload->GetDatabase().Filename()).parent_path());
4293-
to_reload.reset();
4294-
to_reload = LoadWallet(context, name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
4295-
return to_reload != nullptr;
4296-
};
42974309
// Reload the main wallet
4310+
wallet_dirs.insert(fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
42984311
success = reload_wallet(local_wallet);
42994312
res.wallet = local_wallet;
43004313
res.wallet_name = wallet_name;
43014314
if (success && res.watchonly_wallet) {
43024315
// Reload watchonly
4316+
wallet_dirs.insert(fs::PathFromString(res.watchonly_wallet->GetDatabase().Filename()).parent_path());
43034317
success = reload_wallet(res.watchonly_wallet);
43044318
}
43054319
if (success && res.solvables_wallet) {
43064320
// Reload solvables
4321+
wallet_dirs.insert(fs::PathFromString(res.solvables_wallet->GetDatabase().Filename()).parent_path());
43074322
success = reload_wallet(res.solvables_wallet);
43084323
}
43094324
}

0 commit comments

Comments
 (0)