@ -136,6 +136,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self . test_include_unsafe ( )
self . test_external_inputs ( )
self . test_22670 ( )
self . test_feerate_rounding ( )
def test_change_position ( self ) :
""" Ensure setting changePosition in fundraw with an exact match is handled properly. """
@ -1129,6 +1130,33 @@ class RawTransactionsTest(BitcoinTestFramework):
do_fund_send ( upper_bound )
self . restart_node ( 0 )
self . connect_nodes ( 0 , 1 )
self . connect_nodes ( 0 , 2 )
self . connect_nodes ( 0 , 3 )
def test_feerate_rounding ( self ) :
self . log . info ( " Test that rounding of GetFee does not result in an assertion " )
self . nodes [ 1 ] . createwallet ( " roundtest " )
w = self . nodes [ 1 ] . get_wallet_rpc ( " roundtest " )
addr = w . getnewaddress ( address_type = " bech32 " )
self . nodes [ 0 ] . sendtoaddress ( addr , 1 )
self . generate ( self . nodes [ 0 ] , 1 )
self . sync_all ( )
# 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.
# At a feerate of 1.85 sat/vb, the input will need a fee of 125.8 sats and the rest 77.7 sats
# The entire tx fee should be 203.5 sats.
# Coin selection rounds the fee individually instead of at the end (due to how CFeeRate::GetFee works).
# If rounding down (which is the incorrect behavior), then the calculated fee will be 125 + 77 = 202.
# If rounding up, then the calculated fee will be 126 + 78 = 204.
# In the former case, the calculated needed fee is higher than the actual fee being paid, so an assertion is reached
# To test this does not happen, we subtract 202 sats from the input value. If working correctly, this should
# fail with insufficient funds rather than bitcoind asserting.
rawtx = w . createrawtransaction ( inputs = [ ] , outputs = [ { self . nodes [ 0 ] . getnewaddress ( address_type = " bech32 " ) : 1 - 0.00000202 } ] )
assert_raises_rpc_error ( - 4 , " Insufficient funds " , w . fundrawtransaction , rawtx , { " fee_rate " : 1.85 } )
if __name__ == ' __main__ ' :
RawTransactionsTest ( ) . main ( )