Bitcoin Core  0.19.99
P2P Digital Currency
signverifymessagedialog.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2019 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),
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 }
51 
53 {
54  delete ui;
55 }
56 
58 {
59  this->model = _model;
60 }
61 
62 void SignVerifyMessageDialog::setAddress_SM(const QString &address)
63 {
64  ui->addressIn_SM->setText(address);
65  ui->messageIn_SM->setFocus();
66 }
67 
68 void SignVerifyMessageDialog::setAddress_VM(const QString &address)
69 {
70  ui->addressIn_VM->setText(address);
71  ui->messageIn_VM->setFocus();
72 }
73 
75 {
76  ui->tabWidget->setCurrentIndex(0);
77  if (fShow)
78  this->show();
79 }
80 
82 {
83  ui->tabWidget->setCurrentIndex(1);
84  if (fShow)
85  this->show();
86 }
87 
89 {
91  {
94  if (dlg.exec())
95  {
97  }
98  }
99 }
100 
102 {
103  setAddress_SM(QApplication::clipboard()->text());
104 }
105 
107 {
108  if (!model)
109  return;
110 
111  /* Clear old signature to ensure users don't get confused on error with an old signature displayed */
112  ui->signatureOut_SM->clear();
113 
114  CTxDestination destination = DecodeDestination(ui->addressIn_SM->text().toStdString());
115  if (!IsValidDestination(destination)) {
116  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
117  ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
118  return;
119  }
120  const PKHash* pkhash = boost::get<PKHash>(&destination);
121  if (!pkhash) {
122  ui->addressIn_SM->setValid(false);
123  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
124  ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
125  return;
126  }
127 
129  if (!ctx.isValid())
130  {
131  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
132  ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled."));
133  return;
134  }
135 
136  const std::string& message = ui->messageIn_SM->document()->toPlainText().toStdString();
137  std::string signature;
138  SigningResult res = model->wallet().signMessage(message, *pkhash, signature);
139 
140  QString error;
141  switch (res) {
142  case SigningResult::OK:
143  error = tr("No error");
144  break;
146  error = tr("Private key for the entered address is not available.");
147  break;
149  error = tr("Message signing failed.");
150  break;
151  // no default case, so the compiler can warn about missing cases
152  }
153 
154  if (res != SigningResult::OK) {
155  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
156  ui->statusLabel_SM->setText(QString("<nobr>") + error + QString("</nobr>"));
157  return;
158  }
159 
160  ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
161  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
162 
163  ui->signatureOut_SM->setText(QString::fromStdString(signature));
164 }
165 
167 {
168  GUIUtil::setClipboard(ui->signatureOut_SM->text());
169 }
170 
172 {
173  ui->addressIn_SM->clear();
174  ui->messageIn_SM->clear();
175  ui->signatureOut_SM->clear();
176  ui->statusLabel_SM->clear();
177 
178  ui->addressIn_SM->setFocus();
179 }
180 
182 {
183  if (model && model->getAddressTableModel())
184  {
187  if (dlg.exec())
188  {
190  }
191  }
192 }
193 
195 {
196  const std::string& address = ui->addressIn_VM->text().toStdString();
197  const std::string& signature = ui->signatureIn_VM->text().toStdString();
198  const std::string& message = ui->messageIn_VM->document()->toPlainText().toStdString();
199 
200  const auto result = MessageVerify(address, signature, message);
201 
202  if (result == MessageVerificationResult::OK) {
203  ui->statusLabel_VM->setStyleSheet("QLabel { color: green; }");
204  } else {
205  ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }");
206  }
207 
208  switch (result) {
210  ui->statusLabel_VM->setText(
211  QString("<nobr>") + tr("Message verified.") + QString("</nobr>")
212  );
213  return;
215  ui->statusLabel_VM->setText(
216  tr("The entered address is invalid.") + QString(" ") +
217  tr("Please check the address and try again.")
218  );
219  return;
221  ui->addressIn_VM->setValid(false);
222  ui->statusLabel_VM->setText(
223  tr("The entered address does not refer to a key.") + QString(" ") +
224  tr("Please check the address and try again.")
225  );
226  return;
228  ui->signatureIn_VM->setValid(false);
229  ui->statusLabel_VM->setText(
230  tr("The signature could not be decoded.") + QString(" ") +
231  tr("Please check the signature and try again.")
232  );
233  return;
235  ui->signatureIn_VM->setValid(false);
236  ui->statusLabel_VM->setText(
237  tr("The signature did not match the message digest.") + QString(" ") +
238  tr("Please check the signature and try again.")
239  );
240  return;
242  ui->statusLabel_VM->setText(
243  QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>")
244  );
245  return;
246  }
247 }
248 
250 {
251  ui->addressIn_VM->clear();
252  ui->signatureIn_VM->clear();
253  ui->messageIn_VM->clear();
254  ui->statusLabel_VM->clear();
255 
256  ui->addressIn_VM->setFocus();
257 }
258 
259 bool SignVerifyMessageDialog::eventFilter(QObject *object, QEvent *event)
260 {
261  if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::FocusIn)
262  {
263  if (ui->tabWidget->currentIndex() == 0)
264  {
265  /* Clear status message on focus change */
266  ui->statusLabel_SM->clear();
267 
268  /* Select generated signature */
269  if (object == ui->signatureOut_SM)
270  {
271  ui->signatureOut_SM->selectAll();
272  return true;
273  }
274  }
275  else if (ui->tabWidget->currentIndex() == 1)
276  {
277  /* Clear status message on focus change */
278  ui->statusLabel_VM->clear();
279  }
280  }
281  return QDialog::eventFilter(object, event);
282 }
bool eventFilter(QObject *object, QEvent *event)
interfaces::Wallet & wallet() const
Definition: walletmodel.h:145
QFont fixedPitchFont()
Definition: guiutil.cpp:81
The provided signature couldn&#39;t be parsed (maybe invalid base64).
void setAddress_VM(const QString &address)
void setModel(AddressTableModel *model)
UnlockContext requestUnlock()
SigningResult
Definition: message.h:42
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:325
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
The message verification was successful.
Open address book to pick address.
virtual SigningResult signMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig)=0
Sign message.
AddressTableModel * getAddressTableModel()
Ui::SignVerifyMessageDialog * ui
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
Definition: guiutil.cpp:104
void setClipboard(const QString &str)
Definition: guiutil.cpp:704
static secp256k1_context * ctx
Definition: tests.c:46
Widget that shows a list of sending or receiving addresses.
SignVerifyMessageDialog(const PlatformStyle *platformStyle, QWidget *parent)
The message was not signed with the private key of the provided address.
CTxDestination DecodeDestination(const std::string &str)
Definition: key_io.cpp:215
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:50
The provided address is invalid.
MessageVerificationResult MessageVerify(const std::string &address, const std::string &signature, const std::string &message)
Verify a signed message.
Definition: message.cpp:24
const PlatformStyle * platformStyle
A public key could not be recovered from the provided signature and message.
boost::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:143
void setModel(WalletModel *model)
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
The provided address is valid but does not refer to a public key.
const QString & getReturnValue() const
void setAddress_SM(const QString &address)