@@ -4083,6 +4083,10 @@ bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error,
40834083 DatabaseOptions options;
40844084 options.require_existing = false ;
40854085 options.require_create = true ;
4086+ options.require_format = DatabaseFormat::SQLITE;
4087+
4088+ WalletContext empty_context;
4089+ empty_context.args = context.args ;
40864090
40874091 // Make the wallets
40884092 options.create_flags = WALLET_FLAG_DISABLE_PRIVATE_KEYS | WALLET_FLAG_BLANK_WALLET | WALLET_FLAG_DESCRIPTORS;
@@ -4098,8 +4102,14 @@ bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error,
40984102 DatabaseStatus status;
40994103 std::vector<bilingual_str> warnings;
41004104 std::string wallet_name = wallet.GetName () + " _watchonly" ;
4101- data->watchonly_wallet = CreateWallet (context, wallet_name, std::nullopt , options, status, error, warnings);
4102- if (status != DatabaseStatus::SUCCESS) {
4105+ std::unique_ptr<WalletDatabase> database = MakeWalletDatabase (wallet_name, options, status, error);
4106+ if (!database) {
4107+ error = strprintf (_ (" Wallet file creation failed: %s" ), error);
4108+ return false ;
4109+ }
4110+
4111+ data->watchonly_wallet = CWallet::Create (empty_context, wallet_name, std::move (database), options.create_flags , error, warnings);
4112+ if (!data->watchonly_wallet ) {
41034113 error = _ (" Error: Failed to create new watchonly wallet" );
41044114 return false ;
41054115 }
@@ -4129,8 +4139,14 @@ bool DoMigration(CWallet& wallet, WalletContext& context, bilingual_str& error,
41294139 DatabaseStatus status;
41304140 std::vector<bilingual_str> warnings;
41314141 std::string wallet_name = wallet.GetName () + " _solvables" ;
4132- data->solvable_wallet = CreateWallet (context, wallet_name, std::nullopt , options, status, error, warnings);
4133- if (status != DatabaseStatus::SUCCESS) {
4142+ std::unique_ptr<WalletDatabase> database = MakeWalletDatabase (wallet_name, options, status, error);
4143+ if (!database) {
4144+ error = strprintf (_ (" Wallet file creation failed: %s" ), error);
4145+ return false ;
4146+ }
4147+
4148+ data->solvable_wallet = CWallet::Create (empty_context, wallet_name, std::move (database), options.create_flags , error, warnings);
4149+ if (!data->solvable_wallet ) {
41344150 error = _ (" Error: Failed to create new watchonly wallet" );
41354151 return false ;
41364152 }
@@ -4233,47 +4249,69 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
42334249 success = DoMigration (*local_wallet, context, error, res);
42344250 }
42354251
4252+ // In case of reloading failure, we need to remember the wallet dirs to remove
4253+ // Set is used as it may be populated with the same wallet directory paths multiple times,
4254+ // both before and after reloading. This ensures the set is complete even if one of the wallets
4255+ // fails to reload.
4256+ std::set<fs::path> wallet_dirs;
42364257 if (success) {
4237- // Migration successful, unload the wallet locally, then reload it.
4238- assert (local_wallet.use_count () == 1 );
4239- local_wallet.reset ();
4240- res.wallet = LoadWallet (context, wallet_name, /* load_on_start=*/ std::nullopt , options, status, error, warnings);
4258+ // Migration successful, unload all wallets locally, then reload them.
4259+ const auto & reload_wallet = [&](std::shared_ptr<CWallet>& to_reload) {
4260+ assert (to_reload.use_count () == 1 );
4261+ std::string name = to_reload->GetName ();
4262+ wallet_dirs.insert (fs::PathFromString (to_reload->GetDatabase ().Filename ()).parent_path ());
4263+ to_reload.reset ();
4264+ to_reload = LoadWallet (context, name, /* load_on_start=*/ std::nullopt , options, status, error, warnings);
4265+ return to_reload != nullptr ;
4266+ };
4267+ // Reload the main wallet
4268+ success = reload_wallet (local_wallet);
4269+ res.wallet = local_wallet;
42414270 res.wallet_name = wallet_name;
4242- } else {
4271+ if (success && res.watchonly_wallet ) {
4272+ // Reload watchonly
4273+ success = reload_wallet (res.watchonly_wallet );
4274+ }
4275+ if (success && res.solvables_wallet ) {
4276+ // Reload solvables
4277+ success = reload_wallet (res.solvables_wallet );
4278+ }
4279+ }
4280+ if (!success) {
42434281 // Migration failed, cleanup
42444282 // Copy the backup to the actual wallet dir
42454283 fs::path temp_backup_location = fsbridge::AbsPathJoin (GetWalletDir (), backup_filename);
42464284 fs::copy_file (backup_path, temp_backup_location, fs::copy_options::none);
42474285
4248- // Remember this wallet's walletdir to remove after unloading
4249- std::vector<fs::path> wallet_dirs;
4250- wallet_dirs.emplace_back (fs::PathFromString (local_wallet->GetDatabase ().Filename ()).parent_path ());
4251-
4252- // Unload the wallet locally
4253- assert (local_wallet.use_count () == 1 );
4254- local_wallet.reset ();
4255-
42564286 // Make list of wallets to cleanup
42574287 std::vector<std::shared_ptr<CWallet>> created_wallets;
4288+ if (local_wallet) created_wallets.push_back (std::move (local_wallet));
42584289 if (res.watchonly_wallet ) created_wallets.push_back (std::move (res.watchonly_wallet ));
42594290 if (res.solvables_wallet ) created_wallets.push_back (std::move (res.solvables_wallet ));
42604291
42614292 // Get the directories to remove after unloading
42624293 for (std::shared_ptr<CWallet>& w : created_wallets) {
4263- wallet_dirs.emplace_back (fs::PathFromString (w->GetDatabase ().Filename ()).parent_path ());
4294+ wallet_dirs.emplace (fs::PathFromString (w->GetDatabase ().Filename ()).parent_path ());
42644295 }
42654296
42664297 // Unload the wallets
42674298 for (std::shared_ptr<CWallet>& w : created_wallets) {
4268- if (!RemoveWallet (context, w, /* load_on_start=*/ false )) {
4269- error += _ (" \n Unable to cleanup failed migration" );
4270- return util::Error{error};
4299+ if (w->HaveChain ()) {
4300+ // Unloading for wallets that were loaded for normal use
4301+ if (!RemoveWallet (context, w, /* load_on_start=*/ false )) {
4302+ error += _ (" \n Unable to cleanup failed migration" );
4303+ return util::Error{error};
4304+ }
4305+ UnloadWallet (std::move (w));
4306+ } else {
4307+ // Unloading for wallets in local context
4308+ assert (w.use_count () == 1 );
4309+ w.reset ();
42714310 }
4272- UnloadWallet (std::move (w));
42734311 }
42744312
42754313 // Delete the wallet directories
4276- for (fs::path& dir : wallet_dirs) {
4314+ for (const fs::path& dir : wallet_dirs) {
42774315 fs::remove_all (dir);
42784316 }
42794317
0 commit comments