From 0c587936c7f0bbab83c54f877f720dbf3387ef73 Mon Sep 17 00:00:00 2001 From: sje397 Date: Mon, 27 Feb 2012 22:55:04 +1100 Subject: [PATCH] Add a menu option to verify a signed message (Also move 'setAttribute(Qt::WA_DeleteOnClose)' out of QRCodeDialog) --- bitcoin-qt.pro | 9 +- src/qt/addressbookpage.cpp | 1 + src/qt/bitcoingui.cpp | 13 +++ src/qt/bitcoingui.h | 3 + src/qt/forms/verifymessagedialog.ui | 149 ++++++++++++++++++++++++++++ src/qt/qrcodedialog.cpp | 1 - src/qt/verifymessagedialog.cpp | 75 ++++++++++++++ src/qt/verifymessagedialog.h | 36 +++++++ 8 files changed, 283 insertions(+), 4 deletions(-) create mode 100644 src/qt/forms/verifymessagedialog.ui create mode 100644 src/qt/verifymessagedialog.cpp create mode 100644 src/qt/verifymessagedialog.h diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index 112e8e9389..10f91e296a 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -159,7 +159,8 @@ HEADERS += src/qt/bitcoingui.h \ src/qt/qtipcserver.h \ src/allocators.h \ src/ui_interface.h \ - src/qt/rpcconsole.h + src/qt/rpcconsole.h \ + src/qt/verifymessagedialog.h SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/qt/transactiontablemodel.cpp \ @@ -214,7 +215,8 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/protocol.cpp \ src/qt/notificator.cpp \ src/qt/qtipcserver.cpp \ - src/qt/rpcconsole.cpp + src/qt/rpcconsole.cpp \ + src/qt/verifymessagedialog.cpp RESOURCES += \ src/qt/bitcoin.qrc @@ -229,7 +231,8 @@ FORMS += \ src/qt/forms/overviewpage.ui \ src/qt/forms/sendcoinsentry.ui \ src/qt/forms/askpassphrasedialog.ui \ - src/qt/forms/rpcconsole.ui + src/qt/forms/rpcconsole.ui \ + src/qt/forms/verifymessagedialog.ui contains(USE_QRCODE, 1) { HEADERS += src/qt/qrcodedialog.h diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index dfc85c66d6..d314e62b5a 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -324,6 +324,7 @@ void AddressBookPage::on_showQRCode_clicked() QString address = index.data().toString(), label = index.sibling(index.row(), 0).data(Qt::EditRole).toString(); QRCodeDialog *dialog = new QRCodeDialog(address, label, tab == ReceivingTab, this); + dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); } #endif diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 55672472ec..855fec3a8b 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -9,6 +9,7 @@ #include "addressbookpage.h" #include "sendcoinsdialog.h" #include "messagepage.h" +#include "verifymessagedialog.h" #include "optionsdialog.h" #include "aboutdialog.h" #include "clientmodel.h" @@ -255,6 +256,8 @@ void BitcoinGUI::createActions() changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption")); openRPCConsoleAction = new QAction(tr("&Debug window"), this); openRPCConsoleAction->setToolTip(tr("Open debugging and diagnostic console")); + verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this); + verifyMessageAction->setToolTip(tr("Verify a message signature")); connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked())); @@ -264,6 +267,7 @@ void BitcoinGUI::createActions() connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool))); connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet())); connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase())); + connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(verifyMessage())); } void BitcoinGUI::createMenuBar() @@ -283,6 +287,7 @@ void BitcoinGUI::createMenuBar() #ifndef FIRST_CLASS_MESSAGING file->addAction(messageAction); #endif + file->addAction(verifyMessageAction); file->addSeparator(); file->addAction(quitAction); @@ -405,6 +410,7 @@ void BitcoinGUI::createTrayIcon() trayIconMenu->addAction(openRPCConsoleAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(messageAction); + trayIconMenu->addAction(verifyMessageAction); #ifndef FIRST_CLASS_MESSAGING trayIconMenu->addSeparator(); #endif @@ -836,6 +842,13 @@ void BitcoinGUI::changePassphrase() dlg.exec(); } +void BitcoinGUI::verifyMessage() +{ + VerifyMessageDialog *dlg = new VerifyMessageDialog(walletModel->getAddressTableModel(), this); + dlg->setAttribute(Qt::WA_DeleteOnClose); + dlg->show(); +} + void BitcoinGUI::unlockWallet() { if(!walletModel) diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index bc3c9a1dfc..88e6d064d7 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -79,6 +79,7 @@ private: QAction *sendCoinsAction; QAction *addressBookAction; QAction *messageAction; + QAction *verifyMessageAction; QAction *aboutAction; QAction *receiveCoinsAction; QAction *optionsAction; @@ -163,6 +164,8 @@ private slots: void backupWallet(); /** Change encrypted wallet passphrase */ void changePassphrase(); + /** Verify a message signature */ + void verifyMessage(); /** Ask for pass phrase to unlock wallet temporarily */ void unlockWallet(); diff --git a/src/qt/forms/verifymessagedialog.ui b/src/qt/forms/verifymessagedialog.ui new file mode 100644 index 0000000000..6b7f94258b --- /dev/null +++ b/src/qt/forms/verifymessagedialog.ui @@ -0,0 +1,149 @@ + + + VerifyMessageDialog + + + + 0 + 0 + 494 + 342 + + + + Verify Signed Message + + + + + + Enter the message and signature below (be careful to correctly copy newlines, spaces, tabs, and other invisible characters), and press apply to obtain the bitcoin address used to sign the message. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + + + + + + + + + Signature + + + + + + + + + + true + + + Address + + + + + + + + + + + + + + + + false + + + Copy the currently selected address to the system clipboard + + + &Copy Address + + + + :/icons/editcopy:/icons/editcopy + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Apply|QDialogButtonBox::Close + + + false + + + + + + + + + + + + + buttonBox + accepted() + VerifyMessageDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + VerifyMessageDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qt/qrcodedialog.cpp b/src/qt/qrcodedialog.cpp index d8e2007a2f..32e5462cee 100644 --- a/src/qt/qrcodedialog.cpp +++ b/src/qt/qrcodedialog.cpp @@ -15,7 +15,6 @@ QRCodeDialog::QRCodeDialog(const QString &addr, const QString &label, bool enabl { ui->setupUi(this); setWindowTitle(QString("%1").arg(address)); - setAttribute(Qt::WA_DeleteOnClose); ui->chkReqPayment->setVisible(enableReq); ui->lnReqAmount->setVisible(enableReq); diff --git a/src/qt/verifymessagedialog.cpp b/src/qt/verifymessagedialog.cpp new file mode 100644 index 0000000000..8842908718 --- /dev/null +++ b/src/qt/verifymessagedialog.cpp @@ -0,0 +1,75 @@ +#include "verifymessagedialog.h" +#include "ui_verifymessagedialog.h" + +#include +#include + +#include +#include +#include +#include + +#include "main.h" +#include "wallet.h" +#include "walletmodel.h" +#include "addresstablemodel.h" +#include "guiutil.h" + +VerifyMessageDialog::VerifyMessageDialog(AddressTableModel *addressModel, QWidget *parent) : + QDialog(parent), + ui(new Ui::VerifyMessageDialog), + model(addressModel) +{ + ui->setupUi(this); + + GUIUtil::setupAddressWidget(ui->lnAddress, this); +} + +VerifyMessageDialog::~VerifyMessageDialog() +{ + delete ui; +} + +bool VerifyMessageDialog::checkAddress() +{ + CDataStream ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << ui->edMessage->document()->toPlainText().toStdString(); + uint256 hash = Hash(ss.begin(), ss.end()); + + bool invalid = true; + std::vector vchSig = DecodeBase64(ui->lnSig->text().toStdString().c_str(), &invalid); + + if(invalid) + { + QMessageBox::warning(this, tr("Invalid Signature"), tr("The signature could not be decoded. Please check the signature and try again.")); + return false; + } + + CKey key; + if(!key.SetCompactSignature(hash, vchSig)) + { + QMessageBox::warning(this, tr("Invalid Signature"), tr("The signature did not match the message digest. Please check the signature and try again.")); + return false; + } + + CBitcoinAddress address(key.GetPubKey()); + QString qStringAddress = QString::fromStdString(address.ToString()); + ui->lnAddress->setText(qStringAddress); + ui->copyToClipboard->setEnabled(true); + + QString label = model->labelForAddress(qStringAddress); + ui->lblStatus->setText(label.isEmpty() ? tr("Address not found in address book.") : tr("Address found in address book: %1").arg(label)); + return true; +} + +void VerifyMessageDialog::on_buttonBox_clicked(QAbstractButton *button) +{ + if(ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) + checkAddress(); +} + +void VerifyMessageDialog::on_copyToClipboard_clicked() +{ + QApplication::clipboard()->setText(ui->lnAddress->text()); +} diff --git a/src/qt/verifymessagedialog.h b/src/qt/verifymessagedialog.h new file mode 100644 index 0000000000..6a641f7731 --- /dev/null +++ b/src/qt/verifymessagedialog.h @@ -0,0 +1,36 @@ +#ifndef VERIFYMESSAGEDIALOG_H +#define VERIFYMESSAGEDIALOG_H + +#include + +class AddressTableModel; + +QT_BEGIN_NAMESPACE +class QAbstractButton; +QT_END_NAMESPACE + +namespace Ui { + class VerifyMessageDialog; +} + +class VerifyMessageDialog : public QDialog +{ + Q_OBJECT + +public: + explicit VerifyMessageDialog(AddressTableModel *addressModel, QWidget *parent = 0); + ~VerifyMessageDialog(); + +private slots: + void on_buttonBox_clicked(QAbstractButton *button); + + void on_copyToClipboard_clicked(); + +private: + bool checkAddress(); + + Ui::VerifyMessageDialog *ui; + AddressTableModel *model; +}; + +#endif // VERIFYMESSAGEDIALOG_H