From 000dc55181f77cd96076c76b2cc13f8bcbe4146e Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Thu, 25 Apr 2013 20:11:27 -0400 Subject: [PATCH] Un-hardcode TX_FEE constants Allow setting of MIN_TX_FEE / MIN_RELAY_TX_FEE with -mintxfee / -mintxrelayfee Default values are the same (0.0001 BTC). --- src/init.cpp | 22 ++++++++++++++++++++++ src/main.cpp | 39 ++++++++++++++++++++++++--------------- src/main.h | 24 +++--------------------- src/qt/bitcoin.cpp | 2 +- src/wallet.cpp | 6 +++--- 5 files changed, 53 insertions(+), 40 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 3845cfad8..058b6a06e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -583,6 +583,28 @@ bool AppInit2(boost::thread_group& threadGroup) const char* pszP2SH = "/P2SH/"; COINBASE_FLAGS << std::vector(pszP2SH, pszP2SH+strlen(pszP2SH)); + // Fee-per-kilobyte amount considered the same as "free" + // If you are mining, be careful setting this: + // if you set it to zero then + // a transaction spammer can cheaply fill blocks using + // 1-satoshi-fee transactions. It should be set above the real + // cost to you of processing a transaction. + if (mapArgs.count("-mintxfee")) + { + int64 n = 0; + if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) + CTransaction::nMinTxFee = n; + else + return InitError(strprintf(_("Invalid amount for -mintxfee=: '%s'"), mapArgs["-mintxfee"].c_str())); + } + if (mapArgs.count("-minrelaytxfee")) + { + int64 n = 0; + if (ParseMoney(mapArgs["-minrelaytxfee"], n) && n > 0) + CTransaction::nMinRelayTxFee = n; + else + return InitError(strprintf(_("Invalid amount for -minrelaytxfee=: '%s'"), mapArgs["-minrelaytxfee"].c_str())); + } if (mapArgs.count("-paytxfee")) { diff --git a/src/main.cpp b/src/main.cpp index d0d6a99eb..91e84aefc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,6 +48,11 @@ bool fBenchmark = false; bool fTxIndex = false; unsigned int nCoinCacheSize = 5000; +/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */ +int64 CTransaction::nMinTxFee = 10000; // Override with -mintxfee +/** Fees smaller than this (in satoshi) are considered zero fee (for relaying) */ +int64 CTransaction::nMinRelayTxFee = 10000; + CMedianFilter cPeerBlockCounts(8, 0); // Amount of blocks that other nodes claim to have map mapOrphanBlocks; @@ -352,9 +357,22 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) ////////////////////////////////////////////////////////////////////////////// // -// CTransaction +// CTransaction / CTxOut // +bool CTxOut::IsDust() const +{ + // "Dust" is defined in terms of CTransaction::nMinRelayTxFee, + // which has units satoshis-per-kilobyte. + // If you'd pay more than 1/3 in fees + // to spend something, then we consider it dust. + // A typical txout is 33 bytes big, and will + // need a CTxIn of at least 148 bytes to spend, + // so dust is a txout less than 54 uBTC + // (5430 satoshis) with default nMinRelayTxFee + return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < CTransaction::nMinRelayTxFee); +} + bool CTransaction::IsStandard() const { if (nVersion > CTransaction::CURRENT_VERSION) @@ -574,8 +592,8 @@ bool CTransaction::CheckTransaction(CValidationState &state) const int64 CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree, enum GetMinFee_mode mode) const { - // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE - int64 nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE; + // Base fee is either nMinTxFee or nMinRelayTxFee + int64 nBaseFee = (mode == GMF_RELAY) ? nMinRelayTxFee : nMinTxFee; unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); unsigned int nNewBlockSize = nBlockSize + nBytes; @@ -598,7 +616,7 @@ int64 CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree, } } - // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01 + // To limit dust spam, require base fee if any output is less than 0.01 if (nMinFee < nBaseFee) { BOOST_FOREACH(const CTxOut& txout, vout) @@ -746,7 +764,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fCheckIn // Continuously rate-limit free transactions // This mitigates 'penny-flooding' -- sending thousands of free transactions just to // be annoying or make others' transactions take longer to confirm. - if (fLimitFree && nFees < MIN_RELAY_TX_FEE) + if (fLimitFree && nFees < CTransaction::nMinRelayTxFee) { static double dFreeCount; static int64 nLastTime; @@ -4184,15 +4202,6 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey) unsigned int nBlockMinSize = GetArg("-blockminsize", 0); nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize); - // Fee-per-kilobyte amount considered the same as "free" - // Be careful setting this: if you set it to zero then - // a transaction spammer can cheaply fill blocks using - // 1-satoshi-fee transactions. It should be set above the real - // cost to you of processing a transaction. - int64 nMinTxFee = MIN_TX_FEE; - if (mapArgs.count("-mintxfee")) - ParseMoney(mapArgs["-mintxfee"], nMinTxFee); - // Collect memory pool transactions into the block int64 nFees = 0; { @@ -4310,7 +4319,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey) continue; // Skip free transactions if we're past the minimum block size: - if (fSortedByFee && (dFeePerKb < nMinTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) + if (fSortedByFee && (dFeePerKb < CTransaction::nMinTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) continue; // Prioritize by fee once past the priority size or we run out of high-priority diff --git a/src/main.h b/src/main.h index 8c1e6d265..905b9fbac 100644 --- a/src/main.h +++ b/src/main.h @@ -44,10 +44,6 @@ static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB /** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */ static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF; -/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */ -static const int64 MIN_TX_FEE = 10000; -/** Fees smaller than this (in satoshi) are considered zero fee (for relaying) */ -static const int64 MIN_RELAY_TX_FEE = 10000; /** No amount larger than this (in satoshi) is valid */ static const int64 MAX_MONEY = 21000000 * COIN; inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } @@ -439,23 +435,7 @@ public: return !(a == b); } - size_t size() const - { - return sizeof(nValue)+scriptPubKey.size(); - } - - bool IsDust() const - { - // "Dust" is defined in terms of MIN_RELAY_TX_FEE, which - // has units satoshis-per-kilobyte. - // If you'd pay more than 1/3 in fees - // to spend something, then we consider it dust. - // A typical txout is 32 bytes big, and will - // need a CTxIn of at least 148 bytes to spend, - // so dust is a txout less than 54 uBTC - // (5400 satoshis) - return ((nValue*1000)/(3*(size()+148)) < MIN_RELAY_TX_FEE); - } + bool IsDust() const; std::string ToString() const { @@ -485,6 +465,8 @@ enum GetMinFee_mode class CTransaction { public: + static int64 nMinTxFee; + static int64 nMinRelayTxFee; static const int CURRENT_VERSION=1; int nVersion; std::vector vin; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 25448ea8c..5bd808a89 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -69,7 +69,7 @@ static bool ThreadSafeAskFee(int64 nFeeRequired) { if(!guiref) return false; - if(nFeeRequired < MIN_TX_FEE || nFeeRequired <= nTransactionFee || fDaemon) + if(nFeeRequired < CTransaction::nMinTxFee || nFeeRequired <= nTransactionFee || fDaemon) return true; bool payFee = false; diff --git a/src/wallet.cpp b/src/wallet.cpp index 65d2c3b68..532a73201 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1197,12 +1197,12 @@ bool CWallet::CreateTransaction(const vector >& vecSend, } int64 nChange = nValueIn - nValue - nFeeRet; - // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE + // if sub-cent change is required, the fee must be raised to at least nMinTxFee // or until nChange becomes zero // NOTE: this depends on the exact behaviour of GetMinFee - if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT) + if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT) { - int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet); + int64 nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet); nChange -= nMoveToFee; nFeeRet += nMoveToFee; }