dogecoin/src/qt/importkeysdialog.cpp
chromatic 0565a85c7c Add GUI to import private keys
Addresses GH #1808.

There are several possible future improvements:

 * add a new icon for key import

 * reduce duplication of code between the RPC private key importer and
 the GUI private key importer

 * improving error messages for various error states
2021-05-23 19:37:09 -07:00

165 lines
4.4 KiB
C++

// Copyright (c) 2021 The Dogecoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif
#include "importkeysdialog.h"
#include "ui_importkeysdialog.h"
#include "base58.h"
#include "guiutil.h"
#include "platformstyle.h"
#include "validation.h"
#include "wallet/wallet.h"
#include "walletmodel.h"
#include "util.h"
#include <QThread>
#include <QDebug>
/* Object for executing key import commands in a separate thread.
*/
class ImportKeyExecutor : public QObject
{
Q_OBJECT
public Q_SLOTS:
void rescan(CWallet*, CBlockIndex*);
Q_SIGNALS:
void rescanWallet(CWallet*, CBlockIndex*);
};
#include "importkeysdialog.moc"
void ImportKeyExecutor::rescan(CWallet* pwallet, CBlockIndex* genesisBlock)
{
qWarning() << "started import key thread";
pwallet->UpdateTimeFirstKey(1);
pwallet->ScanForWalletTransactions(genesisBlock, true);
qWarning() << "quitting import key thread";
QObject::thread()->quit();
}
ImportKeysDialog::ImportKeysDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::ImportKeysDialog),
platformStyle(_platformStyle)
{
ui->setupUi(this);
/* Main elements init */
if (fPruneMode) {
ui->rescanCheckBox->setEnabled(false);
}
}
ImportKeysDialog::~ImportKeysDialog()
{
thread.wait();
delete ui;
}
void ImportKeysDialog::on_okButton_clicked()
{
if (importKey()) {
resetDialogValues();
accept();
};
}
void ImportKeysDialog::on_cancelButton_clicked()
{
reject();
}
void ImportKeysDialog::on_resetButton_clicked()
{
resetDialogValues();
}
bool ImportKeysDialog::importKey()
{
const QString privateKey = ui->privateKey->text();
const QString privateKeyLabel = ui->privateKeyLabel->text();
const bool rescan = ui->rescanCheckBox->isChecked();
resetDialogValues();
CBitcoinSecret vchSecret;
bool fGood = vchSecret.SetString(privateKey.toStdString());
if (!fGood) {
vchSecret.SetString("");
ui->privateKeyImportTextMessage->setText(tr("Invalid private key; please check and try again!"));
return false;
}
CKey key = vchSecret.GetKey();
if (!key.IsValid()) {
vchSecret.SetString("");
ui->privateKeyImportTextMessage->setText(tr("Invalid private key; please check and try again!"));
return false;
}
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
CKeyID vchAddress = pubkey.GetID();
pwalletMain->MarkDirty();
pwalletMain->SetAddressBook(vchAddress, privateKeyLabel.toStdString(), "receive");
if (pwalletMain->HaveKey(vchAddress)) {
vchSecret.SetString("");
ui->privateKeyImportTextMessage->setText(
tr("Invalid address generated from private key; please check and try again!"
));
return false;
}
pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1;
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
vchSecret.SetString("");
ui->privateKeyImportTextMessage->setText(tr("Failed to add private key."));
return false;
}
pwalletMain->UpdateTimeFirstKey(1);
if (rescan) {
ImportKeyExecutor *executor = new ImportKeyExecutor();
executor->moveToThread(&thread);
connect(this, SIGNAL(rescanWallet(CWallet*, CBlockIndex*)), executor, SLOT(rescan(CWallet*, CBlockIndex*)));
// On stopExecutor signal
// - quit the Qt event loop in the execution thread
connect(this, SIGNAL(stopExecutor()), &thread, SLOT(quit()));
// - queue executor for deletion (in execution thread)
connect(&thread, SIGNAL(finished()), executor, SLOT(deleteLater()), Qt::DirectConnection);
// Default implementation of QThread::run() simply spins up an event loop in the thread,
// which is what we want.
thread.start();
ui->privateKeyImportTextMessage->setText(tr("Rescanning..."));
Q_EMIT rescanWallet(pwalletMain, chainActive.Genesis());
}
vchSecret.SetString("");
return true;
}
void ImportKeysDialog::resetDialogValues()
{
ui->privateKey->clear();
ui->privateKeyLabel->clear();
ui->rescanCheckBox->setCheckState(Qt::Unchecked);
}
void ImportKeysDialog::setOkButtonState(bool fState)
{
ui->okButton->setEnabled(fState);
}