Skip to content

Commit 1983ca6

Browse files
committed
Use CoinControl to pass custom fee setting from QT.
This fixes buggy behavior where we were temporarily setting and unsetting the global payTxFee when trying to send a transaction with a custom fee from the GUI. The previous behavior was inconsistent depending on the order of using the RPC call settxfee and clicking various radio buttons in the sendcoinsdialog. The new behavior is that transactions sent with the GUI will always use either the smartfee slider value or the custom fee set on the GUI and they will not affect the global defaults which are only for RPC and initial GUI values.
1 parent 03ee701 commit 1983ca6

File tree

2 files changed

+25
-37
lines changed

2 files changed

+25
-37
lines changed

src/qt/sendcoinsdialog.cpp

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -175,26 +175,20 @@ void SendCoinsDialog::setModel(WalletModel *_model)
175175
ui->confTargetSelector->addItem(tr("%1 (%2 blocks)").arg(GUIUtil::formatNiceTimeOffset(n*Params().GetConsensus().nPowTargetSpacing)).arg(n));
176176
}
177177
connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSmartFeeLabel()));
178-
connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(updateGlobalFeeVariables()));
179178
connect(ui->confTargetSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(coinControlUpdateLabels()));
180179
connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateFeeSectionControls()));
181-
connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(updateGlobalFeeVariables()));
182180
connect(ui->groupFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels()));
183-
connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, SLOT(updateGlobalFeeVariables()));
184181
connect(ui->groupCustomFee, SIGNAL(buttonClicked(int)), this, SLOT(coinControlUpdateLabels()));
185-
connect(ui->customFee, SIGNAL(valueChanged()), this, SLOT(updateGlobalFeeVariables()));
186182
connect(ui->customFee, SIGNAL(valueChanged()), this, SLOT(coinControlUpdateLabels()));
187183
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(setMinimumFee()));
188184
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateFeeSectionControls()));
189-
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables()));
190185
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
191186
connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(updateSmartFeeLabel()));
192187
connect(ui->optInRBF, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
193188
ui->customFee->setSingleStep(CWallet::GetRequiredFee(1000));
194189
updateFeeSectionControls();
195190
updateMinFeeLabel();
196191
updateSmartFeeLabel();
197-
updateGlobalFeeVariables();
198192

199193
// set default rbf checkbox state
200194
ui->optInRBF->setCheckState(model->getDefaultWalletRbf() ? Qt::Checked : Qt::Unchecked);
@@ -274,12 +268,8 @@ void SendCoinsDialog::on_sendButton_clicked()
274268
CCoinControl ctrl;
275269
if (model->getOptionsModel()->getCoinControlFeatures())
276270
ctrl = *CoinControlDialog::coinControl;
277-
if (ui->radioSmartFee->isChecked()) {
278-
ctrl.m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex());
279-
} else {
280-
ctrl.m_confirm_target = boost::none;
281-
}
282-
ctrl.signalRbf = ui->optInRBF->isChecked();
271+
272+
updateCoinControlState(ctrl);
283273

284274
prepareStatus = model->prepareTransaction(currentTransaction, ctrl);
285275

@@ -636,18 +626,6 @@ void SendCoinsDialog::updateFeeSectionControls()
636626
ui->customFee ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked());
637627
}
638628

639-
void SendCoinsDialog::updateGlobalFeeVariables()
640-
{
641-
if (ui->radioSmartFee->isChecked())
642-
{
643-
payTxFee = CFeeRate(0);
644-
}
645-
else
646-
{
647-
payTxFee = CFeeRate(ui->customFee->value());
648-
}
649-
}
650-
651629
void SendCoinsDialog::updateFeeMinimizedLabel()
652630
{
653631
if(!model || !model->getOptionsModel())
@@ -669,15 +647,30 @@ void SendCoinsDialog::updateMinFeeLabel()
669647
);
670648
}
671649

650+
void SendCoinsDialog::updateCoinControlState(CCoinControl& ctrl)
651+
{
652+
if (ui->radioCustomFee->isChecked()) {
653+
ctrl.m_feerate = CFeeRate(ui->customFee->value());
654+
} else {
655+
ctrl.m_feerate = boost::none;
656+
}
657+
// Avoid using global defaults when sending money from the GUI
658+
// Either custom fee will be used or if not selected, the confirmation target from dropdown box
659+
ctrl.m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex());
660+
ctrl.signalRbf = ui->optInRBF->isChecked();
661+
}
662+
672663
void SendCoinsDialog::updateSmartFeeLabel()
673664
{
674665
if(!model || !model->getOptionsModel())
675666
return;
676-
677-
int nBlocksToConfirm = getConfTargetForIndex(ui->confTargetSelector->currentIndex());
667+
CCoinControl coin_control;
668+
updateCoinControlState(coin_control);
669+
coin_control.m_feerate = boost::none; // Explicitly use only fee estimation rate for smart fee labels
678670
FeeCalculation feeCalc;
679-
bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET, ui->optInRBF->isChecked());
680-
CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocksToConfirm, &feeCalc, ::mempool, conservative_estimate);
671+
bool conservative_estimate = CalculateEstimateType(FeeEstimateMode::UNSET, coin_control.signalRbf);
672+
CFeeRate feeRate = ::feeEstimator.estimateSmartFee(*coin_control.m_confirm_target, &feeCalc, ::mempool, conservative_estimate);
673+
681674
if (feeRate <= CFeeRate(0)) // not enough data => minfee
682675
{
683676
ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(),
@@ -752,8 +745,6 @@ void SendCoinsDialog::coinControlFeatureChanged(bool checked)
752745
if (!checked && model) // coin control features disabled
753746
CoinControlDialog::coinControl->SetNull();
754747

755-
// make sure we set back the confirmation target
756-
updateGlobalFeeVariables();
757748
coinControlUpdateLabels();
758749
}
759750

@@ -844,15 +835,11 @@ void SendCoinsDialog::coinControlUpdateLabels()
844835
if (!model || !model->getOptionsModel())
845836
return;
846837

838+
updateCoinControlState(*CoinControlDialog::coinControl);
839+
847840
// set pay amounts
848841
CoinControlDialog::payAmounts.clear();
849842
CoinControlDialog::fSubtractFeeFromAmount = false;
850-
if (ui->radioSmartFee->isChecked()) {
851-
CoinControlDialog::coinControl->m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex());
852-
} else {
853-
CoinControlDialog::coinControl->m_confirm_target = boost::none;
854-
}
855-
CoinControlDialog::coinControl->signalRbf = ui->optInRBF->isChecked();
856843

857844
for(int i = 0; i < ui->entries->count(); ++i)
858845
{

src/qt/sendcoinsdialog.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public Q_SLOTS:
6868
void processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg = QString());
6969
void minimizeFeeSection(bool fMinimize);
7070
void updateFeeMinimizedLabel();
71+
// Update the passed in CCoinControl with state from the GUI
72+
void updateCoinControlState(CCoinControl& ctrl);
7173

7274
private Q_SLOTS:
7375
void on_sendButton_clicked();
@@ -91,7 +93,6 @@ private Q_SLOTS:
9193
void updateFeeSectionControls();
9294
void updateMinFeeLabel();
9395
void updateSmartFeeLabel();
94-
void updateGlobalFeeVariables();
9596

9697
Q_SIGNALS:
9798
// Fired when a message should be reported to the user

0 commit comments

Comments
 (0)