Bitcoin ABC  0.26.3
P2P Digital Currency
walletview.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2016 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 
5 #include <qt/walletview.h>
6 
7 #include <config.h> // For GetConfig
8 #include <interfaces/node.h>
9 #include <node/psbt.h>
10 #include <node/transaction.h>
11 #include <node/ui_interface.h>
12 #include <policy/policy.h>
13 #include <qt/addressbookpage.h>
14 #include <qt/askpassphrasedialog.h>
15 #include <qt/clientmodel.h>
16 #include <qt/guiutil.h>
17 #include <qt/optionsmodel.h>
18 #include <qt/overviewpage.h>
19 #include <qt/platformstyle.h>
20 #include <qt/receivecoinsdialog.h>
21 #include <qt/sendcoinsdialog.h>
24 #include <qt/transactionview.h>
25 #include <qt/walletmodel.h>
26 #include <util/fs_helpers.h>
27 #include <util/strencodings.h>
28 
29 #include <QAction>
30 #include <QActionGroup>
31 #include <QFileDialog>
32 #include <QHBoxLayout>
33 #include <QProgressDialog>
34 #include <QPushButton>
35 #include <QVBoxLayout>
36 
37 #include <fstream>
38 
39 using node::AnalyzePSBT;
41 using node::PSBTAnalysis;
42 
43 WalletView::WalletView(const PlatformStyle *_platformStyle,
44  WalletModel *_walletModel, QWidget *parent)
45  : QStackedWidget(parent), clientModel(nullptr), walletModel(_walletModel),
46  platformStyle(_platformStyle) {
47  // Create tabs
49 
50  transactionsPage = new QWidget(this);
51  QVBoxLayout *vbox = new QVBoxLayout();
52  QHBoxLayout *hbox_buttons = new QHBoxLayout();
54  vbox->addWidget(transactionView);
55  QPushButton *exportButton = new QPushButton(tr("&Export"), this);
56  exportButton->setToolTip(
57  tr("Export the data in the current tab to a file"));
59  exportButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
60  }
61  hbox_buttons->addStretch();
62  hbox_buttons->addWidget(exportButton);
63  vbox->addLayout(hbox_buttons);
64  transactionsPage->setLayout(vbox);
65 
68 
75 
76  addWidget(overviewPage);
77  addWidget(transactionsPage);
78  addWidget(receiveCoinsPage);
79  addWidget(sendCoinsPage);
80 
83  // Clicking on a transaction on the overview pre-selects the transaction on
84  // the transaction history page
86  static_cast<void (TransactionView::*)(const QModelIndex &)>(
88 
91 
94  // Highlight transaction after send
96  static_cast<void (TransactionView::*)(const uint256 &)>(
98 
99  // Clicking on "Export" allows to export the transaction list
100  connect(exportButton, &QPushButton::clicked, transactionView,
102 
103  // Pass through messages from sendCoinsPage
104  connect(sendCoinsPage, &SendCoinsDialog::message, this,
106  // Pass through messages from transactionView
109  connect(this, &WalletView::setPrivacy, overviewPage,
111 
112  // Set the model properly.
114 }
115 
117 
119  this->clientModel = _clientModel;
120 
121  overviewPage->setClientModel(_clientModel);
122  sendCoinsPage->setClientModel(_clientModel);
123  if (walletModel) {
124  walletModel->setClientModel(_clientModel);
125  }
126 }
127 
129  this->walletModel = _walletModel;
130 
131  // Put transaction list in tabs
132  transactionView->setModel(_walletModel);
133  overviewPage->setWalletModel(_walletModel);
134  receiveCoinsPage->setModel(_walletModel);
135  sendCoinsPage->setModel(_walletModel);
137  _walletModel ? _walletModel->getAddressTableModel() : nullptr);
139  _walletModel ? _walletModel->getAddressTableModel() : nullptr);
140 
141  if (_walletModel) {
142  // Receive and pass through messages from wallet model
143  connect(_walletModel, &WalletModel::message, this,
145 
146  // Handle changes in encryption status
147  connect(_walletModel, &WalletModel::encryptionStatusChanged, this,
150 
151  // update HD status
152  Q_EMIT hdEnabledStatusChanged();
153 
154  // Balloon pop-up for new transaction
155  connect(_walletModel->getTransactionTableModel(),
156  &TransactionTableModel::rowsInserted, this,
158 
159  // Ask for passphrase if needed
160  connect(_walletModel, &WalletModel::requireUnlock, this,
162 
163  // Show progress dialog
164  connect(_walletModel, &WalletModel::showProgress, this,
166  }
167 }
168 
169 void WalletView::processNewTransaction(const QModelIndex &parent, int start,
170  int end) {
171  // Prevent balloon-spam when initial block download is in progress
172  if (!walletModel || !clientModel ||
174  return;
175  }
176 
178  if (!ttm || ttm->processingQueuedTransactions()) {
179  return;
180  }
181 
182  QString date = ttm->index(start, TransactionTableModel::Date, parent)
183  .data()
184  .toString();
185  qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
186  .data(Qt::EditRole)
187  .toULongLong();
188  QString type = ttm->index(start, TransactionTableModel::Type, parent)
189  .data()
190  .toString();
191  QModelIndex index = ttm->index(start, 0, parent);
192  QString address =
193  ttm->data(index, TransactionTableModel::AddressRole).toString();
194  QString label = GUIUtil::HtmlEscape(
195  ttm->data(index, TransactionTableModel::LabelRole).toString());
196 
197  Q_EMIT incomingTransaction(
199  int64_t(amount) * SATOSHI, type, address, label,
201 }
202 
204  setCurrentWidget(overviewPage);
205 }
206 
208  setCurrentWidget(transactionsPage);
209 }
210 
212  setCurrentWidget(receiveCoinsPage);
213 }
214 
215 void WalletView::gotoSendCoinsPage(QString addr) {
216  setCurrentWidget(sendCoinsPage);
217 
218  if (!addr.isEmpty()) {
219  sendCoinsPage->setAddress(addr);
220  }
221 }
222 
223 void WalletView::gotoSignMessageTab(QString addr) {
224  // calls show() in showTab_SM()
225  SignVerifyMessageDialog *signVerifyMessageDialog =
227  signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
228  signVerifyMessageDialog->setModel(walletModel);
229  signVerifyMessageDialog->showTab_SM(true);
230 
231  if (!addr.isEmpty()) {
232  signVerifyMessageDialog->setAddress_SM(addr);
233  }
234 }
235 
237  // calls show() in showTab_VM()
238  SignVerifyMessageDialog *signVerifyMessageDialog =
240  signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
241  signVerifyMessageDialog->setModel(walletModel);
242  signVerifyMessageDialog->showTab_VM(true);
243 
244  if (!addr.isEmpty()) {
245  signVerifyMessageDialog->setAddress_VM(addr);
246  }
247 }
248 
250  QString filename = GUIUtil::getOpenFileName(
251  this, tr("Load Transaction Data"), QString(),
252  tr("Partially Signed Transaction (*.psbt)"), nullptr);
253  if (filename.isEmpty()) {
254  return;
255  }
256  if (GetFileSize(filename.toLocal8Bit().data(), MAX_FILE_SIZE_PSBT) ==
258  Q_EMIT message(tr("Error"),
259  tr("PSBT file must be smaller than 100 MiB"),
261  return;
262  }
263  std::ifstream in{filename.toLocal8Bit().data(), std::ios::binary};
264  std::string dataStr(std::istreambuf_iterator<char>{in}, {});
265 
266  std::string error;
268  if (!DecodeRawPSBT(psbtx, dataStr, error)) {
269  Q_EMIT message(tr("Error"),
270  tr("Unable to decode PSBT file") + "\n" +
271  QString::fromStdString(error),
273  return;
274  }
275 
277  bool complete = false;
278  PSBTAnalysis analysis = AnalyzePSBT(psbtx);
279  QMessageBox msgBox;
280  msgBox.setText("PSBT");
281  switch (analysis.next) {
282  case PSBTRole::CREATOR:
283  case PSBTRole::UPDATER:
284  msgBox.setInformativeText(
285  "PSBT is incomplete. Copy to clipboard for manual inspection?");
286  break;
287  case PSBTRole::SIGNER:
288  msgBox.setInformativeText(
289  "Transaction needs more signatures. Copy to clipboard?");
290  break;
291  case PSBTRole::FINALIZER:
292  case PSBTRole::EXTRACTOR:
293  complete = FinalizeAndExtractPSBT(psbtx, mtx);
294  if (complete) {
295  msgBox.setInformativeText(
296  tr("Would you like to send this transaction?"));
297  } else {
298  // The analyzer missed something, e.g. if there are
299  // final_scriptSig but with invalid signatures.
300  msgBox.setInformativeText(
301  tr("There was an unexpected problem processing the PSBT. "
302  "Copy to clipboard for manual inspection?"));
303  }
304  }
305 
306  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
307  switch (msgBox.exec()) {
308  case QMessageBox::Yes: {
309  if (complete) {
310  std::string err_string;
312 
314  *clientModel->node().context(), tx, err_string,
315  DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK(), /* relay */ true,
316  /* wait_callback */ false);
317  if (result == TransactionError::OK) {
318  Q_EMIT message(tr("Success"),
319  tr("Broadcasted transaction successfully."),
322  } else {
323  Q_EMIT message(tr("Error"),
324  QString::fromStdString(err_string),
326  }
327  } else {
328  // Serialize the PSBT
330  ssTx << psbtx;
331  GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str());
332  Q_EMIT message(tr("PSBT copied"), "Copied to clipboard",
334  return;
335  }
336  }
337  case QMessageBox::Cancel:
338  break;
339  default:
340  assert(false);
341  }
342 }
343 
345  return sendCoinsPage->handlePaymentRequest(recipient);
346 }
347 
350 }
351 
353  Q_EMIT encryptionStatusChanged();
354 }
355 
357  if (!walletModel) {
358  return;
359  }
361  dlg.setModel(walletModel);
362  dlg.exec();
363 
365 }
366 
368  QString filename =
369  GUIUtil::getSaveFileName(this, tr("Backup Wallet"), QString(),
370  tr("Wallet Data (*.dat)"), nullptr);
371 
372  if (filename.isEmpty()) {
373  return;
374  }
375 
376  if (!walletModel->wallet().backupWallet(filename.toLocal8Bit().data())) {
377  Q_EMIT message(
378  tr("Backup Failed"),
379  tr("There was an error trying to save the wallet data to %1.")
380  .arg(filename),
382  } else {
383  Q_EMIT message(
384  tr("Backup Successful"),
385  tr("The wallet data was successfully saved to %1.").arg(filename),
387  }
388 }
389 
392  dlg.setModel(walletModel);
393  dlg.exec();
394 }
395 
397  if (!walletModel) {
398  return;
399  }
400 
401  // Unlock wallet when requested by wallet model
404  dlg.setModel(walletModel);
405  dlg.exec();
406  }
407 }
408 
410  if (!walletModel) {
411  return;
412  }
413 
415 }
416 
418  if (!walletModel) {
419  return;
420  }
421 
423 }
424 
425 void WalletView::showProgress(const QString &title, int nProgress) {
426  if (nProgress == 0) {
427  progressDialog = new QProgressDialog(title, tr("Cancel"), 0, 100);
429  progressDialog->setWindowModality(Qt::ApplicationModal);
430  progressDialog->setMinimumDuration(0);
431  progressDialog->setAutoClose(false);
432  progressDialog->setValue(0);
433  } else if (nProgress == 100) {
434  if (progressDialog) {
435  progressDialog->close();
436  progressDialog->deleteLater();
437  progressDialog = nullptr;
438  }
439  } else if (progressDialog) {
440  if (progressDialog->wasCanceled()) {
442  } else {
443  progressDialog->setValue(nProgress);
444  }
445  }
446 }
447 
449  Q_EMIT outOfSyncWarningClicked();
450 }
static constexpr Amount SATOSHI
Definition: amount.h:143
Widget that shows a list of sending or receiving addresses.
@ ForEditing
Open address book for editing.
void setModel(AddressTableModel *model)
Multifunctional dialog to ask for passphrases.
void setModel(WalletModel *model)
@ Unlock
Ask passphrase and unlock.
@ Encrypt
Ask passphrase twice and encrypt.
@ ChangePass
Ask old passphrase + new passphrase twice.
@ MSG_INFORMATION
Predefined combinations for certain default usage cases.
Definition: ui_interface.h:71
@ MODAL
Force blocking, modal message box dialog (not just OS notification)
Definition: ui_interface.h:65
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:177
std::string str() const
Definition: streams.h:212
Amount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:54
A mutable version of CTransaction.
Definition: transaction.h:274
Model for Bitcoin network client.
Definition: clientmodel.h:43
interfaces::Node & node() const
Definition: clientmodel.h:58
int getDisplayUnit() const
Definition: optionsmodel.h:97
Overview ("home") page widget.
Definition: overviewpage.h:28
void setWalletModel(WalletModel *walletModel)
void setClientModel(ClientModel *clientModel)
void transactionClicked(const QModelIndex &index)
void outOfSyncWarningClicked()
void showOutOfSyncWarning(bool fShow)
void setPrivacy(bool privacy)
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
bool getImagesOnButtons() const
Definition: platformstyle.h:20
Dialog for requesting payment of bitcoins.
void setModel(WalletModel *model)
Dialog for sending bitcoins.
void setClientModel(ClientModel *clientModel)
void setModel(WalletModel *model)
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
void setAddress(const QString &address)
void message(const QString &title, const QString &message, unsigned int style)
void coinsSent(const uint256 &txid)
void setAddress_SM(const QString &address)
void setModel(WalletModel *model)
void setAddress_VM(const QString &address)
UI model for the transaction table of a wallet.
@ LabelRole
Label of address related to transaction.
@ AddressRole
Address of transaction.
QVariant data(const QModelIndex &index, int role) const override
bool processingQueuedTransactions() const
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Widget showing the transaction list for a wallet, including a filter row.
void setModel(WalletModel *model)
void message(const QString &title, const QString &message, unsigned int style)
Fired when a message should be reported to the user.
void focusTransaction(const QModelIndex &)
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:47
void showProgress(const QString &title, int nProgress)
void message(const QString &title, const QString &message, unsigned int style)
void setClientModel(ClientModel *client_model)
Definition: walletmodel.cpp:57
AddressTableModel * getAddressTableModel()
OptionsModel * getOptionsModel()
interfaces::Wallet & wallet() const
Definition: walletmodel.h:150
EncryptionStatus getEncryptionStatus() const
void requireUnlock()
void encryptionStatusChanged()
QString getWalletName() const
TransactionTableModel * getTransactionTableModel()
const PlatformStyle * platformStyle
Definition: walletview.h:74
void gotoHistoryPage()
Switch to history (transactions) page.
Definition: walletview.cpp:207
void gotoVerifyMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to verify message tab.
Definition: walletview.cpp:236
void setWalletModel(WalletModel *walletModel)
Set the wallet model.
Definition: walletview.cpp:128
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
Definition: walletview.cpp:344
void gotoSendCoinsPage(QString addr="")
Switch to send coins page.
Definition: walletview.cpp:215
void incomingTransaction(const QString &date, int unit, const Amount amount, const QString &type, const QString &address, const QString &label, const QString &walletName)
Notify that a new transaction appeared.
void changePassphrase()
Change encrypted wallet passphrase.
Definition: walletview.cpp:390
QProgressDialog * progressDialog
Definition: walletview.h:73
SendCoinsDialog * sendCoinsPage
Definition: walletview.h:67
OverviewPage * overviewPage
Definition: walletview.h:64
void setClientModel(ClientModel *clientModel)
Set the client model.
Definition: walletview.cpp:118
void outOfSyncWarningClicked()
Notify that the out of sync warning icon has been pressed.
void gotoReceiveCoinsPage()
Switch to receive coins page.
Definition: walletview.cpp:211
void gotoSignMessageTab(QString addr="")
Show Sign/Verify Message dialog and switch to sign message tab.
Definition: walletview.cpp:223
QWidget * transactionsPage
Definition: walletview.h:65
void usedSendingAddresses()
Show used sending addresses.
Definition: walletview.cpp:409
ReceiveCoinsDialog * receiveCoinsPage
Definition: walletview.h:66
void encryptWallet()
Encrypt the wallet.
Definition: walletview.cpp:356
TransactionView * transactionView
Definition: walletview.h:71
WalletView(const PlatformStyle *platformStyle, WalletModel *walletModel, QWidget *parent)
Definition: walletview.cpp:43
void showProgress(const QString &title, int nProgress)
Show progress dialog e.g.
Definition: walletview.cpp:425
void message(const QString &title, const QString &message, unsigned int style)
Fired when a message should be reported to the user.
AddressBookPage * usedReceivingAddressesPage
Definition: walletview.h:69
void backupWallet()
Backup the wallet.
Definition: walletview.cpp:367
ClientModel * clientModel
Definition: walletview.h:61
void gotoLoadPSBT()
Load Partially Signed Bitcoin Transaction.
Definition: walletview.cpp:249
void requestedSyncWarningInfo()
User has requested more information about the out of sync state.
Definition: walletview.cpp:448
AddressBookPage * usedSendingAddressesPage
Definition: walletview.h:68
void unlockWallet()
Ask for passphrase to unlock wallet temporarily.
Definition: walletview.cpp:396
WalletModel * walletModel
Definition: walletview.h:62
void gotoOverviewPage()
Switch to overview (home) page.
Definition: walletview.cpp:203
void usedReceivingAddresses()
Show used receiving addresses.
Definition: walletview.cpp:417
void transactionClicked()
void updateEncryptionStatus()
Re-emit encryption status signal.
Definition: walletview.cpp:352
void hdEnabledStatusChanged()
HD-Enabled status of wallet changed (only possible during startup)
void coinsSent()
void setPrivacy(bool privacy)
void processNewTransaction(const QModelIndex &parent, int start, int end)
Show incoming transaction notification for new transactions.
Definition: walletview.cpp:169
void showOutOfSyncWarning(bool fShow)
Definition: walletview.cpp:348
void encryptionStatusChanged()
Encryption status of wallet changed.
WalletModel * getWalletModel()
Definition: walletview.h:48
virtual node::NodeContext * context()
Get and set internal node context.
Definition: node.h:261
virtual bool isInitialBlockDownload()=0
Is initial block download.
virtual void abortRescan()=0
Abort a rescan.
virtual bool backupWallet(const std::string &filename)=0
Back up wallet.
256-bit opaque blob.
Definition: uint256.h:129
TransactionError
Definition: error.h:22
std::streampos GetFileSize(const char *path, std::streamsize max)
Get the size of a file by scanning it.
Definition: fs_helpers.cpp:119
bool error(const char *fmt, const Args &...args)
Definition: logging.h:226
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:251
void PolishProgressDialog(QProgressDialog *dialog)
Definition: guiutil.cpp:953
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get open filename, convenience wrapper for QFileDialog::getOpenFileName.
Definition: guiutil.cpp:337
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix when ...
Definition: guiutil.cpp:294
void bringToFront(QWidget *w)
Definition: guiutil.cpp:390
void setClipboard(const QString &str)
Definition: guiutil.cpp:776
PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
Provides helpful miscellaneous information about where a PSBT is in the signing workflow.
Definition: psbt.cpp:16
TransactionError BroadcastTransaction(const NodeContext &node, const CTransactionRef tx, std::string &err_string, const Amount max_tx_fee, bool relay, bool wait_callback)
Submit a transaction to the mempool and (optionally) relay it to all P2P peers.
Definition: transaction.cpp:37
static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE
Maximum fee rate for sendrawtransaction and testmempoolaccept RPC calls.
Definition: transaction.h:33
static CTransactionRef MakeTransactionRef()
Definition: transaction.h:316
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
bool DecodeRawPSBT(PartiallySignedTransaction &psbt, const std::string &tx_data, std::string &error)
Decode a raw (binary blob) PSBT into a PartiallySignedTransaction.
Definition: psbt.cpp:307
bool FinalizeAndExtractPSBT(PartiallySignedTransaction &psbtx, CMutableTransaction &result)
Finalizes a PSBT if possible, and extracts it to a CMutableTransaction if it could be finalized.
Definition: psbt.cpp:247
const std::streamsize MAX_FILE_SIZE_PSBT
Definition: psbt.h:41
@ SER_NETWORK
Definition: serialize.h:152
std::string EncodeBase64(Span< const uint8_t > input)
A version of CTransaction with the PSBT format.
Definition: psbt.h:334
Holds the results of AnalyzePSBT (miscellaneous information about a PSBT)
Definition: psbt.h:35
PSBTRole next
Which of the BIP 174 roles needs to handle the transaction next.
Definition: psbt.h:45
assert(!tx.IsCoinBase())
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:11