Skip to content

Commit b7fe9cd

Browse files
committed
Merge pull request #5200
c1c9d5b [Qt] Add Smartfee to GUI (Cozz Lovan) e7876b2 [Wallet] Prevent user from paying a non-sense fee (Cozz Lovan) ed3e5e4 [Wallet] Add global boolean whether to pay at least the custom fee (default=true) (Cozz Lovan) 0ed9675 [Wallet] Add global boolean whether to send free transactions (default=true) (Cozz Lovan)
2 parents 8c41853 + c1c9d5b commit b7fe9cd

21 files changed

+911
-164
lines changed

src/init.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ std::string HelpMessage(HelpMessageMode mode)
290290
strUsage += " -paytxfee=<amt> " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n";
291291
strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n";
292292
strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n";
293+
strUsage += " -sendfreetransactions " + strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), 0) + "\n";
293294
strUsage += " -spendzeroconfchange " + strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), 1) + "\n";
294295
strUsage += " -txconfirmtarget=<n> " + strprintf(_("If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: %u)"), 1) + "\n";
295296
strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n";
@@ -704,6 +705,7 @@ bool AppInit2(boost::thread_group& threadGroup)
704705
}
705706
nTxConfirmTarget = GetArg("-txconfirmtarget", 1);
706707
bSpendZeroConfChange = GetArg("-spendzeroconfchange", true);
708+
fSendFreeTransactions = GetArg("-sendfreetransactions", false);
707709

708710
std::string strWalletFile = GetArg("-wallet", "wallet.dat");
709711
#endif // ENABLE_WALLET

src/qt/bitcoinamountfield.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@ void BitcoinAmountField::clear()
221221
unit->setCurrentIndex(0);
222222
}
223223

224+
void BitcoinAmountField::setEnabled(bool fEnabled)
225+
{
226+
amount->setEnabled(fEnabled);
227+
unit->setEnabled(fEnabled);
228+
}
229+
224230
bool BitcoinAmountField::validate()
225231
{
226232
bool valid = false;

src/qt/bitcoinamountfield.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ class BitcoinAmountField: public QWidget
4848
/** Make field empty and ready for new input. */
4949
void clear();
5050

51+
/** Enable/Disable. */
52+
void setEnabled(bool fEnabled);
53+
5154
/** Qt messes up the tab chain by default in some cases (issue https://bugreports.qt-project.org/browse/QTBUG-10907),
5255
in these cases we have to set it up manually.
5356
*/

src/qt/coincontroldialog.cpp

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <QDialogButtonBox>
2525
#include <QFlags>
2626
#include <QIcon>
27+
#include <QSettings>
2728
#include <QString>
2829
#include <QTreeWidget>
2930
#include <QTreeWidgetItem>
@@ -130,10 +131,22 @@ CoinControlDialog::CoinControlDialog(QWidget *parent) :
130131

131132
// default view is sorted by amount desc
132133
sortView(COLUMN_AMOUNT_INT64, Qt::DescendingOrder);
134+
135+
// restore list mode and sortorder as a convenience feature
136+
QSettings settings;
137+
if (settings.contains("nCoinControlMode") && !settings.value("nCoinControlMode").toBool())
138+
ui->radioTreeMode->click();
139+
if (settings.contains("nCoinControlSortColumn") && settings.contains("nCoinControlSortOrder"))
140+
sortView(settings.value("nCoinControlSortColumn").toInt(), ((Qt::SortOrder)settings.value("nCoinControlSortOrder").toInt()));
133141
}
134142

135143
CoinControlDialog::~CoinControlDialog()
136144
{
145+
QSettings settings;
146+
settings.setValue("nCoinControlMode", ui->radioListMode->isChecked());
147+
settings.setValue("nCoinControlSortColumn", sortColumn);
148+
settings.setValue("nCoinControlSortOrder", (int)sortOrder);
149+
137150
delete ui;
138151
}
139152

@@ -290,19 +303,19 @@ void CoinControlDialog::clipboardAmount()
290303
// copy label "Fee" to clipboard
291304
void CoinControlDialog::clipboardFee()
292305
{
293-
GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")));
306+
GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")).replace("~", ""));
294307
}
295308

296309
// copy label "After fee" to clipboard
297310
void CoinControlDialog::clipboardAfterFee()
298311
{
299-
GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")));
312+
GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace("~", ""));
300313
}
301314

302315
// copy label "Bytes" to clipboard
303316
void CoinControlDialog::clipboardBytes()
304317
{
305-
GUIUtil::setClipboard(ui->labelCoinControlBytes->text());
318+
GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace("~", ""));
306319
}
307320

308321
// copy label "Priority" to clipboard
@@ -320,7 +333,7 @@ void CoinControlDialog::clipboardLowOutput()
320333
// copy label "Change" to clipboard
321334
void CoinControlDialog::clipboardChange()
322335
{
323-
GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")));
336+
GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")).replace("~", ""));
324337
}
325338

326339
// treeview: sort
@@ -402,26 +415,22 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
402415
}
403416

404417
// return human readable label for priority number
405-
QString CoinControlDialog::getPriorityLabel(const CTxMemPool& pool, double dPriority)
418+
QString CoinControlDialog::getPriorityLabel(double dPriority, double mempoolEstimatePriority)
406419
{
407-
// confirmations -> textual description
408-
typedef std::map<unsigned int, QString> PriorityDescription;
409-
const static PriorityDescription priorityDescriptions = boost::assign::map_list_of
410-
(1, tr("highest"))(2, tr("higher"))(3, tr("high"))
411-
(5, tr("medium-high"))(6, tr("medium"))
412-
(10, tr("low-medium"))(15, tr("low"))
413-
(20, tr("lower"));
414-
415-
BOOST_FOREACH(const PriorityDescription::value_type& i, priorityDescriptions)
416-
{
417-
double p = mempool.estimatePriority(i.first);
418-
if (p > 0 && dPriority >= p) return i.second;
419-
}
420-
// Note: if mempool hasn't accumulated enough history (estimatePriority
421-
// returns -1) we're conservative and classify as "lowest"
422-
if (mempool.estimatePriority(nTxConfirmTarget) <= 0 && AllowFree(dPriority))
423-
return ">=" + tr("medium");
424-
return tr("lowest");
420+
double dPriorityMedium = mempoolEstimatePriority;
421+
422+
if (dPriorityMedium <= 0)
423+
dPriorityMedium = AllowFreeThreshold(); // not enough data, back to hard-coded
424+
425+
if (dPriority / 1000000 > dPriorityMedium) return tr("highest");
426+
else if (dPriority / 100000 > dPriorityMedium) return tr("higher");
427+
else if (dPriority / 10000 > dPriorityMedium) return tr("high");
428+
else if (dPriority / 1000 > dPriorityMedium) return tr("medium-high");
429+
else if (dPriority > dPriorityMedium) return tr("medium");
430+
else if (dPriority * 10 > dPriorityMedium) return tr("low-medium");
431+
else if (dPriority * 100 > dPriorityMedium) return tr("low");
432+
else if (dPriority * 1000 > dPriorityMedium) return tr("lower");
433+
else return tr("lowest");
425434
}
426435

427436
// shows count of locked unspent outputs
@@ -470,6 +479,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
470479
double dPriorityInputs = 0;
471480
unsigned int nQuantity = 0;
472481
int nQuantityUncompressed = 0;
482+
bool fAllowFree = false;
473483

474484
vector<COutPoint> vCoinControl;
475485
vector<COutput> vOutputs;
@@ -522,24 +532,22 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
522532
nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here
523533

524534
// Priority
535+
double mempoolEstimatePriority = mempool.estimatePriority(nTxConfirmTarget);
525536
dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority)
526-
sPriorityLabel = CoinControlDialog::getPriorityLabel(mempool, dPriority);
537+
sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority, mempoolEstimatePriority);
527538

528-
// Voluntary Fee
529-
nPayFee = payTxFee.GetFee(max((unsigned int)1000, nBytes));
539+
// Fee
540+
nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
530541

531-
// Min Fee
532-
if (nPayFee == 0)
533-
{
534-
nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
535-
536-
double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget);
537-
if (dPriorityNeeded <= 0 && !AllowFree(dPriority)) // not enough mempool history: never send free
538-
dPriorityNeeded = std::numeric_limits<double>::max();
542+
// Allow free?
543+
double dPriorityNeeded = mempoolEstimatePriority;
544+
if (dPriorityNeeded <= 0)
545+
dPriorityNeeded = AllowFreeThreshold(); // not enough data, back to hard-coded
546+
fAllowFree = (dPriority >= dPriorityNeeded);
539547

540-
if (nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE && dPriority >= dPriorityNeeded)
548+
if (fSendFreeTransactions)
549+
if (fAllowFree && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
541550
nPayFee = 0;
542-
}
543551

544552
if (nPayAmount > 0)
545553
{
@@ -595,7 +603,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
595603
l6->setText(sPriorityLabel); // Priority
596604
l7->setText(fDust ? tr("yes") : tr("no")); // Dust
597605
l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change
598-
if (nPayFee > 0)
606+
if (nPayFee > 0 && !(payTxFee.GetFeePerK() > 0 && fPayAtLeastCustomFee && nBytes < 1000))
599607
{
600608
l3->setText("~" + l3->text());
601609
l4->setText("~" + l4->text());
@@ -605,7 +613,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
605613

606614
// turn labels "red"
607615
l5->setStyleSheet((nBytes >= MAX_FREE_TRANSACTION_CREATE_SIZE) ? "color:red;" : "");// Bytes >= 1000
608-
l6->setStyleSheet((dPriority > 0 && !AllowFree(dPriority)) ? "color:red;" : ""); // Priority < "medium"
616+
l6->setStyleSheet((dPriority > 0 && !fAllowFree) ? "color:red;" : ""); // Priority < "medium"
609617
l7->setStyleSheet((fDust) ? "color:red;" : ""); // Dust = "yes"
610618

611619
// tool tips
@@ -620,7 +628,11 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
620628
QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, ::minRelayTxFee.GetFee(546)));
621629

622630
// how many satoshis the estimated fee can vary per byte we guess wrong
623-
double dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), std::max(payTxFee.GetFeePerK(), mempool.estimateFee(nTxConfirmTarget).GetFeePerK())) / 1000;
631+
double dFeeVary;
632+
if (payTxFee.GetFeePerK() > 0)
633+
dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000;
634+
else
635+
dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), mempool.estimateFee(nTxConfirmTarget).GetFeePerK()) / 1000;
624636
QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);
625637

626638
l3->setToolTip(toolTip4);
@@ -656,6 +668,7 @@ void CoinControlDialog::updateView()
656668
QFlags<Qt::ItemFlag> flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate;
657669

658670
int nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
671+
double mempoolEstimatePriority = mempool.estimatePriority(nTxConfirmTarget);
659672

660673
map<QString, vector<COutput> > mapCoins;
661674
model->listCoins(mapCoins);
@@ -745,7 +758,7 @@ void CoinControlDialog::updateView()
745758

746759
// priority
747760
double dPriority = ((double)out.tx->vout[out.i].nValue / (nInputSize + 78)) * (out.nDepth+1); // 78 = 2 * 34 + 10
748-
itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(mempool, dPriority));
761+
itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPriority, mempoolEstimatePriority));
749762
itemOutput->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPriority), 20, " "));
750763
dPrioritySum += (double)out.tx->vout[out.i].nValue * (out.nDepth+1);
751764
nInputSum += nInputSize;
@@ -778,7 +791,7 @@ void CoinControlDialog::updateView()
778791
itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")");
779792
itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum));
780793
itemWalletAddress->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(nSum), 15, " "));
781-
itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(mempool, dPrioritySum));
794+
itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPrioritySum, mempoolEstimatePriority));
782795
itemWalletAddress->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPrioritySum), 20, " "));
783796
}
784797
}

src/qt/coincontroldialog.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class CoinControlDialog : public QDialog
3737

3838
// static because also called from sendcoinsdialog
3939
static void updateLabels(WalletModel*, QDialog*);
40-
static QString getPriorityLabel(const CTxMemPool& pool, double);
40+
static QString getPriorityLabel(double dPriority, double mempoolEstimatePriority);
4141

4242
static QList<CAmount> payAmounts;
4343
static CCoinControl *coinControl;

src/qt/forms/optionsdialog.ui

Lines changed: 13 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -137,65 +137,6 @@
137137
<string>W&amp;allet</string>
138138
</attribute>
139139
<layout class="QVBoxLayout" name="verticalLayout_Wallet">
140-
<item>
141-
<widget class="QLabel" name="transactionFeeInfoLabel">
142-
<property name="text">
143-
<string>Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB.</string>
144-
</property>
145-
<property name="textFormat">
146-
<enum>Qt::PlainText</enum>
147-
</property>
148-
<property name="wordWrap">
149-
<bool>true</bool>
150-
</property>
151-
</widget>
152-
</item>
153-
<item>
154-
<layout class="QHBoxLayout" name="horizontalLayout_1_Wallet">
155-
<item>
156-
<widget class="QLabel" name="transactionFeeLabel">
157-
<property name="text">
158-
<string>Pay transaction &amp;fee</string>
159-
</property>
160-
<property name="textFormat">
161-
<enum>Qt::PlainText</enum>
162-
</property>
163-
<property name="buddy">
164-
<cstring>transactionFee</cstring>
165-
</property>
166-
</widget>
167-
</item>
168-
<item>
169-
<widget class="BitcoinAmountField" name="transactionFee"/>
170-
</item>
171-
<item>
172-
<spacer name="horizontalSpacer_1_Wallet">
173-
<property name="orientation">
174-
<enum>Qt::Horizontal</enum>
175-
</property>
176-
<property name="sizeHint" stdset="0">
177-
<size>
178-
<width>40</width>
179-
<height>20</height>
180-
</size>
181-
</property>
182-
</spacer>
183-
</item>
184-
</layout>
185-
</item>
186-
<item>
187-
<spacer name="verticalSpacer_Wallet">
188-
<property name="orientation">
189-
<enum>Qt::Vertical</enum>
190-
</property>
191-
<property name="sizeHint" stdset="0">
192-
<size>
193-
<width>20</width>
194-
<height>40</height>
195-
</size>
196-
</property>
197-
</spacer>
198-
</item>
199140
<item>
200141
<widget class="QGroupBox" name="groupBox">
201142
<property name="title">
@@ -225,6 +166,19 @@
225166
</layout>
226167
</widget>
227168
</item>
169+
<item>
170+
<spacer name="verticalSpacer_Wallet">
171+
<property name="orientation">
172+
<enum>Qt::Vertical</enum>
173+
</property>
174+
<property name="sizeHint" stdset="0">
175+
<size>
176+
<width>20</width>
177+
<height>40</height>
178+
</size>
179+
</property>
180+
</spacer>
181+
</item>
228182
</layout>
229183
</widget>
230184
<widget class="QWidget" name="tabNetwork">
@@ -632,12 +586,6 @@
632586
</layout>
633587
</widget>
634588
<customwidgets>
635-
<customwidget>
636-
<class>BitcoinAmountField</class>
637-
<extends>QLineEdit</extends>
638-
<header>bitcoinamountfield.h</header>
639-
<container>1</container>
640-
</customwidget>
641589
<customwidget>
642590
<class>QValidatedLineEdit</class>
643591
<extends>QLineEdit</extends>

0 commit comments

Comments
 (0)