wizard: allow restoring from spendkey

This commit is contained in:
tobtoht 2023-01-26 18:56:09 +01:00
parent 15aea81ea4
commit 285ce6469a
No known key found for this signature in database
GPG key ID: E45B10DD027D2472
4 changed files with 205 additions and 158 deletions

View file

@ -163,6 +163,12 @@ void WindowManager::tryOpenWallet(const QString &path, const QString &password)
} }
void WindowManager::onWalletOpened(Wallet *wallet) { void WindowManager::onWalletOpened(Wallet *wallet) {
if (!wallet) {
QString err{"Unable to open wallet"};
this->handleWalletError(err);
return;
}
auto status = wallet->status(); auto status = wallet->status();
if (status != Wallet::Status_Ok) { if (status != Wallet::Status_Ok) {
QString errMsg = wallet->errorString(); QString errMsg = wallet->errorString();
@ -305,6 +311,17 @@ void WindowManager::tryCreateWalletFromKeys(const QString &path, const QString &
return; return;
} }
Wallet *wallet;
if (address.isEmpty() && viewkey.isEmpty() && !spendkey.isEmpty()) {
wallet = m_walletManager->createDeterministicWalletFromSpendKey(path, password, constants::seedLanguage, constants::networkType, spendkey, restoreHeight, constants::kdfRounds, "", subaddressLookahead);
}
else {
if (!spendkey.isEmpty() && !WalletManager::keyValid(spendkey, address, false, constants::networkType)) {
auto err = QString("Failed to create wallet. Invalid spendkey provided.").arg(path);
this->handleWalletError(err);
return;
}
if (!WalletManager::addressValid(address, constants::networkType)) { if (!WalletManager::addressValid(address, constants::networkType)) {
auto err = QString("Failed to create wallet. Invalid address provided.").arg(path); auto err = QString("Failed to create wallet. Invalid address provided.").arg(path);
this->handleWalletError(err); this->handleWalletError(err);
@ -317,15 +334,11 @@ void WindowManager::tryCreateWalletFromKeys(const QString &path, const QString &
return; return;
} }
if (!spendkey.isEmpty() && !WalletManager::keyValid(spendkey, address, false, constants::networkType)) { wallet = m_walletManager->createWalletFromKeys(path, password, constants::seedLanguage, constants::networkType, address, viewkey, spendkey, restoreHeight, constants::kdfRounds, subaddressLookahead);
auto err = QString("Failed to create wallet. Invalid spendkey provided.").arg(path);
this->handleWalletError(err);
return;
} }
Wallet *wallet = m_walletManager->createWalletFromKeys(path, password, constants::seedLanguage, constants::networkType, address, viewkey, spendkey, restoreHeight, constants::kdfRounds, subaddressLookahead);
m_openingWallet = true; m_openingWallet = true;
m_walletManager->walletOpened(wallet); this->onWalletOpened(wallet);
} }
void WindowManager::onWalletCreated(Wallet *wallet) { void WindowManager::onWalletCreated(Wallet *wallet) {

View file

@ -21,9 +21,6 @@ PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *pare
this->setTitle("Restore wallet from keys"); this->setTitle("Restore wallet from keys");
ui->label_errorString->hide(); ui->label_errorString->hide();
QPixmap pixmap = QPixmap(":/assets/images/key.png");
ui->icon->setPixmap(pixmap.scaledToWidth(32, Qt::SmoothTransformation));
#ifndef QT_NO_CURSOR #ifndef QT_NO_CURSOR
QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
QGuiApplication::restoreOverrideCursor(); QGuiApplication::restoreOverrideCursor();
@ -35,19 +32,48 @@ PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *pare
ui->line_address->setPlaceholderText("5..."); ui->line_address->setPlaceholderText("5...");
} }
QRegularExpression keyRe(R"([0-9a-fA-F]{64})");
QValidator *keyValidator = new QRegularExpressionValidator(keyRe, this);
ui->line_viewkey->setValidator(keyValidator);
ui->line_spendkey->setValidator(keyValidator);
connect(ui->btnOptions, &QPushButton::clicked, this, &PageWalletRestoreKeys::onOptionsClicked); connect(ui->btnOptions, &QPushButton::clicked, this, &PageWalletRestoreKeys::onOptionsClicked);
connect(ui->combo_walletType, &QComboBox::currentTextChanged, this, &PageWalletRestoreKeys::showInputLines);
} }
void PageWalletRestoreKeys::initializePage() { void PageWalletRestoreKeys::initializePage() {
ui->line_address->setText(""); this->showInputLines();
ui->line_viewkey->setText("");
ui->line_spendkey->setText("");
} }
int PageWalletRestoreKeys::nextId() const { int PageWalletRestoreKeys::nextId() const {
return WalletWizard::Page_SetRestoreHeight; return WalletWizard::Page_SetRestoreHeight;
} }
void PageWalletRestoreKeys::showInputLines() {
ui->label_errorString->hide();
if (ui->combo_walletType->currentIndex() == walletType::ViewOnly) {
ui->frame_address->show();
ui->frame_viewKey->show();
ui->frame_spendKey->hide();
}
else if (ui->combo_walletType->currentIndex() == walletType::Spendable) {
ui->frame_address->hide();
ui->frame_viewKey->hide();
ui->frame_spendKey->show();
}
else {
ui->frame_address->show();
ui->frame_viewKey->show();
ui->frame_spendKey->show();
}
ui->line_address->setText("");
ui->line_viewkey->setText("");
ui->line_spendkey->setText("");
}
bool PageWalletRestoreKeys::validatePage() { bool PageWalletRestoreKeys::validatePage() {
auto errStyle = "QLineEdit{border: 1px solid red;}"; auto errStyle = "QLineEdit{border: 1px solid red;}";
@ -59,26 +85,33 @@ bool PageWalletRestoreKeys::validatePage() {
QString viewkey = ui->line_viewkey->text().trimmed(); QString viewkey = ui->line_viewkey->text().trimmed();
QString spendkey = ui->line_spendkey->text().trimmed(); QString spendkey = ui->line_spendkey->text().trimmed();
if(!WalletManager::addressValid(address, constants::networkType)){ if (walletType() == walletType::ViewOnly || walletType() == walletType::Spendable_Nondeterministic) {
if (!WalletManager::addressValid(address, constants::networkType)){
ui->label_errorString->show(); ui->label_errorString->show();
ui->label_errorString->setText("Invalid address."); ui->label_errorString->setText("Error: Invalid address.");
ui->line_address->setStyleSheet(errStyle); ui->line_address->setStyleSheet(errStyle);
return false; return false;
} }
if(!WalletManager::keyValid(viewkey, address, true, constants::networkType)) { if (!WalletManager::keyValid(viewkey, address, true, constants::networkType)) {
ui->label_errorString->show(); ui->label_errorString->show();
ui->label_errorString->setText("Invalid key."); ui->label_errorString->setText("Error: Invalid key.");
ui->line_viewkey->setStyleSheet(errStyle); ui->line_viewkey->setStyleSheet(errStyle);
return false; return false;
} }
}
if(!spendkey.isEmpty() && !WalletManager::keyValid(spendkey, address, false, constants::networkType)) { if (walletType() == walletType::Spendable || walletType() == walletType::Spendable_Nondeterministic) {
bool spendKeyValid = (ui->line_spendkey->hasAcceptableInput() && walletType() == walletType::Spendable)
|| (WalletManager::keyValid(spendkey, address, false, constants::networkType) && walletType() == walletType::Spendable_Nondeterministic);
if (!spendKeyValid) {
ui->label_errorString->show(); ui->label_errorString->show();
ui->label_errorString->setText("Invalid key."); ui->label_errorString->setText("Error: Invalid key.");
ui->line_viewkey->setStyleSheet(errStyle); ui->line_spendkey->setStyleSheet(errStyle);
return false; return false;
} }
}
m_fields->address = address; m_fields->address = address;
m_fields->secretViewKey = viewkey; m_fields->secretViewKey = viewkey;
@ -105,3 +138,7 @@ void PageWalletRestoreKeys::onOptionsClicked() {
m_fields->showSetSubaddressLookaheadPage = check_subaddressLookahead.isChecked(); m_fields->showSetSubaddressLookaheadPage = check_subaddressLookahead.isChecked();
} }
int PageWalletRestoreKeys::walletType() {
return ui->combo_walletType->currentIndex();
}

View file

@ -21,14 +21,22 @@ class PageWalletRestoreKeys : public QWizardPage
{ {
Q_OBJECT Q_OBJECT
enum walletType {
ViewOnly = 0,
Spendable = 1,
Spendable_Nondeterministic = 2
};
public: public:
explicit PageWalletRestoreKeys(WizardFields *fields, QWidget *parent = nullptr); explicit PageWalletRestoreKeys(WizardFields *fields, QWidget *parent = nullptr);
void initializePage() override; void initializePage() override;
bool validatePage() override; bool validatePage() override;
int nextId() const override; int nextId() const override;
void showInputLines();
private: private:
void onOptionsClicked(); void onOptionsClicked();
int walletType();
Ui::PageWalletRestoreKeys *ui; Ui::PageWalletRestoreKeys *ui;
WizardFields *m_fields; WizardFields *m_fields;

View file

@ -6,49 +6,18 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>759</width> <width>529</width>
<height>460</height> <height>434</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>ViewOnlyPage</string> <string>ViewOnlyPage</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="topMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QFrame" name="frame_address"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item> <item>
<widget class="QFrame" name="frame"> <widget class="QLabel" name="label_5">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="icon">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred"> <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -56,84 +25,36 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string>icon</string> <string>Wallet type:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer"> <widget class="QComboBox" name="combo_walletType">
<item>
<property name="text">
<string>View Only</string>
</property>
</item>
<item>
<property name="text">
<string>Spendable</string>
</property>
</item>
<item>
<property name="text">
<string>Spendable (Non-deterministic)</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>To restore a view-only wallet leave the spend key blank.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Primary address</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_address"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_viewKey">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Secret view key</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_viewkey"/>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>
@ -160,7 +81,7 @@
<item> <item>
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>Secret spend key (optional)</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Secret &lt;span style=&quot; font-weight:600;&quot;&gt;spend&lt;/span&gt; key&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -170,6 +91,74 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QFrame" name="frame_viewKey">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_viewKey">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Secret &lt;span style=&quot; font-weight:600;&quot;&gt;view&lt;/span&gt; key&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_viewkey"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_address">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Primary address</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_address"/>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QFrame" name="restoreFrame"> <widget class="QFrame" name="restoreFrame">
<property name="frameShape"> <property name="frameShape">