mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
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.
This commit is contained in:
parent
9332c7edda
commit
78ba0e6748
1 changed files with 37 additions and 22 deletions
|
@ -4213,11 +4213,13 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
||||||
std::vector<bilingual_str> warnings;
|
std::vector<bilingual_str> warnings;
|
||||||
|
|
||||||
// If the wallet is still loaded, unload it so that nothing else tries to use it while we're changing it
|
// If the wallet is still loaded, unload it so that nothing else tries to use it while we're changing it
|
||||||
|
bool was_loaded = false;
|
||||||
if (auto wallet = GetWallet(context, wallet_name)) {
|
if (auto wallet = GetWallet(context, wallet_name)) {
|
||||||
if (!RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt, warnings)) {
|
if (!RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt, warnings)) {
|
||||||
return util::Error{_("Unable to unload the wallet before migrating")};
|
return util::Error{_("Unable to unload the wallet before migrating")};
|
||||||
}
|
}
|
||||||
UnloadWallet(std::move(wallet));
|
UnloadWallet(std::move(wallet));
|
||||||
|
was_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the wallet but only in the context of this function.
|
// Load the wallet but only in the context of this function.
|
||||||
|
@ -4238,8 +4240,20 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
||||||
return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
|
return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper to reload as normal for some of our exit scenarios
|
||||||
|
const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
|
||||||
|
assert(to_reload.use_count() == 1);
|
||||||
|
std::string name = to_reload->GetName();
|
||||||
|
to_reload.reset();
|
||||||
|
to_reload = LoadWallet(context, name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
|
||||||
|
return to_reload != nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
// Before anything else, check if there is something to migrate.
|
// Before anything else, check if there is something to migrate.
|
||||||
if (local_wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
|
if (local_wallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
|
||||||
|
if (was_loaded) {
|
||||||
|
reload_wallet(local_wallet);
|
||||||
|
}
|
||||||
return util::Error{_("Error: This wallet is already a descriptor wallet")};
|
return util::Error{_("Error: This wallet is already a descriptor wallet")};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4248,16 +4262,20 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
||||||
fs::path backup_filename = fs::PathFromString(strprintf("%s-%d.legacy.bak", wallet_name, GetTime()));
|
fs::path backup_filename = fs::PathFromString(strprintf("%s-%d.legacy.bak", wallet_name, GetTime()));
|
||||||
fs::path backup_path = this_wallet_dir / backup_filename;
|
fs::path backup_path = this_wallet_dir / backup_filename;
|
||||||
if (!local_wallet->BackupWallet(fs::PathToString(backup_path))) {
|
if (!local_wallet->BackupWallet(fs::PathToString(backup_path))) {
|
||||||
|
if (was_loaded) {
|
||||||
|
reload_wallet(local_wallet);
|
||||||
|
}
|
||||||
return util::Error{_("Error: Unable to make a backup of your wallet")};
|
return util::Error{_("Error: Unable to make a backup of your wallet")};
|
||||||
}
|
}
|
||||||
res.backup_path = backup_path;
|
res.backup_path = backup_path;
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
{
|
|
||||||
LOCK(local_wallet->cs_wallet);
|
|
||||||
|
|
||||||
// Unlock the wallet if needed
|
// Unlock the wallet if needed
|
||||||
if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
|
if (local_wallet->IsLocked() && !local_wallet->Unlock(passphrase)) {
|
||||||
|
if (was_loaded) {
|
||||||
|
reload_wallet(local_wallet);
|
||||||
|
}
|
||||||
if (passphrase.find('\0') == std::string::npos) {
|
if (passphrase.find('\0') == std::string::npos) {
|
||||||
return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
|
return util::Error{Untranslated("Error: Wallet decryption failed, the wallet passphrase was not provided or was incorrect.")};
|
||||||
} else {
|
} else {
|
||||||
|
@ -4269,6 +4287,8 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
LOCK(local_wallet->cs_wallet);
|
||||||
// First change to using SQLite
|
// First change to using SQLite
|
||||||
if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
|
if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};
|
||||||
|
|
||||||
|
@ -4286,24 +4306,19 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
||||||
std::set<fs::path> wallet_dirs;
|
std::set<fs::path> wallet_dirs;
|
||||||
if (success) {
|
if (success) {
|
||||||
// Migration successful, unload all wallets locally, then reload them.
|
// Migration successful, unload all wallets locally, then reload them.
|
||||||
const auto& reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
|
|
||||||
assert(to_reload.use_count() == 1);
|
|
||||||
std::string name = to_reload->GetName();
|
|
||||||
wallet_dirs.insert(fs::PathFromString(to_reload->GetDatabase().Filename()).parent_path());
|
|
||||||
to_reload.reset();
|
|
||||||
to_reload = LoadWallet(context, name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
|
|
||||||
return to_reload != nullptr;
|
|
||||||
};
|
|
||||||
// Reload the main wallet
|
// Reload the main wallet
|
||||||
|
wallet_dirs.insert(fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
|
||||||
success = reload_wallet(local_wallet);
|
success = reload_wallet(local_wallet);
|
||||||
res.wallet = local_wallet;
|
res.wallet = local_wallet;
|
||||||
res.wallet_name = wallet_name;
|
res.wallet_name = wallet_name;
|
||||||
if (success && res.watchonly_wallet) {
|
if (success && res.watchonly_wallet) {
|
||||||
// Reload watchonly
|
// Reload watchonly
|
||||||
|
wallet_dirs.insert(fs::PathFromString(res.watchonly_wallet->GetDatabase().Filename()).parent_path());
|
||||||
success = reload_wallet(res.watchonly_wallet);
|
success = reload_wallet(res.watchonly_wallet);
|
||||||
}
|
}
|
||||||
if (success && res.solvables_wallet) {
|
if (success && res.solvables_wallet) {
|
||||||
// Reload solvables
|
// Reload solvables
|
||||||
|
wallet_dirs.insert(fs::PathFromString(res.solvables_wallet->GetDatabase().Filename()).parent_path());
|
||||||
success = reload_wallet(res.solvables_wallet);
|
success = reload_wallet(res.solvables_wallet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue