|
|
|
|
@@ -16,6 +16,8 @@
|
|
|
|
|
#include "main.h"
|
|
|
|
|
#include "wallet.h"
|
|
|
|
|
|
|
|
|
|
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
|
|
|
|
|
|
|
|
|
|
#include <QApplication>
|
|
|
|
|
#include <QCheckBox>
|
|
|
|
|
#include <QCursor>
|
|
|
|
|
@@ -400,23 +402,24 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// return human readable label for priority number
|
|
|
|
|
QString CoinControlDialog::getPriorityLabel(double dPriority)
|
|
|
|
|
QString CoinControlDialog::getPriorityLabel(const CTxMemPool& pool, double dPriority)
|
|
|
|
|
{
|
|
|
|
|
if (AllowFree(dPriority)) // at least medium
|
|
|
|
|
// confirmations -> textual description
|
|
|
|
|
typedef std::map<unsigned int, QString> PriorityDescription;
|
|
|
|
|
const static PriorityDescription priorityDescriptions = boost::assign::map_list_of
|
|
|
|
|
(1, tr("highest"))(2, tr("higher"))(3, tr("high"))
|
|
|
|
|
(5, tr("medium-high"))(6, tr("medium"))
|
|
|
|
|
(10, tr("low-medium"))(15, tr("low"))
|
|
|
|
|
(20, tr("lower"));
|
|
|
|
|
|
|
|
|
|
BOOST_FOREACH(const PriorityDescription::value_type& i, priorityDescriptions)
|
|
|
|
|
{
|
|
|
|
|
if (AllowFree(dPriority / 1000000)) return tr("highest");
|
|
|
|
|
else if (AllowFree(dPriority / 100000)) return tr("higher");
|
|
|
|
|
else if (AllowFree(dPriority / 10000)) return tr("high");
|
|
|
|
|
else if (AllowFree(dPriority / 1000)) return tr("medium-high");
|
|
|
|
|
else return tr("medium");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (AllowFree(dPriority * 10)) return tr("low-medium");
|
|
|
|
|
else if (AllowFree(dPriority * 100)) return tr("low");
|
|
|
|
|
else if (AllowFree(dPriority * 1000)) return tr("lower");
|
|
|
|
|
else return tr("lowest");
|
|
|
|
|
double p = mempool.estimatePriority(i.first);
|
|
|
|
|
if (p > 0 && dPriority >= p) return i.second;
|
|
|
|
|
}
|
|
|
|
|
// Note: if mempool hasn't accumulated enough history (estimatePriority
|
|
|
|
|
// returns -1) we're conservative and classify as "lowest"
|
|
|
|
|
return tr("lowest");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// shows count of locked unspent outputs
|
|
|
|
|
@@ -449,7 +452,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
|
|
|
|
{
|
|
|
|
|
CTxOut txout(amount, (CScript)vector<unsigned char>(24, 0));
|
|
|
|
|
txDummy.vout.push_back(txout);
|
|
|
|
|
if (txout.IsDust(CTransaction::minRelayTxFee))
|
|
|
|
|
if (txout.IsDust(::minRelayTxFee))
|
|
|
|
|
fDust = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -518,15 +521,20 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
|
|
|
|
|
|
|
|
|
// Priority
|
|
|
|
|
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)
|
|
|
|
|
sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority);
|
|
|
|
|
sPriorityLabel = CoinControlDialog::getPriorityLabel(mempool, dPriority);
|
|
|
|
|
|
|
|
|
|
// Fee
|
|
|
|
|
int64_t nFee = payTxFee.GetFee(max((unsigned int)1000, nBytes));
|
|
|
|
|
|
|
|
|
|
// Min Fee
|
|
|
|
|
int64_t nMinFee = GetMinFee(txDummy, nBytes, AllowFree(dPriority), GMF_SEND);
|
|
|
|
|
nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
|
|
|
|
|
|
|
|
|
|
nPayFee = max(nFee, nMinFee);
|
|
|
|
|
double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget);
|
|
|
|
|
if (dPriorityNeeded <= 0) // Not enough mempool history: never send free
|
|
|
|
|
dPriorityNeeded = std::numeric_limits<double>::max();
|
|
|
|
|
|
|
|
|
|
if (nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE && dPriority >= dPriorityNeeded)
|
|
|
|
|
nPayFee = 0;
|
|
|
|
|
|
|
|
|
|
if (nPayAmount > 0)
|
|
|
|
|
{
|
|
|
|
|
@@ -536,7 +544,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
|
|
|
|
if (nChange > 0 && nChange < CENT)
|
|
|
|
|
{
|
|
|
|
|
CTxOut txout(nChange, (CScript)vector<unsigned char>(24, 0));
|
|
|
|
|
if (txout.IsDust(CTransaction::minRelayTxFee))
|
|
|
|
|
if (txout.IsDust(::minRelayTxFee))
|
|
|
|
|
{
|
|
|
|
|
nPayFee += nChange;
|
|
|
|
|
nChange = 0;
|
|
|
|
|
@@ -591,23 +599,23 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// turn labels "red"
|
|
|
|
|
l5->setStyleSheet((nBytes >= 1000) ? "color:red;" : ""); // Bytes >= 1000
|
|
|
|
|
l5->setStyleSheet((nBytes >= MAX_FREE_TRANSACTION_CREATE_SIZE) ? "color:red;" : "");// Bytes >= 1000
|
|
|
|
|
l6->setStyleSheet((dPriority > 0 && !AllowFree(dPriority)) ? "color:red;" : ""); // Priority < "medium"
|
|
|
|
|
l7->setStyleSheet((fDust) ? "color:red;" : ""); // Dust = "yes"
|
|
|
|
|
|
|
|
|
|
// tool tips
|
|
|
|
|
QString toolTip1 = tr("This label turns red, if the transaction size is greater than 1000 bytes.") + "<br /><br />";
|
|
|
|
|
toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK())) + "<br /><br />";
|
|
|
|
|
toolTip1 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::minTxFee.GetFeePerK())) + "<br /><br />";
|
|
|
|
|
toolTip1 += tr("Can vary +/- 1 byte per input.");
|
|
|
|
|
|
|
|
|
|
QString toolTip2 = tr("Transactions with higher priority are more likely to get included into a block.") + "<br /><br />";
|
|
|
|
|
toolTip2 += tr("This label turns red, if the priority is smaller than \"medium\".") + "<br /><br />";
|
|
|
|
|
toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minTxFee.GetFeePerK()));
|
|
|
|
|
toolTip2 += tr("This means a fee of at least %1 per kB is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CWallet::minTxFee.GetFeePerK()));
|
|
|
|
|
|
|
|
|
|
QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CTransaction::minRelayTxFee.GetFee(546)));
|
|
|
|
|
QString toolTip3 = tr("This label turns red, if any recipient receives an amount smaller than %1.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, ::minRelayTxFee.GetFee(546)));
|
|
|
|
|
|
|
|
|
|
// how many satoshis the estimated fee can vary per byte we guess wrong
|
|
|
|
|
double dFeeVary = (double)std::max(CTransaction::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000;
|
|
|
|
|
double dFeeVary = (double)std::max(CWallet::minTxFee.GetFeePerK(), payTxFee.GetFeePerK()) / 1000;
|
|
|
|
|
QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);
|
|
|
|
|
|
|
|
|
|
l3->setToolTip(toolTip4);
|
|
|
|
|
@@ -732,7 +740,7 @@ void CoinControlDialog::updateView()
|
|
|
|
|
|
|
|
|
|
// priority
|
|
|
|
|
double dPriority = ((double)out.tx->vout[out.i].nValue / (nInputSize + 78)) * (out.nDepth+1); // 78 = 2 * 34 + 10
|
|
|
|
|
itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPriority));
|
|
|
|
|
itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(mempool, dPriority));
|
|
|
|
|
itemOutput->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPriority), 20, " "));
|
|
|
|
|
dPrioritySum += (double)out.tx->vout[out.i].nValue * (out.nDepth+1);
|
|
|
|
|
nInputSum += nInputSize;
|
|
|
|
|
@@ -765,7 +773,7 @@ void CoinControlDialog::updateView()
|
|
|
|
|
itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")");
|
|
|
|
|
itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum));
|
|
|
|
|
itemWalletAddress->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(nSum), 15, " "));
|
|
|
|
|
itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPrioritySum));
|
|
|
|
|
itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(mempool, dPrioritySum));
|
|
|
|
|
itemWalletAddress->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64_t)dPrioritySum), 20, " "));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|