aboutsummaryrefslogtreecommitdiff
path: root/src/qt
diff options
context:
space:
mode:
authorJonas Schnelli <dev@jonasschnelli.ch>2017-05-18 11:17:55 +0200
committerJonas Schnelli <dev@jonasschnelli.ch>2017-05-18 11:18:23 +0200
commit962cd3f0587e87de1e38c1777151dca282f3dd84 (patch)
tree2d7fc61ef6c4945f6834ac720e4a335bc9db6ca9 /src/qt
parent2acface32aba5454c383556a30cebee1010db39f (diff)
parenta38783747b1c9a9209f70204639e4efcea4193c6 (diff)
downloadbitcoin-962cd3f0587e87de1e38c1777151dca282f3dd84.tar.xz
Merge #9697: [Qt] simple fee bumper with user verification
a38783747 Make sure we re-check the conditions of a feebump during commit (Jonas Schnelli) 9b9ca538c Only update the transactionrecord if the fee bump has been commited (Jonas Schnelli) 6ed4368f1 Make sure we use nTxConfirmTarget during Qt fee bumps (Jonas Schnelli) be08fc39d Make sure we always update the table row after a bumpfee call (Jonas Schnelli) 2678d3dc6 Show old-fee, increase a new-fee in Qt fee bumper confirmation dialog (Jonas Schnelli) 2ec911f60 Add cs_wallet lock assertion to SignTransaction() (Jonas Schnelli) fbf385cc8 [Qt] simple fee bumper with user verification (Jonas Schnelli) Tree-SHA512: a3ce626201abf64cee496dd1d83870de51ba633de40c48eb0219c3eba5085c038af34c284512130d2544de20c1bff9fea1b78f92e3574c21dd4e96c11b8e7d76
Diffstat (limited to 'src/qt')
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/sendcoinsdialog.h3
-rw-r--r--src/qt/transactionview.cpp25
-rw-r--r--src/qt/transactionview.h2
-rw-r--r--src/qt/walletmodel.cpp85
-rw-r--r--src/qt/walletmodel.h3
6 files changed, 116 insertions, 4 deletions
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 098cda6d32..8dcb0fd016 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -31,8 +31,6 @@
#include <QTextDocument>
#include <QTimer>
-#define SEND_CONFIRM_DELAY 3
-
SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
QDialog(parent),
ui(new Ui::SendCoinsDialog),
diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h
index a402edc961..a932f129be 100644
--- a/src/qt/sendcoinsdialog.h
+++ b/src/qt/sendcoinsdialog.h
@@ -100,13 +100,14 @@ Q_SIGNALS:
};
+#define SEND_CONFIRM_DELAY 3
class SendConfirmationDialog : public QMessageBox
{
Q_OBJECT
public:
- SendConfirmationDialog(const QString &title, const QString &text, int secDelay = 0, QWidget *parent = 0);
+ SendConfirmationDialog(const QString &title, const QString &text, int secDelay = SEND_CONFIRM_DELAY, QWidget *parent = 0);
int exec();
private Q_SLOTS:
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 30f4db9450..9008c81634 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -11,6 +11,7 @@
#include "guiutil.h"
#include "optionsmodel.h"
#include "platformstyle.h"
+#include "sendcoinsdialog.h"
#include "transactiondescdialog.h"
#include "transactionfilterproxy.h"
#include "transactionrecord.h"
@@ -37,7 +38,7 @@
TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *parent) :
QWidget(parent), model(0), transactionProxyModel(0),
- transactionView(0), abandonAction(0), columnResizingFixer(0)
+ transactionView(0), abandonAction(0), bumpFeeAction(0), columnResizingFixer(0)
{
// Build filter row
setContentsMargins(0,0,0,0);
@@ -138,6 +139,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
// Actions
abandonAction = new QAction(tr("Abandon transaction"), this);
+ bumpFeeAction = new QAction(tr("Increase transaction fee"), this);
QAction *copyAddressAction = new QAction(tr("Copy address"), this);
QAction *copyLabelAction = new QAction(tr("Copy label"), this);
QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
@@ -156,6 +158,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
contextMenu->addAction(copyTxPlainText);
contextMenu->addAction(showDetailsAction);
contextMenu->addSeparator();
+ contextMenu->addAction(bumpFeeAction);
contextMenu->addAction(abandonAction);
contextMenu->addAction(editLabelAction);
@@ -173,6 +176,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex)));
connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
+ connect(bumpFeeAction, SIGNAL(triggered()), this, SLOT(bumpFee()));
connect(abandonAction, SIGNAL(triggered()), this, SLOT(abandonTx()));
connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
@@ -372,6 +376,7 @@ void TransactionView::contextualMenu(const QPoint &point)
uint256 hash;
hash.SetHex(selection.at(0).data(TransactionTableModel::TxHashRole).toString().toStdString());
abandonAction->setEnabled(model->transactionCanBeAbandoned(hash));
+ bumpFeeAction->setEnabled(model->transactionSignalsRBF(hash));
if(index.isValid())
{
@@ -397,6 +402,24 @@ void TransactionView::abandonTx()
model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, false);
}
+void TransactionView::bumpFee()
+{
+ if(!transactionView || !transactionView->selectionModel())
+ return;
+ QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
+
+ // get the hash from the TxHashRole (QVariant / QString)
+ uint256 hash;
+ QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString();
+ hash.SetHex(hashQStr.toStdString());
+
+ // Bump tx fee over the walletModel
+ if (model->bumpFee(hash)) {
+ // Update the table
+ model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, false);
+ }
+}
+
void TransactionView::copyAddress()
{
GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole);
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index 595701cdd9..52e57cae4c 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -76,6 +76,7 @@ private:
QDateTimeEdit *dateFrom;
QDateTimeEdit *dateTo;
QAction *abandonAction;
+ QAction *bumpFeeAction;
QWidget *createDateRangeWidget();
@@ -99,6 +100,7 @@ private Q_SLOTS:
void openThirdPartyTxUrl(QString url);
void updateWatchOnlyColumn(bool fHaveWatchOnly);
void abandonTx();
+ void bumpFee();
Q_SIGNALS:
void doubleClicked(const QModelIndex&);
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index a2a9271904..37af8abb38 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -8,8 +8,10 @@
#include "consensus/validation.h"
#include "guiconstants.h"
#include "guiutil.h"
+#include "optionsmodel.h"
#include "paymentserver.h"
#include "recentrequeststablemodel.h"
+#include "sendcoinsdialog.h"
#include "transactiontablemodel.h"
#include "base58.h"
@@ -17,15 +19,18 @@
#include "keystore.h"
#include "validation.h"
#include "net.h" // for g_connman
+#include "policy/rbf.h"
#include "sync.h"
#include "ui_interface.h"
#include "util.h" // for GetBoolArg
+#include "wallet/feebumper.h"
#include "wallet/wallet.h"
#include "wallet/walletdb.h" // for BackupWallet
#include <stdint.h>
#include <QDebug>
+#include <QMessageBox>
#include <QSet>
#include <QTimer>
@@ -693,6 +698,86 @@ bool WalletModel::abandonTransaction(uint256 hash) const
return wallet->AbandonTransaction(hash);
}
+bool WalletModel::transactionSignalsRBF(uint256 hash) const
+{
+ LOCK2(cs_main, wallet->cs_wallet);
+ const CWalletTx *wtx = wallet->GetWalletTx(hash);
+ if (wtx && SignalsOptInRBF(*wtx))
+ return true;
+ return false;
+}
+
+bool WalletModel::bumpFee(uint256 hash)
+{
+ std::unique_ptr<CFeeBumper> feeBump;
+ {
+ LOCK2(cs_main, wallet->cs_wallet);
+ feeBump.reset(new CFeeBumper(wallet, hash, nTxConfirmTarget, false, 0, true));
+ }
+ if (feeBump->getResult() != BumpFeeResult::OK)
+ {
+ QMessageBox::critical(0, tr("Fee bump error"), tr("Increasing transaction fee failed") + "<br />(" +
+ (feeBump->getErrors().size() ? QString::fromStdString(feeBump->getErrors()[0]) : "") +")");
+ return false;
+ }
+
+ // allow a user based fee verification
+ QString questionString = tr("Do you want to increase the fee?");
+ questionString.append("<br />");
+ CAmount oldFee = feeBump->getOldFee();
+ CAmount newFee = feeBump->getNewFee();
+ questionString.append("<table style=\"text-align: left;\">");
+ questionString.append("<tr><td>");
+ questionString.append(tr("Current fee:"));
+ questionString.append("</td><td>");
+ questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), oldFee));
+ questionString.append("</td></tr><tr><td>");
+ questionString.append(tr("Increase:"));
+ questionString.append("</td><td>");
+ questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), newFee - oldFee));
+ questionString.append("</td></tr><tr><td>");
+ questionString.append(tr("New fee:"));
+ questionString.append("</td><td>");
+ questionString.append(BitcoinUnits::formatHtmlWithUnit(getOptionsModel()->getDisplayUnit(), newFee));
+ questionString.append("</td></tr></table>");
+ SendConfirmationDialog confirmationDialog(tr("Confirm fee bump"), questionString);
+ confirmationDialog.exec();
+ QMessageBox::StandardButton retval = (QMessageBox::StandardButton)confirmationDialog.result();
+
+ // cancel sign&broadcast if users doesn't want to bump the fee
+ if (retval != QMessageBox::Yes) {
+ return false;
+ }
+
+ WalletModel::UnlockContext ctx(requestUnlock());
+ if(!ctx.isValid())
+ {
+ return false;
+ }
+
+ // sign bumped transaction
+ bool res = false;
+ {
+ LOCK2(cs_main, wallet->cs_wallet);
+ res = feeBump->signTransaction(wallet);
+ }
+ if (!res) {
+ QMessageBox::critical(0, tr("Fee bump error"), tr("Can't sign transaction."));
+ return false;
+ }
+ // commit the bumped transaction
+ {
+ LOCK2(cs_main, wallet->cs_wallet);
+ res = feeBump->commit(wallet);
+ }
+ if(!res) {
+ QMessageBox::critical(0, tr("Fee bump error"), tr("Could not commit transaction") + "<br />(" +
+ QString::fromStdString(feeBump->getErrors()[0])+")");
+ return false;
+ }
+ return true;
+}
+
bool WalletModel::isWalletEnabled()
{
return !GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET);
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 78e45dc369..df5acaf684 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -207,6 +207,9 @@ public:
bool transactionCanBeAbandoned(uint256 hash) const;
bool abandonTransaction(uint256 hash) const;
+ bool transactionSignalsRBF(uint256 hash) const;
+ bool bumpFee(uint256 hash);
+
static bool isWalletEnabled();
bool hdEnabled() const;