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

Code before:
        if (success && res.solvables_wallet) {
            // Reload solvables
            track_for_cleanup(*res.solvables_wallet);
            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::rename(backup_path, temp_backup_location);

        // 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>& wallet : created_wallets) {
            track_for_cleanup(*wallet);
        }

        // 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();
            }
        }

        // First, delete the db files we have created throughout this process and nothing else
        for (const fs::path& file : wallet_files_to_remove) {
            fs::remove(file);
        }

        // Second, delete the created wallet directories and nothing else. They must be empty at this point.
        for (const fs::path& dir : wallet_empty_dirs_to_remove) {
            Assume(fs::is_empty(dir));
            fs::remove(dir);
        }

        // Restore the backup

Review comment (bug):
Note that by changing this line, the error that 29.x would previously hit on an unnamed wallet migration failure is removed, and would introduce the bug present on 30.0 here. However, this is safe to do because of the other changes in this commit which prevent the deletions.

Code after:


    if (success) {
        // Migration successful, unload all wallets locally, then reload them.
        // Reload the main wallet
        LogInfo("Loading new wallets after migration...\n");
        track_for_cleanup(*local_wallet);
        success = reload_wallet(local_wallet);
        res.wallet = local_wallet;
        res.wallet_name = wallet_name;
        if (success && res.watchonly_wallet) {
            // Reload watchonly
            track_for_cleanup(*res.watchonly_wallet);
            success = reload_wallet(res.watchonly_wallet);
        }
        if (success && res.solvables_wallet) {
            // Reload solvables
            track_for_cleanup(*res.solvables_wallet);
            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::rename(backup_path, temp_backup_location);

        // 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>& wallet : created_wallets) {
            track_for_cleanup(*wallet);
        }

        // 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();