Skip to content

Commit 21876d3

Browse files
committed
Merge branch 'smartfee_wallet'
2 parents 07b6c2b + 13fc83c commit 21876d3

18 files changed

+179
-107
lines changed

doc/release-notes.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
(note: this is a temporary file, to be added-to by anybody, and moved to
22
release-notes at release time)
33

4+
Transaction fee changes
5+
=======================
6+
7+
This release automatically estimates how high a transaction fee (or how
8+
high a priority) transactions require to be confirmed quickly. The default
9+
settings will create transactions that confirm quickly; see the new
10+
'txconfirmtarget' setting to control the tradeoff between fees and
11+
confirmation times.
12+
13+
Prior releases used hard-coded fees (and priorities), and would
14+
sometimes create transactions that took a very long time to confirm.
15+
16+
17+
New Command Line Options
18+
========================
19+
20+
-txconfirmtarget=n : create transactions that have enough fees (or priority)
21+
so they are likely to confirm within n blocks (default: 1). This setting
22+
is over-ridden by the -paytxfee option.
23+
424
New RPC methods
525
===============
626

src/core.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ CFeeRate::CFeeRate(int64_t nFeePaid, size_t nSize)
8080
nSatoshisPerK = 0;
8181
}
8282

83-
int64_t CFeeRate::GetFee(size_t nSize)
83+
int64_t CFeeRate::GetFee(size_t nSize) const
8484
{
8585
return nSatoshisPerK*nSize / 1000;
8686
}

src/core.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,14 @@ class CFeeRate
125125
CFeeRate(int64_t nFeePaid, size_t nSize);
126126
CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
127127

128-
int64_t GetFee(size_t size); // unit returned is satoshis
129-
int64_t GetFeePerK() { return GetFee(1000); } // satoshis-per-1000-bytes
128+
int64_t GetFee(size_t size) const; // unit returned is satoshis
129+
int64_t GetFeePerK() const { return GetFee(1000); } // satoshis-per-1000-bytes
130130

131131
friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
132132
friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
133133
friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; }
134-
134+
friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; }
135+
friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
135136
std::string ToString() const;
136137

137138
IMPLEMENT_SERIALIZE( READWRITE(nSatoshisPerK); )
@@ -216,8 +217,6 @@ class CTransaction
216217
void UpdateHash() const;
217218

218219
public:
219-
static CFeeRate minTxFee;
220-
static CFeeRate minRelayTxFee;
221220
static const int CURRENT_VERSION=1;
222221

223222
// The local variables are made const to prevent unintended modification

src/init.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,16 @@ std::string HelpMessage(HelpMessageMode mode)
253253
#ifdef ENABLE_WALLET
254254
strUsage += "\n" + _("Wallet options:") + "\n";
255255
strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n";
256+
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";
256257
strUsage += " -paytxfee=<amt> " + strprintf(_("Fee (in BTC/kB) to add to transactions you send (default: %s)"), FormatMoney(payTxFee.GetFeePerK())) + "\n";
257258
strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + " " + _("on startup") + "\n";
259+
strUsage += " -respendnotify=<cmd> " + _("Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)") + "\n";
258260
strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + " " + _("on startup") + "\n";
259261
strUsage += " -spendzeroconfchange " + _("Spend unconfirmed change when sending transactions (default: 1)") + "\n";
262+
strUsage += " -txconfirmtarget=<n> " + _("If paytxfee is not set, include enough fee so transactions are confirmed on average within n blocks (default: 1)") + "\n";
260263
strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + " " + _("on startup") + "\n";
261264
strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + " " + _("(default: wallet.dat)") + "\n";
262265
strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n";
263-
strUsage += " -respendnotify=<cmd> " + _("Execute command when a network tx respends wallet tx input (%s=respend TxID, %t=wallet TxID)") + "\n";
264266
strUsage += " -zapwallettxes=<mode> " + _("Delete all wallet transactions and only recover those part of the blockchain through -rescan on startup") + "\n";
265267
strUsage += " " + _("(default: 1, 1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)") + "\n";
266268
#endif
@@ -294,8 +296,7 @@ std::string HelpMessage(HelpMessageMode mode)
294296
strUsage += " -limitfreerelay=<n> " + _("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default:15)") + "\n";
295297
strUsage += " -maxsigcachesize=<n> " + _("Limit size of signature cache to <n> entries (default: 50000)") + "\n";
296298
}
297-
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";
298-
strUsage += " -minrelaytxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(CTransaction::minRelayTxFee.GetFeePerK())) + "\n";
299+
strUsage += " -minrelaytxfee=<amt> " + strprintf(_("Fees (in BTC/Kb) smaller than this are considered zero fee for relaying (default: %s)"), FormatMoney(::minRelayTxFee.GetFeePerK())) + "\n";
299300
strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n";
300301
if (GetBoolArg("-help-debug", false))
301302
{
@@ -609,24 +610,24 @@ bool AppInit2(boost::thread_group& threadGroup)
609610
// a transaction spammer can cheaply fill blocks using
610611
// 1-satoshi-fee transactions. It should be set above the real
611612
// cost to you of processing a transaction.
612-
if (mapArgs.count("-mintxfee"))
613-
{
614-
int64_t n = 0;
615-
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
616-
CTransaction::minTxFee = CFeeRate(n);
617-
else
618-
return InitError(strprintf(_("Invalid amount for -mintxfee=<amount>: '%s'"), mapArgs["-mintxfee"]));
619-
}
620613
if (mapArgs.count("-minrelaytxfee"))
621614
{
622615
int64_t n = 0;
623616
if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0)
624-
CTransaction::minRelayTxFee = CFeeRate(n);
617+
::minRelayTxFee = CFeeRate(n);
625618
else
626619
return InitError(strprintf(_("Invalid amount for -minrelaytxfee=<amount>: '%s'"), mapArgs["-minrelaytxfee"]));
627620
}
628621

629622
#ifdef ENABLE_WALLET
623+
if (mapArgs.count("-mintxfee"))
624+
{
625+
int64_t n = 0;
626+
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
627+
CWallet::minTxFee = CFeeRate(n);
628+
else
629+
return InitError(strprintf(_("Invalid amount for -mintxfee=<amount>: '%s'"), mapArgs["-mintxfee"]));
630+
}
630631
if (mapArgs.count("-paytxfee"))
631632
{
632633
int64_t nFeePerK = 0;
@@ -635,7 +636,13 @@ bool AppInit2(boost::thread_group& threadGroup)
635636
if (nFeePerK > nHighTransactionFeeWarning)
636637
InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
637638
payTxFee = CFeeRate(nFeePerK, 1000);
639+
if (payTxFee < ::minRelayTxFee)
640+
{
641+
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
642+
mapArgs["-paytxfee"], ::minRelayTxFee.ToString()));
643+
}
638644
}
645+
nTxConfirmTarget = GetArg("-txconfirmtarget", 1);
639646
bSpendZeroConfChange = GetArg("-spendzeroconfchange", true);
640647

641648
std::string strWalletFile = GetArg("-wallet", "wallet.dat");

src/main.cpp

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ using namespace boost;
3838

3939
CCriticalSection cs_main;
4040

41-
CTxMemPool mempool;
42-
4341
map<uint256, CBlockIndex*> mapBlockIndex;
4442
CChain chainActive;
4543
int64_t nTimeBestReceived = 0;
@@ -50,10 +48,10 @@ bool fBenchmark = false;
5048
bool fTxIndex = false;
5149
unsigned int nCoinCacheSize = 5000;
5250

53-
/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */
54-
CFeeRate CTransaction::minTxFee = CFeeRate(10000); // Override with -mintxfee
5551
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
56-
CFeeRate CTransaction::minRelayTxFee = CFeeRate(1000);
52+
CFeeRate minRelayTxFee = CFeeRate(1000);
53+
54+
CTxMemPool mempool(::minRelayTxFee);
5755

5856
struct COrphanBlock {
5957
uint256 hashBlock;
@@ -617,7 +615,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
617615
}
618616
if (whichType == TX_NULL_DATA)
619617
nDataOut++;
620-
else if (txout.IsDust(CTransaction::minRelayTxFee)) {
618+
else if (txout.IsDust(::minRelayTxFee)) {
621619
reason = "dust";
622620
return false;
623621
}
@@ -858,7 +856,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
858856
return true;
859857
}
860858

861-
int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, enum GetMinFee_mode mode)
859+
int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree)
862860
{
863861
{
864862
LOCK(mempool.cs);
@@ -870,20 +868,15 @@ int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree,
870868
return 0;
871869
}
872870

873-
// Base fee is either minTxFee or minRelayTxFee
874-
CFeeRate baseFeeRate = (mode == GMF_RELAY) ? tx.minRelayTxFee : tx.minTxFee;
875-
876-
int64_t nMinFee = baseFeeRate.GetFee(nBytes);
871+
int64_t nMinFee = ::minRelayTxFee.GetFee(nBytes);
877872

878873
if (fAllowFree)
879874
{
880875
// There is a free transaction area in blocks created by most miners,
881876
// * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000
882877
// to be considered to fall into this category. We don't want to encourage sending
883878
// multiple transactions instead of one big transaction to avoid fees.
884-
// * If we are creating a transaction we allow transactions up to 1,000 bytes
885-
// to be considered safe and assume they can likely make it into this section.
886-
if (nBytes < (mode == GMF_SEND ? 1000 : (DEFAULT_BLOCK_PRIORITY_SIZE - 1000)))
879+
if (nBytes < (DEFAULT_BLOCK_PRIORITY_SIZE - 1000))
887880
nMinFee = 0;
888881
}
889882

@@ -1005,7 +998,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
1005998
unsigned int nSize = entry.GetTxSize();
1006999

10071000
// Don't accept it if it can't get into a block
1008-
int64_t txMinFee = GetMinFee(tx, nSize, true, GMF_RELAY);
1001+
int64_t txMinFee = GetMinRelayFee(tx, nSize, true);
10091002
if (fLimitFree && nFees < txMinFee)
10101003
return state.DoS(0, error("AcceptToMemoryPool : not enough fees %s, %d < %d",
10111004
hash.ToString(), nFees, txMinFee),
@@ -1014,7 +1007,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
10141007
// Continuously rate-limit free (really, very-low-fee)transactions
10151008
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
10161009
// be annoying or make others' transactions take longer to confirm.
1017-
if (fLimitFree && nFees < CTransaction::minRelayTxFee.GetFee(nSize))
1010+
if (fLimitFree && nFees < ::minRelayTxFee.GetFee(nSize))
10181011
{
10191012
static double dFreeCount;
10201013
static int64_t nLastFreeTime;
@@ -1027,10 +1020,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
10271020
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
10281021
}
10291022

1030-
if (fRejectInsaneFee && nFees > CTransaction::minRelayTxFee.GetFee(nSize) * 10000)
1023+
if (fRejectInsaneFee && nFees > ::minRelayTxFee.GetFee(nSize) * 10000)
10311024
return error("AcceptToMemoryPool: : insane fees %s, %d > %d",
10321025
hash.ToString(),
1033-
nFees, CTransaction::minRelayTxFee.GetFee(nSize) * 10000);
1026+
nFees, ::minRelayTxFee.GetFee(nSize) * 10000);
10341027

10351028
// Check against previous transactions
10361029
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
@@ -1134,10 +1127,10 @@ int CMerkleTx::GetBlocksToMaturity() const
11341127
}
11351128

11361129

1137-
bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree)
1130+
bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectInsaneFee)
11381131
{
11391132
CValidationState state;
1140-
return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL);
1133+
return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectInsaneFee);
11411134
}
11421135

11431136

src/main.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ extern bool fBenchmark;
9393
extern int nScriptCheckThreads;
9494
extern bool fTxIndex;
9595
extern unsigned int nCoinCacheSize;
96+
extern CFeeRate minRelayTxFee;
9697

9798
// Minimum disk space required - used in CheckDiskSpace()
9899
static const uint64_t nMinDiskSpace = 52428800;
@@ -245,14 +246,7 @@ struct CDiskTxPos : public CDiskBlockPos
245246
};
246247

247248

248-
249-
enum GetMinFee_mode
250-
{
251-
GMF_RELAY,
252-
GMF_SEND,
253-
};
254-
255-
int64_t GetMinFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree, enum GetMinFee_mode mode);
249+
int64_t GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
256250

257251
//
258252
// Check transaction inputs, and make sure any
@@ -459,7 +453,7 @@ class CMerkleTx : public CTransaction
459453
int GetDepthInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
460454
bool IsInMainChain() const { CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
461455
int GetBlocksToMaturity() const;
462-
bool AcceptToMemoryPool(bool fLimitFree=true);
456+
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectInsaneFee=true);
463457
};
464458

465459

src/miner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
236236
double dPriorityDelta = 0;
237237
int64_t nFeeDelta = 0;
238238
mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
239-
if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < CTransaction::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
239+
if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
240240
continue;
241241

242242
// Prioritise by fee once past the priority size or we run out of high-priority

0 commit comments

Comments
 (0)