diff --git a/configure.ac b/configure.ac index 97b1dc468f4..d1ec160af8f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 28) -define(_CLIENT_VERSION_MINOR, 2) +define(_CLIENT_VERSION_MINOR, 3) define(_CLIENT_VERSION_BUILD, 0) -define(_CLIENT_VERSION_RC, 0) +define(_CLIENT_VERSION_RC, 1) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2025) define(_COPYRIGHT_HOLDERS,[The %s developers]) diff --git a/doc/man/bitcoin-cli.1 b/doc/man/bitcoin-cli.1 index 80f1fd6b312..f1171c63b12 100644 --- a/doc/man/bitcoin-cli.1 +++ b/doc/man/bitcoin-cli.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIN-CLI "1" "June 2025" "bitcoin-cli v28.2.0" "User Commands" +.TH BITCOIN-CLI "1" "September 2025" "bitcoin-cli v28.3.0rc1" "User Commands" .SH NAME -bitcoin-cli \- manual page for bitcoin-cli v28.2.0 +bitcoin-cli \- manual page for bitcoin-cli v28.3.0rc1 .SH SYNOPSIS .B bitcoin-cli [\fI\,options\/\fR] \fI\, \/\fR[\fI\,params\/\fR] \fI\,Send command to Bitcoin Core\/\fR @@ -15,7 +15,7 @@ bitcoin-cli \- manual page for bitcoin-cli v28.2.0 .B bitcoin-cli [\fI\,options\/\fR] \fI\,help Get help for a command\/\fR .SH DESCRIPTION -Bitcoin Core RPC client version v28.2.0 +Bitcoin Core RPC client version v28.3.0rc1 .SH OPTIONS .HP \-? diff --git a/doc/man/bitcoin-qt.1 b/doc/man/bitcoin-qt.1 index 9b358991e05..c9635410a79 100644 --- a/doc/man/bitcoin-qt.1 +++ b/doc/man/bitcoin-qt.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIN-QT "1" "June 2025" "bitcoin-qt v28.2.0" "User Commands" +.TH BITCOIN-QT "1" "September 2025" "bitcoin-qt v28.3.0rc1" "User Commands" .SH NAME -bitcoin-qt \- manual page for bitcoin-qt v28.2.0 +bitcoin-qt \- manual page for bitcoin-qt v28.3.0rc1 .SH SYNOPSIS .B bitcoin-qt [\fI\,command-line options\/\fR] [\fI\,URI\/\fR] .SH DESCRIPTION -Bitcoin Core version v28.2.0 +Bitcoin Core version v28.3.0rc1 .PP Optional URI is a Bitcoin address in BIP21 URI format. .SH OPTIONS @@ -705,7 +705,7 @@ replaceability signaling (default: 1) \fB\-minrelaytxfee=\fR .IP Fees (in BTC/kvB) smaller than this are considered zero fee for -relaying, mining and transaction creation (default: 0.00001) +relaying, mining and transaction creation (default: 0.000001) .HP \fB\-permitbaremultisig\fR .IP @@ -732,7 +732,7 @@ Set maximum BIP141 block weight (default: 3996000) \fB\-blockmintxfee=\fR .IP Set lowest fee rate (in BTC/kvB) for transactions to be included in -block creation. (default: 0.00001) +block creation. (default: 0.00000001) .PP RPC server options: .HP diff --git a/doc/man/bitcoin-tx.1 b/doc/man/bitcoin-tx.1 index 9176add4ed6..bab1c28d5b8 100644 --- a/doc/man/bitcoin-tx.1 +++ b/doc/man/bitcoin-tx.1 @@ -1,7 +1,7 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIN-TX "1" "June 2025" "bitcoin-tx v28.2.0" "User Commands" +.TH BITCOIN-TX "1" "September 2025" "bitcoin-tx v28.3.0rc1" "User Commands" .SH NAME -bitcoin-tx \- manual page for bitcoin-tx v28.2.0 +bitcoin-tx \- manual page for bitcoin-tx v28.3.0rc1 .SH SYNOPSIS .B bitcoin-tx [\fI\,options\/\fR] \fI\, \/\fR[\fI\,commands\/\fR] \fI\,Update hex-encoded bitcoin transaction\/\fR @@ -9,7 +9,7 @@ bitcoin-tx \- manual page for bitcoin-tx v28.2.0 .B bitcoin-tx [\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR] \fI\,Create hex-encoded bitcoin transaction\/\fR .SH DESCRIPTION -Bitcoin Core bitcoin\-tx utility version v28.2.0 +Bitcoin Core bitcoin\-tx utility version v28.3.0rc1 .SH OPTIONS .HP \-? diff --git a/doc/man/bitcoin-util.1 b/doc/man/bitcoin-util.1 index 1abc8bd5568..f41d0756e59 100644 --- a/doc/man/bitcoin-util.1 +++ b/doc/man/bitcoin-util.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIN-UTIL "1" "June 2025" "bitcoin-util v28.2.0" "User Commands" +.TH BITCOIN-UTIL "1" "September 2025" "bitcoin-util v28.3.0rc1" "User Commands" .SH NAME -bitcoin-util \- manual page for bitcoin-util v28.2.0 +bitcoin-util \- manual page for bitcoin-util v28.3.0rc1 .SH SYNOPSIS .B bitcoin-util [\fI\,options\/\fR] [\fI\,commands\/\fR] \fI\,Do stuff\/\fR .SH DESCRIPTION -Bitcoin Core bitcoin\-util utility version v28.2.0 +Bitcoin Core bitcoin\-util utility version v28.3.0rc1 .SH OPTIONS .HP \-? diff --git a/doc/man/bitcoin-wallet.1 b/doc/man/bitcoin-wallet.1 index 9242497f0d3..04886604d84 100644 --- a/doc/man/bitcoin-wallet.1 +++ b/doc/man/bitcoin-wallet.1 @@ -1,9 +1,9 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIN-WALLET "1" "June 2025" "bitcoin-wallet v28.2.0" "User Commands" +.TH BITCOIN-WALLET "1" "September 2025" "bitcoin-wallet v28.3.0rc1" "User Commands" .SH NAME -bitcoin-wallet \- manual page for bitcoin-wallet v28.2.0 +bitcoin-wallet \- manual page for bitcoin-wallet v28.3.0rc1 .SH DESCRIPTION -Bitcoin Core bitcoin\-wallet version v28.2.0 +Bitcoin Core bitcoin\-wallet version v28.3.0rc1 .PP bitcoin\-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files. By default bitcoin\-wallet will act on wallets in the default mainnet wallet directory in the datadir. diff --git a/doc/man/bitcoind.1 b/doc/man/bitcoind.1 index 73e3d225eb5..10ce497c2ba 100644 --- a/doc/man/bitcoind.1 +++ b/doc/man/bitcoind.1 @@ -1,12 +1,12 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3. -.TH BITCOIND "1" "June 2025" "bitcoind v28.2.0" "User Commands" +.TH BITCOIND "1" "September 2025" "bitcoind v28.3.0rc1" "User Commands" .SH NAME -bitcoind \- manual page for bitcoind v28.2.0 +bitcoind \- manual page for bitcoind v28.3.0rc1 .SH SYNOPSIS .B bitcoind [\fI\,options\/\fR] \fI\,Start Bitcoin Core\/\fR .SH DESCRIPTION -Bitcoin Core version v28.2.0 +Bitcoin Core version v28.3.0rc1 .SH OPTIONS .HP \-? @@ -703,7 +703,7 @@ replaceability signaling (default: 1) \fB\-minrelaytxfee=\fR .IP Fees (in BTC/kvB) smaller than this are considered zero fee for -relaying, mining and transaction creation (default: 0.00001) +relaying, mining and transaction creation (default: 0.000001) .HP \fB\-permitbaremultisig\fR .IP @@ -730,7 +730,7 @@ Set maximum BIP141 block weight (default: 3996000) \fB\-blockmintxfee=\fR .IP Set lowest fee rate (in BTC/kvB) for transactions to be included in -block creation. (default: 0.00001) +block creation. (default: 0.00000001) .PP RPC server options: .HP diff --git a/doc/release-notes.md b/doc/release-notes.md index 97280d5c0da..ffeab2d3c00 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -37,6 +37,22 @@ unsupported systems. Notable changes =============== +### Policy + + The minimum block feerate (`-blockmintxfee`) has been changed to 1 satoshi per kvB. It can still be changed using the +configuration option. + +- The default minimum relay feerate (`-minrelaytxfee`) and incremental relay feerate (`-incrementalrelayfee`) have been +changed to 100 satoshis per kvB. They can still be changed using their respective configuration options, but it is +recommended to change both together if you decide to do so. + - Other minimum feerates (e.g. the dust feerate, the minimum returned by the fee estimator, and all feerates used by + the wallet) remain unchanged. The mempool minimum feerate still changes in response to high volume. + - Note that unless these lower defaults are widely adopted across the network, transactions created with lower fee + rates are not guaranteed to propagate or confirm. The wallet feerates remain unchanged; `-mintxfee` must be changed + before attempting to create transactions with lower feerates using the wallet. + +- #33106 policy: lower the default blockmintxfee, incrementalrelayfee, minrelaytxfee + ### P2P - #33395 net: do not apply whitelist permissions to onion inbounds @@ -45,6 +61,9 @@ Notable changes - #32765 test: Fix list index out of range error in feature_bip68_sequence.py - #33001 test: Do not pass tests on unhandled exceptions +- #30125 test: improve BDB parser (handle internal/overflow pages, support all page sizes) +- #30948 test: Add missing sync_mempools() to fill_mempool() +- #30784 test: add BulkTransaction helper to unit test transaction utils ### Build @@ -70,6 +89,7 @@ Credits Thanks to everyone who directly contributed to this release: - 0xB10C - fanquake +- glozow - Hennadii Stepanov - MarcoFalke - Martin Zumsande diff --git a/share/examples/bitcoin.conf b/share/examples/bitcoin.conf index a8dfc2735d9..bda3ca86dd7 100644 --- a/share/examples/bitcoin.conf +++ b/share/examples/bitcoin.conf @@ -591,7 +591,7 @@ #mempoolfullrbf=1 # Fees (in BTC/kvB) smaller than this are considered zero fee for -# relaying, mining and transaction creation (default: 0.00001) +# relaying, mining and transaction creation (default: 0.000001) #minrelaytxfee= # Relay transactions creating non-P2SH multisig outputs (default: 1) @@ -615,7 +615,7 @@ #blockmaxweight= # Set lowest fee rate (in BTC/kvB) for transactions to be included in -# block creation. (default: 0.00001) +# block creation. (default: 0.00000001) #blockmintxfee= diff --git a/src/node/mempool_args.cpp b/src/node/mempool_args.cpp index a488c1b1498..eceff59301b 100644 --- a/src/node/mempool_args.cpp +++ b/src/node/mempool_args.cpp @@ -56,6 +56,7 @@ util::Result ApplyArgsManOptions(const ArgsManager& argsman, const CChainP } } + static_assert(DEFAULT_MIN_RELAY_TX_FEE == DEFAULT_INCREMENTAL_RELAY_FEE); if (argsman.IsArgSet("-minrelaytxfee")) { if (std::optional min_relay_feerate = ParseMoney(argsman.GetArg("-minrelaytxfee", ""))) { // High fee check is done afterward in CWallet::Create() diff --git a/src/policy/policy.h b/src/policy/policy.h index a82488a28c9..94da3c1af54 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -22,7 +22,7 @@ class CScript; /** Default for -blockmaxweight, which controls the range of block weights the mining code will create **/ static constexpr unsigned int DEFAULT_BLOCK_MAX_WEIGHT{MAX_BLOCK_WEIGHT - 4000}; /** Default for -blockmintxfee, which sets the minimum feerate for a transaction in blocks created by mining code **/ -static constexpr unsigned int DEFAULT_BLOCK_MIN_TX_FEE{1000}; +static constexpr unsigned int DEFAULT_BLOCK_MIN_TX_FEE{1}; /** The maximum weight for transactions we're willing to relay/mine */ static constexpr int32_t MAX_STANDARD_TX_WEIGHT{400000}; /** The minimum non-witness size for transactions we're willing to relay/mine: one larger than 64 */ @@ -32,7 +32,7 @@ static constexpr unsigned int MAX_P2SH_SIGOPS{15}; /** The maximum number of sigops we're willing to relay/mine in a single tx */ static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/5}; /** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or replacement **/ -static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{1000}; +static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{100}; /** Default for -bytespersigop */ static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP{20}; /** Default for -permitbaremultisig */ @@ -54,7 +54,7 @@ static constexpr unsigned int MAX_STANDARD_SCRIPTSIG_SIZE{1650}; * outputs below the new threshold */ static constexpr unsigned int DUST_RELAY_TX_FEE{3000}; /** Default for -minrelaytxfee, minimum relay fee for transactions */ -static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE{1000}; +static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE{100}; /** Default for -limitancestorcount, max number of in-mempool ancestors */ static constexpr unsigned int DEFAULT_ANCESTOR_LIMIT{25}; /** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */ diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp index 9f8d434213b..9e6136bc9f4 100644 --- a/src/test/mempool_tests.cpp +++ b/src/test/mempool_tests.cpp @@ -443,7 +443,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) tx1.vout.resize(1); tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; tx1.vout[0].nValue = 10 * COIN; - pool.addUnchecked(entry.Fee(10000LL).FromTx(tx1)); + pool.addUnchecked(entry.Fee(1000LL).FromTx(tx1)); CMutableTransaction tx2 = CMutableTransaction(); tx2.vin.resize(1); @@ -451,7 +451,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) tx2.vout.resize(1); tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL; tx2.vout[0].nValue = 10 * COIN; - pool.addUnchecked(entry.Fee(5000LL).FromTx(tx2)); + pool.addUnchecked(entry.Fee(500LL).FromTx(tx2)); pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing BOOST_CHECK(pool.exists(GenTxid::Txid(tx1.GetHash()))); @@ -469,7 +469,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) tx3.vout.resize(1); tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL; tx3.vout[0].nValue = 10 * COIN; - pool.addUnchecked(entry.Fee(20000LL).FromTx(tx3)); + pool.addUnchecked(entry.Fee(2000LL).FromTx(tx3)); pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP) BOOST_CHECK(!pool.exists(GenTxid::Txid(tx1.GetHash()))); @@ -481,8 +481,8 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) BOOST_CHECK(!pool.exists(GenTxid::Txid(tx2.GetHash()))); BOOST_CHECK(!pool.exists(GenTxid::Txid(tx3.GetHash()))); - CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2))); - BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000); + CFeeRate maxFeeRateRemoved(2500, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2))); + BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE); CMutableTransaction tx4 = CMutableTransaction(); tx4.vin.resize(2); @@ -532,10 +532,10 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL; tx7.vout[1].nValue = 10 * COIN; - pool.addUnchecked(entry.Fee(7000LL).FromTx(tx4)); - pool.addUnchecked(entry.Fee(1000LL).FromTx(tx5)); - pool.addUnchecked(entry.Fee(1100LL).FromTx(tx6)); - pool.addUnchecked(entry.Fee(9000LL).FromTx(tx7)); + pool.addUnchecked(entry.Fee(700LL).FromTx(tx4)); + pool.addUnchecked(entry.Fee(100LL).FromTx(tx5)); + pool.addUnchecked(entry.Fee(110LL).FromTx(tx6)); + pool.addUnchecked(entry.Fee(900LL).FromTx(tx7)); // we only require this to remove, at max, 2 txn, because it's not clear what we're really optimizing for aside from that pool.TrimToSize(pool.DynamicMemoryUsage() - 1); @@ -544,8 +544,8 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) BOOST_CHECK(!pool.exists(GenTxid::Txid(tx7.GetHash()))); if (!pool.exists(GenTxid::Txid(tx5.GetHash()))) - pool.addUnchecked(entry.Fee(1000LL).FromTx(tx5)); - pool.addUnchecked(entry.Fee(9000LL).FromTx(tx7)); + pool.addUnchecked(entry.Fee(100LL).FromTx(tx5)); + pool.addUnchecked(entry.Fee(900LL).FromTx(tx7)); pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7 BOOST_CHECK(pool.exists(GenTxid::Txid(tx4.GetHash()))); @@ -553,34 +553,34 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest) BOOST_CHECK(pool.exists(GenTxid::Txid(tx6.GetHash()))); BOOST_CHECK(!pool.exists(GenTxid::Txid(tx7.GetHash()))); - pool.addUnchecked(entry.Fee(1000LL).FromTx(tx5)); - pool.addUnchecked(entry.Fee(9000LL).FromTx(tx7)); + pool.addUnchecked(entry.Fee(100LL).FromTx(tx5)); + pool.addUnchecked(entry.Fee(900LL).FromTx(tx7)); std::vector vtx; SetMockTime(42); SetMockTime(42 + CTxMemPool::ROLLING_FEE_HALFLIFE); - BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000); + BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE); // ... we should keep the same min fee until we get a block pool.removeForBlock(vtx, 1); SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE); - BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + 1000)/2.0)); + BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE)/2.0)); // ... then feerate should drop 1/2 each halflife SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2); - BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 5 / 2).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + 1000)/4.0)); + BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 5 / 2).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE)/4.0)); // ... with a 1/2 halflife when mempool is < 1/2 its target size SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4); - BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 9 / 2).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + 1000)/8.0)); + BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 9 / 2).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE)/8.0)); // ... with a 1/4 halflife when mempool is < 1/4 its target size SetMockTime(42 + 7*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4); - BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), 1000); - // ... but feerate should never drop below 1000 + BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), DEFAULT_INCREMENTAL_RELAY_FEE); + // ... but feerate should never drop below DEFAULT_INCREMENTAL_RELAY_FEE SetMockTime(42 + 8*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4); BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), 0); - // ... unless it has gone all the way to 0 (after getting past 1000/2) + // ... unless it has gone all the way to 0 (after getting past DEFAULT_INCREMENTAL_RELAY_FEE/2) } inline CTransactionRef make_tx(std::vector&& output_values, std::vector&& inputs=std::vector(), std::vector&& input_indices=std::vector()) diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index c4cf6f8a400..f82e50553b8 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -183,6 +184,9 @@ void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const tx.vout.resize(2); tx.vout[0].nValue = 5000000000LL - 100000000; tx.vout[1].nValue = 100000000; // 1BTC output + // Increase size to avoid rounding errors: when the feerate is extremely small (i.e. 1sat/kvB), evaluating the fee + // at a smaller transaction size gives us a rounded value of 0. + BulkTransaction(tx, 4000); Txid hashFreeTx2 = tx.GetHash(); tx_mempool.addUnchecked(entry.Fee(0).SpendsCoinbase(true).FromTx(tx)); diff --git a/src/test/rbf_tests.cpp b/src/test/rbf_tests.cpp index 19e45c550a0..66da3a71e91 100644 --- a/src/test/rbf_tests.cpp +++ b/src/test/rbf_tests.cpp @@ -238,10 +238,10 @@ BOOST_FIXTURE_TEST_CASE(rbf_helper_functions, TestChain100Setup) BOOST_CHECK(PaysForRBF(high_fee, high_fee - 1, 1, CFeeRate(0), unused_txid).has_value()); BOOST_CHECK(PaysForRBF(high_fee + 1, high_fee, 1, CFeeRate(0), unused_txid).has_value()); // Additional fees must cover the replacement's vsize at incremental relay fee - BOOST_CHECK(PaysForRBF(high_fee, high_fee + 1, 2, incremental_relay_feerate, unused_txid).has_value()); - BOOST_CHECK(PaysForRBF(high_fee, high_fee + 2, 2, incremental_relay_feerate, unused_txid) == std::nullopt); - BOOST_CHECK(PaysForRBF(high_fee, high_fee + 2, 2, higher_relay_feerate, unused_txid).has_value()); - BOOST_CHECK(PaysForRBF(high_fee, high_fee + 4, 2, higher_relay_feerate, unused_txid) == std::nullopt); + BOOST_CHECK(PaysForRBF(high_fee, high_fee + 1, 11, incremental_relay_feerate, unused_txid).has_value()); + BOOST_CHECK(PaysForRBF(high_fee, high_fee + 1, 10, incremental_relay_feerate, unused_txid) == std::nullopt); + BOOST_CHECK(PaysForRBF(high_fee, high_fee + 2, 11, higher_relay_feerate, unused_txid).has_value()); + BOOST_CHECK(PaysForRBF(high_fee, high_fee + 4, 20, higher_relay_feerate, unused_txid) == std::nullopt); BOOST_CHECK(PaysForRBF(low_fee, high_fee, 99999999, incremental_relay_feerate, unused_txid).has_value()); BOOST_CHECK(PaysForRBF(low_fee, high_fee + 99999999, 99999999, incremental_relay_feerate, unused_txid) == std::nullopt); diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 62ff61b227d..cd937b2fb4b 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -582,6 +583,9 @@ void TestChain100Setup::MockMempoolMinFee(const CFeeRate& target_feerate) CMutableTransaction mtx = CMutableTransaction(); mtx.vin.emplace_back(COutPoint{Txid::FromUint256(g_insecure_rand_ctx.rand256()), 0}); mtx.vout.emplace_back(1 * COIN, GetScriptForDestination(WitnessV0ScriptHash(CScript() << OP_TRUE))); + // Set a large size so that the fee evaluated at target_feerate (which is usually in sats/kvB) is an integer. + // Otherwise, GetMinFee() may end up slightly different from target_feerate. + BulkTransaction(mtx, 4000); const auto tx{MakeTransactionRef(mtx)}; LockPoints lp; // The new mempool min feerate is equal to the removed package's feerate + incremental feerate. diff --git a/src/test/util/transaction_utils.cpp b/src/test/util/transaction_utils.cpp index 300caa577ca..5727da44440 100644 --- a/src/test/util/transaction_utils.cpp +++ b/src/test/util/transaction_utils.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include +#include #include