Bitcoin Core  27.99.0
P2P Digital Currency
signverifymessagedialog.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2022 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  platformStyle(_platformStyle)
25 {
26  ui->setupUi(this);
27 
28  ui->addressBookButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
29  ui->pasteButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editpaste"));
30  ui->copySignatureButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editcopy"));
31  ui->signMessageButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/edit"));
32  ui->clearButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
33  ui->addressBookButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
34  ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
35  ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
36 
37  GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
38  GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
39 
40  ui->addressIn_SM->installEventFilter(this);
41  ui->messageIn_SM->installEventFilter(this);
42  ui->signatureOut_SM->installEventFilter(this);
43  ui->addressIn_VM->installEventFilter(this);
44  ui->messageIn_VM->installEventFilter(this);
45  ui->signatureIn_VM->installEventFilter(this);
46 
47  ui->signatureOut_SM->setFont(GUIUtil::fixedPitchFont());
48  ui->signatureIn_VM->setFont(GUIUtil::fixedPitchFont());
49 
51 }
52 
54 {
55  delete ui;
56 }
57 
59 {
60  this->model = _model;
61 }
62 
63 void SignVerifyMessageDialog::setAddress_SM(const QString &address)
64 {
65  ui->addressIn_SM->setText(address);
66  ui->messageIn_SM->setFocus();
67 }
68 
69 void SignVerifyMessageDialog::setAddress_VM(const QString &address)
70 {
71  ui->addressIn_VM->setText(address);
72  ui->messageIn_VM->setFocus();
73 }
74 
76 {
77  ui->tabWidget->setCurrentIndex(0);
78  if (fShow)
79  this->show();
80 }
81 
83 {
84  ui->tabWidget->setCurrentIndex(1);
85  if (fShow)
86  this->show();
87 }
88 
90 {
92  {
93  model->refresh(/*pk_hash_only=*/true);
96  if (dlg.exec())
97  {
99  }
100  }
101 }
102 
104 {
105  setAddress_SM(QApplication::clipboard()->text());
106 }
107 
109 {
110  if (!model)
111  return;
112 
113  /* Clear old signature to ensure users don't get confused on error with an old signature displayed */
114  ui->signatureOut_SM->clear();
115 
116  CTxDestination destination = DecodeDestination(ui->addressIn_SM->text().toStdString());
117  if (!IsValidDestination(destination)) {
118  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
119  ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
120  return;
121  }
122  const PKHash* pkhash = std::get_if<PKHash>(&destination);
123  if (!pkhash) {
124  ui->addressIn_SM->setValid(false);
125  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
126  ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
127  return;
128  }
129 
131  if (!ctx.isValid())
132  {
133  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
134  ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled."));
135  return;
136  }
137 
138  const std::string& message = ui->messageIn_SM->document()->toPlainText().toStdString();
139  std::string signature;
140  SigningResult res = model->wallet().signMessage(message, *pkhash, signature);
141 
142  QString error;
143  switch (res) {
144  case SigningResult::OK:
145  error = tr("No error");
146  break;
148  error = tr("Private key for the entered address is not available.");
149  break;
151  error = tr("Message signing failed.");
152  break;
153  // no default case, so the compiler can warn about missing cases
154  }
155 
156  if (res != SigningResult::OK) {
157  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
158  ui->statusLabel_SM->setText(QString("<nobr>") + error + QString("</nobr>"));
159  return;
160  }
161 
162  ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
163  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
164 
165  ui->signatureOut_SM->setText(QString::fromStdString(signature));
166 }
167 
169 {
170  GUIUtil::setClipboard(ui->signatureOut_SM->text());
171 }
172 
174 {
175  ui->addressIn_SM->clear();
176  ui->messageIn_SM->clear();
177  ui->signatureOut_SM->clear();
178  ui->statusLabel_SM->clear();
179 
180  ui->addressIn_SM->setFocus();
181 }
182 
184 {
185  if (model && model->getAddressTableModel())
186  {
189  if (dlg.exec())
190  {
192  }
193  }
194 }
195 
197 {
198  const std::string& address = ui->addressIn_VM->text().toStdString();
199  const std::string& signature = ui->signatureIn_VM->text().toStdString();
200  const std::string& message = ui->messageIn_VM->document()->toPlainText().toStdString();
201 
202  const auto result = MessageVerify(address, signature, message);
203 
204  if (result == MessageVerificationResult::OK) {
205  ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
206  } else {
207  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
208  }
209 
210  switch (result) {
212  ui->statusLabel_VM->setText(
213  QString("<nobr>") + tr("Message verified.") + QString("</nobr>")
214  );
215  return;
217  ui->statusLabel_VM->setText(
218  tr("The entered address is invalid.") + QString(" ") +
219  tr("Please check the address and try again.")
220  );
221  return;
223  ui->addressIn_VM->setValid(false);
224  ui->statusLabel_VM->setText(
225  tr("The entered address does not refer to a key.") + QString(" ") +
226  tr("Please check the address and try again.")
227  );
228  return;
230  ui->signatureIn_VM->setValid(false);
231  ui->statusLabel_VM->setText(
232  tr("The signature could not be decoded.") + QString(" ") +
233  tr("Please check the signature and try again.")
234  );
235  return;
237  ui->signatureIn_VM->setValid(false);
238  ui->statusLabel_VM->setText(
239  tr("The signature did not match the message digest.") + QString(" ") +
240  tr("Please check the signature and try again.")
241  );
242  return;
244  ui->statusLabel_VM->setText(
245  QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>")
246  );
247  return;
248  }
249 }
250 
252 {
253  ui->addressIn_VM->clear();
254  ui->signatureIn_VM->clear();
255  ui->messageIn_VM->clear();
256  ui->statusLabel_VM->clear();
257 
258  ui->addressIn_VM->setFocus();
259 }
260 
261 bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event)
262 {
263  if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn)
264  {
265  if (ui->tabWidget->currentIndex() == 0)
266  {
267  /* Clear status message on focus change */
268  ui->statusLabel_SM->clear();
269 
270  /* Select generated signature */
271  if (object == ui->signatureOut_SM)
272  {
273  ui->signatureOut_SM->selectAll();
274  return true;
275  }
276  }
277  else if (ui->tabWidget->currentIndex() == 1)
278  {
279  /* Clear status message on focus change */
280  ui->statusLabel_VM->clear();
281  }
282  }
283  return QDialog::eventFilter(object, event);
284 }
285 
287 {
288  if (e->type() == QEvent::PaletteChange) {
289  ui->addressBookButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/address-book")));
290  ui->pasteButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/editpaste")));
291  ui->copySignatureButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/editcopy")));
292  ui->signMessageButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/edit")));
293  ui->clearButton_SM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/remove")));
294  ui->addressBookButton_VM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/address-book")));
295  ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/transaction_0")));
296  ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/remove")));
297  }
298 
299  QDialog::changeEvent(e);
300 }
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:131
Widget that shows a list of sending or receiving addresses.
@ ForSelection
Open address book to pick address.
void setModel(AddressTableModel *model)
const QString & getReturnValue() const
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
bool eventFilter(QObject *object, QEvent *event) override
void setAddress_SM(const QString &address)
void changeEvent(QEvent *e) override
SignVerifyMessageDialog(const PlatformStyle *platformStyle, QWidget *parent)
const PlatformStyle * platformStyle
void setModel(WalletModel *model)
Ui::SignVerifyMessageDialog * ui
void setAddress_VM(const QString &address)
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:48
void refresh(bool pk_hash_only=false)
AddressTableModel * getAddressTableModel() const
interfaces::Wallet & wallet() const
Definition: walletmodel.h:138
UnlockContext requestUnlock()
virtual SigningResult signMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig)=0
Sign message.
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:292
SigningResult
Definition: message.h:43
@ PRIVATE_KEY_NOT_AVAILABLE
@ OK
No error.
@ ERR_MALFORMED_SIGNATURE
The provided signature couldn't be parsed (maybe invalid base64).
@ ERR_INVALID_ADDRESS
The provided address is invalid.
@ ERR_ADDRESS_NO_KEY
The provided address is valid but does not refer to a public key.
@ ERR_NOT_SIGNED
The message was not signed with the private key of the provided address.
@ OK
The message verification was successful.
@ ERR_PUBKEY_NOT_RECOVERED
A public key could not be recovered from the provided signature and message.
Utility functions used by the Bitcoin Qt UI.
Definition: bitcoingui.h:60
QFont fixedPitchFont(bool use_embedded_font)
Definition: guiutil.cpp:104
void handleCloseWindowShortcut(QWidget *w)
Definition: guiutil.cpp:427
constexpr auto dialog_flags
Definition: guiutil.h:60
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
Definition: guiutil.cpp:134
void setClipboard(const QString &str)
Definition: guiutil.cpp:664
MessageVerificationResult MessageVerify(const std::string &address, const std::string &signature, const std::string &message)
Verify a signed message.
Definition: message.cpp:26