Merge #17327: test: add rpc_fundrawtransaction logging

ff22751417c6fbbd22f4eefd0e23431a83335c13 test: rm ascii art in rpc_fundrawtransaction (Jon Atack)
94fcc08541cf58bee864ab7c28a6c77e42472f17 test: add rpc_fundrawtransaction logging (Jon Atack)

Pull request description:

  `test/functional/rpc_fundrawtransaction.py` is fairly slow to run and has no logging, so it can appear to be stalled.

  This commit adds info logging at each test to provide feedback on the test run.

ACKs for top commit:
  instagibbs:
    utACK ff22751417
  jnewbery:
    tACK ff22751417c6fbbd22f4eefd0e23431a83335c13

Tree-SHA512: f4fabad8ef51c29981351bb4e66fb0c0e0517418a4a15892ef804df11d16b2d2ae1a1abc958d2b121819850278de90a2003b0edb8d7098d00360b89fa76e9062
This commit is contained in:
MarcoFalke 2019-11-01 11:06:12 -04:00 committed by munkybooty
parent 37ef9bb465
commit f27bb545e7

View File

@ -42,6 +42,7 @@ class RawTransactionsTest(BitcoinTestFramework):
connect_nodes(self.nodes[0], 3) connect_nodes(self.nodes[0], 3)
def run_test(self): def run_test(self):
self.log.info("Connect nodes, set fees, generate blocks, and sync")
self.min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee'] self.min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
# This test is not meant to test fee estimation and we'd like # This test is not meant to test fee estimation and we'd like
# to be sure all txs are sent at a consistent desired feerate # to be sure all txs are sent at a consistent desired feerate
@ -90,7 +91,8 @@ class RawTransactionsTest(BitcoinTestFramework):
self.test_option_subtract_fee_from_outputs() self.test_option_subtract_fee_from_outputs()
def test_change_position(self): def test_change_position(self):
# ensure that setting changePosition in fundraw with an exact match is handled properly """Ensure setting changePosition in fundraw with an exact match is handled properly."""
self.log.info("Test fundrawtxn changePosition option")
rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress():500}) rawmatch = self.nodes[2].createrawtransaction([], {self.nodes[2].getnewaddress():500})
rawmatch = self.nodes[2].fundrawtransaction(rawmatch, {"changePosition":1, "subtractFeeFromOutputs":[0]}) rawmatch = self.nodes[2].fundrawtransaction(rawmatch, {"changePosition":1, "subtractFeeFromOutputs":[0]})
assert_equal(rawmatch["changepos"], -1) assert_equal(rawmatch["changepos"], -1)
@ -115,9 +117,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.sync_all() self.sync_all()
def test_simple(self): def test_simple(self):
############### self.log.info("Test fundrawtxn")
# simple test #
###############
inputs = [ ] inputs = [ ]
outputs = { self.nodes[0].getnewaddress() : 10 } outputs = { self.nodes[0].getnewaddress() : 10 }
rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
@ -127,9 +127,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert len(dec_tx['vin']) > 0 #test that we have enough inputs assert len(dec_tx['vin']) > 0 #test that we have enough inputs
def test_simple_two_coins(self): def test_simple_two_coins(self):
############################## self.log.info("Test fundrawtxn with 2 coins")
# simple test with two coins #
##############################
inputs = [ ] inputs = [ ]
outputs = { self.nodes[0].getnewaddress() : 22 } outputs = { self.nodes[0].getnewaddress() : 22 }
rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
@ -141,9 +139,8 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
def test_simple_two_outputs(self): def test_simple_two_outputs(self):
################################ self.log.info("Test fundrawtxn with 2 outputs")
# simple test with two outputs #
################################
inputs = [ ] inputs = [ ]
outputs = { self.nodes[0].getnewaddress() : 26, self.nodes[1].getnewaddress() : 25 } outputs = { self.nodes[0].getnewaddress() : 26, self.nodes[1].getnewaddress() : 25 }
rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
@ -159,9 +156,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '') assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
def test_change(self): def test_change(self):
######################################################################### self.log.info("Test fundrawtxn with a vin > required amount")
# test a fundrawtransaction with a VIN greater than the required amount #
#########################################################################
utx = get_unspent(self.nodes[2].listunspent(), 50) utx = get_unspent(self.nodes[2].listunspent(), 50)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
@ -181,9 +176,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee
def test_no_change(self): def test_no_change(self):
##################################################################### self.log.info("Test fundrawtxn not having a change output")
# test a fundrawtransaction with which will not get a change output #
#####################################################################
utx = get_unspent(self.nodes[2].listunspent(), 50) utx = get_unspent(self.nodes[2].listunspent(), 50)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
@ -203,9 +196,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee
def test_invalid_option(self): def test_invalid_option(self):
#################################################### self.log.info("Test fundrawtxn with an invalid option")
# test a fundrawtransaction with an invalid option #
####################################################
utx = get_unspent(self.nodes[2].listunspent(), 50) utx = get_unspent(self.nodes[2].listunspent(), 50)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
@ -220,9 +211,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_raises_rpc_error(-3, "Unexpected key reserveChangeKey", lambda: self.nodes[2].fundrawtransaction(hexstring=rawtx, options={'reserveChangeKey': True})) assert_raises_rpc_error(-3, "Unexpected key reserveChangeKey", lambda: self.nodes[2].fundrawtransaction(hexstring=rawtx, options={'reserveChangeKey': True}))
def test_invalid_change_address(self): def test_invalid_change_address(self):
############################################################ self.log.info("Test fundrawtxn with an invalid change address")
# test a fundrawtransaction with an invalid change address #
############################################################
utx = get_unspent(self.nodes[2].listunspent(), 50) utx = get_unspent(self.nodes[2].listunspent(), 50)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
@ -234,9 +223,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_raises_rpc_error(-5, "changeAddress must be a valid dash address", self.nodes[2].fundrawtransaction, rawtx, {'changeAddress':'foobar'}) assert_raises_rpc_error(-5, "changeAddress must be a valid dash address", self.nodes[2].fundrawtransaction, rawtx, {'changeAddress':'foobar'})
def test_valid_change_address(self): def test_valid_change_address(self):
############################################################ self.log.info("Test fundrawtxn with a provided change address")
# test a fundrawtransaction with a provided change address #
############################################################
utx = get_unspent(self.nodes[2].listunspent(), 50) utx = get_unspent(self.nodes[2].listunspent(), 50)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ] inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
@ -253,9 +240,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(change, out['scriptPubKey']['addresses'][0]) assert_equal(change, out['scriptPubKey']['addresses'][0])
def test_coin_selection(self): def test_coin_selection(self):
######################################################################### self.log.info("Test fundrawtxn with a vin < required amount")
# test a fundrawtransaction with a VIN smaller than the required amount #
#########################################################################
utx = get_unspent(self.nodes[2].listunspent(), 10) utx = get_unspent(self.nodes[2].listunspent(), 10)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}] inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
@ -287,9 +272,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(len(dec_tx['vout']), 2) assert_equal(len(dec_tx['vout']), 2)
def test_two_vin(self): def test_two_vin(self):
########################################### self.log.info("Test fundrawtxn with 2 vins")
# test a fundrawtransaction with two VINs #
###########################################
utx = get_unspent(self.nodes[2].listunspent(), 10) utx = get_unspent(self.nodes[2].listunspent(), 10)
utx2 = get_unspent(self.nodes[2].listunspent(), 50) utx2 = get_unspent(self.nodes[2].listunspent(), 50)
@ -320,9 +303,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(matchingIns, 2) #we now must see two vins identical to vins given as params assert_equal(matchingIns, 2) #we now must see two vins identical to vins given as params
def test_two_vin_two_vout(self): def test_two_vin_two_vout(self):
######################################################### self.log.info("Test fundrawtxn with 2 vins and 2 vouts")
# test a fundrawtransaction with two VINs and two vOUTs #
#########################################################
utx = get_unspent(self.nodes[2].listunspent(), 10) utx = get_unspent(self.nodes[2].listunspent(), 10)
utx2 = get_unspent(self.nodes[2].listunspent(), 50) utx2 = get_unspent(self.nodes[2].listunspent(), 50)
@ -345,52 +326,54 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(len(dec_tx['vout']), 3) assert_equal(len(dec_tx['vout']), 3)
def test_invalid_input(self): def test_invalid_input(self):
############################################## self.log.info("Test fundrawtxn with an invalid vin")
# test a fundrawtransaction with invalid vin #
##############################################
inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin! inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin!
outputs = { self.nodes[0].getnewaddress() : 10} outputs = { self.nodes[0].getnewaddress() : 10}
rawtx = self.nodes[2].createrawtransaction(inputs, outputs) rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].fundrawtransaction, rawtx) assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[2].fundrawtransaction, rawtx)
def test_fee_p2pkh(self): def test_fee_p2pkh(self):
############################################################ """Compare fee of a standard pubkeyhash transaction."""
#compare fee of a standard pubkeyhash transaction self.log.info("Test fundrawtxn p2pkh fee")
inputs = [] inputs = []
outputs = {self.nodes[1].getnewaddress():11} outputs = {self.nodes[1].getnewaddress():11}
rawtx = self.nodes[0].createrawtransaction(inputs, outputs) rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[0].fundrawtransaction(rawtx) fundedTx = self.nodes[0].fundrawtransaction(rawtx)
#create same transaction over sendtoaddress # Create same transaction over sendtoaddress.
txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 11) txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 11)
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
#compare fee # Compare fee.
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
assert feeDelta >= 0 and feeDelta <= self.fee_tolerance assert feeDelta >= 0 and feeDelta <= self.fee_tolerance
############################################################
def test_fee_p2pkh_multi_out(self): def test_fee_p2pkh_multi_out(self):
############################################################ """Compare fee of a standard pubkeyhash transaction with multiple outputs."""
#compare fee of a standard pubkeyhash transaction with multiple outputs self.log.info("Test fundrawtxn p2pkh fee with multiple outputs")
inputs = [] inputs = []
outputs = {self.nodes[1].getnewaddress():11,self.nodes[1].getnewaddress():12,self.nodes[1].getnewaddress():1,self.nodes[1].getnewaddress():13,self.nodes[1].getnewaddress():2,self.nodes[1].getnewaddress():3} outputs = {
self.nodes[1].getnewaddress():11,
self.nodes[1].getnewaddress():12,
self.nodes[1].getnewaddress():1,
self.nodes[1].getnewaddress():13,
self.nodes[1].getnewaddress():2,
self.nodes[1].getnewaddress():3,
}
rawtx = self.nodes[0].createrawtransaction(inputs, outputs) rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[0].fundrawtransaction(rawtx) fundedTx = self.nodes[0].fundrawtransaction(rawtx)
#create same transaction over sendtoaddress
# Create same transaction over sendtoaddress.
txId = self.nodes[0].sendmany("", outputs) txId = self.nodes[0].sendmany("", outputs)
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
#compare fee # Compare fee.
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
assert feeDelta >= 0 and feeDelta <= self.fee_tolerance assert feeDelta >= 0 and feeDelta <= self.fee_tolerance
############################################################
def test_fee_p2sh(self): def test_fee_p2sh(self):
############################################################ """Compare fee of a 2-of-2 multisig p2sh transaction."""
#compare fee of a 2of2 multisig p2sh transaction # Create 2-of-2 addr.
# create 2of2 addr
addr1 = self.nodes[1].getnewaddress() addr1 = self.nodes[1].getnewaddress()
addr2 = self.nodes[1].getnewaddress() addr2 = self.nodes[1].getnewaddress()
@ -404,20 +387,19 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[0].createrawtransaction(inputs, outputs) rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[0].fundrawtransaction(rawtx) fundedTx = self.nodes[0].fundrawtransaction(rawtx)
#create same transaction over sendtoaddress # Create same transaction over sendtoaddress.
txId = self.nodes[0].sendtoaddress(mSigObj, 11) txId = self.nodes[0].sendtoaddress(mSigObj, 11)
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
#compare fee # Compare fee.
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
assert feeDelta >= 0 and feeDelta <= self.fee_tolerance assert feeDelta >= 0 and feeDelta <= self.fee_tolerance
############################################################
def test_fee_4of5(self): def test_fee_4of5(self):
############################################################ """Compare fee of a standard pubkeyhash transaction."""
#compare fee of a standard pubkeyhash transaction self.log.info("Test fundrawtxn fee with 4-of-5 addresses")
# create 4of5 addr # Create 4-of-5 addr.
addr1 = self.nodes[1].getnewaddress() addr1 = self.nodes[1].getnewaddress()
addr2 = self.nodes[1].getnewaddress() addr2 = self.nodes[1].getnewaddress()
addr3 = self.nodes[1].getnewaddress() addr3 = self.nodes[1].getnewaddress()
@ -430,35 +412,48 @@ class RawTransactionsTest(BitcoinTestFramework):
addr4Obj = self.nodes[1].getaddressinfo(addr4) addr4Obj = self.nodes[1].getaddressinfo(addr4)
addr5Obj = self.nodes[1].getaddressinfo(addr5) addr5Obj = self.nodes[1].getaddressinfo(addr5)
mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])['address'] mSigObj = self.nodes[1].addmultisigaddress(
4,
[
addr1Obj['pubkey'],
addr2Obj['pubkey'],
addr3Obj['pubkey'],
addr4Obj['pubkey'],
addr5Obj['pubkey'],
]
)['address']
inputs = [] inputs = []
outputs = {mSigObj:11} outputs = {mSigObj:11}
rawtx = self.nodes[0].createrawtransaction(inputs, outputs) rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[0].fundrawtransaction(rawtx) fundedTx = self.nodes[0].fundrawtransaction(rawtx)
#create same transaction over sendtoaddress # Create same transaction over sendtoaddress.
txId = self.nodes[0].sendtoaddress(mSigObj, 11) txId = self.nodes[0].sendtoaddress(mSigObj, 11)
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
#compare fee # Compare fee.
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
assert feeDelta >= 0 and feeDelta <= self.fee_tolerance assert feeDelta >= 0 and feeDelta <= self.fee_tolerance
############################################################
def test_spend_2of2(self): def test_spend_2of2(self):
############################################################ """Spend a 2-of-2 multisig transaction over fundraw."""
# spend a 2of2 multisig transaction over fundraw self.log.info("Test fundrawtxn spending 2-of-2 multisig")
# create 2of2 addr # Create 2-of-2 addr.
addr1 = self.nodes[2].getnewaddress() addr1 = self.nodes[2].getnewaddress()
addr2 = self.nodes[2].getnewaddress() addr2 = self.nodes[2].getnewaddress()
addr1Obj = self.nodes[2].getaddressinfo(addr1) addr1Obj = self.nodes[2].getaddressinfo(addr1)
addr2Obj = self.nodes[2].getaddressinfo(addr2) addr2Obj = self.nodes[2].getaddressinfo(addr2)
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address'] mSigObj = self.nodes[2].addmultisigaddress(
2,
[
addr1Obj['pubkey'],
addr2Obj['pubkey'],
]
)['address']
# send 12 DASH to msig addr # send 12 DASH to msig addr
self.nodes[0].sendtoaddress(mSigObj, 12) self.nodes[0].sendtoaddress(mSigObj, 12)
@ -478,18 +473,18 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[1].generate(1) self.nodes[1].generate(1)
self.sync_all() self.sync_all()
# make sure funds are received at node1 # Make sure funds are received at node1.
assert_equal(oldBalance+Decimal('11.0000000'), self.nodes[1].getbalance()) assert_equal(oldBalance+Decimal('11.0000000'), self.nodes[1].getbalance())
def test_locked_wallet(self): def test_locked_wallet(self):
############################################################ self.log.info("Test fundrawtxn with locked wallet")
# locked wallet test
self.nodes[1].encryptwallet("test") self.nodes[1].encryptwallet("test")
self.stop_nodes() self.stop_nodes()
self.start_nodes() self.start_nodes()
# This test is not meant to test fee estimation and we'd like # This test is not meant to test fee estimation and we'd like
# to be sure all txs are sent at a consistent desired feerate # to be sure all txns are sent at a consistent desired feerate.
for node in self.nodes: for node in self.nodes:
node.settxfee(self.min_relay_tx_fee) node.settxfee(self.min_relay_tx_fee)
@ -498,11 +493,11 @@ class RawTransactionsTest(BitcoinTestFramework):
connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[0], 2)
connect_nodes(self.nodes[0], 3) connect_nodes(self.nodes[0], 3)
# Again lock the watchonly UTXO or nodes[0] may spend it, because # Again lock the watchonly UTXO or nodes[0] may spend it, because
# lockunspent is memory-only and thus lost on restart # lockunspent is memory-only and thus lost on restart.
self.nodes[0].lockunspent(False, [{"txid": self.watchonly_txid, "vout": self.watchonly_vout}]) self.nodes[0].lockunspent(False, [{"txid": self.watchonly_txid, "vout": self.watchonly_vout}])
self.sync_all() self.sync_all()
# drain the keypool # Drain the keypool.
self.nodes[1].getnewaddress() self.nodes[1].getnewaddress()
inputs = [] inputs = []
outputs = {self.nodes[0].getnewaddress():1.1} outputs = {self.nodes[0].getnewaddress():1.1}
@ -511,7 +506,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# creating the key must be impossible because the wallet is locked # creating the key must be impossible because the wallet is locked
assert_raises_rpc_error(-4, "Keypool ran out, please call keypoolrefill first", self.nodes[1].fundrawtransaction, rawtx) assert_raises_rpc_error(-4, "Keypool ran out, please call keypoolrefill first", self.nodes[1].fundrawtransaction, rawtx)
#refill the keypool # Refill the keypool.
self.nodes[1].walletpassphrase("test", 100) self.nodes[1].walletpassphrase("test", 100)
self.nodes[1].walletlock() self.nodes[1].walletlock()
@ -524,22 +519,21 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[1].createrawtransaction(inputs, outputs) rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[1].fundrawtransaction(rawtx) fundedTx = self.nodes[1].fundrawtransaction(rawtx)
#now we need to unlock # Now we need to unlock.
self.nodes[1].walletpassphrase("test", 600) self.nodes[1].walletpassphrase("test", 600)
signedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex']) signedTx = self.nodes[1].signrawtransactionwithwallet(fundedTx['hex'])
self.nodes[1].sendrawtransaction(signedTx['hex']) self.nodes[1].sendrawtransaction(signedTx['hex'])
self.nodes[1].generate(1) self.nodes[1].generate(1)
self.sync_all() self.sync_all()
# make sure funds are received at node1 # Make sure funds are received at node1.
assert_equal(oldBalance+Decimal('511.0000000'), self.nodes[0].getbalance()) assert_equal(oldBalance+Decimal('511.0000000'), self.nodes[0].getbalance())
def test_many_inputs_fee(self): def test_many_inputs_fee(self):
############################################### """Multiple (~19) inputs tx test | Compare fee."""
# multiple (~19) inputs tx test | Compare fee # self.log.info("Test fundrawtxn fee with many inputs")
###############################################
#empty node1, send some small coins from node0 to node1 # Empty node1, send some small coins from node0 to node1.
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True) self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
self.sync_all() self.sync_all()
self.nodes[0].generate(1) self.nodes[0].generate(1)
@ -550,26 +544,25 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[0].generate(1) self.nodes[0].generate(1)
self.sync_all() self.sync_all()
#fund a tx with ~20 small inputs # Fund a tx with ~20 small inputs.
inputs = [] inputs = []
outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
rawtx = self.nodes[1].createrawtransaction(inputs, outputs) rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[1].fundrawtransaction(rawtx) fundedTx = self.nodes[1].fundrawtransaction(rawtx)
#create same transaction over sendtoaddress # Create same transaction over sendtoaddress.
txId = self.nodes[1].sendmany("", outputs) txId = self.nodes[1].sendmany("", outputs)
signedFee = self.nodes[1].getrawmempool(True)[txId]['fee'] signedFee = self.nodes[1].getrawmempool(True)[txId]['fee']
#compare fee # Compare fee.
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee) feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
assert feeDelta >= 0 and feeDelta <= self.fee_tolerance * 19 #~19 inputs assert feeDelta >= 0 and feeDelta <= self.fee_tolerance * 19 #~19 inputs
def test_many_inputs_send(self): def test_many_inputs_send(self):
############################################# """Multiple (~19) inputs tx test | sign/send."""
# multiple (~19) inputs tx test | sign/send # self.log.info("Test fundrawtxn sign+send with many inputs")
#############################################
#again, empty node1, send some small coins from node0 to node1 # Again, empty node1, send some small coins from node0 to node1.
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True) self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
self.sync_all() self.sync_all()
self.nodes[0].generate(1) self.nodes[0].generate(1)
@ -580,7 +573,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[0].generate(1) self.nodes[0].generate(1)
self.sync_all() self.sync_all()
#fund a tx with ~20 small inputs # Fund a tx with ~20 small inputs.
oldBalance = self.nodes[0].getbalance() oldBalance = self.nodes[0].getbalance()
inputs = [] inputs = []
@ -595,9 +588,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(oldBalance+Decimal('500.19000000'), self.nodes[0].getbalance()) #0.19+block reward assert_equal(oldBalance+Decimal('500.19000000'), self.nodes[0].getbalance()) #0.19+block reward
def test_op_return(self): def test_op_return(self):
##################################################### self.log.info("Test fundrawtxn with OP_RETURN and no vin")
# test fundrawtransaction with OP_RETURN and no vin #
#####################################################
rawtx = "0100000000010000000000000000066a047465737400000000" rawtx = "0100000000010000000000000000066a047465737400000000"
dec_tx = self.nodes[2].decoderawtransaction(rawtx) dec_tx = self.nodes[2].decoderawtransaction(rawtx)
@ -612,9 +603,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(len(dec_tx['vout']), 2) # one change output added assert_equal(len(dec_tx['vout']), 2) # one change output added
def test_watchonly(self): def test_watchonly(self):
################################################## self.log.info("Test fundrawtxn using only watchonly")
# test a fundrawtransaction using only watchonly #
##################################################
inputs = [] inputs = []
outputs = {self.nodes[2].getnewaddress(): self.watchonly_amount / 2} outputs = {self.nodes[2].getnewaddress(): self.watchonly_amount / 2}
@ -629,15 +618,13 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_greater_than(result["changepos"], -1) assert_greater_than(result["changepos"], -1)
def test_all_watched_funds(self): def test_all_watched_funds(self):
############################################################### self.log.info("Test fundrawtxn using entirety of watched funds")
# test fundrawtransaction using the entirety of watched funds #
###############################################################
inputs = [] inputs = []
outputs = {self.nodes[2].getnewaddress(): self.watchonly_amount} outputs = {self.nodes[2].getnewaddress(): self.watchonly_amount}
rawtx = self.nodes[3].createrawtransaction(inputs, outputs) rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
# Backward compatibility test (2nd param is includeWatching) # Backward compatibility test (2nd param is includeWatching).
result = self.nodes[3].fundrawtransaction(rawtx, True) result = self.nodes[3].fundrawtransaction(rawtx, True)
res_dec = self.nodes[0].decoderawtransaction(result["hex"]) res_dec = self.nodes[0].decoderawtransaction(result["hex"])
assert_equal(len(res_dec["vin"]), 2) assert_equal(len(res_dec["vin"]), 2)
@ -656,11 +643,9 @@ class RawTransactionsTest(BitcoinTestFramework):
self.sync_all() self.sync_all()
def test_option_feerate(self): def test_option_feerate(self):
####################### self.log.info("Test fundrawtxn feeRate option")
# Test feeRate option #
#######################
# Make sure there is exactly one input so coin selection can't skew the result # Make sure there is exactly one input so coin selection can't skew the result.
assert_equal(len(self.nodes[3].listunspent(1)), 1) assert_equal(len(self.nodes[3].listunspent(1)), 1)
inputs = [] inputs = []
@ -675,9 +660,8 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate) assert_fee_amount(result3['fee'], count_bytes(result3['hex']), 10 * result_fee_rate)
def test_address_reuse(self): def test_address_reuse(self):
################################ """Test no address reuse occurs."""
# Test no address reuse occurs # self.log.info("Test fundrawtxn does not reuse addresses")
################################
rawtx = self.nodes[3].createrawtransaction(inputs=[], outputs={self.nodes[3].getnewaddress(): 1}) rawtx = self.nodes[3].createrawtransaction(inputs=[], outputs={self.nodes[3].getnewaddress(): 1})
result3 = self.nodes[3].fundrawtransaction(rawtx) result3 = self.nodes[3].fundrawtransaction(rawtx)
@ -688,15 +672,13 @@ class RawTransactionsTest(BitcoinTestFramework):
changeaddress += out['scriptPubKey']['addresses'][0] changeaddress += out['scriptPubKey']['addresses'][0]
assert changeaddress != "" assert changeaddress != ""
nextaddr = self.nodes[3].getnewaddress() nextaddr = self.nodes[3].getnewaddress()
# Now the change address key should be removed from the keypool # Now the change address key should be removed from the keypool.
assert changeaddress != nextaddr assert changeaddress != nextaddr
def test_option_subtract_fee_from_outputs(self): def test_option_subtract_fee_from_outputs(self):
###################################### self.log.info("Test fundrawtxn subtractFeeFromOutputs option")
# Test subtractFeeFromOutputs option #
######################################
# Make sure there is exactly one input so coin selection can't skew the result # Make sure there is exactly one input so coin selection can't skew the result.
assert_equal(len(self.nodes[3].listunspent(1)), 1) assert_equal(len(self.nodes[3].listunspent(1)), 1)
inputs = [] inputs = []
@ -728,38 +710,39 @@ class RawTransactionsTest(BitcoinTestFramework):
# Add changePosition=4 to circumvent BIP69 input/output sorting # Add changePosition=4 to circumvent BIP69 input/output sorting
result = [self.nodes[3].fundrawtransaction(rawtx, {"changePosition": 4}), result = [self.nodes[3].fundrawtransaction(rawtx, {"changePosition": 4}),
# split the fee between outputs 0, 2, and 3, but not output 1 # Split the fee between outputs 0, 2, and 3, but not output 1.
self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0, 2, 3], "changePosition": 4})] self.nodes[3].fundrawtransaction(rawtx, {"subtractFeeFromOutputs": [0, 2, 3], "changePosition": 4})]
dec_tx = [self.nodes[3].decoderawtransaction(result[0]['hex']), dec_tx = [self.nodes[3].decoderawtransaction(result[0]['hex']),
self.nodes[3].decoderawtransaction(result[1]['hex'])] self.nodes[3].decoderawtransaction(result[1]['hex'])]
# Nested list of non-change output amounts for each transaction # Nested list of non-change output amounts for each transaction.
output = [[out['value'] for i, out in enumerate(d['vout']) if i != r['changepos']] output = [[out['value'] for i, out in enumerate(d['vout']) if i != r['changepos']]
for d, r in zip(dec_tx, result)] for d, r in zip(dec_tx, result)]
# List of differences in output amounts between normal and subtractFee transactions # List of differences in output amounts between normal and subtractFee transactions.
share = [o0 - o1 for o0, o1 in zip(output[0], output[1])] share = [o0 - o1 for o0, o1 in zip(output[0], output[1])]
# output 1 is the same in both transactions # Output 1 is the same in both transactions.
assert_equal(share[1], 0) assert_equal(share[1], 0)
# the other 3 outputs are smaller as a result of subtractFeeFromOutputs # The other 3 outputs are smaller as a result of subtractFeeFromOutputs.
assert_greater_than(share[0], 0) assert_greater_than(share[0], 0)
assert_greater_than(share[2], 0) assert_greater_than(share[2], 0)
assert_greater_than(share[3], 0) assert_greater_than(share[3], 0)
# outputs 2 and 3 take the same share of the fee # Outputs 2 and 3 take the same share of the fee.
assert_equal(share[2], share[3]) assert_equal(share[2], share[3])
# output 0 takes at least as much share of the fee, and no more than 2 satoshis more, than outputs 2 and 3 # Output 0 takes at least as much share of the fee, and no more than 2
# satoshis more, than outputs 2 and 3.
assert_greater_than_or_equal(share[0], share[2]) assert_greater_than_or_equal(share[0], share[2])
assert_greater_than_or_equal(share[2] + Decimal(2e-8), share[0]) assert_greater_than_or_equal(share[2] + Decimal(2e-8), share[0])
# the fee is the same in both transactions # The fee is the same in both transactions.
assert_equal(result[0]['fee'], result[1]['fee']) assert_equal(result[0]['fee'], result[1]['fee'])
# the total subtracted from the outputs is equal to the fee # The total subtracted from the outputs is equal to the fee.
assert_equal(share[0] + share[2] + share[3], result[0]['fee']) assert_equal(share[0] + share[2] + share[3], result[0]['fee'])
if __name__ == '__main__': if __name__ == '__main__':