PIVX Core  5.6.99
P2P Digital Currency
bittoolwidget.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019-2021 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_bittoolwidget.h"
7 
8 #include "qtutils.h"
9 
10 #include "guiutil.h"
11 #include "walletmodel.h"
12 
13 #include "bip38.h"
14 #include "key_io.h"
15 #include "wallet/wallet.h"
16 #include "askpassphrasedialog.h"
17 
18 #include <string>
19 #include <vector>
20 
21 
23  PWidget(_window, parent),
24  ui(new Ui::SettingsBitToolWidget)
25 {
26  ui->setupUi(this);
27 
28  this->setStyleSheet(parent->styleSheet());
29 
30  /* Containers */
31  setCssProperty(ui->left, "container");
32  ui->left->setContentsMargins(10,10,10,10);
33 
34  /* Title */
35  setCssTitleScreen(ui->labelTitle);
36 
37  //Button Group
38  setCssProperty(ui->pushLeft, "btn-check-left");
39  setCssProperty(ui->pushRight, "btn-check-right");
40  ui->pushLeft->setChecked(true);
41 
42  // Subtitle
43  setCssSubtitleScreen(ui->labelSubtitle1);
44 
45  // Key
46  setCssProperty(ui->labelSubtitleKey, "text-title");
47  initCssEditLine(ui->lineEditKey);
48 
49  // Passphrase
50  setCssProperty(ui->labelSubtitlePassphrase, "text-title");
51  initCssEditLine(ui->lineEditPassphrase);
52 
53  // Decrypt controls
54  setCssProperty(ui->labelSubtitleDecryptResult, "text-title");
55  ui->lineEditDecryptResult->setAttribute(Qt::WA_MacShowFocusRect, 0);
56  ui->lineEditDecryptResult->setReadOnly(true);
57  initCssEditLine(ui->lineEditDecryptResult);
58 
59  // Buttons
60  setCssBtnPrimary(ui->pushButtonDecrypt);
61  setCssProperty(ui->pushButtonImport, "btn-text-primary");
62  ui->pushButtonImport->setVisible(false);
63 
64  connect(ui->pushLeft, &QPushButton::clicked, [this](){onEncryptSelected(true);});
65  connect(ui->pushRight, &QPushButton::clicked, [this](){onEncryptSelected(false);});
66 
67 
68  // Encrypt
69 
70  // Address
71  setCssProperty(ui->labelSubtitleAddress, "text-title");
72  setCssProperty(ui->addressIn_ENC, "edit-primary-multi-book");
73  ui->addressIn_ENC->setAttribute(Qt::WA_MacShowFocusRect, 0);
74  setShadow(ui->addressIn_ENC);
75 
76  // Message
77  setCssProperty(ui->labelSubtitleMessage, "text-title");
78  setCssProperty(ui->passphraseIn_ENC, "edit-primary");
79  setShadow(ui->passphraseIn_ENC);
80  ui->passphraseIn_ENC->setAttribute(Qt::WA_MacShowFocusRect, 0);
81 
82  // Encrypted Key
83  setCssProperty(ui->labelSubtitleEncryptedKey, "text-title");
84  ui->encryptedKeyOut_ENC->setAttribute(Qt::WA_MacShowFocusRect, 0);
85  ui->encryptedKeyOut_ENC->setReadOnly(true);
86  initCssEditLine(ui->encryptedKeyOut_ENC);
87 
88  btnContact = ui->addressIn_ENC->addAction(QIcon("://ic-contact-arrow-down"), QLineEdit::TrailingPosition);
89  setCssBtnPrimary(ui->pushButtonEncrypt);
90  setCssBtnSecondary(ui->pushButtonClear);
91  setCssBtnSecondary(ui->pushButtonDecryptClear);
92 
93  ui->statusLabel_ENC->setStyleSheet("QLabel { color: transparent; }");
94  ui->statusLabel_DEC->setStyleSheet("QLabel { color: transparent; }");
95 
96  connect(ui->pushButtonEncrypt, &QPushButton::clicked, this, &SettingsBitToolWidget::onEncryptKeyButtonENCClicked);
97  connect(ui->pushButtonDecrypt, &QPushButton::clicked, this, &SettingsBitToolWidget::onDecryptClicked);
98  connect(ui->pushButtonImport, &QPushButton::clicked, this, &SettingsBitToolWidget::importAddressFromDecKey);
99  connect(btnContact, &QAction::triggered, this, &SettingsBitToolWidget::onAddressesClicked);
100  connect(ui->pushButtonClear, &QPushButton::clicked, this, &SettingsBitToolWidget::onClearAll);
101  connect(ui->pushButtonDecryptClear, &QPushButton::clicked, this, &SettingsBitToolWidget::onClearDecrypt);
102 }
103 
104 void SettingsBitToolWidget::setAddress_ENC(const QString& address)
105 {
106  ui->addressIn_ENC->setText(address);
107  ui->passphraseIn_ENC->setFocus();
108 }
109 
111 {
112  ui->stackedWidget->setCurrentIndex(isEncr);
113 }
114 
115 QString specialChar = "\"@!#$%&'()*+,-./:;<=>?`{|}~^_[]\\";
116 QString validChar = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + specialChar;
117 
118 bool isValidPassphrase(QString strPassphrase, QString& strInvalid)
119 {
120  for (int i = 0; i < strPassphrase.size(); i++) {
121  if (!validChar.contains(strPassphrase[i], Qt::CaseSensitive)) {
122  if (QString("\"'").contains(strPassphrase[i]))
123  continue;
124 
125  strInvalid = strPassphrase[i];
126  return false;
127  }
128  }
129 
130  return true;
131 }
132 
134 {
135  if (!walletModel)
136  return;
137 
138  QString qstrPassphrase = ui->passphraseIn_ENC->text();
139  QString strInvalid;
140  if (!isValidPassphrase(qstrPassphrase, strInvalid)) {
141  ui->statusLabel_ENC->setStyleSheet("QLabel { color: red; }");
142  ui->statusLabel_ENC->setText(tr("The entered passphrase is invalid. ") + strInvalid + QString(" is not valid") + QString(" ") + tr("Allowed: 0-9,a-z,A-Z,") + specialChar);
143  return;
144  }
145 
146  CTxDestination dest = DecodeDestination(ui->addressIn_ENC->text().toStdString());
147  if (!IsValidDestination(dest)) {
148  ui->statusLabel_ENC->setStyleSheet("QLabel { color: red; }");
149  ui->statusLabel_ENC->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again."));
150  return;
151  }
152 
153  const CKeyID* keyID = boost::get<CKeyID>(&dest);
154  if (!keyID) {
155  //ui->addressIn_ENC->setValid(false);
156  ui->statusLabel_ENC->setStyleSheet("QLabel { color: red; }");
157  ui->statusLabel_ENC->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again."));
158  return;
159  }
160 
162  if (!ctx.isValid()) {
163  ui->statusLabel_ENC->setStyleSheet("QLabel { color: red; }");
164  ui->statusLabel_ENC->setText(tr("Wallet unlock was cancelled."));
165  return;
166  }
167 
168  CKey key;
169  if (!walletModel->getKey(*keyID, key)) {
170  ui->statusLabel_ENC->setStyleSheet("QLabel { color: red; }");
171  ui->statusLabel_ENC->setText(tr("Private key for the entered address is not available."));
172  return;
173  }
174 
175  std::string encryptedKey = BIP38_Encrypt(EncodeDestination(dest), qstrPassphrase.toStdString(), key.GetPrivKey_256(), key.IsCompressed());
176  ui->encryptedKeyOut_ENC->setText(QString::fromStdString(encryptedKey));
177 
178  ui->statusLabel_ENC->setStyleSheet("QLabel { color: green; }");
179  ui->statusLabel_ENC->setText(QString("<nobr>") + tr("Address encrypted.") + QString("</nobr>"));
180 }
181 
183 {
184  ui->addressIn_ENC->clear();
185  ui->passphraseIn_ENC->clear();
186  ui->encryptedKeyOut_ENC->clear();
187  ui->statusLabel_ENC->clear();
188  ui->addressIn_ENC->setFocus();
189 }
190 
192 {
193  int addressSize = walletModel->getAddressTableModel()->sizeRecv();
194  if (addressSize == 0) {
195  inform(tr("No addresses available, you can go to the receive screen and add some there!"));
196  return;
197  }
198 
199  int height = (addressSize <= 2) ? ui->addressIn_ENC->height() * ( 2 * (addressSize + 1 )) : ui->addressIn_ENC->height() * 4;
200  int width = ui->containerAddressEnc->width();
201 
202  if (!menuContacts) {
204  width,
205  height,
206  this
207  );
209  connect(menuContacts, &ContactsDropdown::contactSelected, [this](QString address, QString label){
210  setAddress_ENC(address);
211  });
212 
213  }
214 
215  if (menuContacts->isVisible()) {
216  menuContacts->hide();
217  return;
218  }
219 
220  menuContacts->resizeList(width, height);
221  menuContacts->setStyleSheet(this->styleSheet());
222  menuContacts->adjustSize();
223 
224  QPoint pos = ui->containerAddressEnc->rect().bottomLeft();
225  pos.setY(pos.y() + ui->containerAddressEnc->height());
226  pos.setX(pos.x() + 10);
227  menuContacts->move(pos);
228  menuContacts->show();
229 }
230 
232 {
233  if (menuContacts && menuContacts->isVisible()) {
234  int width = ui->containerAddress->width();
235  menuContacts->resizeList(width, menuContacts->height());
236  menuContacts->resize(width, menuContacts->height());
237  QPoint pos = ui->containerAddressEnc->rect().bottomLeft();
238  pos.setY(pos.y() + ui->containerAddressEnc->height());
239  pos.setX(pos.x() + 10);
240  menuContacts->move(pos);
241  }
242 }
243 
245 {
246  ui->lineEditKey->clear();
247  ui->lineEditDecryptResult->clear();
248  ui->lineEditPassphrase->clear();
249  ui->pushButtonImport->setVisible(false);
250  key = CKey();
251 }
252 
254 {
255  std::string strPassphrase = ui->lineEditPassphrase->text().toStdString();
256  std::string strKey = ui->lineEditKey->text().toStdString();
257 
258  uint256 privKey;
259  bool fCompressed;
260  if (!BIP38_Decrypt(strPassphrase, strKey, privKey, fCompressed)) {
261  ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }");
262  ui->statusLabel_DEC->setText(tr("Failed to decrypt.") + QString(" ") + tr("Please check the key and passphrase and try again."));
263  return;
264  }
265 
266  key.Set(privKey.begin(), privKey.end(), fCompressed);
267  CPubKey pubKey = key.GetPubKey();
268  ui->lineEditDecryptResult->setText(QString::fromStdString(EncodeDestination(pubKey.GetID())));
269  ui->pushButtonImport->setVisible(true);
270 }
271 
273 {
274  // whenever a key is imported, we need to scan the whole chain
276  if (!reserver.reserve()) {
277  ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }");
278  ui->statusLabel_DEC->setText(tr("Wallet is currently rescanning. Abort existing rescan or wait."));
279  return;
280  }
282  if (!ctx.isValid()) {
283  ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }");
284  ui->statusLabel_DEC->setText(tr("Wallet unlock was cancelled."));
285  return;
286  }
287 
288  CTxDestination dest = DecodeDestination(ui->lineEditDecryptResult->text().toStdString());
289  CPubKey pubkey = key.GetPubKey();
290 
291  if (!IsValidDestination(dest) || !key.IsValid() || EncodeDestination(pubkey.GetID()) != EncodeDestination(dest)) {
292  ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }");
293  ui->statusLabel_DEC->setText(tr("Data Not Valid.") + QString(" ") + tr("Please try again."));
294  return;
295  }
296 
297  CKeyID vchAddress = pubkey.GetID();
298  {
299  ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }");
300  ui->statusLabel_DEC->setText(tr("Please wait while key is imported"));
301 
303 
304  // Don't throw error in case a key is already there
305  if (walletModel->haveKey(vchAddress)) {
306  ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }");
307  ui->statusLabel_DEC->setText(tr("Cannot import address, key already held by the wallet"));
308  return;
309  }
310 
311  if (!walletModel->addKeys(key, pubkey, reserver)) {
312  ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }");
313  ui->statusLabel_DEC->setText(tr("Error adding key to the wallet"));
314  return;
315  }
316  }
317 
318  ui->statusLabel_DEC->setStyleSheet("QLabel { color: green; }");
319  ui->statusLabel_DEC->setText(tr("Successfully added private key to the wallet"));
320 }
321 
322 void SettingsBitToolWidget::resizeEvent(QResizeEvent *event)
323 {
324  resizeMenu();
325  QWidget::resizeEvent(event);
326 }
327 
329 {
330  delete ui;
331 }
bool BIP38_Decrypt(std::string strPassphrase, std::string strEncryptedKey, uint256 &privKey, bool &fCompressed)
Definition: bip38.cpp:169
std::string BIP38_Encrypt(std::string strAddress, std::string strPassphrase, uint256 privKey, bool fCompressed)
Definition: bip38.cpp:119
bool isValidPassphrase(QString strPassphrase, QString &strInvalid)
QString validChar
QString specialChar
static const QString Receive
Specifies receive address.
An encapsulated private key.
Definition: key.h:30
uint256 GetPrivKey_256()
Definition: key.cpp:167
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:95
bool IsCompressed() const
Check whether the public key corresponding to this private key is (to be) compressed.
Definition: key.h:98
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:186
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
Definition: key.h:76
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:21
An encapsulated public key.
Definition: pubkey.h:44
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:167
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
Ui::SettingsBitToolWidget * ui
Definition: bittoolwidget.h:37
void setAddress_ENC(const QString &address)
SettingsBitToolWidget(PIVXGUI *_window, QWidget *parent=nullptr)
void resizeEvent(QResizeEvent *event) override
ContactsDropdown * menuContacts
Definition: bittoolwidget.h:39
void onEncryptSelected(bool isEncr)
bool updateAddressBookLabels(const CWDestination &address, const std::string &strName, const std::string &strPurpose)
bool haveKey(const CKeyID &keyID) const
Definition: walletmodel.h:296
WalletRescanReserver getRescanReserver() const
Return new wallet rescan reserver.
Definition: walletmodel.h:287
bool addKeys(const CKey &key, const CPubKey &pubkey, WalletRescanReserver &reserver)
AddressTableModel * getAddressTableModel()
bool getKey(const CKeyID &keyID, CKey &key) const
Definition: walletmodel.h:295
UnlockContext requestUnlock()
RAII object to check and reserve a wallet rescan.
Definition: wallet.h:1324
unsigned char * end()
Definition: uint256.h:68
unsigned char * begin()
Definition: uint256.h:63
256-bit opaque blob.
Definition: uint256.h:138
bool IsValidDestination(const CWDestination &address)
std::string EncodeDestination(const CWDestination &address, const CChainParams::Base58Type addrType)
CWDestination DecodeDestination(const std::string &strAddress)
void setCssTitleScreen(QLabel *label)
Definition: qtutils.cpp:324
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 setCssSubtitleScreen(QWidget *wid)
Definition: qtutils.cpp:329
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