diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py --- a/test/functional/rpc_fundrawtransaction.py +++ b/test/functional/rpc_fundrawtransaction.py @@ -14,6 +14,7 @@ assert_greater_than_or_equal, assert_raises_rpc_error, connect_nodes_bi, + find_vout_for_address, ) @@ -73,6 +74,13 @@ self.nodes[3].importpubkey(watchonly_pubkey, "", True) watchonly_txid = self.nodes[0].sendtoaddress( watchonly_address, watchonly_amount) + + # Lock UTXO so nodes[0] doesn't accidentally spend it + watchonly_vout = find_vout_for_address( + self.nodes[0], watchonly_txid, watchonly_address) + self.nodes[0].lockunspent( + False, [{"txid": watchonly_txid, "vout": watchonly_vout}]) + self.nodes[0].sendtoaddress( self.nodes[3].getnewaddress(), watchonly_amount / 10) @@ -488,6 +496,10 @@ connect_nodes_bi(self.nodes[1], self.nodes[2]) connect_nodes_bi(self.nodes[0], self.nodes[2]) connect_nodes_bi(self.nodes[0], self.nodes[3]) + # Again lock the watchonly UTXO or nodes[0] may spend it, because + # lockunspent is memory-only and thus lost on restart + self.nodes[0].lockunspent( + False, [{"txid": watchonly_txid, "vout": watchonly_vout}]) self.sync_all() # drain the keypool diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -633,3 +633,16 @@ txid = node.sendrawtransaction(signresult["hex"], True) txids.append(txid) return txids + + +def find_vout_for_address(node, txid, addr): + """ + Locate the vout index of the given transaction sending to the + given address. Raises runtime error exception if not found. + """ + tx = node.getrawtransaction(txid, True) + for i in range(len(tx["vout"])): + if any([addr == a for a in tx["vout"][i]["scriptPubKey"]["addresses"]]): + return i + raise RuntimeError( + "Vout not found for address: txid={}, addr={}".format(txid, addr))