Bitcoin Core 29.99.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
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
24SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
25 QDialog(parent, GUIUtil::dialog_flags),
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
66void SignVerifyMessageDialog::setAddress_SM(const QString &address)
67{
68 ui->addressIn_SM->setText(address);
69 ui->messageIn_SM->setFocus();
70}
71
72void 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) {
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{
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
207 if (result == MessageVerificationResult::OK) {
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
261bool 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, PayToAnchor, WitnessUnknown > CTxDestination
A txout script categorized into standard templates.
Definition: addresstype.h:143
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:49
void refresh(bool pk_hash_only=false)
AddressTableModel * getAddressTableModel() const
interfaces::Wallet & wallet() const
Definition: walletmodel.h:139
UnlockContext requestUnlock()
virtual SigningResult signMessage(const std::string &message, const PKHash &pkhash, std::string &str_sig)=0
Sign message.
MessageVerificationResult MessageVerify(const std::string &address, const std::string &signature, const std::string &message)
Verify a signed message.
Definition: signmessage.cpp:26
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:299
Utility functions used by the Bitcoin Qt UI.
Definition: bitcoingui.h:58
QFont fixedPitchFont(bool use_embedded_font)
Definition: guiutil.cpp:100
void handleCloseWindowShortcut(QWidget *w)
Definition: guiutil.cpp:431
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:668
SigningResult
Definition: signmessage.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.