dogecoin/src/qt/signverifymessagedialog.cpp
Jonas Schnelli a9024a42fc
Merge #17918: qt: Hide non PKHash-Addresses in signing address book
c4ea501e96 qt: Hide non PKHash-Addresses in signing address book (Emil Engler)

Pull request description:

  [Video Demo](https://www.youtube.com/watch?v=T-Rp2pFRmzY)

  This PR hides all non PKHash addresses in the signing GUI in the Address Book when it is opened through the signing dialog, as non PKHash addresses are useless there.

ACKs for top commit:
  jonasschnelli:
    Code Review ACK c4ea501e96

Tree-SHA512: e321d45e15534b2d68da5a1297b1c7551cdd784f03203f54c9385c2ce0bb2b7316c09f9e8c3eb41bfa1e7207ecc94c8ed08f012e2d6c117b803996ade26feb2f
2020-05-29 10:23:08 +02:00

286 lines
9.4 KiB
C++

// Copyright (c) 2011-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <qt/signverifymessagedialog.h>
#include <qt/forms/ui_signverifymessagedialog.h>
#include <qt/addressbookpage.h>
#include <qt/guiutil.h>
#include <qt/platformstyle.h>
#include <qt/walletmodel.h>
#include <key_io.h>
#include <util/message.h> // For MessageSign(), MessageVerify()
#include <wallet/wallet.h>
#include <vector>
#include <QClipboard>
SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::SignVerifyMessageDialog),
model(nullptr),
platformStyle(_platformStyle)
{
ui->setupUi(this);
ui->addressBookButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
ui->pasteButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editpaste"));
ui->copySignatureButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editcopy"));
ui->signMessageButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/edit"));
ui->clearButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
ui->addressBookButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
ui->addressIn_SM->installEventFilter(this);
ui->messageIn_SM->installEventFilter(this);
ui->signatureOut_SM->installEventFilter(this);
ui->addressIn_VM->installEventFilter(this);
ui->messageIn_VM->installEventFilter(this);
ui->signatureIn_VM->installEventFilter(this);
ui->signatureOut_SM->setFont(GUIUtil::fixedPitchFont());
ui->signatureIn_VM->setFont(GUIUtil::fixedPitchFont());
GUIUtil::handleCloseWindowShortcut(this);
}
SignVerifyMessageDialog::~SignVerifyMessageDialog()
{
delete ui;
}
void SignVerifyMessageDialog::setModel(WalletModel *_model)
{
this->model = _model;
}
void SignVerifyMessageDialog::setAddress_SM(const QString &address)
{
ui->addressIn_SM->setText(address);
ui->messageIn_SM->setFocus();
}
void SignVerifyMessageDialog::setAddress_VM(const QString &address)
{
ui->addressIn_VM->setText(address);
ui->messageIn_VM->setFocus();
}
void SignVerifyMessageDialog::showTab_SM(bool fShow)
{
ui->tabWidget->setCurrentIndex(0);
if (fShow)
this->show();
}
void SignVerifyMessageDialog::showTab_VM(bool fShow)
{
ui->tabWidget->setCurrentIndex(1);
if (fShow)
this->show();
}
void SignVerifyMessageDialog::on_addressBookButton_SM_clicked()
{
if (model && model->getAddressTableModel())
{
model->refresh(/* pk_hash_only */ true);
AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::ReceivingTab, this);
dlg.setModel(model->getAddressTableModel());
if (dlg.exec())
{
setAddress_SM(dlg.getReturnValue());
}
}
}
void SignVerifyMessageDialog::on_pasteButton_SM_clicked()
{
setAddress_SM(QApplication::clipboard()->text());
}
void SignVerifyMessageDialog::on_signMessageButton_SM_clicked()
{
if (!model)
return;
/* Clear old signature to ensure users don't get confused on error with an old signature displayed */
ui->signatureOut_SM->clear();
CTxDestination destination = DecodeDestination(ui->addressIn_SM->text().toStdString());
if (!IsValidDestination(destination)) {
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
return;
}
const PKHash* pkhash = boost::get<PKHash>(&destination);
if (!pkhash) {
ui->addressIn_SM->setValid(false);
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
return;
}
WalletModel::UnlockContext ctx(model->requestUnlock());
if (!ctx.isValid())
{
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled."));
return;
}
const std::string& message = ui->messageIn_SM->document()->toPlainText().toStdString();
std::string signature;
SigningResult res = model->wallet().signMessage(message, *pkhash, signature);
QString error;
switch (res) {
case SigningResult::OK:
error = tr("No error");
break;
case SigningResult::PRIVATE_KEY_NOT_AVAILABLE:
error = tr("Private key for the entered address is not available.");
break;
case SigningResult::SIGNING_FAILED:
error = tr("Message signing failed.");
break;
// no default case, so the compiler can warn about missing cases
}
if (res != SigningResult::OK) {
ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
ui->statusLabel_SM->setText(QString("<nobr>") + error + QString("</nobr>"));
return;
}
ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
ui->signatureOut_SM->setText(QString::fromStdString(signature));
}
void SignVerifyMessageDialog::on_copySignatureButton_SM_clicked()
{
GUIUtil::setClipboard(ui->signatureOut_SM->text());
}
void SignVerifyMessageDialog::on_clearButton_SM_clicked()
{
ui->addressIn_SM->clear();
ui->messageIn_SM->clear();
ui->signatureOut_SM->clear();
ui->statusLabel_SM->clear();
ui->addressIn_SM->setFocus();
}
void SignVerifyMessageDialog::on_addressBookButton_VM_clicked()
{
if (model && model->getAddressTableModel())
{
AddressBookPage dlg(platformStyle, AddressBookPage::ForSelection, AddressBookPage::SendingTab, this);
dlg.setModel(model->getAddressTableModel());
if (dlg.exec())
{
setAddress_VM(dlg.getReturnValue());
}
}
}
void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked()
{
const std::string& address = ui->addressIn_VM->text().toStdString();
const std::string& signature = ui->signatureIn_VM->text().toStdString();
const std::string& message = ui->messageIn_VM->document()->toPlainText().toStdString();
const auto result = MessageVerify(address, signature, message);
if (result == MessageVerificationResult::OK) {
ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
} else {
ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
}
switch (result) {
case MessageVerificationResult::OK:
ui->statusLabel_VM->setText(
QString("<nobr>") + tr("Message verified.") + QString("</nobr>")
);
return;
case MessageVerificationResult::ERR_INVALID_ADDRESS:
ui->statusLabel_VM->setText(
tr("The entered address is invalid.") + QString(" ") +
tr("Please check the address and try again.")
);
return;
case MessageVerificationResult::ERR_ADDRESS_NO_KEY:
ui->addressIn_VM->setValid(false);
ui->statusLabel_VM->setText(
tr("The entered address does not refer to a key.") + QString(" ") +
tr("Please check the address and try again.")
);
return;
case MessageVerificationResult::ERR_MALFORMED_SIGNATURE:
ui->signatureIn_VM->setValid(false);
ui->statusLabel_VM->setText(
tr("The signature could not be decoded.") + QString(" ") +
tr("Please check the signature and try again.")
);
return;
case MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED:
ui->signatureIn_VM->setValid(false);
ui->statusLabel_VM->setText(
tr("The signature did not match the message digest.") + QString(" ") +
tr("Please check the signature and try again.")
);
return;
case MessageVerificationResult::ERR_NOT_SIGNED:
ui->statusLabel_VM->setText(
QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>")
);
return;
}
}
void SignVerifyMessageDialog::on_clearButton_VM_clicked()
{
ui->addressIn_VM->clear();
ui->signatureIn_VM->clear();
ui->messageIn_VM->clear();
ui->statusLabel_VM->clear();
ui->addressIn_VM->setFocus();
}
bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn)
{
if (ui->tabWidget->currentIndex() == 0)
{
/* Clear status message on focus change */
ui->statusLabel_SM->clear();
/* Select generated signature */
if (object == ui->signatureOut_SM)
{
ui->signatureOut_SM->selectAll();
return true;
}
}
else if (ui->tabWidget->currentIndex() == 1)
{
/* Clear status message on focus change */
ui->statusLabel_VM->clear();
}
}
return QDialog::eventFilter(object, event);
}