@ -97,6 +97,8 @@ class WalletSendTest(BitcoinTestFramework):
except AssertionError :
# Provide debug info if the test fails
self . log . error ( " Unexpected successful result: " )
self . log . error ( arg_conf_target )
self . log . error ( arg_estimate_mode )
self . log . error ( options )
res = from_wallet . send ( outputs = outputs , conf_target = arg_conf_target , estimate_mode = arg_estimate_mode , options = options )
self . log . error ( res )
@ -224,8 +226,10 @@ class WalletSendTest(BitcoinTestFramework):
assert_equal ( self . nodes [ 1 ] . decodepsbt ( res1 [ " psbt " ] ) [ " fee " ] ,
self . nodes [ 1 ] . decodepsbt ( res2 [ " psbt " ] ) [ " fee " ] )
# but not at the same time
for mode in [ " unset " , " economical " , " conservative " , " btc/kb " , " sat/b " ] :
self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , arg_conf_target = 1 , arg_estimate_mode = " economical " ,
conf_target = 1 , estimate_mode = " economical " , add_to_wallet = False , expect_error = ( - 8 , " Use either conf_target and estimate_mode or the options dictionary to control fee rate " ) )
conf_target = 1 , estimate_mode = mode , add_to_wallet = False ,
expect_error = ( - 8 , " Use either conf_target and estimate_mode or the options dictionary to control fee rate " ) )
self . log . info ( " Create PSBT from watch-only wallet w3, sign with w2... " )
res = self . test_send ( from_wallet = w3 , to_wallet = w1 , amount = 1 )
@ -246,19 +250,61 @@ class WalletSendTest(BitcoinTestFramework):
res = w2 . walletprocesspsbt ( res [ " psbt " ] )
assert res [ " complete " ]
self . log . info ( " Set fee rate... " )
self . log . info ( " Test setting explicit fee rate " )
res1 = self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , arg_conf_target = 1 , arg_estimate_mode = " economical " , add_to_wallet = False )
res2 = self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , conf_target = 1 , estimate_mode = " economical " , add_to_wallet = False )
assert_equal ( self . nodes [ 1 ] . decodepsbt ( res1 [ " psbt " ] ) [ " fee " ] , self . nodes [ 1 ] . decodepsbt ( res2 [ " psbt " ] ) [ " fee " ] )
res = self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , conf_target = 0.00007 , estimate_mode = " btc/kb " , add_to_wallet = False )
fee = self . nodes [ 1 ] . decodepsbt ( res [ " psbt " ] ) [ " fee " ]
assert_fee_amount ( fee , Decimal ( len ( res [ " hex " ] ) / 2 ) , Decimal ( " 0.00007 " ) )
res = self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , conf_target = 2 , estimate_mode = " sat/b " , add_to_wallet = False )
fee = self . nodes [ 1 ] . decodepsbt ( res [ " psbt " ] ) [ " fee " ]
assert_fee_amount ( fee , Decimal ( len ( res [ " hex " ] ) / 2 ) , Decimal ( " 0.00002 " ) )
self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , conf_target = - 1 , estimate_mode = " sat/b " ,
expect_error = ( - 3 , " Amount out of range " ) )
# Fee rate of 0.1 satoshi per byte should throw an error
# TODO: error should use sat/b
self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , conf_target = 0.1 , estimate_mode = " sat/b " ,
expect_error = ( - 4 , " Fee rate (0.00000100 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB) " ) )
self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , conf_target = 0.000001 , estimate_mode = " BTC/KB " ,
expect_error = ( - 4 , " Fee rate (0.00000100 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB) " ) )
res = self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , arg_conf_target = 0.00004531 , arg_estimate_mode = " btc/kb " , add_to_wallet = False )
fee = self . nodes [ 1 ] . decodepsbt ( res [ " psbt " ] ) [ " fee " ]
assert_fee_amount ( fee , Decimal ( len ( res [ " hex " ] ) / 2 ) , Decimal ( " 0.00004531 " ) )
res = self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , arg_conf_target = 3 , arg_estimate_mode = " sat/b " , add_to_wallet = False )
fee = self . nodes [ 1 ] . decodepsbt ( res [ " psbt " ] ) [ " fee " ]
assert_fee_amount ( fee , Decimal ( len ( res [ " hex " ] ) / 2 ) , Decimal ( " 0.00003 " ) )
# TODO: This test should pass with all modes, e.g. with the next line uncommented, for consistency with the other explicit feerate RPCs.
# for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]:
for mode in [ " btc/kb " , " sat/b " ] :
self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , conf_target = - 1 , estimate_mode = mode ,
expect_error = ( - 3 , " Amount out of range " ) )
self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , conf_target = 0 , estimate_mode = mode ,
expect_error = ( - 4 , " Fee rate (0.00000000 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB) " ) )
for mode in [ " foo " , Decimal ( " 3.141592 " ) ] :
self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , conf_target = 0.1 , estimate_mode = mode ,
expect_error = ( - 8 , " Invalid estimate_mode parameter " ) )
# TODO: these 2 equivalent sends with an invalid estimate_mode arg should both fail, but they do not...why?
# self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_conf_target=0.1, arg_estimate_mode=mode,
# expect_error=(-8, "Invalid estimate_mode parameter"))
# assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", lambda: w0.send({w1.getnewaddress(): 1}, 0.1, mode))
# TODO: These tests should pass for consistency with the other explicit feerate RPCs, but they do not.
# for mode in ["unset", "economical", "conservative", "btc/kb", "sat/b"]:
# self.log.debug("{}".format(mode))
# for k, v in {"string": "", "object": {"foo": "bar"}}.items():
# self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=v, estimate_mode=mode,
# expect_error=(-3, "Expected type number for conf_target, got {}".format(k)))
# TODO: error should use sat/B instead of BTC/kB if sat/B is selected.
# Test setting explicit fee rate just below the minimum.
for unit , fee_rate in { " sat/B " : 0.99999999 , " BTC/kB " : 0.00000999 } . items ( ) :
self . log . info ( " Explicit fee rate raises RPC error ' fee rate too low ' if conf_target {} and estimate_mode {} are passed " . format ( fee_rate , unit ) )
self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , conf_target = fee_rate , estimate_mode = unit ,
expect_error = ( - 4 , " Fee rate (0.00000999 BTC/kB) is lower than the minimum fee rate setting (0.00001000 BTC/kB) " ) )
self . log . info ( " Explicit fee rate raises RPC error if estimate_mode is passed without a conf_target " )
for unit , fee_rate in { " sat/B " : 100 , " BTC/kB " : 0.001 } . items ( ) :
self . test_send ( from_wallet = w0 , to_wallet = w1 , amount = 1 , estimate_mode = unit ,
expect_error = ( - 8 , " Selected estimate_mode {} requires a fee rate to be specified in conf_target " . format ( unit ) ) )
# TODO: Return hex if fee rate is below -maxmempool
# res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b", add_to_wallet=False)