Merge #8989: [Qt] overhaul smart-fee slider, adjust default confirmation target

cfe77ef [Qt] overhaul smart-fee slider, adjust default confirmation target (Jonas Schnelli)
6f02899 [Qt] Hide nTxConfirmTarget behind WalletModel (Jonas Schnelli)
004168d CoinControl: add option for custom confirmation target (Jonas Schnelli)
This commit is contained in:
Wladimir J. van der Laan 2016-10-28 14:08:39 +02:00
commit d2143dc937
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
7 changed files with 64 additions and 13 deletions

View File

@ -411,7 +411,7 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QFormLayout" name="formLayoutCoinControl4"> <layout class="QFormLayout" name="formLayoutCoinControl4">
@ -1031,7 +1031,7 @@
<item> <item>
<widget class="QLabel" name="labelSmartFee3"> <widget class="QLabel" name="labelSmartFee3">
<property name="text"> <property name="text">
<string>Confirmation time:</string> <string>Confirmation time target:</string>
</property> </property>
<property name="margin"> <property name="margin">
<number>2</number> <number>2</number>
@ -1095,6 +1095,26 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="confirmationTargetLabel">
<property name="text">
<string>(count)</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_3"> <spacer name="horizontalSpacer_3">
<property name="orientation"> <property name="orientation">

View File

@ -110,7 +110,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
ui->groupCustomFee->setId(ui->radioCustomPerKilobyte, 0); ui->groupCustomFee->setId(ui->radioCustomPerKilobyte, 0);
ui->groupCustomFee->setId(ui->radioCustomAtLeast, 1); ui->groupCustomFee->setId(ui->radioCustomAtLeast, 1);
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->sliderSmartFee->setValue(settings.value("nSmartFeeSliderPosition").toInt());
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());
minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool()); minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool());
@ -172,6 +171,13 @@ void SendCoinsDialog::setModel(WalletModel *_model)
updateMinFeeLabel(); updateMinFeeLabel();
updateSmartFeeLabel(); updateSmartFeeLabel();
updateGlobalFeeVariables(); updateGlobalFeeVariables();
// set the smartfee-sliders default value (wallets default conf.target or last stored value)
QSettings settings;
if (settings.value("nSmartFeeSliderPosition").toInt() == 0)
ui->sliderSmartFee->setValue(ui->sliderSmartFee->maximum() - model->getDefaultConfirmTarget() + 1);
else
ui->sliderSmartFee->setValue(settings.value("nSmartFeeSliderPosition").toInt());
} }
} }
@ -229,10 +235,17 @@ void SendCoinsDialog::on_sendButton_clicked()
// prepare transaction for getting txFee earlier // prepare transaction for getting txFee earlier
WalletModelTransaction currentTransaction(recipients); WalletModelTransaction currentTransaction(recipients);
WalletModel::SendCoinsReturn prepareStatus; WalletModel::SendCoinsReturn prepareStatus;
if (model->getOptionsModel()->getCoinControlFeatures()) // coin control enabled
prepareStatus = model->prepareTransaction(currentTransaction, CoinControlDialog::coinControl); // Always use a CCoinControl instance, use the CoinControlDialog instance if CoinControl has been enabled
CCoinControl ctrl;
if (model->getOptionsModel()->getCoinControlFeatures())
ctrl = *CoinControlDialog::coinControl;
if (ui->radioSmartFee->isChecked())
ctrl.nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 1;
else else
prepareStatus = model->prepareTransaction(currentTransaction); ctrl.nConfirmTarget = 0;
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
processSendCoinsReturn(prepareStatus, processSendCoinsReturn(prepareStatus,
@ -576,6 +589,7 @@ void SendCoinsDialog::updateFeeSectionControls()
ui->labelFeeEstimation ->setEnabled(ui->radioSmartFee->isChecked()); ui->labelFeeEstimation ->setEnabled(ui->radioSmartFee->isChecked());
ui->labelSmartFeeNormal ->setEnabled(ui->radioSmartFee->isChecked()); ui->labelSmartFeeNormal ->setEnabled(ui->radioSmartFee->isChecked());
ui->labelSmartFeeFast ->setEnabled(ui->radioSmartFee->isChecked()); ui->labelSmartFeeFast ->setEnabled(ui->radioSmartFee->isChecked());
ui->confirmationTargetLabel ->setEnabled(ui->radioSmartFee->isChecked());
ui->checkBoxMinimumFee ->setEnabled(ui->radioCustomFee->isChecked()); ui->checkBoxMinimumFee ->setEnabled(ui->radioCustomFee->isChecked());
ui->labelMinFeeWarning ->setEnabled(ui->radioCustomFee->isChecked()); ui->labelMinFeeWarning ->setEnabled(ui->radioCustomFee->isChecked());
ui->radioCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); ui->radioCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked());
@ -587,15 +601,17 @@ void SendCoinsDialog::updateGlobalFeeVariables()
{ {
if (ui->radioSmartFee->isChecked()) if (ui->radioSmartFee->isChecked())
{ {
nTxConfirmTarget = defaultConfirmTarget - ui->sliderSmartFee->value(); int nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 1;
payTxFee = CFeeRate(0); payTxFee = CFeeRate(0);
// set nMinimumTotalFee to 0 to not accidentally pay a custom fee // set nMinimumTotalFee to 0 to not accidentally pay a custom fee
CoinControlDialog::coinControl->nMinimumTotalFee = 0; CoinControlDialog::coinControl->nMinimumTotalFee = 0;
// show the estimated reuquired time for confirmation
ui->confirmationTargetLabel->setText(GUIUtil::formatDurationStr(nConfirmTarget*600)+" / "+tr("%n block(s)", "", nConfirmTarget));
} }
else else
{ {
nTxConfirmTarget = defaultConfirmTarget;
payTxFee = CFeeRate(ui->customFee->value()); payTxFee = CFeeRate(ui->customFee->value());
// if user has selected to set a minimum absolute fee, pass the value to coincontrol // if user has selected to set a minimum absolute fee, pass the value to coincontrol
@ -630,7 +646,7 @@ void SendCoinsDialog::updateSmartFeeLabel()
if(!model || !model->getOptionsModel()) if(!model || !model->getOptionsModel())
return; return;
int nBlocksToConfirm = defaultConfirmTarget - ui->sliderSmartFee->value(); int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 1;
int estimateFoundAtBlocks = nBlocksToConfirm; int estimateFoundAtBlocks = nBlocksToConfirm;
CFeeRate feeRate = mempool.estimateSmartFee(nBlocksToConfirm, &estimateFoundAtBlocks); CFeeRate feeRate = mempool.estimateSmartFee(nBlocksToConfirm, &estimateFoundAtBlocks);
if (feeRate <= CFeeRate(0)) // not enough data => minfee if (feeRate <= CFeeRate(0)) // not enough data => minfee
@ -701,6 +717,8 @@ void SendCoinsDialog::coinControlFeatureChanged(bool checked)
if (!checked && model) // coin control features disabled if (!checked && model) // coin control features disabled
CoinControlDialog::coinControl->SetNull(); CoinControlDialog::coinControl->SetNull();
// make sure we set back the confirmation target
updateGlobalFeeVariables();
coinControlUpdateLabels(); coinControlUpdateLabels();
} }

View File

@ -26,8 +26,6 @@ QT_BEGIN_NAMESPACE
class QUrl; class QUrl;
QT_END_NAMESPACE QT_END_NAMESPACE
const int defaultConfirmTarget = 25;
/** Dialog for sending bitcoins */ /** Dialog for sending bitcoins */
class SendCoinsDialog : public QDialog class SendCoinsDialog : public QDialog
{ {

View File

@ -700,3 +700,8 @@ bool WalletModel::hdEnabled() const
{ {
return wallet->IsHDEnabled(); return wallet->IsHDEnabled();
} }
int WalletModel::getDefaultConfirmTarget() const
{
return nTxConfirmTarget;
}

View File

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

View File

@ -22,6 +22,8 @@ public:
bool fOverrideFeeRate; bool fOverrideFeeRate;
//! Feerate to use if overrideFeeRate is true //! Feerate to use if overrideFeeRate is true
CFeeRate nFeeRate; CFeeRate nFeeRate;
//! Override the default confirmation target, 0 = use default
int nConfirmTarget;
CCoinControl() CCoinControl()
{ {
@ -37,6 +39,7 @@ public:
nMinimumTotalFee = 0; nMinimumTotalFee = 0;
nFeeRate = CFeeRate(0); nFeeRate = CFeeRate(0);
fOverrideFeeRate = false; fOverrideFeeRate = false;
nConfirmTarget = 0;
} }
bool HasSelected() const bool HasSelected() const

View File

@ -2434,17 +2434,22 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
dPriority = wtxNew.ComputePriority(dPriority, nBytes); dPriority = wtxNew.ComputePriority(dPriority, nBytes);
// Allow to override the default confirmation target over the CoinControl instance
int currentConfirmationTarget = nTxConfirmTarget;
if (coinControl && coinControl->nConfirmTarget > 0)
currentConfirmationTarget = coinControl->nConfirmTarget;
// Can we complete this as a free transaction? // Can we complete this as a free transaction?
if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE) if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
{ {
// Not enough fee: enough priority? // Not enough fee: enough priority?
double dPriorityNeeded = mempool.estimateSmartPriority(nTxConfirmTarget); double dPriorityNeeded = mempool.estimateSmartPriority(currentConfirmationTarget);
// Require at least hard-coded AllowFree. // Require at least hard-coded AllowFree.
if (dPriority >= dPriorityNeeded && AllowFree(dPriority)) if (dPriority >= dPriorityNeeded && AllowFree(dPriority))
break; break;
} }
CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool); CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, mempool);
if (coinControl && nFeeNeeded > 0 && coinControl->nMinimumTotalFee > nFeeNeeded) { if (coinControl && nFeeNeeded > 0 && coinControl->nMinimumTotalFee > nFeeNeeded) {
nFeeNeeded = coinControl->nMinimumTotalFee; nFeeNeeded = coinControl->nMinimumTotalFee;
} }