Skip to content

Commit d52fa1b

Browse files
committed
tests: Make sure that bumpfee feerate checks work when replacing outputs
When replacing the outputs of a transaction, we can end up with fees that are drastically different from the original. This tests that the feerate checks we perform will properly detect when the bumping tx will have an insufficient feerate.
1 parent be177c1 commit d52fa1b

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

test/functional/wallet_bumpfee.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
assert_equal,
2727
assert_greater_than,
2828
assert_raises_rpc_error,
29+
get_fee,
2930
)
3031
from test_framework.wallet import MiniWallet
3132

@@ -100,6 +101,7 @@ def run_test(self):
100101
test_change_script_match(self, rbf_node, dest_address)
101102
test_settxfee(self, rbf_node, dest_address)
102103
test_maxtxfee_fails(self, rbf_node, dest_address)
104+
test_feerate_checks_replaced_outputs(self, rbf_node)
103105
# These tests wipe out a number of utxos that are expected in other tests
104106
test_small_output_with_feerate_succeeds(self, rbf_node, dest_address)
105107
test_no_more_inputs_fails(self, rbf_node, dest_address)
@@ -668,5 +670,30 @@ def test_no_more_inputs_fails(self, rbf_node, dest_address):
668670
self.clear_mempool()
669671

670672

673+
def test_feerate_checks_replaced_outputs(self, rbf_node):
674+
self.log.info("Test that feerate checks use replaced outputs")
675+
outputs = []
676+
for i in range(50):
677+
outputs.append({rbf_node.getnewaddress(address_type="bech32"): 1})
678+
tx_res = rbf_node.send(outputs=outputs, fee_rate=5)
679+
tx_details = rbf_node.gettransaction(txid=tx_res["txid"], verbose=True)
680+
681+
# Calculate the minimum feerate required for the bump to work.
682+
# Since the bumped tx will replace all of the outputs with a single output, we can estimate that its size will 31 * (len(outputs) - 1) bytes smaller
683+
tx_size = tx_details["decoded"]["vsize"]
684+
est_bumped_size = tx_size - (len(tx_details["decoded"]["vout"]) - 1) * 31
685+
inc_fee_rate = max(rbf_node.getmempoolinfo()["incrementalrelayfee"], Decimal(0.00005000)) # Wallet has a fixed incremental relay fee of 5 sat/vb
686+
# RPC gives us fee as negative
687+
min_fee = (-tx_details["fee"] + get_fee(est_bumped_size, inc_fee_rate)) * Decimal(1e8)
688+
min_fee_rate = (min_fee / est_bumped_size).quantize(Decimal("1.000"))
689+
690+
# Attempt to bumpfee and replace all outputs with a single one using a feerate slightly less than the minimum
691+
new_outputs = [{rbf_node.getnewaddress(address_type="bech32"): 49}]
692+
assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, tx_res["txid"], {"fee_rate": min_fee_rate - 1, "outputs": new_outputs})
693+
694+
# Bumpfee and replace all outputs with a single one using the minimum feerate
695+
rbf_node.bumpfee(tx_res["txid"], {"fee_rate": min_fee_rate, "outputs": new_outputs})
696+
697+
671698
if __name__ == "__main__":
672699
BumpFeeTest().main()

0 commit comments

Comments
 (0)