mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-09-11 21:20:39 +02:00
wallet: make loading the wallet after migrating optional
Loading the wallet after migrating is not a necessary step. By making it optional pruned nodes can also migrate legacy wallets. Also remove the migrated wallet from the list of wallets to load on startup.
This commit is contained in:
@@ -109,7 +109,14 @@ bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
|
||||
bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
|
||||
{
|
||||
const auto update_function = [&wallet_name](common::SettingsValue& setting_value) {
|
||||
if (!setting_value.isArray()) return interfaces::SettingsAction::SKIP_WRITE;
|
||||
if (!setting_value.isArray()) {
|
||||
if (wallet_name.empty() && setting_value.isNull()) {
|
||||
// Empty setting suppresses backwards-compatible default wallet autoload.
|
||||
setting_value.setArray();
|
||||
return interfaces::SettingsAction::WRITE;
|
||||
}
|
||||
return interfaces::SettingsAction::SKIP_WRITE;
|
||||
}
|
||||
common::SettingsValue new_value(common::SettingsValue::VARR);
|
||||
for (const auto& value : setting_value.getValues()) {
|
||||
if (!value.isStr() || value.get_str() != wallet_name) new_value.push_back(value);
|
||||
@@ -4177,7 +4184,7 @@ static std::string MigrationPrefixName(CWallet& wallet)
|
||||
return name.empty() ? "default_wallet" : name;
|
||||
}
|
||||
|
||||
bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error, MigrationResult& res) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
|
||||
bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error, MigrationResult& res, const bool load_on_startup = true) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet)
|
||||
{
|
||||
AssertLockHeld(wallet.cs_wallet);
|
||||
|
||||
@@ -4240,7 +4247,7 @@ bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error,
|
||||
}
|
||||
|
||||
// Add the wallet to settings
|
||||
UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
|
||||
UpdateWalletSetting(*context.chain, wallet_name, load_on_startup, warnings);
|
||||
}
|
||||
if (data->solvable_descs.size() > 0) {
|
||||
wallet.WalletLogPrintf("Making a new watchonly wallet containing the unwatched solvable scripts\n");
|
||||
@@ -4279,7 +4286,7 @@ bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error,
|
||||
}
|
||||
|
||||
// Add the wallet to settings
|
||||
UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/true, warnings);
|
||||
UpdateWalletSetting(*context.chain, wallet_name, load_on_startup, warnings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4294,7 +4301,7 @@ bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error,
|
||||
});
|
||||
}
|
||||
|
||||
util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& wallet_name, const SecureString& passphrase, WalletContext& context)
|
||||
util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& wallet_name, const SecureString& passphrase, WalletContext& context, bool load_wallet)
|
||||
{
|
||||
std::vector<bilingual_str> warnings;
|
||||
bilingual_str error;
|
||||
@@ -4336,10 +4343,10 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
|
||||
return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
|
||||
}
|
||||
|
||||
return MigrateLegacyToDescriptor(std::move(local_wallet), passphrase, context);
|
||||
return MigrateLegacyToDescriptor(std::move(local_wallet), passphrase, context, load_wallet);
|
||||
}
|
||||
|
||||
util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context)
|
||||
util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context, bool load_wallet)
|
||||
{
|
||||
MigrationResult res;
|
||||
bilingual_str error;
|
||||
@@ -4405,7 +4412,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
|
||||
|
||||
// Do the migration of keys and scripts for non-empty wallets, and cleanup if it fails
|
||||
if (HasLegacyRecords(*local_wallet)) {
|
||||
success = DoMigration(*local_wallet, context, error, res);
|
||||
success = DoMigration(*local_wallet, context, error, res, load_wallet);
|
||||
// No scripts mean empty wallet after migration
|
||||
empty_local_wallet = local_wallet->GetAllScriptPubKeyMans().empty();
|
||||
} else {
|
||||
@@ -4447,30 +4454,37 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet>
|
||||
for (const auto& path_to_remove : paths_to_remove) fs::remove(path_to_remove);
|
||||
}
|
||||
|
||||
LogInfo("Loading new wallets after migration...\n");
|
||||
// Migration successful, load all the migrated wallets.
|
||||
if (load_wallet) {
|
||||
LogInfo("Loading new wallets after migration...\n");
|
||||
/** We only override the load_on_startup setting in case the user explicitly said
|
||||
* that he does not want to load the wallet, otherwise keep the old wallet configuration */
|
||||
} else {
|
||||
UpdateWalletSetting(*context.chain, wallet_name, /*load_on_startup=*/false, warnings);
|
||||
}
|
||||
// Migration successful, if load_wallet is set load all the migrated wallets.
|
||||
bool main_wallet_set{false};
|
||||
for (std::shared_ptr<CWallet>* wallet_ptr : {&local_wallet, &res.watchonly_wallet, &res.solvables_wallet}) {
|
||||
if (success && *wallet_ptr) {
|
||||
std::shared_ptr<CWallet>& wallet = *wallet_ptr;
|
||||
// Track db path and load wallet
|
||||
// Track db path
|
||||
track_for_cleanup(*wallet);
|
||||
assert(wallet.use_count() == 1);
|
||||
std::string wallet_name = wallet->GetName();
|
||||
wallet.reset();
|
||||
wallet = LoadWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
|
||||
if (!wallet) {
|
||||
LogError("Failed to load wallet '%s' after migration. Rolling back migration to preserve consistency. "
|
||||
"Error cause: %s\n", wallet_name, error.original);
|
||||
success = false;
|
||||
break;
|
||||
if (load_wallet) {
|
||||
wallet = LoadWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
|
||||
if (!wallet) {
|
||||
LogError("Failed to load wallet '%s' after migration. Rolling back migration to preserve consistency. "
|
||||
"Error cause: %s\n", wallet_name, error.original);
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the first successfully loaded wallet as the main one.
|
||||
// Set the first wallet as the main one.
|
||||
// The loop order is intentional and must always start with the local wallet.
|
||||
if (!main_wallet_set) {
|
||||
res.wallet_name = wallet_name;
|
||||
res.wallet = std::move(wallet);
|
||||
if (load_wallet) res.wallet = std::move(wallet);
|
||||
main_wallet_set = true;
|
||||
}
|
||||
if (wallet_ptr == &res.watchonly_wallet) {
|
||||
|
||||
@@ -1143,9 +1143,9 @@ struct MigrationResult {
|
||||
};
|
||||
|
||||
//! Do all steps to migrate a legacy wallet to a descriptor wallet
|
||||
[[nodiscard]] util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& wallet_name, const SecureString& passphrase, WalletContext& context);
|
||||
[[nodiscard]] util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& wallet_name, const SecureString& passphrase, WalletContext& context, bool load_wallet = true);
|
||||
//! Requirement: The wallet provided to this function must be isolated, with no attachment to the node's context.
|
||||
[[nodiscard]] util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context);
|
||||
[[nodiscard]] util::Result<MigrationResult> MigrateLegacyToDescriptor(std::shared_ptr<CWallet> local_wallet, const SecureString& passphrase, WalletContext& context, bool load_wallet = true);
|
||||
|
||||
//! Determine the path that the wallet is stored in
|
||||
util::Result<fs::path> GetWalletPath(const std::string& name);
|
||||
|
||||
Reference in New Issue
Block a user