# HG changeset patch # User sje397 # Date 1330343704 -39600 # Node ID bb8cc367bd00cea751938dbcc76c10a5ed8995b9 # Parent 4cc81040de044c9c57aa4fb46825405235f1a4fa Add a menu option to verify a signed message (Also move 'setAttribute(Qt::WA_DeleteOnClose)' out of QRCodeDialog) diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -159,7 +159,8 @@ 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 @@ 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 @@ 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 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -324,6 +324,7 @@ 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 --- 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 @@ 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 @@ 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 @@ #ifndef FIRST_CLASS_MESSAGING file->addAction(messageAction); #endif + file->addAction(verifyMessageAction); file->addSeparator(); file->addAction(quitAction); @@ -405,6 +410,7 @@ trayIconMenu->addAction(openRPCConsoleAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(messageAction); + trayIconMenu->addAction(verifyMessageAction); #ifndef FIRST_CLASS_MESSAGING trayIconMenu->addSeparator(); #endif @@ -836,6 +842,13 @@ 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 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -79,6 +79,7 @@ QAction *sendCoinsAction; QAction *addressBookAction; QAction *messageAction; + QAction *verifyMessageAction; QAction *aboutAction; QAction *receiveCoinsAction; QAction *optionsAction; @@ -163,6 +164,8 @@ 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 --- /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 --- a/src/qt/qrcodedialog.cpp +++ b/src/qt/qrcodedialog.cpp @@ -15,7 +15,6 @@ { 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 --- /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 --- /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