Merge #9592: [Qt] Add checkbox in the GUI to opt-in to RBF when creating a transaction

c4e4792 [Qt] Change RBF checkbox to reflect -walletrbf setting (Russell Yanofsky)
838a58e [Qt] Add simple optin-RBF checkbox and confirmation info (Jonas Schnelli)
568c05a Allow to opt-into RBF when creating a transaction (Jonas Schnelli)

Tree-SHA512: 3d52dcd4e44da8aed4d631748074afef78d38c860f2a8b95323f4801a989d6599a3498a753fc10daba4098c527ef5a0eb942e5b3f1bfd656e1a6bd272b8e6c57
This commit is contained in:
Jonas Schnelli 2017-03-17 15:31:21 +01:00
commit 9c7b7cf0bb
No known key found for this signature in database
GPG Key ID: 1EB776BB03C7922D
6 changed files with 35 additions and 3 deletions

View File

@ -1180,6 +1180,16 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QCheckBox" name="optInRBF">
<property name="text">
<string>Request Replace-By-Fee</string>
</property>
<property name="toolTip">
<string>Indicates that the sender may wish to replace this transaction with a new one paying higher fees (prior to being confirmed).</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -1190,8 +1200,8 @@
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>800</width> <width>40</width>
<height>1</height> <height>5</height>
</size> </size>
</property> </property>
</spacer> </spacer>

View File

@ -114,6 +114,7 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
ui->groupCustomFee->button((int)std::max(0, std::min(1, settings.value("nCustomFeeRadio").toInt())))->setChecked(true); ui->groupCustomFee->button((int)std::max(0, std::min(1, settings.value("nCustomFeeRadio").toInt())))->setChecked(true);
ui->customFee->setValue(settings.value("nTransactionFee").toLongLong()); ui->customFee->setValue(settings.value("nTransactionFee").toLongLong());
ui->checkBoxMinimumFee->setChecked(settings.value("fPayOnlyMinFee").toBool()); ui->checkBoxMinimumFee->setChecked(settings.value("fPayOnlyMinFee").toBool());
ui->optInRBF->setCheckState(model->getDefaultWalletRbf() ? Qt::Checked : Qt::Unchecked);
minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool()); minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool());
} }
@ -247,6 +248,8 @@ void SendCoinsDialog::on_sendButton_clicked()
else else
ctrl.nConfirmTarget = 0; ctrl.nConfirmTarget = 0;
ctrl.signalRbf = ui->optInRBF->isChecked();
prepareStatus = model->prepareTransaction(currentTransaction, &ctrl); prepareStatus = model->prepareTransaction(currentTransaction, &ctrl);
// process prepareStatus and on error generate message shown to user // process prepareStatus and on error generate message shown to user
@ -326,6 +329,13 @@ void SendCoinsDialog::on_sendButton_clicked()
questionString.append(QString("<span style='font-size:10pt;font-weight:normal;'><br />(=%2)</span>") questionString.append(QString("<span style='font-size:10pt;font-weight:normal;'><br />(=%2)</span>")
.arg(alternativeUnits.join(" " + tr("or") + "<br />"))); .arg(alternativeUnits.join(" " + tr("or") + "<br />")));
if (ui->optInRBF->isChecked())
{
questionString.append("<hr /><span>");
questionString.append(tr("This transaction signals replaceability (optin-RBF)."));
questionString.append("</span>");
}
SendConfirmationDialog confirmationDialog(tr("Confirm send coins"), SendConfirmationDialog confirmationDialog(tr("Confirm send coins"),
questionString.arg(formatted.join("<br />")), SEND_CONFIRM_DELAY, this); questionString.arg(formatted.join("<br />")), SEND_CONFIRM_DELAY, this);
confirmationDialog.exec(); confirmationDialog.exec();

View File

@ -706,3 +706,8 @@ int WalletModel::getDefaultConfirmTarget() const
{ {
return nTxConfirmTarget; return nTxConfirmTarget;
} }
bool WalletModel::getDefaultWalletRbf() const
{
return fWalletRbf;
}

View File

@ -213,6 +213,8 @@ public:
int getDefaultConfirmTarget() const; int getDefaultConfirmTarget() const;
bool getDefaultWalletRbf() const;
private: private:
CWallet *wallet; CWallet *wallet;
bool fHaveWatchOnly; bool fHaveWatchOnly;

View File

@ -6,6 +6,7 @@
#define BITCOIN_WALLET_COINCONTROL_H #define BITCOIN_WALLET_COINCONTROL_H
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include "wallet/wallet.h"
/** Coin Control Features. */ /** Coin Control Features. */
class CCoinControl class CCoinControl
@ -24,6 +25,8 @@ public:
CFeeRate nFeeRate; CFeeRate nFeeRate;
//! Override the default confirmation target, 0 = use default //! Override the default confirmation target, 0 = use default
int nConfirmTarget; int nConfirmTarget;
//! Signal BIP-125 replace by fee.
bool signalRbf;
CCoinControl() CCoinControl()
{ {
@ -40,6 +43,7 @@ public:
nFeeRate = CFeeRate(0); nFeeRate = CFeeRate(0);
fOverrideFeeRate = false; fOverrideFeeRate = false;
nConfirmTarget = 0; nConfirmTarget = 0;
signalRbf = fWalletRbf;
} }
bool HasSelected() const bool HasSelected() const

View File

@ -2517,9 +2517,10 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// to avoid conflicting with other possible uses of nSequence, // to avoid conflicting with other possible uses of nSequence,
// and in the spirit of "smallest possible change from prior // and in the spirit of "smallest possible change from prior
// behavior." // behavior."
bool rbf = coinControl ? coinControl->signalRbf : fWalletRbf;
for (const auto& coin : setCoins) for (const auto& coin : setCoins)
txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(), txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(),
std::numeric_limits<unsigned int>::max() - (fWalletRbf ? 2 : 1))); std::numeric_limits<unsigned int>::max() - (rbf ? 2 : 1)));
// Fill in dummy signatures for fee calculation. // Fill in dummy signatures for fee calculation.
if (!DummySignTx(txNew, setCoins)) { if (!DummySignTx(txNew, setCoins)) {