Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct WalletBalances;
struct WalletTx;
struct WalletTxOut;
struct WalletTxStatus;
struct WalletMigrationResult;
namespace CoinJoin {
class Loader;
}
Expand Down Expand Up @@ -401,6 +402,9 @@ class WalletLoader : public ChainClient
//! Restore backup wallet
virtual util::Result<std::unique_ptr<Wallet>> restoreWallet(const fs::path& backup_file, const std::string& wallet_name, std::vector<bilingual_str>& warnings) = 0;

//! Migrate a wallet
virtual util::Result<WalletMigrationResult> migrateWallet(const std::string& name, const SecureString& passphrase) = 0;

//! Return available wallets in wallet directory.
virtual std::vector<std::string> listWalletDir() = 0;

Expand Down Expand Up @@ -504,6 +508,15 @@ struct WalletTxOut
bool is_spent = false;
};

//! Migrated wallet info
struct WalletMigrationResult
{
std::unique_ptr<Wallet> wallet;
std::optional<std::string> watchonly_wallet_name;
std::optional<std::string> solvables_wallet_name;
fs::path backup_path;
};

//! Return implementation of Wallet interface. This function is defined in
//! dummywallet.cpp and throws if the wallet component is not compiled.
std::unique_ptr<Wallet> MakeWallet(wallet::WalletContext& context, const std::shared_ptr<wallet::CWallet>& wallet);
Expand Down
7 changes: 4 additions & 3 deletions src/qt/askpassphrasedialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,10 @@ void AskPassphraseDialog::accept()
"the first null character. If this is successful, please set a new "
"passphrase to avoid this issue in the future."));
}
}
else
{
} else {
if (m_passphrase_out) {
m_passphrase_out->assign(oldpass);
}
QDialog::accept(); // Success
}
} catch (const std::runtime_error& e) {
Expand Down
13 changes: 12 additions & 1 deletion src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,10 @@ void BitcoinGUI::createActions()
m_close_all_wallets_action = new QAction(tr("Close All Wallets…"), this);
m_close_all_wallets_action->setStatusTip(tr("Close all wallets"));

m_migrate_wallet_action = new QAction(tr("Migrate Wallet"), this);
m_migrate_wallet_action->setEnabled(false);
m_migrate_wallet_action->setStatusTip(tr("Migrate a wallet"));

showHelpMessageAction = new QAction(tr("&Command-line options"), this);
showHelpMessageAction->setMenuRole(QAction::NoRole);
showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Dash command-line options").arg(PACKAGE_NAME));
Expand Down Expand Up @@ -615,7 +619,11 @@ void BitcoinGUI::createActions()
connect(m_close_all_wallets_action, &QAction::triggered, [this] {
m_wallet_controller->closeAllWallets(this);
});

connect(m_migrate_wallet_action, &QAction::triggered, [this] {
auto activity = new MigrateWalletActivity(m_wallet_controller, this);
connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
activity->migrate(walletFrame->currentWalletModel());
});
Comment on lines +622 to +626

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Propagate migrated wallet selection to RPC console as well.

Migration updates the GUI current wallet, but not the RPC console context (unlike open/create/restore flows).

Suggested fix
         connect(m_migrate_wallet_action, &QAction::triggered, [this] {
             auto activity = new MigrateWalletActivity(m_wallet_controller, this);
             connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
+            connect(activity, &MigrateWalletActivity::migrated, rpcConsole, &RPCConsole::setCurrentWallet);
             activity->migrate(walletFrame->currentWalletModel());
         });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
connect(m_migrate_wallet_action, &QAction::triggered, [this] {
auto activity = new MigrateWalletActivity(m_wallet_controller, this);
connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
activity->migrate(walletFrame->currentWalletModel());
});
connect(m_migrate_wallet_action, &QAction::triggered, [this] {
auto activity = new MigrateWalletActivity(m_wallet_controller, this);
connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
connect(activity, &MigrateWalletActivity::migrated, rpcConsole, &RPCConsole::setCurrentWallet);
activity->migrate(walletFrame->currentWalletModel());
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/qt/bitcoingui.cpp` around lines 622 - 626, After migrating a wallet via
m_migrate_wallet_action, also update the RPC console context so it matches the
GUI current wallet; modify the lambda that creates MigrateWalletActivity to,
after calling BitcoinGUI::setCurrentWallet with
walletFrame->currentWalletModel(), invoke the same RPC-console update used by
the open/create/restore flows (for example call the existing RPC console update
method such as
rpcConsole->setCurrentWalletModel(walletFrame->currentWalletModel()) or the
BitcoinGUI helper that those flows use) so the RPC console's wallet context is
switched to the migrated wallet as well.

connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::setPrivacy);
}
#endif // ENABLE_WALLET
Expand All @@ -633,6 +641,7 @@ void BitcoinGUI::createMenuBar()
file->addAction(m_open_wallet_action);
file->addAction(m_close_wallet_action);
file->addAction(m_close_all_wallets_action);
file->addAction(m_migrate_wallet_action);
file->addSeparator();
file->addAction(backupWalletAction);
file->addAction(m_restore_wallet_action);
Expand Down Expand Up @@ -1051,6 +1060,7 @@ void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
}
}
updateWindowTitle();
m_migrate_wallet_action->setEnabled(wallet_model->wallet().isLegacy());
}

void BitcoinGUI::setCurrentWalletBySelectorIndex(int index)
Expand Down Expand Up @@ -1101,6 +1111,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
openAction->setEnabled(enabled);
m_close_wallet_action->setEnabled(enabled);
m_close_all_wallets_action->setEnabled(enabled);
m_migrate_wallet_action->setEnabled(enabled);

updateWidth();
}
Expand Down
2 changes: 2 additions & 0 deletions src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ class BitcoinGUI : public QMainWindow
QAction* m_close_all_wallets_action{nullptr};
QAction* m_wallet_selector_action = nullptr;
QAction* m_mask_values_action{nullptr};
QAction* m_migrate_wallet_action{nullptr};
QMenu* m_migrate_wallet_menu{nullptr};

QComboBox* m_wallet_selector = nullptr;

Expand Down
64 changes: 64 additions & 0 deletions src/qt/walletcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,3 +558,67 @@ void RescanWalletActivity::finish()

Q_EMIT finished();
}

void MigrateWalletActivity::migrate(WalletModel* wallet_model)
{
// Warn the user about migration
QMessageBox box(m_parent_widget);
box.setWindowTitle(tr("Migrate wallet"));
box.setText(tr("Are you sure you wish to migrate the wallet <i>%1</i>?").arg(GUIUtil::HtmlEscape(wallet_model->getDisplayName())));
box.setInformativeText(tr("Migrating the wallet will convert this wallet to one or more descriptor wallets. A new wallet backup will need to be made.\n"
"If this wallet contains any watchonly scripts, a new wallet will be created which contains those watchonly scripts.\n"
"If this wallet contains any solvable but not watched scripts, a different and new wallet will be created which contains those scripts.\n\n"
"The migration process will create a backup of the wallet before migrating. This backup file will be named "
"<wallet name>-<timestamp>.legacy.bak and can be found in the directory for this wallet. In the event of "
"an incorrect migration, the backup can be restored with the \"Restore Wallet\" functionality."));
box.setStandardButtons(QMessageBox::Yes|QMessageBox::Cancel);
box.setDefaultButton(QMessageBox::Yes);
if (box.exec() != QMessageBox::Yes) return;

// Get the passphrase if it is encrypted regardless of it is locked or unlocked. We need the passphrase itself.
SecureString passphrase;
WalletModel::EncryptionStatus enc_status = wallet_model->getEncryptionStatus();
if (enc_status == WalletModel::EncryptionStatus::Locked || enc_status == WalletModel::EncryptionStatus::Unlocked) {
AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, m_parent_widget, &passphrase);
dlg.setModel(wallet_model);
dlg.exec();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Abort migration when passphrase entry is rejected

For encrypted wallets, dlg.exec() can return Rejected when the user cancels or closes the passphrase dialog, but this result is ignored and the code immediately removes the wallet model and starts migration with an empty passphrase. In that scenario migration fails decryption after unloading/removing the wallet from the GUI, leaving the user’s wallet closed even though they canceled; return early unless the dialog is accepted.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

backported code; if there's no relevant backport from bitcoin-core, this comment would be ignored. @thepastaclaw any relevant backport for this fix?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes — the relevant upstream follow-up is bitcoin-core/gui#824, specifically commit d56a450 (gui: Use wallet name for wallet migration rather than WalletModel).

That commit changes the migration passphrase flow to use AskPassphraseDialog::UnlockMigration and returns early on cancellation:

AskPassphraseDialog dlg(AskPassphraseDialog::UnlockMigration, m_parent_widget, &passphrase);
if (dlg.exec() == QDialog::Rejected) return;

So this Codex finding is real upstream-covered behavior, but it is part of the broader “migrate legacy wallets that are not loaded” GUI follow-up rather than a small standalone fix on top of gui#738.

@knst knst Jun 9, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it can't be done right now, because bitcoin-core/gui#824 depends on bitcoin#27790 which seems impossible to be done right now; I am going to prioritize it for batch 3 but it seems as non-trivial yet.

For Bitcoin Core the gap between bitcoin-core/gui#824 and bitcoin-core/gui#738 is 2 major versions btw.

}

// GUI needs to remove the wallet so that it can actually be unloaded by migration
const std::string name = wallet_model->wallet().getWalletName();
m_wallet_controller->removeAndDeleteWallet(wallet_model);

Comment on lines +581 to +590

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Abort migration when passphrase entry is cancelled.

The dialog result is ignored, so canceling still removes the wallet and proceeds with migration using an empty passphrase.

Suggested fix
     if (enc_status == WalletModel::EncryptionStatus::Locked || enc_status == WalletModel::EncryptionStatus::Unlocked) {
         AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, m_parent_widget, &passphrase);
         dlg.setModel(wallet_model);
-        dlg.exec();
+        if (dlg.exec() != QDialog::Accepted) return;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (enc_status == WalletModel::EncryptionStatus::Locked || enc_status == WalletModel::EncryptionStatus::Unlocked) {
AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, m_parent_widget, &passphrase);
dlg.setModel(wallet_model);
dlg.exec();
}
// GUI needs to remove the wallet so that it can actually be unloaded by migration
const std::string name = wallet_model->wallet().getWalletName();
m_wallet_controller->removeAndDeleteWallet(wallet_model);
if (enc_status == WalletModel::EncryptionStatus::Locked || enc_status == WalletModel::EncryptionStatus::Unlocked) {
AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, m_parent_widget, &passphrase);
dlg.setModel(wallet_model);
if (dlg.exec() != QDialog::Accepted) return;
}
// GUI needs to remove the wallet so that it can actually be unloaded by migration
const std::string name = wallet_model->wallet().getWalletName();
m_wallet_controller->removeAndDeleteWallet(wallet_model);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/qt/walletcontroller.cpp` around lines 581 - 590, The AskPassphraseDialog
result is ignored, allowing cancellation to continue migration with an empty
passphrase; change the flow so the wallet removal and subsequent migration only
proceed when the dialog is accepted. After creating AskPassphraseDialog
(AskPassphraseDialog::Unlock) and setting the model
(dlg.setModel(wallet_model)), check the dialog result (e.g. if (dlg.exec() ==
QDialog::Accepted) or dlg.result() == QDialog::Accepted) and only then continue
to call m_wallet_controller->removeAndDeleteWallet(wallet_model) and perform
migration; if the dialog is rejected/cancelled, abort/return from the enclosing
function to avoid removing the wallet or using an empty passphrase.

showProgressDialog(tr("Migrate Wallet"), tr("Migrating Wallet <b>%1</b>…").arg(GUIUtil::HtmlEscape(name)));

QTimer::singleShot(0, worker(), [this, name, passphrase] {
auto res{node().walletLoader().migrateWallet(name, passphrase)};

if (res) {
m_success_message = tr("The wallet '%1' was migrated successfully.").arg(GUIUtil::HtmlEscape(res->wallet->getWalletName()));
if (res->watchonly_wallet_name) {
m_success_message += QChar(' ') + tr("Watchonly scripts have been migrated to a new wallet named '%1'.").arg(GUIUtil::HtmlEscape(res->watchonly_wallet_name.value()));
}
if (res->solvables_wallet_name) {
m_success_message += QChar(' ') + tr("Solvable but not watched scripts have been migrated to a new wallet named '%1'.").arg(GUIUtil::HtmlEscape(res->solvables_wallet_name.value()));
}
m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(res->wallet));
} else {
m_error_message = util::ErrorString(res);
}

QTimer::singleShot(0, this, &MigrateWalletActivity::finish);
});
}

void MigrateWalletActivity::finish()
{
if (!m_error_message.empty()) {
QMessageBox::critical(m_parent_widget, tr("Migration failed"), QString::fromStdString(m_error_message.translated));
} else {
QMessageBox::information(m_parent_widget, tr("Migration Successful"), m_success_message);
}

if (m_wallet_model) Q_EMIT migrated(m_wallet_model);

Q_EMIT finished();
}
22 changes: 22 additions & 0 deletions src/qt/walletcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class path;
class AskPassphraseDialog;
class CreateWalletActivity;
class CreateWalletDialog;
class MigrateWalletActivity;
class OpenWalletActivity;
class WalletControllerActivity;

Expand All @@ -64,6 +65,8 @@ class WalletController : public QObject
void closeWallet(WalletModel* wallet_model, QWidget* parent = nullptr);
void closeAllWallets(QWidget* parent = nullptr);

void migrateWallet(WalletModel* wallet_model, QWidget* parent = nullptr);

Q_SIGNALS:
void walletAdded(WalletModel* wallet_model);
void walletRemoved(WalletModel* wallet_model);
Expand All @@ -81,6 +84,7 @@ class WalletController : public QObject
std::unique_ptr<interfaces::Handler> m_handler_load_wallet;

friend class WalletControllerActivity;
friend class MigrateWalletActivity;
};

class WalletControllerActivity : public QObject
Expand Down Expand Up @@ -193,4 +197,22 @@ class RescanWalletActivity : public WalletControllerActivity
wallet::RescanStatus m_rescan_status{};
};

class MigrateWalletActivity : public WalletControllerActivity
{
Q_OBJECT

public:
MigrateWalletActivity(WalletController* wallet_controller, QWidget* parent) : WalletControllerActivity(wallet_controller, parent) {}

void migrate(WalletModel* wallet_model);

Q_SIGNALS:
void migrated(WalletModel* wallet_model);

private:
QString m_success_message;

void finish();
};

#endif // BITCOIN_QT_WALLETCONTROLLER_H
13 changes: 13 additions & 0 deletions src/wallet/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ using interfaces::Wallet;
using interfaces::WalletAddress;
using interfaces::WalletBalances;
using interfaces::WalletLoader;
using interfaces::WalletMigrationResult;
using interfaces::WalletOrderForm;
using interfaces::WalletTx;
using interfaces::WalletTxOut;
Expand Down Expand Up @@ -809,6 +810,18 @@ class WalletLoaderImpl : public WalletLoader
return util::Error{error};
}
}
util::Result<WalletMigrationResult> migrateWallet(const std::string& name, const SecureString& passphrase) override
{
auto res = wallet::MigrateLegacyToDescriptor(name, passphrase, m_context);
if (!res) return util::Error{util::ErrorString(res)};
WalletMigrationResult out{
.wallet = MakeWallet(m_context, res->wallet),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat failed reload as migration failure

If the post-migration LoadWallet in wallet.cpp fails after the on-disk migration succeeds, res->wallet is left null; MakeWallet then returns a null WalletMigrationResult::wallet while this interface still reports success. The GUI success path immediately dereferences res->wallet in MigrateWalletActivity, so a reload error turns into a GUI crash instead of an error message. Please validate the reloaded wallet and propagate the load failure before returning success.

Useful? React with 👍 / 👎.

.watchonly_wallet_name = res->watchonly_wallet ? std::make_optional(res->watchonly_wallet->GetName()) : std::nullopt,
.solvables_wallet_name = res->solvables_wallet ? std::make_optional(res->solvables_wallet->GetName()) : std::nullopt,
.backup_path = res->backup_path,
};
return {std::move(out)}; // std::move to work around clang bug
}
std::string getWalletDir() override
{
return fs::PathToString(GetWalletDir());
Expand Down
20 changes: 11 additions & 9 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3240,6 +3240,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
for (auto spk_man : walletInstance->GetActiveScriptPubKeyMans()) {
if (spk_man->HavePrivateKeys()) {
warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
break;
}
}
}
Expand Down Expand Up @@ -4363,16 +4364,19 @@ bool CWallet::MigrateToSQLite(bilingual_str& error)

// Close this database and delete the file
fs::path db_path = fs::PathFromString(m_database->Filename());
fs::path db_dir = db_path.parent_path();
m_database->Close();
fs::remove(db_path);

// Generate the path for the location of the migrated wallet
// Wallets that are plain files rather than wallet directories will be migrated to be wallet directories.
const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::PathFromString(m_name));

// Make new DB
DatabaseOptions opts;
opts.require_create = true;
opts.require_format = DatabaseFormat::SQLITE;
DatabaseStatus db_status;
std::unique_ptr<WalletDatabase> new_db = MakeDatabase(db_dir, opts, db_status, error);
std::unique_ptr<WalletDatabase> new_db = MakeDatabase(wallet_path, opts, db_status, error);
assert(new_db); // This is to prevent doing anything further with this wallet. The original file was deleted, but a backup exists.
m_database.reset();
m_database = std::move(new_db);
Expand Down Expand Up @@ -4552,7 +4556,7 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
return false;
}
} else {
// Labels for everything else (send) should be cloned to all
// Labels for everything else ("send") should be cloned to all
if (data.watchonly_wallet) {
LOCK(data.watchonly_wallet->cs_wallet);
// Add to the watchonly. Preserve the labels, purpose, and change-ness
Expand All @@ -4564,7 +4568,6 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
if (!addr_pair.second.IsChange()) {
data.watchonly_wallet->m_address_book[addr_pair.first].SetLabel(label);
}
continue;
}
if (data.solvable_wallet) {
LOCK(data.solvable_wallet->cs_wallet);
Expand All @@ -4577,7 +4580,6 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
if (!addr_pair.second.IsChange()) {
data.solvable_wallet->m_address_book[addr_pair.first].SetLabel(label);
}
continue;
}
}
}
Expand All @@ -4589,10 +4591,10 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
for (const auto& [destination, addr_book_data] : wallet.m_address_book) {
auto address{EncodeDestination(destination)};
auto purpose{addr_book_data.purpose};
auto label{addr_book_data.GetLabel()};
// don't bother writing default values (unknown purpose, empty label)
std::optional<std::string> label = addr_book_data.IsChange() ? std::nullopt : std::make_optional(addr_book_data.GetLabel());
// don't bother writing default values (unknown purpose)
if (purpose != "unknown") batch.WritePurpose(address, purpose);
if (!label.empty()) batch.WriteName(address, label);
if (label) batch.WriteName(address, *label);
}
};
if (data.watchonly_wallet) persist_address_book(*data.watchonly_wallet);
Expand Down Expand Up @@ -4798,7 +4800,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
// Migration successful, unload the wallet locally, then reload it.
assert(local_wallet.use_count() == 1);
local_wallet.reset();
LoadWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
res.wallet = LoadWallet(context, wallet_name, /*load_on_start=*/std::nullopt, options, status, error, warnings);
res.wallet_name = wallet_name;
} else {
// Migration failed, cleanup
Expand Down
1 change: 1 addition & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,7 @@ bool FillInputToWeight(CTxIn& txin, int64_t target_weight);

struct MigrationResult {
std::string wallet_name;
std::shared_ptr<CWallet> wallet;
std::shared_ptr<CWallet> watchonly_wallet;
std::shared_ptr<CWallet> solvables_wallet;
fs::path backup_path;
Expand Down
8 changes: 4 additions & 4 deletions test/functional/test_framework/test_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,11 @@ def parse_args(self):
self.options.descriptors = None
elif self.options.descriptors is None:
# Some wallet is either required or optionally used by the test.
# Prefer BDB unless it isn't available
if self.is_bdb_compiled():
self.options.descriptors = False
elif self.is_sqlite_compiled():
# Prefer SQLite unless it isn't available
if self.is_sqlite_compiled():
self.options.descriptors = True
elif self.is_bdb_compiled():
self.options.descriptors = False
else:
# If neither are compiled, tests requiring a wallet will be skipped and the value of self.options.descriptors won't matter
# It still needs to exist and be None in order for tests to work however.
Expand Down
Loading
Loading