Bitcoin Core  22.99.0
P2P Digital Currency
signverifymessagedialog.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
6 #include <qt/forms/ui_signverifymessagedialog.h>
7 
8 #include <qt/addressbookpage.h>
9 #include <qt/guiutil.h>
10 #include <qt/platformstyle.h>
11 #include <qt/walletmodel.h>
12 
13 #include <key_io.h>
14 #include <util/message.h> // For MessageSign(), MessageVerify()
15 #include <wallet/wallet.h>
16 
17 #include <vector>
18 
19 #include <QClipboard>
20 
21 SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
22  QDialog(parent, GUIUtil::dialog_flags),
23  ui(new Ui::SignVerifyMessageDialog),
24  model(nullptr),
25  platformStyle(_platformStyle)
26 {
27  ui->setupUi(this);
28 
29  ui->addressBookButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
30  ui->pasteButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editpaste"));
31  ui->copySignatureButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editcopy"));
32  ui->signMessageButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/edit"));
33  ui->clearButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
34  ui->addressBookButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
35  ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
36  ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
37 
38  GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
39  GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
40 
41  ui->addressIn_SM->installEventFilter(this);
42  ui->messageIn_SM->installEventFilter(this);
43  ui->signatureOut_SM->installEventFilter(this);
44  ui->addressIn_VM->installEventFilter(this);
45  ui->messageIn_VM->installEventFilter(this);
46  ui->signatureIn_VM->installEventFilter(this);
47 
48  ui->signatureOut_SM->setFont(GUIUtil::fixedPitchFont());
49  ui->signatureIn_VM->setFont(GUIUtil::fixedPitchFont());
50 
52 }
53 
55 {
56  delete ui;
57 }
58 
60 {
61  this->model = _model;
62 }
63 
64 void SignVerifyMessageDialog::setAddress_SM(const QString &address)
65 {
66  ui->addressIn_SM->setText(address);
67  ui->messageIn_SM->setFocus();
68 }
69 
70 void SignVerifyMessageDialog::setAddress_VM(const QString &address)
71 {
72  ui->addressIn_VM->setText(address);
73  ui->messageIn_VM->setFocus();
74 }
75 
77 {
78  ui->tabWidget->setCurrentIndex(0);
79  if (fShow)
80  this->show();
81 }
82 
84 {
85  ui->tabWidget->setCurrentIndex(1);
86  if (fShow)
87  this->show();
88 }
89 
91 {
93  {
94  model->refresh(/* pk_hash_only */ true);
97  if (dlg.exec())
98  {
100  }
101  }
102 }
103 
105 {
106  setAddress_SM(QApplication::clipboard()->text());
107 }
108 
110 {
111  if (!model)
112  return;
113 
114  /* Clear old signature to ensure users don't get confused on error with an old signature displayed */
115  ui->signatureOut_SM->clear();
116 
117  CTxDestination destination = DecodeDestination(ui->addressIn_SM->text().toStdString());
118  if (!IsValidDestination(destination)) {
119  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
120  ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
121  return;
122  }
123  const PKHash* pkhash = std::get_if<PKHash>(&destination);
124  if (!pkhash) {
125  ui->addressIn_SM->setValid(false);
126  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
127  ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
128  return;
129  }
130 
132  if (!ctx.isValid())
133  {
134  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
135  ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled."));
136  return;
137  }
138 
139  const std::string& message = ui->messageIn_SM->document()->toPlainText().toStdString();
140  std::string signature;
141  SigningResult res = model->wallet().signMessage(message, *pkhash, signature);
142 
143  QString error;
144  switch (res) {
145  case SigningResult::OK:
146  error = tr("No error");
147  break;
149  error = tr("Private key for the entered address is not available.");
150  break;
152  error = tr("Message signing failed.");
153  break;
154  // no default case, so the compiler can warn about missing cases
155  }
156 
157  if (res != SigningResult::OK) {
158  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
159  ui->statusLabel_SM->setText(QString("<nobr>") + error + QString("</nobr>"));
160  return;
161  }
162 
163  ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
164  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
165 
166  ui->signatureOut_SM->setText(QString::fromStdString(signature));
167 }
168 
170 {
171  GUIUtil::setClipboard(ui->signatureOut_SM->text());
172 }
173 
175 {
176  ui->addressIn_SM->clear();
177  ui->messageIn_SM->clear();
178  ui->signatureOut_SM->clear();
179  ui->statusLabel_SM->clear();
180 
181  ui->addressIn_SM->setFocus();
182 }
183 
185 {
186  if (model && model->getAddressTableModel())
187  {
190  if (dlg.exec())
191  {
193  }
194  }
195 }
196 
198 {
199  const std::string& address = ui->addressIn_VM->text().toStdString();
200  const std::string& signature = ui->signatureIn_VM->text().toStdString();
201  const std::string& message = ui->messageIn_VM->document()->toPlainText().toStdString();
202 
203  const auto result = MessageVerify(address, signature, message);
204 
205  if (result == MessageVerificationResult::OK) {
206  ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
207  } else {
208  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
209  }
210 
211  switch (result) {
213  ui->statusLabel_VM->setText(
214  QString("<nobr>") + tr("Message verified.") + QString("</nobr>")
215  );
216  return;
218  ui->statusLabel_VM->setText(
219  tr("The entered address is invalid.") + QString(" ") +
220  tr("Please check the address and try again.")
221  );
222  return;
224  ui->addressIn_VM->setValid(false);
225  ui->statusLabel_VM->setText(
226  tr("The entered address does not refer to a key.") + QString(" ") +
227  tr("Please check the address and try again.")
228  );
229  return;
231  ui->signatureIn_VM->setValid(false);
232  ui->statusLabel_VM->setText(
233  tr("The signature could not be decoded.") + QString(" ") +
234  tr("Please check the signature and try again.")
235  );
236  return;
238  ui->signatureIn_VM->setValid(false);
239  ui->statusLabel_VM->setText(
240  tr("The signature did not match the message digest.") + QString(" ") +
241  tr("Please check the signature and try again.")
242  );
243  return;
245  ui->statusLabel_VM->setText(
246  QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>")
247  );
248  return;
249  }
250 }
251 
253 {
254  ui->addressIn_VM->clear();
255  ui->signatureIn_VM->clear();
256  ui->messageIn_VM->clear();
257  ui->statusLabel_VM->clear();
258 
259  ui->addressIn_VM->setFocus();
260 }
261 
262 bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event)
263 {
264  if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn)
265  {
266  if (ui->tabWidget->currentIndex() == 0)
267  {
268  /* Clear status message on focus change */
269  ui->statusLabel_SM->clear();
270 
271  /* Select generated signature */
272  if (object == ui->signatureOut_SM)
273  {
274  ui->signatureOut_SM->selectAll();
275  return true;
276  }
277  }
278  else if (ui->tabWidget->currentIndex() == 1)
279  {
280  /* Clear status message on focus change */
281  ui->statusLabel_VM->clear();
282  }
283  }
284  return QDialog::eventFilter(object, event);
285 }
286 
288 {
289  if (e->type() == QEvent::PaletteChange) {
290  ui->addressBookButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/address-book")));
291  ui->pasteButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/editpaste")));
292  ui->copySignatureButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/editcopy")));
293  ui->signMessageButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/edit")));
294  ui->clearButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/remove")));
295  ui->addressBookButton_VM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/address-book")));
296  ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/transaction_0")));
297  ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/remove")));
298  }
299 
300  QDialog::changeEvent(e);
301 }
signverifymessagedialog.h
WalletModel::refresh
void refresh(bool pk_hash_only=false)
Definition: walletmodel.cpp:588
AddressBookPage::setModel
void setModel(AddressTableModel *model)
Definition: addressbookpage.cpp:136
AddressBookPage::SendingTab
@ SendingTab
Definition: addressbookpage.h:32
MessageVerificationResult::ERR_MALFORMED_SIGNATURE
@ ERR_MALFORMED_SIGNATURE
The provided signature couldn't be parsed (maybe invalid base64).
SigningResult::OK
@ OK
No error.
SignVerifyMessageDialog::on_signMessageButton_SM_clicked
void on_signMessageButton_SM_clicked()
Definition: signverifymessagedialog.cpp:109
wallet.h
WalletModel
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:51
SignVerifyMessageDialog::setAddress_VM
void setAddress_VM(const QString &address)
Definition: signverifymessagedialog.cpp:70
key_io.h
PlatformStyle::SingleColorIcon
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
Definition: platformstyle.cpp:105
addressbookpage.h
SignVerifyMessageDialog::showTab_VM
void showTab_VM(bool fShow)
Definition: signverifymessagedialog.cpp:83
walletmodel.h
WalletModel::getAddressTableModel
AddressTableModel * getAddressTableModel()
Definition: walletmodel.cpp:289
interfaces::Wallet::signMessage
virtual SigningResult signMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig)=0
Sign message.
GUIUtil
Utility functions used by the Bitcoin Qt UI.
Definition: bitcoingui.h:59
MessageVerify
MessageVerificationResult MessageVerify(const std::string &address, const std::string &signature, const std::string &message)
Verify a signed message.
Definition: message.cpp:24
MessageVerificationResult::ERR_NOT_SIGNED
@ ERR_NOT_SIGNED
The message was not signed with the private key of the provided address.
SignVerifyMessageDialog::setModel
void setModel(WalletModel *model)
Definition: signverifymessagedialog.cpp:59
WalletModel::requestUnlock
UnlockContext requestUnlock()
Definition: walletmodel.cpp:433
GUIUtil::dialog_flags
constexpr auto dialog_flags
Definition: guiutil.h:59
SignVerifyMessageDialog
Definition: signverifymessagedialog.h:17
SigningResult
SigningResult
Definition: message.h:42
GUIUtil::setClipboard
void setClipboard(const QString &str)
Definition: guiutil.cpp:638
WalletModel::wallet
interfaces::Wallet & wallet() const
Definition: walletmodel.h:144
SignVerifyMessageDialog::model
WalletModel * model
Definition: signverifymessagedialog.h:38
CTxDestination
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:157
IsValidDestination
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:373
SignVerifyMessageDialog::on_addressBookButton_VM_clicked
void on_addressBookButton_VM_clicked()
Definition: signverifymessagedialog.cpp:184
SignVerifyMessageDialog::changeEvent
void changeEvent(QEvent *e) override
Definition: signverifymessagedialog.cpp:287
message.h
SignVerifyMessageDialog::ui
Ui::SignVerifyMessageDialog * ui
Definition: signverifymessagedialog.h:37
SigningResult::PRIVATE_KEY_NOT_AVAILABLE
@ PRIVATE_KEY_NOT_AVAILABLE
MessageVerificationResult::ERR_INVALID_ADDRESS
@ ERR_INVALID_ADDRESS
The provided address is invalid.
AddressBookPage
Widget that shows a list of sending or receiving addresses.
Definition: addressbookpage.h:26
guiutil.h
SignVerifyMessageDialog::platformStyle
const PlatformStyle * platformStyle
Definition: signverifymessagedialog.h:39
DecodeDestination
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
Definition: key_io.cpp:261
MessageVerificationResult::ERR_PUBKEY_NOT_RECOVERED
@ ERR_PUBKEY_NOT_RECOVERED
A public key could not be recovered from the provided signature and message.
SignVerifyMessageDialog::~SignVerifyMessageDialog
~SignVerifyMessageDialog()
Definition: signverifymessagedialog.cpp:54
SignVerifyMessageDialog::on_copySignatureButton_SM_clicked
void on_copySignatureButton_SM_clicked()
Definition: signverifymessagedialog.cpp:169
GUIUtil::fixedPitchFont
QFont fixedPitchFont(bool use_embedded_font)
Definition: guiutil.cpp:87
SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked
void on_verifyMessageButton_VM_clicked()
Definition: signverifymessagedialog.cpp:197
MessageVerificationResult::ERR_ADDRESS_NO_KEY
@ ERR_ADDRESS_NO_KEY
The provided address is valid but does not refer to a public key.
SignVerifyMessageDialog::setAddress_SM
void setAddress_SM(const QString &address)
Definition: signverifymessagedialog.cpp:64
SignVerifyMessageDialog::eventFilter
bool eventFilter(QObject *object, QEvent *event) override
Definition: signverifymessagedialog.cpp:262
platformstyle.h
PKHash
Definition: standard.h:79
Ui
Definition: addressbookpage.h:14
SignVerifyMessageDialog::on_pasteButton_SM_clicked
void on_pasteButton_SM_clicked()
Definition: signverifymessagedialog.cpp:104
WalletModel::UnlockContext
Definition: walletmodel.h:114
SignVerifyMessageDialog::SignVerifyMessageDialog
SignVerifyMessageDialog(const PlatformStyle *platformStyle, QWidget *parent)
Definition: signverifymessagedialog.cpp:21
SignVerifyMessageDialog::on_addressBookButton_SM_clicked
void on_addressBookButton_SM_clicked()
Definition: signverifymessagedialog.cpp:90
SigningResult::SIGNING_FAILED
@ SIGNING_FAILED
MessageVerificationResult::OK
@ OK
The message verification was successful.
SignVerifyMessageDialog::on_clearButton_VM_clicked
void on_clearButton_VM_clicked()
Definition: signverifymessagedialog.cpp:252
AddressBookPage::getReturnValue
const QString & getReturnValue() const
Definition: addressbookpage.h:45
GUIUtil::handleCloseWindowShortcut
void handleCloseWindowShortcut(QWidget *w)
Definition: guiutil.cpp:402
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
PlatformStyle
Definition: platformstyle.h:13
GUIUtil::setupAddressWidget
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
Definition: guiutil.cpp:113
SignVerifyMessageDialog::showTab_SM
void showTab_SM(bool fShow)
Definition: signverifymessagedialog.cpp:76
SignVerifyMessageDialog::on_clearButton_SM_clicked
void on_clearButton_SM_clicked()
Definition: signverifymessagedialog.cpp:174
ctx
static secp256k1_context * ctx
Definition: tests.c:42
AddressBookPage::ForSelection
@ ForSelection
Open address book to pick address.
Definition: addressbookpage.h:37
AddressBookPage::ReceivingTab
@ ReceivingTab
Definition: addressbookpage.h:33