[test] RBF rule 4 for various incrementalrelayfee settings
What changed, and why it matters
This commit only adds new automated tests for Bitcoin Core's Replace-By-Fee (RBF) fee-bumping rules. It does not change any production code, network protocol, or wallet behavior. The tests verify that a transaction replacement must pay a higher fee when the node's '-incrementalrelayfee' setting is raised. There is no security fix or vulnerability patch here.
No security action needed. Treat as routine test coverage improvement. Reviewers may optionally confirm the test's fee arithmetic matches BIP125 rule 4 and the incremental relay fee semantics in policy/rbf.cpp.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff extends test/functional/feature_rbf.py with a new test_incremental_relay_feerates() method. It restarts a regtest node with various -incrementalrelayfee values, creates a replacee transaction, computes the required replacement fee as replacee fee + incremental_relay_fee * replacement_vsize, and asserts that a replacement paying one satoshi less is rejected with ‘insufficient fee’ while one paying exactly the required fee is accepted. No consensus, mempool policy, or P2P code is modified.
Changed components
test/functional/feature_rbf.pyInspect captured patch +38 / −0
diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py
index 3c9b21dd..5f462512 100755
--- a/test/functional/feature_rbf.py
+++ b/test/functional/feature_rbf.py
@@ -13,7 +13,10 @@ from test_framework.messages import (
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
+ assert_greater_than,
+ assert_greater_than_or_equal,
assert_raises_rpc_error,
+ get_fee,
)
from test_framework.wallet import MiniWallet
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
@@ -74,6 +77,9 @@ class ReplaceByFeeTest(BitcoinTestFramework):
self.log.info("Running test full replace by fee...")
self.test_fullrbf()
+ self.log.info("Running test incremental relay feerates...")
+ self.test_incremental_relay_feerates()
+
self.log.info("Passed")
def make_utxo(self, node, amount, *, confirmed=True, scriptPubKey=None):
@@ -583,6 +589,38 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx.vout[0].nValue -= 1
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, tx.serialize().hex())
+ def test_incremental_relay_feerates(self):
+ self.log.info("Test that incremental relay fee is applied correctly in RBF for various settings...")
+ node = self.nodes[0]
+ for incremental_setting in (0, 5, 10, 50, 100, 234, 1000, 5000, 21000):
+ incremental_setting_decimal = incremental_setting / Decimal(COIN)
+ self.log.info(f"-> Test -incrementalrelayfee={incremental_setting_decimal:.8f}sat/kvB...")
+ self.restart_node(0, extra_args=[f"-incrementalrelayfee={incremental_setting_decimal:.8f}", "-persistmempool=0"])
+
+ # When incremental relay feerate is higher than min relay feerate, min relay feerate is automatically increased.
+ min_relay_feerate = node.getmempoolinfo()["minrelaytxfee"]
+ assert_greater_than_or_equal(min_relay_feerate, incremental_setting_decimal)
+
+ low_feerate = min_relay_feerate * 2
+ confirmed_utxo = self.wallet.get_utxo(confirmed_only=True)
+ replacee_tx = self.wallet.create_self_transfer(utxo_to_spend=confirmed_utxo, fee_rate=low_feerate, target_vsize=5000)
+ node.sendrawtransaction(replacee_tx['hex'])
+
+ replacement_placeholder_tx = self.wallet.create_self_transfer(utxo_to_spend=confirmed_utxo)
+ replacement_expected_size = replacement_placeholder_tx['tx'].get_vsize()
+ replacement_required_fee = get_fee(replacement_expected_size, incremental_setting_decimal) + replacee_tx['fee']
+
+ # Should always be required to pay additional fees
+ if incremental_setting > 0:
+ assert_greater_than(replacement_required_fee, replacee_tx['fee'])
+
+ # 1 satoshi shy of the required fee
+ failed_replacement_tx = self.wallet.create_self_transfer(utxo_to_spend=confirmed_utxo, fee=replacement_required_fee - Decimal("0.00000001"))
+ assert_raises_rpc_error(-26, "insufficient fee", node.sendrawtransaction, failed_replacement_tx['hex'])
+
+ replacement_tx = self.wallet.create_self_transfer(utxo_to_spend=confirmed_utxo, fee=replacement_required_fee)
+ node.sendrawtransaction(replacement_tx['hex'])
+
def test_fullrbf(self):
# BIP125 signaling is not respected
Why this scored 12/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.