Skip to content

Commit f66bc42

Browse files
achow101fanquake
authored andcommitted
tests: Test for assertion when feerate is rounded down
When calculating a txs absolute fee, if the fee is rounded down to the nearest satoshi, it is possible for the coin selection algorithms to undercalculate the fee needed. This can lead to an assertion error in some situations. One such scenario is added to rpc_fundrawtransaction.py. Github-Pull: #22949 Rebased-From: ce2cc44
1 parent bd7e08e commit f66bc42

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

test/functional/rpc_fundrawtransaction.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ def run_test(self):
100100
self.test_transaction_too_large()
101101
self.test_include_unsafe()
102102
self.test_22670()
103+
self.test_feerate_rounding()
103104

104105
def test_change_position(self):
105106
"""Ensure setting changePosition in fundraw with an exact match is handled properly."""
@@ -1026,6 +1027,33 @@ def do_fund_send(target):
10261027
do_fund_send(upper_bound)
10271028

10281029
self.restart_node(0)
1030+
self.connect_nodes(0, 1)
1031+
self.connect_nodes(0, 2)
1032+
self.connect_nodes(0, 3)
1033+
1034+
def test_feerate_rounding(self):
1035+
self.log.info("Test that rounding of GetFee does not result in an assertion")
1036+
1037+
self.nodes[1].createwallet("roundtest")
1038+
w = self.nodes[1].get_wallet_rpc("roundtest")
1039+
1040+
addr = w.getnewaddress(address_type="bech32")
1041+
self.nodes[0].sendtoaddress(addr, 1)
1042+
self.nodes[0].generate(1)
1043+
self.sync_all()
1044+
1045+
# A P2WPKH input costs 68 vbytes; With a single P2WPKH output, the rest of the tx is 42 vbytes for a total of 110 vbytes.
1046+
# At a feerate of 1.85 sat/vb, the input will need a fee of 125.8 sats and the rest 77.7 sats
1047+
# The entire tx fee should be 203.5 sats.
1048+
# Coin selection rounds the fee individually instead of at the end (due to how CFeeRate::GetFee works).
1049+
# If rounding down (which is the incorrect behavior), then the calculated fee will be 125 + 77 = 202.
1050+
# If rounding up, then the calculated fee will be 126 + 78 = 204.
1051+
# In the former case, the calculated needed fee is higher than the actual fee being paid, so an assertion is reached
1052+
# To test this does not happen, we subtract 202 sats from the input value. If working correctly, this should
1053+
# fail with insufficient funds rather than bitcoind asserting.
1054+
rawtx = w.createrawtransaction(inputs=[], outputs=[{self.nodes[0].getnewaddress(address_type="bech32"): 1 - 0.00000202}])
1055+
assert_raises_rpc_error(-4, "Insufficient funds", w.fundrawtransaction, rawtx, {"fee_rate": 1.85})
1056+
10291057

10301058
if __name__ == '__main__':
10311059
RawTransactionsTest().main()

0 commit comments

Comments
 (0)