Bitcoin Core  31.0.0
P2P Digital Currency
signverifymessagedialog.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-present 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 <common/signmessage.h>
14 #include <bitcoin-build-config.h> // IWYU pragma: keep
15 #include <key_io.h>
16 #include <wallet/wallet.h>
17 
18 #include <string>
19 #include <variant>
20 #include <vector>
21 
22 #include <QClipboard>
23 
24 SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
25  QDialog(parent, GUIUtil::dialog_flags),
26  ui(new Ui::SignVerifyMessageDialog),
27  platformStyle(_platformStyle)
28 {
29  ui->setupUi(this);
30 
31  ui->addressBookButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
32  ui->pasteButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editpaste"));
33  ui->copySignatureButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/editcopy"));
34  ui->signMessageButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/edit"));
35  ui->clearButton_SM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
36  ui->addressBookButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/address-book"));
37  ui->verifyMessageButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/transaction_0"));
38  ui->clearButton_VM->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
39 
40  GUIUtil::setupAddressWidget(ui->addressIn_SM, this);
41  GUIUtil::setupAddressWidget(ui->addressIn_VM, this);
42 
43  ui->addressIn_SM->installEventFilter(this);
44  ui->messageIn_SM->installEventFilter(this);
45  ui->signatureOut_SM->installEventFilter(this);
46  ui->addressIn_VM->installEventFilter(this);
47  ui->messageIn_VM->installEventFilter(this);
48  ui->signatureIn_VM->installEventFilter(this);
49 
50  ui->signatureOut_SM->setFont(GUIUtil::fixedPitchFont());
51  ui->signatureIn_VM->setFont(GUIUtil::fixedPitchFont());
52 
54 }
55 
57 {
58  delete ui;
59 }
60 
62 {
63  this->model = _model;
64 }
65 
66 void SignVerifyMessageDialog::setAddress_SM(const QString &address)
67 {
68  ui->addressIn_SM->setText(address);
69  ui->messageIn_SM->setFocus();
70 }
71 
72 void SignVerifyMessageDialog::setAddress_VM(const QString &address)
73 {
74  ui->addressIn_VM->setText(address);
75  ui->messageIn_VM->setFocus();
76 }
77 
79 {
80  ui->tabWidget->setCurrentIndex(0);
81  if (fShow)
82  this->show();
83 }
84 
86 {
87  ui->tabWidget->setCurrentIndex(1);
88  if (fShow)
89  this->show();
90 }
91 
93 {
95  {
96  model->refresh(/*pk_hash_only=*/true);
99  if (dlg.exec())
100  {
102  }
103  }
104 }
105 
107 {
108  setAddress_SM(QApplication::clipboard()->text());
109 }
110 
112 {
113  if (!model)
114  return;
115 
116  /* Clear old signature to ensure users don't get confused on error with an old signature displayed */
117  ui->signatureOut_SM->clear();
118 
119  CTxDestination destination = DecodeDestination(ui->addressIn_SM->text().toStdString());
120  if (!IsValidDestination(destination)) {
121  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
122  ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
123  return;
124  }
125  const PKHash* pkhash = std::get_if<PKHash>(&destination);
126  if (!pkhash) {
127  ui->addressIn_SM->setValid(false);
128  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
129  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));
130  return;
131  }
132 
134  if (!ctx.isValid())
135  {
136  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
137  ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled."));
138  return;
139  }
140 
141  const std::string& message = ui->messageIn_SM->document()->toPlainText().toStdString();
142  std::string signature;
143  SigningResult res = model->wallet().signMessage(message, *pkhash, signature);
144 
145  QString error;
146  switch (res) {
147  case SigningResult::OK:
148  error = tr("No error");
149  break;
151  error = tr("Private key for the entered address is not available.");
152  break;
154  error = tr("Message signing failed.");
155  break;
156  // no default case, so the compiler can warn about missing cases
157  }
158 
159  if (res != SigningResult::OK) {
160  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
161  ui->statusLabel_SM->setText(QString("<nobr>") + error + QString("</nobr>"));
162  return;
163  }
164 
165  ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
166  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
167 
168  ui->signatureOut_SM->setText(QString::fromStdString(signature));
169 }
170 
172 {
173  GUIUtil::setClipboard(ui->signatureOut_SM->text());
174 }
175 
177 {
178  ui->addressIn_SM->clear();
179  ui->messageIn_SM->clear();
180  ui->signatureOut_SM->clear();
181  ui->statusLabel_SM->clear();
182 
183  ui->addressIn_SM->setFocus();
184 }
185 
187 {
188  if (model && model->getAddressTableModel())
189  {
192  if (dlg.exec())
193  {
195  }
196  }
197 }
198 
200 {
201  const std::string& address = ui->addressIn_VM->text().toStdString();
202  const std::string& signature = ui->signatureIn_VM->text().toStdString();
203  const std::string& message = ui->messageIn_VM->document()->toPlainText().toStdString();
204 
205  const auto result = MessageVerify(address, signature, message);
206 
208  ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
209  } else {
210  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
211  }
212 
213  switch (result) {
215  ui->statusLabel_VM->setText(
216  QString("<nobr>") + tr("Message verified.") + QString("</nobr>")
217  );
218  return;
220  ui->statusLabel_VM->setText(
221  tr("The entered address is invalid.") + QString(" ") +
222  tr("Please check the address and try again.")
223  );
224  return;
226  ui->addressIn_VM->setValid(false);
227  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));
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 }
interfaces::Wallet & wallet() const
Definition: walletmodel.h:138
Utility functions used by the Bitcoin Qt UI.
Definition: bitcoingui.h:58
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination corresponds to one with an address.
A public key could not be recovered from the provided signature and message.
The message verification was successful.
void setAddress_VM(const QString &address)
The provided address is invalid.
void setModel(AddressTableModel *model)
UnlockContext requestUnlock()
The provided signature couldn&#39;t be parsed (maybe invalid base64).
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
SigningResult
Definition: signmessage.h:43
QFont fixedPitchFont(bool use_embedded_font)
Definition: guiutil.cpp:100
MessageVerificationResult MessageVerify(const std::string &address, const std::string &signature, const std::string &message)
Verify a signed message.
Definition: signmessage.cpp:26
Open address book to pick address.
virtual SigningResult signMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig)=0
Sign message.
void changeEvent(QEvent *e) override
Ui::SignVerifyMessageDialog * ui
constexpr auto dialog_flags
Definition: guiutil.h:60
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
Definition: guiutil.cpp:131
void setClipboard(const QString &str)
Definition: guiutil.cpp:661
void handleCloseWindowShortcut(QWidget *w)
Definition: guiutil.cpp:424
void refresh(bool pk_hash_only=false)
Widget that shows a list of sending or receiving addresses.
SignVerifyMessageDialog(const PlatformStyle *platformStyle, QWidget *parent)
auto result
Definition: common-types.h:74
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:48
std::variant< CNoDestination, PubKeyDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:143
bool eventFilter(QObject *object, QEvent *event) override
The message was not signed with the private key of the provided address.
The provided address is valid but does not refer to a public key.
AddressTableModel * getAddressTableModel() const
const PlatformStyle * platformStyle
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:299
void setModel(WalletModel *model)
const QString & getReturnValue() const
void setAddress_SM(const QString &address)