[policy] lower default minrelaytxfee and incrementalrelayfee to 100sat/kvB

Let's say an attacker wants to use/exhaust the network's bandwidth, and
has the choice between renting resources from a commercial provider and
getting the network to "spam" itself it by sending unconfirmed
transactions. We'd like the latter to be more expensive than the former.

The bandwidth for relaying a transaction across the network is roughly
its serialized size (plus relay overhead) x number of nodes. A 1000vB
transaction is 1000-4000B serialized. With 100k nodes, that's 0.1-0.4GB
If the going rate for commercial services is 10c/GB, that's like 1-4c per kvB
of transaction data, so a 1000vB transaction should pay at least $0.04.

At a price of 120k USD/BTC, 100sat is about $0.12. This price allows us
to tolerate a large decrease in the conversion rate or increase in the
number of nodes.
This commit is contained in:
glozow committed 2025-08-11 17:07:43 -04:00
1 parent 2e515d2897
commit 6da5de58ca
12 files changed
+49 -47

No files matched your search

+2 -2
View File
@@ -41,7 +41,7 @@ static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/
/** The maximum number of potentially executed legacy signature operations in a single standard tx */ /** The maximum number of potentially executed legacy signature operations in a single standard tx */
static constexpr unsigned int MAX_TX_LEGACY_SIGOPS{2'500}; static constexpr unsigned int MAX_TX_LEGACY_SIGOPS{2'500};
/** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or replacement **/ /** 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 */ /** Default for -bytespersigop */
static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP{20}; static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP{20};
/** Default for -permitbaremultisig */ /** Default for -permitbaremultisig */
@@ -63,7 +63,7 @@ static constexpr unsigned int MAX_STANDARD_SCRIPTSIG_SIZE{1650};
* outputs below the new threshold */ * outputs below the new threshold */
static constexpr unsigned int DUST_RELAY_TX_FEE{3000}; static constexpr unsigned int DUST_RELAY_TX_FEE{3000};
/** Default for -minrelaytxfee, minimum relay fee for transactions */ /** 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 */ /** Default for -limitancestorcount, max number of in-mempool ancestors */
static constexpr unsigned int DEFAULT_ANCESTOR_LIMIT{25}; static constexpr unsigned int DEFAULT_ANCESTOR_LIMIT{25};
/** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */ /** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */
+12 -12
View File
@@ -443,7 +443,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
tx1.vout.resize(1); tx1.vout.resize(1);
tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL; tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
tx1.vout[0].nValue = 10 * COIN; tx1.vout[0].nValue = 10 * COIN;
AddToMempool(pool, entry.Fee(10000LL).FromTx(tx1)); AddToMempool(pool, entry.Fee(1000LL).FromTx(tx1));
CMutableTransaction tx2 = CMutableTransaction(); CMutableTransaction tx2 = CMutableTransaction();
tx2.vin.resize(1); tx2.vin.resize(1);
@@ -451,7 +451,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
tx2.vout.resize(1); tx2.vout.resize(1);
tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL; tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
tx2.vout[0].nValue = 10 * COIN; tx2.vout[0].nValue = 10 * COIN;
AddToMempool(pool, entry.Fee(5000LL).FromTx(tx2)); AddToMempool(pool, entry.Fee(500LL).FromTx(tx2));
pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing
BOOST_CHECK(pool.exists(tx1.GetHash())); BOOST_CHECK(pool.exists(tx1.GetHash()));
@@ -469,7 +469,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
tx3.vout.resize(1); tx3.vout.resize(1);
tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL; tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
tx3.vout[0].nValue = 10 * COIN; tx3.vout[0].nValue = 10 * COIN;
AddToMempool(pool, entry.Fee(20000LL).FromTx(tx3)); AddToMempool(pool, entry.Fee(2000LL).FromTx(tx3));
pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP) pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP)
BOOST_CHECK(!pool.exists(tx1.GetHash())); BOOST_CHECK(!pool.exists(tx1.GetHash()));
@@ -481,7 +481,7 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
BOOST_CHECK(!pool.exists(tx2.GetHash())); BOOST_CHECK(!pool.exists(tx2.GetHash()));
BOOST_CHECK(!pool.exists(tx3.GetHash())); BOOST_CHECK(!pool.exists(tx3.GetHash()));
CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2))); CFeeRate maxFeeRateRemoved(2500, GetVirtualTransactionSize(CTransaction(tx3)) + GetVirtualTransactionSize(CTransaction(tx2)));
BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE); BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + DEFAULT_INCREMENTAL_RELAY_FEE);
CMutableTransaction tx4 = CMutableTransaction(); CMutableTransaction tx4 = CMutableTransaction();
@@ -532,10 +532,10 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL; tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
tx7.vout[1].nValue = 10 * COIN; tx7.vout[1].nValue = 10 * COIN;
AddToMempool(pool, entry.Fee(7000LL).FromTx(tx4)); AddToMempool(pool, entry.Fee(700LL).FromTx(tx4));
AddToMempool(pool, entry.Fee(1000LL).FromTx(tx5)); AddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
AddToMempool(pool, entry.Fee(1100LL).FromTx(tx6)); AddToMempool(pool, entry.Fee(110LL).FromTx(tx6));
AddToMempool(pool, entry.Fee(9000LL).FromTx(tx7)); AddToMempool(pool, 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 // 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); pool.TrimToSize(pool.DynamicMemoryUsage() - 1);
@@ -544,8 +544,8 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
BOOST_CHECK(!pool.exists(tx7.GetHash())); BOOST_CHECK(!pool.exists(tx7.GetHash()));
if (!pool.exists(tx5.GetHash())) if (!pool.exists(tx5.GetHash()))
AddToMempool(pool, entry.Fee(1000LL).FromTx(tx5)); AddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
AddToMempool(pool, entry.Fee(9000LL).FromTx(tx7)); AddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7 pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7
BOOST_CHECK(pool.exists(tx4.GetHash())); BOOST_CHECK(pool.exists(tx4.GetHash()));
@@ -553,8 +553,8 @@ BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
BOOST_CHECK(pool.exists(tx6.GetHash())); BOOST_CHECK(pool.exists(tx6.GetHash()));
BOOST_CHECK(!pool.exists(tx7.GetHash())); BOOST_CHECK(!pool.exists(tx7.GetHash()));
AddToMempool(pool, entry.Fee(1000LL).FromTx(tx5)); AddToMempool(pool, entry.Fee(100LL).FromTx(tx5));
AddToMempool(pool, entry.Fee(9000LL).FromTx(tx7)); AddToMempool(pool, entry.Fee(900LL).FromTx(tx7));
std::vector<CTransactionRef> vtx; std::vector<CTransactionRef> vtx;
SetMockTime(42); SetMockTime(42);
+4 -4
View File
@@ -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, 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()); 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 // 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 + 1, 11, 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 + 1, 10, 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 + 2, 11, 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 + 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, incremental_relay_feerate, unused_txid).has_value());
BOOST_CHECK(PaysForRBF(low_fee, high_fee + 99999999, 99999999, incremental_relay_feerate, unused_txid) == std::nullopt); BOOST_CHECK(PaysForRBF(low_fee, high_fee + 99999999, 99999999, incremental_relay_feerate, unused_txid) == std::nullopt);
+1 -1
View File
@@ -585,7 +585,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Higher fee, higher feerate, different txid, but the replacement does not provide a relay # Higher fee, higher feerate, different txid, but the replacement does not provide a relay
# fee conforming to node's `incrementalrelayfee` policy of 1000 sat per KB. # fee conforming to node's `incrementalrelayfee` policy of 1000 sat per KB.
assert_equal(self.nodes[0].getmempoolinfo()["incrementalrelayfee"], Decimal("0.00001")) assert_equal(self.nodes[0].getmempoolinfo()["incrementalrelayfee"], Decimal("0.000001"))
tx.vout[0].nValue -= 1 tx.vout[0].nValue -= 1
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx.serialize().hex()) assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx.serialize().hex())
+1 -1
View File
@@ -216,7 +216,7 @@ class EphemeralDustTest(BitcoinTestFramework):
res = self.nodes[0].submitpackage([dusty_tx["hex"], sweep_tx["hex"]]) res = self.nodes[0].submitpackage([dusty_tx["hex"], sweep_tx["hex"]])
assert_equal(res["package_msg"], "transaction failed") assert_equal(res["package_msg"], "transaction failed")
assert_equal(res["tx-results"][dusty_tx["wtxid"]]["error"], "min relay fee not met, 0 < 147") assert_equal(res["tx-results"][dusty_tx["wtxid"]]["error"], "min relay fee not met, 0 < 15")
assert_equal(self.nodes[0].getrawmempool(), []) assert_equal(self.nodes[0].getrawmempool(), [])
+3 -3
View File
@@ -206,7 +206,7 @@ class MempoolLimitTest(BitcoinTestFramework):
# coin is no longer available, but the cache could still contain the tx. # coin is no longer available, but the cache could still contain the tx.
cpfp_parent = self.wallet.create_self_transfer( cpfp_parent = self.wallet.create_self_transfer(
utxo_to_spend=replaced_tx["new_utxo"], utxo_to_spend=replaced_tx["new_utxo"],
fee_rate=mempoolmin_feerate - Decimal('0.00001'), fee_rate=mempoolmin_feerate - Decimal('0.000001'),
confirmed_only=True) confirmed_only=True)
self.wallet.rescan_utxos() self.wallet.rescan_utxos()
@@ -312,9 +312,9 @@ class MempoolLimitTest(BitcoinTestFramework):
target_vsize_each = 50000 target_vsize_each = 50000
assert_greater_than(target_vsize_each * 2 * 3, node.getmempoolinfo()["maxmempool"] - node.getmempoolinfo()["bytes"]) assert_greater_than(target_vsize_each * 2 * 3, node.getmempoolinfo()["maxmempool"] - node.getmempoolinfo()["bytes"])
# Should be a true CPFP: parent's feerate is just below mempool min feerate # Should be a true CPFP: parent's feerate is just below mempool min feerate
parent_feerate = mempoolmin_feerate - Decimal("0.000001") # 0.1 sats/vbyte below min feerate parent_feerate = mempoolmin_feerate - Decimal("0.0000001") # 0.01 sats/vbyte below min feerate
# Parent + child is above mempool minimum feerate # Parent + child is above mempool minimum feerate
child_feerate = (worst_feerate_btcvb * 1000) - Decimal("0.000001") # 0.1 sats/vbyte below worst feerate child_feerate = (worst_feerate_btcvb * 1000) - Decimal("0.0000001") # 0.01 sats/vbyte below worst feerate
# However, when eviction is triggered, these transactions should be at the bottom. # However, when eviction is triggered, these transactions should be at the bottom.
# This assertion assumes parent and child are the same size. # This assertion assumes parent and child are the same size.
miniwallet.rescan_utxos() miniwallet.rescan_utxos()
+5 -4
View File
@@ -162,13 +162,13 @@ class PackageRBFTest(BitcoinTestFramework):
self.log.info("Check replacement pays for incremental bandwidth") self.log.info("Check replacement pays for incremental bandwidth")
_, placeholder_txns3 = self.create_simple_package(coin) _, placeholder_txns3 = self.create_simple_package(coin)
package_3_size = sum([tx.get_vsize() for tx in placeholder_txns3]) package_3_size = sum([tx.get_vsize() for tx in placeholder_txns3])
incremental_sats_required = Decimal(package_3_size) / COIN incremental_sats_required = (Decimal(package_3_size * 0.1) / COIN).quantize(Decimal("0.00000001"))
incremental_sats_short = incremental_sats_required - Decimal("0.00000001") incremental_sats_short = incremental_sats_required - Decimal("0.00000005")
# Recreate the package with slightly higher fee once we know the size of the new package, but still short of required fee # Recreate the package with slightly higher fee once we know the size of the new package, but still short of required fee
failure_package_hex3, failure_package_txns3 = self.create_simple_package(coin, parent_fee=DEFAULT_FEE, child_fee=DEFAULT_CHILD_FEE + incremental_sats_short) failure_package_hex3, failure_package_txns3 = self.create_simple_package(coin, parent_fee=DEFAULT_FEE, child_fee=DEFAULT_CHILD_FEE + incremental_sats_short)
assert_equal(package_3_size, sum([tx.get_vsize() for tx in failure_package_txns3])) assert_equal(package_3_size, sum([tx.get_vsize() for tx in failure_package_txns3]))
pkg_results3 = node.submitpackage(failure_package_hex3) pkg_results3 = node.submitpackage(failure_package_hex3)
assert_equal(f"package RBF failed: insufficient anti-DoS fees, rejecting replacement {failure_package_txns3[1].txid_hex}, not enough additional fees to relay; {incremental_sats_short} < {incremental_sats_required}", pkg_results3["package_msg"]) assert_equal(f"package RBF failed: insufficient anti-DoS fees, rejecting replacement {failure_package_txns3[1].txid_hex}, not enough additional fees to relay; {incremental_sats_short:8f} < {incremental_sats_required:8f}", pkg_results3["package_msg"])
self.assert_mempool_contents(expected=package_txns1) self.assert_mempool_contents(expected=package_txns1)
success_package_hex3, success_package_txns3 = self.create_simple_package(coin, parent_fee=DEFAULT_FEE, child_fee=DEFAULT_CHILD_FEE + incremental_sats_required) success_package_hex3, success_package_txns3 = self.create_simple_package(coin, parent_fee=DEFAULT_FEE, child_fee=DEFAULT_CHILD_FEE + incremental_sats_required)
@@ -562,12 +562,13 @@ class PackageRBFTest(BitcoinTestFramework):
) )
node.sendrawtransaction(grandparent_result["hex"]) node.sendrawtransaction(grandparent_result["hex"])
minrelayfeerate = node.getnetworkinfo()["relayfee"]
# Now make package of two descendants that looks # Now make package of two descendants that looks
# like a cpfp where the parent can't get in on its own # like a cpfp where the parent can't get in on its own
self.ctr += 1 self.ctr += 1
parent_result = self.wallet.create_self_transfer( parent_result = self.wallet.create_self_transfer(
fee_rate=Decimal('0.00001000'), fee_rate=minrelayfeerate,
utxo_to_spend=grandparent_result["new_utxo"], utxo_to_spend=grandparent_result["new_utxo"],
sequence=MAX_BIP125_RBF_SEQUENCE - self.ctr, sequence=MAX_BIP125_RBF_SEQUENCE - self.ctr,
) )
+8 -9
View File
@@ -13,9 +13,11 @@ from decimal import Decimal
from math import ceil from math import ceil
from test_framework.mempool_util import ( from test_framework.mempool_util import (
DEFAULT_MIN_RELAY_TX_FEE,
fill_mempool, fill_mempool,
) )
from test_framework.messages import ( from test_framework.messages import (
COIN,
msg_tx, msg_tx,
) )
from test_framework.p2p import ( from test_framework.p2p import (
@@ -31,9 +33,6 @@ from test_framework.wallet import (
MiniWalletMode, MiniWalletMode,
) )
# 1sat/vB feerate denominated in BTC/KvB
FEERATE_1SAT_VB = Decimal("0.00001000")
class PackageRelayTest(BitcoinTestFramework): class PackageRelayTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.setup_clean_chain = True self.setup_clean_chain = True
@@ -49,12 +48,12 @@ class PackageRelayTest(BitcoinTestFramework):
self.log.debug("Check that all nodes' mempool minimum feerates are above min relay feerate") self.log.debug("Check that all nodes' mempool minimum feerates are above min relay feerate")
for node in self.nodes: for node in self.nodes:
assert_equal(node.getmempoolinfo()['minrelaytxfee'], FEERATE_1SAT_VB) assert_equal(node.getmempoolinfo()['minrelaytxfee'], Decimal(DEFAULT_MIN_RELAY_TX_FEE) / COIN)
assert_greater_than(node.getmempoolinfo()['mempoolminfee'], FEERATE_1SAT_VB) assert_greater_than(node.getmempoolinfo()['mempoolminfee'], Decimal(DEFAULT_MIN_RELAY_TX_FEE) / COIN)
def create_basic_1p1c(self, wallet): def create_basic_1p1c(self, wallet):
low_fee_parent = wallet.create_self_transfer(fee_rate=FEERATE_1SAT_VB, confirmed_only=True) low_fee_parent = wallet.create_self_transfer(fee_rate=Decimal(DEFAULT_MIN_RELAY_TX_FEE) / COIN, confirmed_only=True)
high_fee_child = wallet.create_self_transfer(utxo_to_spend=low_fee_parent["new_utxo"], fee_rate=999*FEERATE_1SAT_VB) high_fee_child = wallet.create_self_transfer(utxo_to_spend=low_fee_parent["new_utxo"], fee_rate=999*Decimal(DEFAULT_MIN_RELAY_TX_FEE)/ COIN)
package_hex_basic = [low_fee_parent["hex"], high_fee_child["hex"]] package_hex_basic = [low_fee_parent["hex"], high_fee_child["hex"]]
return package_hex_basic, low_fee_parent["tx"], high_fee_child["tx"] return package_hex_basic, low_fee_parent["tx"], high_fee_child["tx"]
@@ -85,8 +84,8 @@ class PackageRelayTest(BitcoinTestFramework):
return [low_fee_parent_2outs["hex"], high_fee_child_2outs["hex"]], low_fee_parent_2outs["tx"], high_fee_child_2outs["tx"] return [low_fee_parent_2outs["hex"], high_fee_child_2outs["hex"]], low_fee_parent_2outs["tx"], high_fee_child_2outs["tx"]
def create_package_2p1c(self, wallet): def create_package_2p1c(self, wallet):
parent1 = wallet.create_self_transfer(fee_rate=FEERATE_1SAT_VB*10, confirmed_only=True) parent1 = wallet.create_self_transfer(fee_rate=Decimal(DEFAULT_MIN_RELAY_TX_FEE) / COIN * 10, confirmed_only=True)
parent2 = wallet.create_self_transfer(fee_rate=FEERATE_1SAT_VB*20, confirmed_only=True) parent2 = wallet.create_self_transfer(fee_rate=Decimal(DEFAULT_MIN_RELAY_TX_FEE) / COIN * 20, confirmed_only=True)
child = wallet.create_self_transfer_multi( child = wallet.create_self_transfer_multi(
utxos_to_spend=[parent1["new_utxo"], parent2["new_utxo"]], utxos_to_spend=[parent1["new_utxo"], parent2["new_utxo"]],
fee_per_output=999*parent1["tx"].get_vsize(), fee_per_output=999*parent1["tx"].get_vsize(),
+4 -4
View File
@@ -28,8 +28,8 @@ from test_framework.p2p import (
) )
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
MAX_FEE_FILTER = Decimal(9170997) / COIN MAX_FEE_FILTER = Decimal(9936506) / COIN
NORMAL_FEE_FILTER = Decimal(100) / COIN NORMAL_FEE_FILTER = Decimal(10) / COIN
class P2PIBDTxRelayTest(BitcoinTestFramework): class P2PIBDTxRelayTest(BitcoinTestFramework):
@@ -37,8 +37,8 @@ class P2PIBDTxRelayTest(BitcoinTestFramework):
self.setup_clean_chain = True self.setup_clean_chain = True
self.num_nodes = 2 self.num_nodes = 2
self.extra_args = [ self.extra_args = [
["-minrelaytxfee={}".format(NORMAL_FEE_FILTER)], ["-minrelaytxfee={:.8f}".format(NORMAL_FEE_FILTER)],
["-minrelaytxfee={}".format(NORMAL_FEE_FILTER)], ["-minrelaytxfee={:.8f}".format(NORMAL_FEE_FILTER)],
] ]
def run_test(self): def run_test(self):
+5 -3
View File
@@ -13,10 +13,12 @@ import time
from test_framework.blocktools import MAX_STANDARD_TX_WEIGHT from test_framework.blocktools import MAX_STANDARD_TX_WEIGHT
from test_framework.mempool_util import ( from test_framework.mempool_util import (
create_large_orphan, create_large_orphan,
DEFAULT_MIN_RELAY_TX_FEE,
fill_mempool, fill_mempool,
) )
from test_framework.messages import ( from test_framework.messages import (
CInv, CInv,
COIN,
COutPoint, COutPoint,
CTransaction, CTransaction,
CTxIn, CTxIn,
@@ -79,13 +81,13 @@ class PackageRelayTest(BitcoinTestFramework):
]] ]]
def create_tx_below_mempoolminfee(self, wallet, utxo_to_spend=None): def create_tx_below_mempoolminfee(self, wallet, utxo_to_spend=None):
"""Create a 1-input 1sat/vB transaction using a confirmed UTXO. Decrement and use """Create a 1-input 0.1sat/vB transaction using a confirmed UTXO. Decrement and use
self.sequence so that subsequent calls to this function result in unique transactions.""" self.sequence so that subsequent calls to this function result in unique transactions."""
self.sequence -= 1 self.sequence -= 1
assert_greater_than(self.nodes[0].getmempoolinfo()["mempoolminfee"], FEERATE_1SAT_VB) assert_greater_than(self.nodes[0].getmempoolinfo()["mempoolminfee"], Decimal(DEFAULT_MIN_RELAY_TX_FEE) / COIN)
return wallet.create_self_transfer(fee_rate=FEERATE_1SAT_VB, sequence=self.sequence, utxo_to_spend=utxo_to_spend, confirmed_only=True) return wallet.create_self_transfer(fee_rate=Decimal(DEFAULT_MIN_RELAY_TX_FEE) / COIN, sequence=self.sequence, utxo_to_spend=utxo_to_spend, confirmed_only=True)
@cleanup @cleanup
def test_basic_child_then_parent(self): def test_basic_child_then_parent(self):
@@ -30,9 +30,9 @@ from .wallet import (
) )
# Default for -minrelaytxfee in sat/kvB # Default for -minrelaytxfee in sat/kvB
DEFAULT_MIN_RELAY_TX_FEE = 1000 DEFAULT_MIN_RELAY_TX_FEE = 100
# Default for -incrementalrelayfee in sat/kvB # Default for -incrementalrelayfee in sat/kvB
DEFAULT_INCREMENTAL_RELAY_FEE = 1000 DEFAULT_INCREMENTAL_RELAY_FEE = 100
def assert_mempool_contents(test_framework, node, expected=None, sync=True): def assert_mempool_contents(test_framework, node, expected=None, sync=True):
"""Assert that all transactions in expected are in the mempool, """Assert that all transactions in expected are in the mempool,
+2 -2
View File
@@ -535,7 +535,7 @@ def test_dust_to_fee(self, rbf_node, dest_address):
def test_settxfee(self, rbf_node, dest_address): def test_settxfee(self, rbf_node, dest_address):
self.log.info('Test settxfee') self.log.info('Test settxfee')
assert_raises_rpc_error(-8, "txfee cannot be less than min relay tx fee", rbf_node.settxfee, Decimal('0.000005')) assert_raises_rpc_error(-8, "txfee cannot be less than min relay tx fee", rbf_node.settxfee, Decimal('0.0000005'))
assert_raises_rpc_error(-8, "txfee cannot be less than wallet min fee", rbf_node.settxfee, Decimal('0.000015')) assert_raises_rpc_error(-8, "txfee cannot be less than wallet min fee", rbf_node.settxfee, Decimal('0.000015'))
# check that bumpfee reacts correctly to the use of settxfee (paytxfee) # check that bumpfee reacts correctly to the use of settxfee (paytxfee)
rbfid = spend_one_input(rbf_node, dest_address) rbfid = spend_one_input(rbf_node, dest_address)
@@ -850,7 +850,7 @@ def test_bumpfee_with_feerate_ignores_walletincrementalrelayfee(self, rbf_node,
# Ensure you can not fee bump if the fee_rate is more than original fee_rate but the total fee from new fee_rate is # Ensure you can not fee bump if the fee_rate is more than original fee_rate but the total fee from new fee_rate is
# less than (original fee + incrementalrelayfee) # less than (original fee + incrementalrelayfee)
assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, tx["txid"], {"fee_rate": 2.8}) assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, tx["txid"], {"fee_rate": 2.05})
# You can fee bump as long as the new fee set from fee_rate is at least (original fee + incrementalrelayfee) # You can fee bump as long as the new fee set from fee_rate is at least (original fee + incrementalrelayfee)
rbf_node.bumpfee(tx["txid"], {"fee_rate": 3}) rbf_node.bumpfee(tx["txid"], {"fee_rate": 3})