Skip to content

Commit 1834d4d

Browse files
committed
Merge #12265: [test] fundrawtransaction: lock watch-only shared address
891beb0 [test] fundrawtransaction: lock watch-only shared address (Karl-Johan Alm) Pull request description: `self.nodes[0]` creates an address which is watch-only-shared with `self.nodes[3]`. If `nodes[0]` spends the associated UTXO during any of its sends later, the watchonly test will fail, as `nodes[3]` now has insufficient funds. I ran into this in #12257 and this commit is in that PR as well, but I figured I'd split it out (and remove from there once/if merged). Tree-SHA512: d04a04b1ecebe82127cccd47c1b3de311bf07f4b51dff80db20ea2f142e1d5c4a85ed6180c5c0b081d550e238c742e119b953f60f487deac5a3f3536e1a8d9fe
2 parents 9458b05 + 891beb0 commit 1834d4d

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

test/functional/rpc_fundrawtransaction.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,18 @@
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55
"""Test the fundrawtransaction RPC."""
66

7+
from decimal import Decimal
78
from test_framework.test_framework import BitcoinTestFramework
8-
from test_framework.util import *
9+
from test_framework.util import (
10+
assert_equal,
11+
assert_fee_amount,
12+
assert_greater_than,
13+
assert_greater_than_or_equal,
14+
assert_raises_rpc_error,
15+
connect_nodes_bi,
16+
count_bytes,
17+
find_vout_for_address,
18+
)
919

1020

1121
def get_unspent(listunspent, amount):
@@ -57,6 +67,11 @@ def run_test(self):
5767
watchonly_amount = Decimal(200)
5868
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
5969
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
70+
71+
# Lock UTXO so nodes[0] doesn't accidentally spend it
72+
watchonly_vout = find_vout_for_address(self.nodes[0], watchonly_txid, watchonly_address)
73+
self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
74+
6075
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
6176

6277
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
@@ -475,6 +490,9 @@ def run_test(self):
475490
connect_nodes_bi(self.nodes,1,2)
476491
connect_nodes_bi(self.nodes,0,2)
477492
connect_nodes_bi(self.nodes,0,3)
493+
# Again lock the watchonly UTXO or nodes[0] may spend it, because
494+
# lockunspent is memory-only and thus lost on restart
495+
self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
478496
self.sync_all()
479497

480498
# drain the keypool

test/functional/test_framework/util.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,3 +556,14 @@ def mine_large_block(node, utxos=None):
556556
fee = 100 * node.getnetworkinfo()["relayfee"]
557557
create_lots_of_big_transactions(node, txouts, utxos, num, fee=fee)
558558
node.generate(1)
559+
560+
def find_vout_for_address(node, txid, addr):
561+
"""
562+
Locate the vout index of the given transaction sending to the
563+
given address. Raises runtime error exception if not found.
564+
"""
565+
tx = node.getrawtransaction(txid, True)
566+
for i in range(len(tx["vout"])):
567+
if any([addr == a for a in tx["vout"][i]["scriptPubKey"]["addresses"]]):
568+
return i
569+
raise RuntimeError("Vout not found for address: txid=%s, addr=%s" % (txid, addr))

0 commit comments

Comments
 (0)