Move fee policy out of core
This commit is contained in:
parent
4b7b1bb1ac
commit
13fc83c77b
@ -80,7 +80,7 @@ CFeeRate::CFeeRate(int64_t nFeePaid, size_t nSize)
|
|||||||
nSatoshisPerK = 0;
|
nSatoshisPerK = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t CFeeRate::GetFee(size_t nSize)
|
int64_t CFeeRate::GetFee(size_t nSize) const
|
||||||
{
|
{
|
||||||
return nSatoshisPerK*nSize / 1000;
|
return nSatoshisPerK*nSize / 1000;
|
||||||
}
|
}
|
||||||
|
@ -125,8 +125,8 @@ public:
|
|||||||
CFeeRate(int64_t nFeePaid, size_t nSize);
|
CFeeRate(int64_t nFeePaid, size_t nSize);
|
||||||
CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
|
CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
|
||||||
|
|
||||||
int64_t GetFee(size_t size); // unit returned is satoshis
|
int64_t GetFee(size_t size) const; // unit returned is satoshis
|
||||||
int64_t GetFeePerK() { return GetFee(1000); } // satoshis-per-1000-bytes
|
int64_t GetFeePerK() const { return GetFee(1000); } // satoshis-per-1000-bytes
|
||||||
|
|
||||||
friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
|
friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
|
||||||
friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
|
friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
|
||||||
@ -217,8 +217,6 @@ private:
|
|||||||
void UpdateHash() const;
|
void UpdateHash() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static CFeeRate minTxFee;
|
|
||||||
static CFeeRate minRelayTxFee;
|
|
||||||
static const int CURRENT_VERSION=1;
|
static const int CURRENT_VERSION=1;
|
||||||
|
|
||||||
// The local variables are made const to prevent unintended modification
|
// The local variables are made const to prevent unintended modification
|
||||||
|
30
src/init.cpp
30
src/init.cpp
@ -253,15 +253,16 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
strUsage += "\n" + _("Wallet options:") + "\n";
|
strUsage += "\n" + _("Wallet options:") + "\n";
|
||||||
strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n";
|
strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n";
|
||||||
|
strUsage += " -mintxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), FormatMoney(CWallet::minTxFee.GetFeePerK())) + "\n";
|
||||||
strUsage += " -paytxfee=<amt> " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n";
|
strUsage += " -paytxfee=<amt> " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n";
|
||||||
strUsage += " -txconfirmtarget=<n> " + _("If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: 1)") + "\n";
|
|
||||||
strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n";
|
strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n";
|
||||||
|
strUsage += " -respendnotify=<cmd> " + _("Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)") + "\n";
|
||||||
strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n";
|
strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n";
|
||||||
strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n";
|
strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n";
|
||||||
|
strUsage += " -txconfirmtarget=<n> " + _("If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: 1)") + "\n";
|
||||||
strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n";
|
strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n";
|
||||||
strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n";
|
strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n";
|
||||||
strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n";
|
strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n";
|
||||||
strUsage += " -respendnotify=<cmd> " + _("Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)") + "\n";
|
|
||||||
strUsage += " -zapwallettxes=<mode> " + _("Delete all wallet transactions and only recover those part of the blockchain through -rescan on startup") + "\n";
|
strUsage += " -zapwallettxes=<mode> " + _("Delete all wallet transactions and only recover those part of the blockchain through -rescan on startup") + "\n";
|
||||||
strUsage += " " + _("(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n";
|
strUsage += " " + _("(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n";
|
||||||
#endif
|
#endif
|
||||||
@ -295,8 +296,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||||||
strUsage += " -limitfreerelay=<n> " + _("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15)") + "\n";
|
strUsage += " -limitfreerelay=<n> " + _("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15)") + "\n";
|
||||||
strUsage += " -maxsigcachesize=<n> " + _("Limit size of signature cache to <n> entries (default: 50000)") + "\n";
|
strUsage += " -maxsigcachesize=<n> " + _("Limit size of signature cache to <n> entries (default: 50000)") + "\n";
|
||||||
}
|
}
|
||||||
strUsage += " -mintxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for transaction creation (default: %s)"), FormatMoney(CTransaction::minTxFee.GetFeePerK())) + "\n";
|
strUsage += " -minrelaytxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())) + "\n";
|
||||||
strUsage += " -minrelaytxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(CTransaction::minRelayTxFee.GetFeePerK())) + "\n";
|
|
||||||
strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n";
|
strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n";
|
||||||
if (GetBoolArg("-help-debug", false))
|
if (GetBoolArg("-help-debug", false))
|
||||||
{
|
{
|
||||||
@ -610,24 +610,24 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||||||
// a transaction spammer can cheaply fill blocks using
|
// a transaction spammer can cheaply fill blocks using
|
||||||
// 1-satoshi-fee transactions. It should be set above the real
|
// 1-satoshi-fee transactions. It should be set above the real
|
||||||
// cost to you of processing a transaction.
|
// cost to you of processing a transaction.
|
||||||
if (mapArgs.count("-mintxfee"))
|
|
||||||
{
|
|
||||||
int64_t n = 0;
|
|
||||||
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
|
|
||||||
CTransaction::minTxFee = CFeeRate(n);
|
|
||||||
else
|
|
||||||
return InitError(strprintf(_("Invalid amount for -mintxfee=<amount>: '%s'"), mapArgs["-mintxfee"]));
|
|
||||||
}
|
|
||||||
if (mapArgs.count("-minrelaytxfee"))
|
if (mapArgs.count("-minrelaytxfee"))
|
||||||
{
|
{
|
||||||
int64_t n = 0;
|
int64_t n = 0;
|
||||||
if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0)
|
if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0)
|
||||||
CTransaction::minRelayTxFee = CFeeRate(n);
|
::minRelayTxFee = CFeeRate(n);
|
||||||
else
|
else
|
||||||
return InitError(strprintf(_("Invalid amount for -minrelaytxfee=<amount>: '%s'"), mapArgs["-minrelaytxfee"]));
|
return InitError(strprintf(_("Invalid amount for -minrelaytxfee=<amount>: '%s'"), mapArgs["-minrelaytxfee"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
|
if (mapArgs.count("-mintxfee"))
|
||||||
|
{
|
||||||
|
int64_t n = 0;
|
||||||
|
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
|
||||||
|
CWallet::minTxFee = CFeeRate(n);
|
||||||
|
else
|
||||||
|
return InitError(strprintf(_("Invalid amount for -mintxfee=<amount>: '%s'"), mapArgs["-mintxfee"]));
|
||||||
|
}
|
||||||
if (mapArgs.count("-paytxfee"))
|
if (mapArgs.count("-paytxfee"))
|
||||||
{
|
{
|
||||||
int64_t nFeePerK = 0;
|
int64_t nFeePerK = 0;
|
||||||
@ -636,10 +636,10 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||||||
if (nFeePerK > nHighTransactionFeeWarning)
|
if (nFeePerK > nHighTransactionFeeWarning)
|
||||||
InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
|
InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
|
||||||
payTxFee = CFeeRate(nFeePerK, 1000);
|
payTxFee = CFeeRate(nFeePerK, 1000);
|
||||||
if (payTxFee < CTransaction::minRelayTxFee)
|
if (payTxFee < ::minRelayTxFee)
|
||||||
{
|
{
|
||||||
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
|
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
|
||||||
mapArgs["-paytxfee"], CTransaction::minRelayTxFee.ToString()));
|
mapArgs["-paytxfee"], ::minRelayTxFee.ToString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nTxConfirmTarget = GetArg("-txconfirmtarget", 1);
|
nTxConfirmTarget = GetArg("-txconfirmtarget", 1);
|
||||||
|
18
src/main.cpp
18
src/main.cpp
@ -38,8 +38,6 @@ using namespace boost;
|
|||||||
|
|
||||||
CCriticalSection cs_main;
|
CCriticalSection cs_main;
|
||||||
|
|
||||||
CTxMemPool mempool;
|
|
||||||
|
|
||||||
map<uint256, CBlockIndex*> mapBlockIndex;
|
map<uint256, CBlockIndex*> mapBlockIndex;
|
||||||
CChain chainActive;
|
CChain chainActive;
|
||||||
int64_t nTimeBestReceived = 0;
|
int64_t nTimeBestReceived = 0;
|
||||||
@ -50,10 +48,10 @@ bool fBenchmark = false;
|
|||||||
bool fTxIndex = false;
|
bool fTxIndex = false;
|
||||||
unsigned int nCoinCacheSize = 5000;
|
unsigned int nCoinCacheSize = 5000;
|
||||||
|
|
||||||
/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */
|
|
||||||
CFeeRate CTransaction::minTxFee = CFeeRate(10000); // Override with -mintxfee
|
|
||||||
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
|
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
|
||||||
CFeeRate CTransaction::minRelayTxFee = CFeeRate(1000);
|
CFeeRate minRelayTxFee = CFeeRate(1000);
|
||||||
|
|
||||||
|
CTxMemPool mempool(::minRelayTxFee);
|
||||||
|
|
||||||
struct COrphanBlock {
|
struct COrphanBlock {
|
||||||
uint256 hashBlock;
|
uint256 hashBlock;
|
||||||
@ -617,7 +615,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
|
|||||||
}
|
}
|
||||||
if (whichType == TX_NULL_DATA)
|
if (whichType == TX_NULL_DATA)
|
||||||
nDataOut++;
|
nDataOut++;
|
||||||
else if (txout.IsDust(CTransaction::minRelayTxFee)) {
|
else if (txout.IsDust(::minRelayTxFee)) {
|
||||||
reason = "dust";
|
reason = "dust";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -870,7 +868,7 @@ int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t nMinFee = tx.minRelayTxFee.GetFee(nBytes);
|
int64_t nMinFee = ::minRelayTxFee.GetFee(nBytes);
|
||||||
|
|
||||||
if (fAllowFree)
|
if (fAllowFree)
|
||||||
{
|
{
|
||||||
@ -1009,7 +1007,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
// Continuously rate-limit free (really, very-low-fee)transactions
|
// Continuously rate-limit free (really, very-low-fee)transactions
|
||||||
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
|
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
|
||||||
// be annoying or make others' transactions take longer to confirm.
|
// be annoying or make others' transactions take longer to confirm.
|
||||||
if (fLimitFree && nFees < CTransaction::minRelayTxFee.GetFee(nSize))
|
if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize))
|
||||||
{
|
{
|
||||||
static double dFreeCount;
|
static double dFreeCount;
|
||||||
static int64_t nLastFreeTime;
|
static int64_t nLastFreeTime;
|
||||||
@ -1022,10 +1020,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
|
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fRejectInsaneFee && nFees > CTransaction::minRelayTxFee.GetFee(nSize) * 10000)
|
if (fRejectInsaneFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000)
|
||||||
return error("AcceptToMemoryPool: : insane fees %s, %d > %d",
|
return error("AcceptToMemoryPool: : insane fees %s, %d > %d",
|
||||||
hash.ToString(),
|
hash.ToString(),
|
||||||
nFees, CTransaction::minRelayTxFee.GetFee(nSize) * 10000);
|
nFees, ::minRelayTxFee.GetFee(nSize) * 10000);
|
||||||
|
|
||||||
// Check against previous transactions
|
// Check against previous transactions
|
||||||
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
||||||
|
@ -93,6 +93,7 @@ extern bool fBenchmark;
|
|||||||
extern int nScriptCheckThreads;
|
extern int nScriptCheckThreads;
|
||||||
extern bool fTxIndex;
|
extern bool fTxIndex;
|
||||||
extern unsigned int nCoinCacheSize;
|
extern unsigned int nCoinCacheSize;
|
||||||
|
extern CFeeRate minRelayTxFee;
|
||||||
|
|
||||||
// Minimum disk space required - used in CheckDiskSpace()
|
// Minimum disk space required - used in CheckDiskSpace()
|
||||||
static const uint64_t nMinDiskSpace = 52428800;
|
static const uint64_t nMinDiskSpace = 52428800;
|
||||||
|
@ -236,7 +236,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||||||
double dPriorityDelta = 0;
|
double dPriorityDelta = 0;
|
||||||
int64_t nFeeDelta = 0;
|
int64_t nFeeDelta = 0;
|
||||||
mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
|
mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
|
||||||
if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < CTransaction::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
|
if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Prioritise by fee once past the priority size or we run out of high-priority
|
// Prioritise by fee once past the priority size or we run out of high-priority
|
||||||
|
@ -406,7 +406,7 @@ QString CoinControlDialog::getPriorityLabel(const CTxMemPool& pool, double dPrio
|
|||||||
{
|
{
|
||||||
// confirmations -> textual description
|
// confirmations -> textual description
|
||||||
typedef std::map<unsigned int, QString> PriorityDescription;
|
typedef std::map<unsigned int, QString> PriorityDescription;
|
||||||
static PriorityDescription priorityDescriptions = boost::assign::map_list_of
|
const static PriorityDescription priorityDescriptions = boost::assign::map_list_of
|
||||||
(1, tr("highest"))(2, tr("higher"))(3, tr("high"))
|
(1, tr("highest"))(2, tr("higher"))(3, tr("high"))
|
||||||
(5, tr("medium-high"))(6, tr("medium"))
|
(5, tr("medium-high"))(6, tr("medium"))
|
||||||
(10, tr("low-medium"))(15, tr("low"))
|
(10, tr("low-medium"))(15, tr("low"))
|
||||||
@ -452,7 +452,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
|||||||
{
|
{
|
||||||
CTxOut txout(amount, (CScript)vector<unsigned char>(24, 0));
|
CTxOut txout(amount, (CScript)vector<unsigned char>(24, 0));
|
||||||
txDummy.vout.push_back(txout);
|
txDummy.vout.push_back(txout);
|
||||||
if (txout.IsDust(CTransaction::minRelayTxFee))
|
if (txout.IsDust(::minRelayTxFee))
|
||||||
fDust = true;
|
fDust = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -544,7 +544,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
|||||||
if (nChange > 0 && nChange < CENT)
|
if (nChange > 0 && nChange < CENT)
|
||||||
{
|
{
|
||||||
CTxOut txout(nChange, (CScript)vector<unsigned char>(24, 0));
|
CTxOut txout(nChange, (CScript)vector<unsigned char>(24, 0));
|
||||||
if (txout.IsDust(CTransaction::minRelayTxFee))
|
if (txout.IsDust(::minRelayTxFee))
|
||||||
{
|
{
|
||||||
nPayFee += nChange;
|
nPayFee += nChange;
|
||||||
nChange = 0;
|
nChange = 0;
|
||||||
@ -605,17 +605,17 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
|||||||
|
|
||||||
// tool tips
|
// tool tips
|
||||||
QString toolTip1 = tr("This label turns red, if the transaction size is greater than 1000 bytes.") + "<br /><br />";
|
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.");
|
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 />";
|
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 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
|
// 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);
|
QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary);
|
||||||
|
|
||||||
l3->setToolTip(toolTip4);
|
l3->setToolTip(toolTip4);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
|
#include "main.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@ -212,7 +213,7 @@ bool isDust(const QString& address, qint64 amount)
|
|||||||
CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
|
CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
|
||||||
CScript script; script.SetDestination(dest);
|
CScript script; script.SetDestination(dest);
|
||||||
CTxOut txOut(amount, script);
|
CTxOut txOut(amount, script);
|
||||||
return txOut.IsDust(CTransaction::minRelayTxFee);
|
return txOut.IsDust(::minRelayTxFee);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HtmlEscape(const QString& str, bool fMultiLine)
|
QString HtmlEscape(const QString& str, bool fMultiLine)
|
||||||
|
@ -14,7 +14,10 @@
|
|||||||
#include "monitoreddatamapper.h"
|
#include "monitoreddatamapper.h"
|
||||||
#include "optionsmodel.h"
|
#include "optionsmodel.h"
|
||||||
|
|
||||||
#include "main.h" // for CTransaction::minTxFee and MAX_SCRIPTCHECK_THREADS
|
#include "main.h" // for MAX_SCRIPTCHECK_THREADS
|
||||||
|
#ifdef ENABLE_WALLET
|
||||||
|
#include "wallet.h" // for CWallet::minTxFee
|
||||||
|
#endif
|
||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
#include "txdb.h" // for -dbcache defaults
|
#include "txdb.h" // for -dbcache defaults
|
||||||
|
|
||||||
@ -101,7 +104,9 @@ OptionsDialog::OptionsDialog(QWidget *parent) :
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ui->unit->setModel(new BitcoinUnits(this));
|
ui->unit->setModel(new BitcoinUnits(this));
|
||||||
ui->transactionFee->setSingleStep(CTransaction::minTxFee.GetFeePerK());
|
#ifdef ENABLE_WALLET
|
||||||
|
ui->transactionFee->setSingleStep(CWallet::minTxFee.GetFeePerK());
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Widget-to-option mapper */
|
/* Widget-to-option mapper */
|
||||||
mapper = new MonitoredDataMapper(this);
|
mapper = new MonitoredDataMapper(this);
|
||||||
|
@ -551,7 +551,7 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
|
|||||||
|
|
||||||
// Extract and check amounts
|
// Extract and check amounts
|
||||||
CTxOut txOut(sendingTo.second, sendingTo.first);
|
CTxOut txOut(sendingTo.second, sendingTo.first);
|
||||||
if (txOut.IsDust(CTransaction::minRelayTxFee)) {
|
if (txOut.IsDust(::minRelayTxFee)) {
|
||||||
emit message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).")
|
emit message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).")
|
||||||
.arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)),
|
.arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)),
|
||||||
CClientUIInterface::MSG_ERROR);
|
CClientUIInterface::MSG_ERROR);
|
||||||
|
@ -84,7 +84,7 @@ Value getinfo(const Array& params, bool fHelp)
|
|||||||
obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
|
obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
|
||||||
obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
|
obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
|
||||||
#endif
|
#endif
|
||||||
obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::minRelayTxFee.GetFeePerK())));
|
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
|
||||||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -372,7 +372,7 @@ Value getnetworkinfo(const Array& params, bool fHelp)
|
|||||||
obj.push_back(Pair("timeoffset", GetTimeOffset()));
|
obj.push_back(Pair("timeoffset", GetTimeOffset()));
|
||||||
obj.push_back(Pair("connections", (int)vNodes.size()));
|
obj.push_back(Pair("connections", (int)vNodes.size()));
|
||||||
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
|
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
|
||||||
obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::minRelayTxFee.GetFeePerK())));
|
obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
|
||||||
Array localAddresses;
|
Array localAddresses;
|
||||||
{
|
{
|
||||||
LOCK(cs_mapLocalHost);
|
LOCK(cs_mapLocalHost);
|
||||||
|
@ -80,13 +80,13 @@ public:
|
|||||||
|
|
||||||
// Used as belt-and-suspenders check when reading to detect
|
// Used as belt-and-suspenders check when reading to detect
|
||||||
// file corruption
|
// file corruption
|
||||||
bool AreSane(const std::vector<CFeeRate>& vecFee)
|
bool AreSane(const std::vector<CFeeRate>& vecFee, const CFeeRate& minRelayFee)
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(CFeeRate fee, vecFee)
|
BOOST_FOREACH(CFeeRate fee, vecFee)
|
||||||
{
|
{
|
||||||
if (fee < CFeeRate(0))
|
if (fee < CFeeRate(0))
|
||||||
return false;
|
return false;
|
||||||
if (fee.GetFee(1000) > CTransaction::minRelayTxFee.GetFee(1000) * 10000)
|
if (fee.GetFeePerK() > minRelayFee.GetFeePerK() * 10000)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -109,10 +109,10 @@ public:
|
|||||||
fileout << vecPriority;
|
fileout << vecPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read(CAutoFile& filein) {
|
void Read(CAutoFile& filein, const CFeeRate& minRelayFee) {
|
||||||
std::vector<CFeeRate> vecFee;
|
std::vector<CFeeRate> vecFee;
|
||||||
filein >> vecFee;
|
filein >> vecFee;
|
||||||
if (AreSane(vecFee))
|
if (AreSane(vecFee, minRelayFee))
|
||||||
feeSamples.insert(feeSamples.end(), vecFee.begin(), vecFee.end());
|
feeSamples.insert(feeSamples.end(), vecFee.begin(), vecFee.end());
|
||||||
else
|
else
|
||||||
throw runtime_error("Corrupt fee value in estimates file.");
|
throw runtime_error("Corrupt fee value in estimates file.");
|
||||||
@ -141,7 +141,7 @@ private:
|
|||||||
|
|
||||||
// nBlocksAgo is 0 based, i.e. transactions that confirmed in the highest seen block are
|
// nBlocksAgo is 0 based, i.e. transactions that confirmed in the highest seen block are
|
||||||
// nBlocksAgo == 0, transactions in the block before that are nBlocksAgo == 1 etc.
|
// nBlocksAgo == 0, transactions in the block before that are nBlocksAgo == 1 etc.
|
||||||
void seenTxConfirm(CFeeRate feeRate, double dPriority, int nBlocksAgo)
|
void seenTxConfirm(const CFeeRate& feeRate, const CFeeRate& minRelayFee, double dPriority, int nBlocksAgo)
|
||||||
{
|
{
|
||||||
// Last entry records "everything else".
|
// Last entry records "everything else".
|
||||||
int nBlocksTruncated = min(nBlocksAgo, (int) history.size() - 1);
|
int nBlocksTruncated = min(nBlocksAgo, (int) history.size() - 1);
|
||||||
@ -149,7 +149,7 @@ private:
|
|||||||
|
|
||||||
// We need to guess why the transaction was included in a block-- either
|
// We need to guess why the transaction was included in a block-- either
|
||||||
// because it is high-priority or because it has sufficient fees.
|
// because it is high-priority or because it has sufficient fees.
|
||||||
bool sufficientFee = (feeRate > CTransaction::minRelayTxFee);
|
bool sufficientFee = (feeRate > minRelayFee);
|
||||||
bool sufficientPriority = AllowFree(dPriority);
|
bool sufficientPriority = AllowFree(dPriority);
|
||||||
const char* assignedTo = "unassigned";
|
const char* assignedTo = "unassigned";
|
||||||
if (sufficientFee && !sufficientPriority)
|
if (sufficientFee && !sufficientPriority)
|
||||||
@ -177,7 +177,7 @@ public:
|
|||||||
history.resize(nEntries);
|
history.resize(nEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void seenBlock(const std::vector<CTxMemPoolEntry>& entries, int nBlockHeight)
|
void seenBlock(const std::vector<CTxMemPoolEntry>& entries, int nBlockHeight, const CFeeRate minRelayFee)
|
||||||
{
|
{
|
||||||
if (nBlockHeight <= nBestSeenHeight)
|
if (nBlockHeight <= nBestSeenHeight)
|
||||||
{
|
{
|
||||||
@ -222,7 +222,7 @@ public:
|
|||||||
// Fees are stored and reported as BTC-per-kb:
|
// Fees are stored and reported as BTC-per-kb:
|
||||||
CFeeRate feeRate(entry->GetFee(), entry->GetTxSize());
|
CFeeRate feeRate(entry->GetFee(), entry->GetTxSize());
|
||||||
double dPriority = entry->GetPriority(entry->GetHeight()); // Want priority when it went IN
|
double dPriority = entry->GetPriority(entry->GetHeight()); // Want priority when it went IN
|
||||||
seenTxConfirm(feeRate, dPriority, i);
|
seenTxConfirm(feeRate, minRelayFee, dPriority, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < history.size(); i++) {
|
for (size_t i = 0; i < history.size(); i++) {
|
||||||
@ -313,7 +313,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read(CAutoFile& filein)
|
void Read(CAutoFile& filein, const CFeeRate& minRelayFee)
|
||||||
{
|
{
|
||||||
filein >> nBestSeenHeight;
|
filein >> nBestSeenHeight;
|
||||||
size_t numEntries;
|
size_t numEntries;
|
||||||
@ -322,14 +322,14 @@ public:
|
|||||||
for (size_t i = 0; i < numEntries; i++)
|
for (size_t i = 0; i < numEntries; i++)
|
||||||
{
|
{
|
||||||
CBlockAverage entry;
|
CBlockAverage entry;
|
||||||
entry.Read(filein);
|
entry.Read(filein, minRelayFee);
|
||||||
history.push_back(entry);
|
history.push_back(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
CTxMemPool::CTxMemPool()
|
CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) : minRelayFee(_minRelayFee)
|
||||||
{
|
{
|
||||||
// Sanity checks off by default for performance, because otherwise
|
// Sanity checks off by default for performance, because otherwise
|
||||||
// accepting transactions becomes O(N^2) where N is the number
|
// accepting transactions becomes O(N^2) where N is the number
|
||||||
@ -445,7 +445,7 @@ void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned i
|
|||||||
if (mapTx.count(hash))
|
if (mapTx.count(hash))
|
||||||
entries.push_back(mapTx[hash]);
|
entries.push_back(mapTx[hash]);
|
||||||
}
|
}
|
||||||
minerPolicyEstimator->seenBlock(entries, nBlockHeight);
|
minerPolicyEstimator->seenBlock(entries, nBlockHeight, minRelayFee);
|
||||||
BOOST_FOREACH(const CTransaction& tx, vtx)
|
BOOST_FOREACH(const CTransaction& tx, vtx)
|
||||||
{
|
{
|
||||||
std::list<CTransaction> dummy;
|
std::list<CTransaction> dummy;
|
||||||
@ -560,7 +560,7 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
|
|||||||
return error("CTxMemPool::ReadFeeEstimates() : up-version (%d) fee estimate file", nVersionRequired);
|
return error("CTxMemPool::ReadFeeEstimates() : up-version (%d) fee estimate file", nVersionRequired);
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
minerPolicyEstimator->Read(filein);
|
minerPolicyEstimator->Read(filein, minRelayFee);
|
||||||
}
|
}
|
||||||
catch (std::exception &e) {
|
catch (std::exception &e) {
|
||||||
LogPrintf("CTxMemPool::ReadFeeEstimates() : unable to read policy estimator data (non-fatal)");
|
LogPrintf("CTxMemPool::ReadFeeEstimates() : unable to read policy estimator data (non-fatal)");
|
||||||
|
@ -67,13 +67,15 @@ private:
|
|||||||
unsigned int nTransactionsUpdated;
|
unsigned int nTransactionsUpdated;
|
||||||
CMinerPolicyEstimator* minerPolicyEstimator;
|
CMinerPolicyEstimator* minerPolicyEstimator;
|
||||||
|
|
||||||
|
CFeeRate minRelayFee; // Passed to constructor to avoid dependency on main
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mutable CCriticalSection cs;
|
mutable CCriticalSection cs;
|
||||||
std::map<uint256, CTxMemPoolEntry> mapTx;
|
std::map<uint256, CTxMemPoolEntry> mapTx;
|
||||||
std::map<COutPoint, CInPoint> mapNextTx;
|
std::map<COutPoint, CInPoint> mapNextTx;
|
||||||
std::map<uint256, std::pair<double, int64_t> > mapDeltas;
|
std::map<uint256, std::pair<double, int64_t> > mapDeltas;
|
||||||
|
|
||||||
CTxMemPool();
|
CTxMemPool(const CFeeRate& _minRelayFee);
|
||||||
~CTxMemPool();
|
~CTxMemPool();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -21,6 +21,9 @@ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
|
|||||||
unsigned int nTxConfirmTarget = 1;
|
unsigned int nTxConfirmTarget = 1;
|
||||||
bool bSpendZeroConfChange = true;
|
bool bSpendZeroConfChange = true;
|
||||||
|
|
||||||
|
/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */
|
||||||
|
CFeeRate CWallet::minTxFee = CFeeRate(10000); // Override with -mintxfee
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// mapWallet
|
// mapWallet
|
||||||
@ -1294,7 +1297,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
|
|||||||
BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
|
BOOST_FOREACH (const PAIRTYPE(CScript, int64_t)& s, vecSend)
|
||||||
{
|
{
|
||||||
CTxOut txout(s.second, s.first);
|
CTxOut txout(s.second, s.first);
|
||||||
if (txout.IsDust(CTransaction::minRelayTxFee))
|
if (txout.IsDust(::minRelayTxFee))
|
||||||
{
|
{
|
||||||
strFailReason = _("Transaction amount too small");
|
strFailReason = _("Transaction amount too small");
|
||||||
return false;
|
return false;
|
||||||
@ -1355,7 +1358,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
|
|||||||
|
|
||||||
// Never create dust outputs; if we would, just
|
// Never create dust outputs; if we would, just
|
||||||
// add the dust to the fee.
|
// add the dust to the fee.
|
||||||
if (newTxOut.IsDust(CTransaction::minRelayTxFee))
|
if (newTxOut.IsDust(::minRelayTxFee))
|
||||||
{
|
{
|
||||||
nFeeRet += nChange;
|
nFeeRet += nChange;
|
||||||
reservekey.ReturnKey();
|
reservekey.ReturnKey();
|
||||||
@ -1537,7 +1540,7 @@ int64_t CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge
|
|||||||
// ... unless we don't have enough mempool data, in which case fall
|
// ... unless we don't have enough mempool data, in which case fall
|
||||||
// back to a hard-coded fee
|
// back to a hard-coded fee
|
||||||
if (nFeeNeeded == 0)
|
if (nFeeNeeded == 0)
|
||||||
nFeeNeeded = CTransaction::minTxFee.GetFee(nTxBytes);
|
nFeeNeeded = minTxFee.GetFee(nTxBytes);
|
||||||
return nFeeNeeded;
|
return nFeeNeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,6 +268,7 @@ public:
|
|||||||
std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew);
|
std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew);
|
||||||
std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew);
|
std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew);
|
||||||
|
|
||||||
|
static CFeeRate minTxFee;
|
||||||
static int64_t GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool);
|
static int64_t GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool);
|
||||||
|
|
||||||
bool NewKeyPool();
|
bool NewKeyPool();
|
||||||
|
Loading…
Reference in New Issue
Block a user