diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -1471,7 +1471,7 @@ if (IsArgSet("-minrelaytxfee")) { Amount n(0); auto parsed = ParseMoney(GetArg("-minrelaytxfee", ""), n); - if (!parsed || Amount(0) == n) + if (!parsed) return InitError( AmountErrMsg("minrelaytxfee", GetArg("-minrelaytxfee", ""))); // High fee check is done afterward in CWallet::ParameterInteraction() diff --git a/src/miner.h b/src/miner.h --- a/src/miner.h +++ b/src/miner.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_MINER_H #define BITCOIN_MINER_H +#include "policy/policy.h" #include "primitives/block.h" #include "txmempool.h" @@ -134,7 +135,7 @@ // Configuration parameters for the block size uint64_t nMaxGeneratedBlockSize; - CFeeRate blockMinFeeRate; + CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); // Information on the current status of the block uint64_t nBlockSize; @@ -161,6 +162,7 @@ CreateNewBlock(const CScript &scriptPubKeyIn); uint64_t GetMaxGeneratedBlockSize() const { return nMaxGeneratedBlockSize; } + void SetBlockMinTxFee(const Amount blockmintxfee); private: // utility functions diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -80,6 +80,10 @@ return nNewTime - nOldTime; } +void BlockAssembler::SetBlockMinTxFee(const Amount blockmintxfee) { + blockMinFeeRate = CFeeRate(blockmintxfee); +} + static uint64_t ComputeMaxGeneratedBlockSize(const Config &config, const CBlockIndex *pindexPrev) { // Block resource limits @@ -106,9 +110,7 @@ if (IsArgSet("-blockmintxfee")) { Amount n(0); ParseMoney(GetArg("-blockmintxfee", ""), n); - blockMinFeeRate = CFeeRate(n); - } else { - blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); + SetBlockMinTxFee(n); } LOCK(cs_main); diff --git a/src/policy/policy.h b/src/policy/policy.h --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -22,7 +22,7 @@ static const uint64_t DEFAULT_BLOCK_PRIORITY_PERCENTAGE = 5; /** Default for -blockmintxfee, which sets the minimum feerate for a transaction * in blocks created by mining code **/ -static const Amount DEFAULT_BLOCK_MIN_TX_FEE(1000); +static const Amount DEFAULT_BLOCK_MIN_TX_FEE(0); /** The maximum size for transactions we're willing to relay/mine */ static const unsigned int MAX_STANDARD_TX_SIZE = 100000; /** Maximum number of signature check operations in an IsStandard() P2SH script diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "miner.h" - #include "chainparams.h" #include "coins.h" #include "config.h" @@ -86,12 +85,40 @@ GlobalConfig config; + // test 0 fee transaction is included in a block with + // default configuration. + blockMinFeeRate = CFeeRate(Amount(0)); + + // Test that a medium fee transaction will be selected after a higher fee + // rate package with a low fee rate parent. + CMutableTransaction tx; + tx.vin.resize(1); + tx.vin[0].scriptSig = CScript() << OP_1; + tx.vin[0].prevout.hash = txFirst[0]->GetId(); + tx.vin[0].prevout.n = 0; + tx.vout.resize(1); + tx.vout[0].nValue = Amount(5000000000LL); + // This tx has a low fee: 1000 satoshis. + // Save this txid for later use. + uint256 zeroFeeTx = tx.GetId(); + mempool.addUnchecked( + zeroFeeTx, + entry.Fee(Amount(0)).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + + std::unique_ptr pblocktemplate = + BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); + BOOST_CHECK(pblocktemplate->block.vtx[1]->GetId() == zeroFeeTx); + // these 3 tests assume blockprioritypercentage is 0. config.SetBlockPriorityPercentage(0); + // the following tests assume that minimum fee rate is 1000 satoshi per kB. + BlockAssembler ba(config, chainparams); + ba.SetBlockMinTxFee(Amount(1000)); + blockMinFeeRate = CFeeRate(Amount(1000)); + // Test that a medium fee transaction will be selected after a higher fee // rate package with a low fee rate parent. - CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].scriptSig = CScript() << OP_1; tx.vin[0].prevout.hash = txFirst[0]->GetId(); @@ -125,8 +152,7 @@ .SpendsCoinbase(false) .FromTx(tx)); - std::unique_ptr pblocktemplate = - BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); + pblocktemplate = ba.CreateNewBlock(scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[1]->GetId() == hashParentTx); BOOST_CHECK(pblocktemplate->block.vtx[2]->GetId() == hashHighFeeTx); BOOST_CHECK(pblocktemplate->block.vtx[3]->GetId() == hashMediumFeeTx); @@ -147,8 +173,7 @@ tx.vout[0].nValue = Amount(5000000000LL - 1000 - 50000) - feeToUse; uint256 hashLowFeeTx = tx.GetId(); mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx)); - pblocktemplate = - BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); + pblocktemplate = ba.CreateNewBlock(scriptPubKey); // Verify that the free tx and the low fee tx didn't get selected. for (size_t i = 0; i < pblocktemplate->block.vtx.size(); ++i) { BOOST_CHECK(pblocktemplate->block.vtx[i]->GetId() != hashFreeTx); @@ -164,8 +189,7 @@ hashLowFeeTx = tx.GetId(); mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse + Amount(2)).FromTx(tx)); - pblocktemplate = - BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); + pblocktemplate = ba.CreateNewBlock(scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[4]->GetId() == hashFreeTx); BOOST_CHECK(pblocktemplate->block.vtx[5]->GetId() == hashLowFeeTx); @@ -189,8 +213,7 @@ uint256 hashLowFeeTx2 = tx.GetId(); mempool.addUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx)); - pblocktemplate = - BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); + pblocktemplate = ba.CreateNewBlock(scriptPubKey); // Verify that this tx isn't selected. for (size_t i = 0; i < pblocktemplate->block.vtx.size(); ++i) { @@ -204,8 +227,7 @@ // 10k satoshi fee. tx.vout[0].nValue = Amount(100000000 - 10000); mempool.addUnchecked(tx.GetId(), entry.Fee(Amount(10000)).FromTx(tx)); - pblocktemplate = - BlockAssembler(config, chainparams).CreateNewBlock(scriptPubKey); + pblocktemplate = ba.CreateNewBlock(scriptPubKey); BOOST_CHECK(pblocktemplate->block.vtx[8]->GetId() == hashLowFeeTx2); } diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -56,7 +56,7 @@ /** Default for DEFAULT_WHITELISTFORCERELAY. */ static const bool DEFAULT_WHITELISTFORCERELAY = true; /** Default for -minrelaytxfee, minimum relay fee for transactions */ -static const Amount DEFAULT_MIN_RELAY_TX_FEE(1000); +static const Amount DEFAULT_MIN_RELAY_TX_FEE(0); //! -maxtxfee default static const Amount DEFAULT_TRANSACTION_MAXFEE(COIN / 10); //! Discourage users to set fees higher than this amount (in satoshis) per kB @@ -139,8 +139,9 @@ /** Additional block download timeout per parallel downloading peer (i.e. 5 min) */ static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000; - -static const unsigned int DEFAULT_LIMITFREERELAY = 0; +/** Continuously rate-limit free/priority transactions to + * limiterfreerelay*1000 bytes per minute. */ +static const unsigned int DEFAULT_LIMITFREERELAY = 20; static const bool DEFAULT_RELAYPRIORITY = true; static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; /** Maximum age of our tip in seconds for us to be considered current for fee