Files
bitcoin/src/qt/signverifymessagedialog.cpp
fanquake 7193245cd6 doc: remove For ... comments
We don't add or maintain these, and they are of little value, as
well as having the effect of polluting diffs.

They are also wrong, i.e DEFAULT_SCRIPTCHECK_THREADS is not in
validation.h.
2025-05-19 16:40:33 +01:00

301 lines
11 KiB
C++

// Copyright (c) 2011-present 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 <common/signmessage.h>
#include <bitcoin-build-config.h> // IWYU pragma: keep
#include <key_io.h>
#include <wallet/wallet.h>
#include <string>
#include <variant>
#include <vector>
#include <QClipboard>
SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent, GUIUtil::dialog_flags),
ui(new Ui::SignVerifyMessageDialog),
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 = std::get_if<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 legacy (P2PKH) key. Message signing for SegWit and other non-P2PKH address types is not supported in this version of %1. Please check the address and try again.").arg(CLIENT_NAME));
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 legacy (P2PKH) key. Message signing for SegWit and other non-P2PKH address types is not supported in this version of %1. Please check the address and try again.").arg(CLIENT_NAME));
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);
}
void SignVerifyMessageDialog::changeEvent(QEvent* e)
{
if (e->type() == QEvent::PaletteChange) {
ui->addressBookButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/address-book")));
ui->pasteButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/editpaste")));
ui->copySignatureButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/editcopy")));
ui->signMessageButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/edit")));
ui->clearButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/remove")));
ui->addressBookButton_VM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/address-book")));
ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/transaction_0")));
ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/remove")));
}
QDialog::changeEvent(e);
}