Repository: bitcoin/bitcoin
File: src/wallet/wallet.cpp (C++)

Code before:
    std::set<fs::path> wallet_dirs;
    if (success) {
        // Migration successful, unload all wallets locally, then reload them.
        // Reload the main wallet
        wallet_dirs.insert(fs::PathFromString(local_wallet->GetDatabase().Filename()).parent_path());
        success = reload_wallet(local_wallet);
        res.wallet = local_wallet;
        res.wallet_name = wallet_name;
        if (success && res.watchonly_wallet) {
            // Reload watchonly
            wallet_dirs.insert(fs::PathFromString(res.watchonly_wallet->GetDatabase().Filename()).parent_path());
            success = reload_wallet(res.watchonly_wallet);
        }
        if (success && res.solvables_wallet) {
            // Reload solvables
            wallet_dirs.insert(fs::PathFromString(res.solvables_wallet->GetDatabase().Filename()).parent_path());
            success = reload_wallet(res.solvables_wallet);
        }
    }
    if (!success) {
        // Migration failed, cleanup
        // Before deleting the wallet's directory, copy the backup file to the top-level wallets dir
        fs::path temp_backup_location = fsbridge::AbsPathJoin(GetWalletDir(), backup_filename);
        fs::copy_file(backup_path, temp_backup_location, fs::copy_options::none);

        // Make list of wallets to cleanup
        std::vector<std::shared_ptr<CWallet>> created_wallets;
        if (local_wallet) created_wallets.push_back(std::move(local_wallet));
        if (res.watchonly_wallet) created_wallets.push_back(std::move(res.watchonly_wallet));
        if (res.solvables_wallet) created_wallets.push_back(std::move(res.solvables_wallet));

        // Get the directories to remove after unloading
        for (std::shared_ptr<CWallet>& w : created_wallets) {
            wallet_dirs.emplace(fs::PathFromString(w->GetDatabase().Filename()).parent_path());
        }

        // Unload the wallets
        for (std::shared_ptr<CWallet>& w : created_wallets) {
            if (w->HaveChain()) {
                // Unloading for wallets that were loaded for normal use
                if (!RemoveWallet(context, w, /*load_on_start=*/false)) {
                    error += _("\nUnable to cleanup failed migration");
                    return util::Error{error};
                }
                WaitForDeleteWallet(std::move(w));
            } else {
                // Unloading for wallets in local context
                assert(w.use_count() == 1);
                w.reset();
            }
        }

Review comment (suggestion):
In b78990734621b8fe46c68a6e7edaf1fbd2f7d351 "wallet: migration, avoid creating spendable wallet from a watch-only legacy wallet"

I think `empty_local_wallet` is unnecessary and the condition can check `local_wallet->GetAllScriptPubKeyMans().empty()` directly.

Code after:
    {
        LOCK(local_wallet->cs_wallet);
        // First change to using SQLite
        if (!local_wallet->MigrateToSQLite(error)) return util::Error{error};

        // 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);
            // No scripts mean empty wallet after migration
            empty_local_wallet = local_wallet->GetAllScriptPubKeyMans().empty();
        } else {
            // Make sure that descriptors flag is actually set
            local_wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
            success = true;
        }
    }

    // In case of reloading failure, we need to remember the wallet dirs to remove
    // Set is used as it may be populated with the same wallet directory paths multiple times,
    // both before and after reloading. This ensures the set is complete even if one of the wallets
    // fails to reload.
    std::set<fs::path> wallet_dirs;
    if (success) {
        Assume(!res.wallet); // We will set it here.
        // Check if the local wallet is empty after migration
        if (empty_local_wallet) {
            // This wallet has no records. We can safely remove it.
            std::vector<fs::path> paths_to_remove = local_wallet->GetDatabase().Files();
            local_wallet.reset();
            for (const auto& path_to_remove : paths_to_remove) fs::remove_all(path_to_remove);
        }

        // Migration successful, unload all wallets locally, then reload them.
        // Note: We use a pointer to the shared_ptr to avoid increasing its reference count,
        // as 'reload_wallet' expects to be the sole owner (use_count == 1).
        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;
                // Save db path and reload wallet
                wallet_dirs.insert(fs::PathFromString(wallet->GetDatabase().Filename()).parent_path());
                success = reload_wallet(wallet);

                // When no wallet is set, set the main wallet.
                if (!res.wallet) {
                    res.wallet_name = wallet->GetName();
                    res.wallet = std::move(wallet);
                }
            }
        }
    }
    if (!success) {