PIVX Core  5.6.99
P2P Digital Currency
signmessagewidgets.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019-2022 The PIVX 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/settings/forms/ui_signmessagewidgets.h"
7 
8 #include "key_io.h"
9 #include "messagesigner.h"
10 #include "qt/askpassphrasedialog.h"
11 #include "qt/walletmodel.h"
12 #include "qtutils.h"
13 #include "util/validation.h"
14 
15 #include <string>
16 #include <vector>
17 
18 #include <QClipboard>
19 
21  PWidget(_window, parent),
23 {
24  ui->setupUi(this);
25 
26  this->setStyleSheet(parent->styleSheet());
27 
28  // Containers
29  ui->left->setProperty("cssClass", "container");
30  ui->left->setContentsMargins(10,10,10,10);
31 
32  // Title
33  ui->labelTitle->setProperty("cssClass", "text-title-screen");
34  ui->labelSubtitle1->setProperty("cssClass", "text-subtitle");
35 
36  // Address
37  ui->labelSubtitleAddress->setProperty("cssClass", "text-title");
38  ui->addressIn_SM->setProperty("cssClass", "edit-primary-multi-book");
39  ui->addressIn_SM->setAttribute(Qt::WA_MacShowFocusRect, 0);
40  setShadow(ui->addressIn_SM);
41 
42  /* Button Group */
43  setCssProperty(ui->pushSign, "btn-check-right");
44  setCssProperty(ui->pushVerify, "btn-check-right");
45  ui->labelSubtitleSwitch->setText(tr("Select mode"));
46  setCssProperty(ui->labelSubtitleSwitch, "text-subtitle");
47  ui->pushSign->setChecked(true);
48  updateMode();
49 
50  // Message
51  ui->labelSubtitleMessage->setProperty("cssClass", "text-title");
52  ui->messageIn_SM->setProperty("cssClass","edit-primary");
53  setShadow(ui->messageIn_SM);
54  ui->messageIn_SM->setAttribute(Qt::WA_MacShowFocusRect, 0);
55 
56  // Signature
57  ui->labelSubtitleSignature->setProperty("cssClass", "text-title");
58  ui->signatureOut_SM->setAttribute(Qt::WA_MacShowFocusRect, 0);
59 
60  initCssEditLine(ui->signatureOut_SM);
61  setShadow(ui->signatureOut_SM);
62 
63  // Buttons
64  btnContact = ui->addressIn_SM->addAction(QIcon("://ic-contact-arrow-down"), QLineEdit::TrailingPosition);
65 
66  setCssBtnPrimary(ui->pushButtonSave);
67  setCssBtnSecondary(ui->pushButtonClear);
68 
69  ui->statusLabel_SM->setStyleSheet("QLabel { color: transparent; }");
70 
71  connect(ui->pushButtonSave, &QPushButton::clicked, this, &SettingsSignMessageWidgets::onGoClicked);
72  connect(btnContact, &QAction::triggered, this, &SettingsSignMessageWidgets::onAddressesClicked);
73  connect(ui->pushButtonClear, &QPushButton::clicked, this, &SettingsSignMessageWidgets::onClearAll);
74  connect(ui->pushSign, &QPushButton::clicked, [this](){onModeSelected(true);});
75  connect(ui->pushVerify, &QPushButton::clicked, [this](){onModeSelected(false);});
76 }
77 
79 {
80  delete ui;
81 }
82 
84 {
85  if (ui->addressIn_SM) ui->addressIn_SM->setFocus();
86 }
87 
89 {
90  this->isSign = isSign;
91  updateMode();
92 }
93 
95 {
96  if (isSign) {
98  } else {
100  }
101 }
102 
104 {
105  QString subtitle;
106  QString go;
107  if (isSign) {
108  subtitle = tr("You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.");
109  go = tr("SIGN");
110  ui->signatureOut_SM->setReadOnly(true);
111  ui->signatureOut_SM->clear();
112  } else {
113  subtitle = tr("Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack.");
114  go = tr("VERIFY");
115  ui->signatureOut_SM->setReadOnly(false);
116  }
117  ui->labelSubtitle1->setText(subtitle);
118  ui->pushButtonSave->setText(go);
119 }
120 
121 void SettingsSignMessageWidgets::setAddress_SM(const QString& address)
122 {
123  ui->addressIn_SM->setText(address);
124  ui->messageIn_SM->setFocus();
125 }
126 
128 {
129  ui->addressIn_SM->clear();
130  ui->signatureOut_SM->clear();
131  ui->messageIn_SM->clear();
132  ui->statusLabel_SM->setStyleSheet("QLabel { color: transparent; }");
133 }
134 
136 {
137  if (!walletModel)
138  return;
139 
140  /* Clear old signature to ensure users don't get confused on error with an old signature displayed */
141  ui->signatureOut_SM->clear();
142 
143  CTxDestination addr = DecodeDestination(ui->addressIn_SM->text().toStdString());
144  if (!IsValidDestination(addr)) {
145  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
146  ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
147  return;
148  }
149  const CKeyID* keyID = boost::get<CKeyID>(&addr);
150  if (!keyID) {
151  // TODO: change css..
152  //ui->addressIn_SM->setValid(false);
153  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
154  ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
155  return;
156  }
157 
159  if (!ctx.isValid()) {
160  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
161  ui->statusLabel_SM->setText(tr("Wallet unlock was cancelled."));
162  return;
163  }
164 
165  CKey key;
166  if (!walletModel->getKey(*keyID, key)) {
167  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
168  ui->statusLabel_SM->setText(tr("Private key for the entered address is not available."));
169  return;
170  }
171 
172  const std::string& message = ui->messageIn_SM->document()->toPlainText().toStdString();
173 
174  std::vector<unsigned char> vchSig;
175  if (!CMessageSigner::SignMessage(message, vchSig, key)) {
176  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
177  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signing failed.") + QString("</nobr>"));
178  return;
179  }
180 
181  ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
182  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message signed.") + QString("</nobr>"));
183  ui->signatureOut_SM->setText(QString::fromStdString(EncodeBase64(vchSig)));
184 }
185 
187 {
195  CTxDestination addr = DecodeDestination(ui->addressIn_SM->text().toStdString());
196  if (!IsValidDestination(addr)) {
197  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
198  ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
199  return;
200  }
201  const CKeyID* keyID = boost::get<CKeyID>(&addr);
202  if (!keyID) {
203  //ui->addressIn_SM->setValid(false);
204  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
205  ui->statusLabel_SM->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
206  return;
207  }
208 
209  bool fInvalid = false;
210  std::vector<unsigned char> vchSig = DecodeBase64(ui->signatureOut_SM->text().toStdString().c_str(), &fInvalid);
211 
212  if (fInvalid) {
213  //ui->signatureOut_SM->setValid(false);
214  ui->signatureOut_SM->setStyleSheet("QLabel { color: red; }");
215  ui->signatureOut_SM->setText(tr("The signature could not be decoded.") + QString(" ") + tr("Please check the signature and try again."));
216  return;
217  }
218 
219  const std::string& message = ui->messageIn_SM->document()->toPlainText().toStdString();
220 
221  std::string err_log;
222  if (!CMessageSigner::VerifyMessage(*keyID, vchSig, message, err_log)) {
223  ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }");
224  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message verification failed.") + QString("</nobr>"));
225  return;
226  }
227 
228  ui->statusLabel_SM->setStyleSheet("QLabel { color: green; }");
229  ui->statusLabel_SM->setText(QString("<nobr>") + tr("Message verified.") + QString("</nobr>"));
230 }
231 
233 {
234  int addressSize = walletModel->getAddressTableModel()->sizeRecv();
235  if (addressSize == 0) {
236  inform(tr("No addresses available, you can go to the receive screen and add some there!"));
237  return;
238  }
239 
240  int height = (addressSize <= 2) ? ui->addressIn_SM->height() * ( 2 * (addressSize + 1 )) : ui->addressIn_SM->height() * 4;
241  int width = ui->containerAddress->width();
242 
243  if (!menuContacts) {
245  width,
246  height,
247  this
248  );
250  connect(menuContacts, &ContactsDropdown::contactSelected, [this](QString address, QString label){
251  setAddress_SM(address);
252  });
253 
254  }
255 
256  if (menuContacts->isVisible()) {
257  menuContacts->hide();
258  return;
259  }
260 
261  menuContacts->resizeList(width, height);
262  menuContacts->setStyleSheet(this->styleSheet());
263  menuContacts->adjustSize();
264 
265  QPoint pos = ui->container_sign->mapToParent(ui->containerAddress->rect().bottomLeft());
266  pos.setY(pos.y() + (ui->containerAddress->height() * 1.4) - 10);
267  menuContacts->move(pos);
268  menuContacts->show();
269 }
270 
272 {
273  if (menuContacts && menuContacts->isVisible()) {
274  int width = ui->containerAddress->width();
275  menuContacts->resizeList(width, menuContacts->height());
276  menuContacts->resize(width, menuContacts->height());
277  QPoint pos = ui->container_sign->mapToParent(ui->containerAddress->rect().bottomLeft());
278  pos.setY(pos.y() + (ui->containerAddress->height() * 1.4) - 10);
279  menuContacts->move(pos);
280  }
281 }
282 
284 {
285  resizeMenu();
286  QWidget::resizeEvent(event);
287 }
static const QString Receive
Specifies receive address.
An encapsulated private key.
Definition: key.h:30
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:21
static bool SignMessage(const std::string &strMessage, std::vector< unsigned char > &vchSigRet, const CKey &key)
Sign the message, returns true if successful.
static bool VerifyMessage(const CPubKey &pubkey, const std::vector< unsigned char > &vchSig, const std::string &strMessage, std::string &strErrorRet)
Verify the message signature, returns true if successful.
void resizeList(int minWidth, int mintHeight)
void contactSelected(QString address, QString label)
void setWalletModel(WalletModel *_model, const QStringList &type)
PIVX GUI main class.
Definition: pivxgui.h:46
void inform(const QString &message)
Definition: pwidget.cpp:45
WalletModel * walletModel
Definition: pwidget.h:61
void message(const QString &title, const QString &body, unsigned int style, bool *ret=nullptr)
SettingsSignMessageWidgets(PIVXGUI *_window, QWidget *parent=nullptr)
Ui::SettingsSignMessageWidgets * ui
void resizeEvent(QResizeEvent *event) override
void setAddress_SM(const QString &address)
ContactsDropdown * menuContacts
void showEvent(QShowEvent *event) override
AddressTableModel * getAddressTableModel()
bool getKey(const CKeyID &keyID, CKey &key) const
Definition: walletmodel.h:295
UnlockContext requestUnlock()
bool IsValidDestination(const CWDestination &address)
CWDestination DecodeDestination(const std::string &strAddress)
void initCssEditLine(QLineEdit *edit, bool isDialog)
Definition: qtutils.cpp:272
void setShadow(QWidget *edit)
Definition: qtutils.cpp:292
void setCssProperty(std::initializer_list< QWidget * > args, const QString &value)
Definition: qtutils.cpp:334
void setCssBtnPrimary(QPushButton *btn, bool forceUpdate)
Definition: qtutils.cpp:302
void setCssBtnSecondary(QPushButton *btn, bool forceUpdate)
Definition: qtutils.cpp:307
boost::variant< CNoDestination, CKeyID, CScriptID, CExchangeKeyID > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:72
std::string EncodeBase64(Span< const unsigned char > input)
std::vector< unsigned char > DecodeBase64(const char *p, bool *pfInvalid)