Skip to content

Commit d56a450

Browse files
achow101furszy
andcommitted
gui: Use wallet name for wallet migration rather than WalletModel
To prepare for migrating wallets that are not loaded, when migration occurs in the GUI, it should not rely on a WalletModel existing. Co-authored-by: furszy <[email protected]>
1 parent c391858 commit d56a450

File tree

9 files changed

+51
-18
lines changed

9 files changed

+51
-18
lines changed

src/interfaces/wallet.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ class WalletLoader : public ChainClient
342342
//! Migrate a wallet
343343
virtual util::Result<WalletMigrationResult> migrateWallet(const std::string& name, const SecureString& passphrase) = 0;
344344

345+
//! Returns true if wallet stores encryption keys
346+
virtual bool isEncrypted(const std::string& wallet_name) = 0;
347+
345348
//! Return available wallets in wallet directory.
346349
virtual std::vector<std::pair<std::string, std::string>> listWalletDir() = 0;
347350

src/qt/askpassphrasedialog.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent, SecureStri
4444
ui->passEdit1->hide();
4545
setWindowTitle(tr("Encrypt wallet"));
4646
break;
47+
case UnlockMigration:
4748
case Unlock: // Ask passphrase
4849
ui->warningLabel->setText(tr("This operation needs your wallet passphrase to unlock the wallet."));
4950
ui->passLabel2->hide();
@@ -80,7 +81,7 @@ void AskPassphraseDialog::setModel(WalletModel *_model)
8081
void AskPassphraseDialog::accept()
8182
{
8283
SecureString oldpass, newpass1, newpass2;
83-
if (!model && mode != Encrypt)
84+
if (!model && mode != Encrypt && mode != UnlockMigration)
8485
return;
8586
oldpass.reserve(MAX_PASSPHRASE_SIZE);
8687
newpass1.reserve(MAX_PASSPHRASE_SIZE);
@@ -181,6 +182,10 @@ void AskPassphraseDialog::accept()
181182
QMessageBox::critical(this, tr("Wallet unlock failed"), e.what());
182183
}
183184
break;
185+
case UnlockMigration:
186+
Assume(m_passphrase_out)->assign(oldpass);
187+
QDialog::accept();
188+
break;
184189
case ChangePass:
185190
if(newpass1 == newpass2)
186191
{
@@ -224,6 +229,7 @@ void AskPassphraseDialog::textChanged()
224229
case Encrypt: // New passphrase x2
225230
acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
226231
break;
232+
case UnlockMigration:
227233
case Unlock: // Old passphrase x1
228234
acceptable = !ui->passEdit1->text().isEmpty();
229235
break;

src/qt/askpassphrasedialog.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class AskPassphraseDialog : public QDialog
2626
Encrypt, /**< Ask passphrase twice and encrypt */
2727
Unlock, /**< Ask passphrase and unlock */
2828
ChangePass, /**< Ask old passphrase + new passphrase twice */
29+
UnlockMigration, /**< Ask passphrase for unlocking during migration */
2930
};
3031

3132
explicit AskPassphraseDialog(Mode mode, QWidget *parent, SecureString* passphrase_out = nullptr);

src/qt/bitcoingui.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ void BitcoinGUI::createActions()
458458
connect(m_migrate_wallet_action, &QAction::triggered, [this] {
459459
auto activity = new MigrateWalletActivity(m_wallet_controller, this);
460460
connect(activity, &MigrateWalletActivity::migrated, this, &BitcoinGUI::setCurrentWallet);
461-
activity->migrate(walletFrame->currentWalletModel());
461+
activity->migrate(walletFrame->currentWalletModel()->wallet().getWalletName());
462462
});
463463
connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::setPrivacy);
464464
connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::enableHistoryAction);

src/qt/walletcontroller.cpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -437,12 +437,12 @@ void RestoreWalletActivity::finish()
437437
Q_EMIT finished();
438438
}
439439

440-
void MigrateWalletActivity::migrate(WalletModel* wallet_model)
440+
void MigrateWalletActivity::migrate(const std::string& name)
441441
{
442442
// Warn the user about migration
443443
QMessageBox box(m_parent_widget);
444444
box.setWindowTitle(tr("Migrate wallet"));
445-
box.setText(tr("Are you sure you wish to migrate the wallet <i>%1</i>?").arg(GUIUtil::HtmlEscape(wallet_model->getDisplayName())));
445+
box.setText(tr("Are you sure you wish to migrate the wallet <i>%1</i>?").arg(GUIUtil::HtmlEscape(GUIUtil::WalletDisplayName(name))));
446446
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"
447447
"If this wallet contains any watchonly scripts, a new wallet will be created which contains those watchonly scripts.\n"
448448
"If this wallet contains any solvable but not watched scripts, a different and new wallet will be created which contains those scripts.\n\n"
@@ -453,29 +453,25 @@ void MigrateWalletActivity::migrate(WalletModel* wallet_model)
453453
box.setDefaultButton(QMessageBox::Yes);
454454
if (box.exec() != QMessageBox::Yes) return;
455455

456-
// Get the passphrase if it is encrypted regardless of it is locked or unlocked. We need the passphrase itself.
457456
SecureString passphrase;
458-
WalletModel::EncryptionStatus enc_status = wallet_model->getEncryptionStatus();
459-
if (enc_status == WalletModel::EncryptionStatus::Locked || enc_status == WalletModel::EncryptionStatus::Unlocked) {
460-
AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, m_parent_widget, &passphrase);
461-
dlg.setModel(wallet_model);
462-
dlg.exec();
457+
if (node().walletLoader().isEncrypted(name)) {
458+
// Get the passphrase for the wallet
459+
AskPassphraseDialog dlg(AskPassphraseDialog::UnlockMigration, m_parent_widget, &passphrase);
460+
if (dlg.exec() == QDialog::Rejected) return;
463461
}
464462

465-
// GUI needs to remove the wallet so that it can actually be unloaded by migration
466-
const std::string name = wallet_model->wallet().getWalletName();
467463
showProgressDialog(tr("Migrate Wallet"), tr("Migrating Wallet <b>%1</b>…").arg(GUIUtil::HtmlEscape(name)));
468464

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

472468
if (res) {
473-
m_success_message = tr("The wallet '%1' was migrated successfully.").arg(GUIUtil::HtmlEscape(res->wallet->getWalletName()));
469+
m_success_message = tr("The wallet '%1' was migrated successfully.").arg(GUIUtil::HtmlEscape(GUIUtil::WalletDisplayName(res->wallet->getWalletName())));
474470
if (res->watchonly_wallet_name) {
475-
m_success_message += QChar(' ') + tr("Watchonly scripts have been migrated to a new wallet named '%1'.").arg(GUIUtil::HtmlEscape(res->watchonly_wallet_name.value()));
471+
m_success_message += QChar(' ') + tr("Watchonly scripts have been migrated to a new wallet named '%1'.").arg(GUIUtil::HtmlEscape(GUIUtil::WalletDisplayName(res->watchonly_wallet_name.value())));
476472
}
477473
if (res->solvables_wallet_name) {
478-
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()));
474+
m_success_message += QChar(' ') + tr("Solvable but not watched scripts have been migrated to a new wallet named '%1'.").arg(GUIUtil::HtmlEscape(GUIUtil::WalletDisplayName(res->solvables_wallet_name.value())));
479475
}
480476
m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(res->wallet));
481477
} else {

src/qt/walletcontroller.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ class WalletController : public QObject
6666
void closeWallet(WalletModel* wallet_model, QWidget* parent = nullptr);
6767
void closeAllWallets(QWidget* parent = nullptr);
6868

69-
void migrateWallet(WalletModel* wallet_model, QWidget* parent = nullptr);
70-
7169
Q_SIGNALS:
7270
void walletAdded(WalletModel* wallet_model);
7371
void walletRemoved(WalletModel* wallet_model);
@@ -186,7 +184,7 @@ class MigrateWalletActivity : public WalletControllerActivity
186184
public:
187185
MigrateWalletActivity(WalletController* wallet_controller, QWidget* parent) : WalletControllerActivity(wallet_controller, parent) {}
188186

189-
void migrate(WalletModel* wallet_model);
187+
void migrate(const std::string& path);
190188

191189
Q_SIGNALS:
192190
void migrated(WalletModel* wallet_model);

src/wallet/interfaces.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,21 @@ class WalletLoaderImpl : public WalletLoader
652652
};
653653
return out;
654654
}
655+
bool isEncrypted(const std::string& wallet_name) override
656+
{
657+
auto wallets{GetWallets(m_context)};
658+
auto it = std::find_if(wallets.begin(), wallets.end(), [&](std::shared_ptr<CWallet> w){ return w->GetName() == wallet_name; });
659+
if (it != wallets.end()) return (*it)->IsCrypted();
660+
661+
// Unloaded wallet, read db
662+
DatabaseOptions options;
663+
options.require_existing = true;
664+
DatabaseStatus status;
665+
bilingual_str error;
666+
auto db = MakeWalletDatabase(wallet_name, options, status, error);
667+
if (!db) return false;
668+
return WalletBatch(*db).IsEncrypted();
669+
}
655670
std::string getWalletDir() override
656671
{
657672
return fs::PathToString(GetWalletDir());

src/wallet/walletdb.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,17 @@ bool WalletBatch::ReadBestBlock(CBlockLocator& locator)
187187
return m_batch->Read(DBKeys::BESTBLOCK_NOMERKLE, locator);
188188
}
189189

190+
bool WalletBatch::IsEncrypted()
191+
{
192+
DataStream prefix;
193+
prefix << DBKeys::MASTER_KEY;
194+
if (auto cursor = m_batch->GetNewPrefixCursor(prefix)) {
195+
DataStream k, v;
196+
if (cursor->Next(k, v) == DatabaseCursor::Status::MORE) return true;
197+
}
198+
return false;
199+
}
200+
190201
bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext)
191202
{
192203
return WriteIC(DBKeys::ORDERPOSNEXT, nOrderPosNext);

src/wallet/walletdb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ class WalletBatch
247247
bool WriteBestBlock(const CBlockLocator& locator);
248248
bool ReadBestBlock(CBlockLocator& locator);
249249

250+
// Returns true if wallet stores encryption keys
251+
bool IsEncrypted();
252+
250253
bool WriteOrderPosNext(int64_t nOrderPosNext);
251254

252255
bool ReadPool(int64_t nPool, CKeyPool& keypool);

0 commit comments

Comments
 (0)