|
8 | 8 | from itertools import product
|
9 | 9 |
|
10 | 10 | from test_framework.descriptors import descsum_create
|
| 11 | +from test_framework.key import ECKey |
11 | 12 | from test_framework.test_framework import BitcoinTestFramework
|
12 | 13 | from test_framework.util import (
|
13 | 14 | assert_approx,
|
|
19 | 20 | count_bytes,
|
20 | 21 | find_vout_for_address,
|
21 | 22 | )
|
| 23 | +from test_framework.wallet_util import bytes_to_wif |
22 | 24 |
|
23 | 25 |
|
24 | 26 | def get_unspent(listunspent, amount):
|
@@ -132,6 +134,7 @@ def run_test(self):
|
132 | 134 | self.test_subtract_fee_with_presets()
|
133 | 135 | self.test_transaction_too_large()
|
134 | 136 | self.test_include_unsafe()
|
| 137 | + self.test_external_inputs() |
135 | 138 | self.test_22670()
|
136 | 139 |
|
137 | 140 | def test_change_position(self):
|
@@ -983,6 +986,56 @@ def test_transaction_too_large(self):
|
983 | 986 | wallet.sendmany("", outputs)
|
984 | 987 | self.generate(self.nodes[0], 10)
|
985 | 988 | assert_raises_rpc_error(-4, "Transaction too large", recipient.fundrawtransaction, rawtx)
|
| 989 | + self.nodes[0].unloadwallet("large") |
| 990 | + |
| 991 | + def test_external_inputs(self): |
| 992 | + self.log.info("Test funding with external inputs") |
| 993 | + |
| 994 | + eckey = ECKey() |
| 995 | + eckey.generate() |
| 996 | + privkey = bytes_to_wif(eckey.get_bytes()) |
| 997 | + |
| 998 | + self.nodes[2].createwallet("extfund") |
| 999 | + wallet = self.nodes[2].get_wallet_rpc("extfund") |
| 1000 | + |
| 1001 | + # Make a weird but signable script. sh(pkh()) descriptor accomplishes this |
| 1002 | + desc = descsum_create("sh(pkh({}))".format(privkey)) |
| 1003 | + if self.options.descriptors: |
| 1004 | + res = self.nodes[0].importdescriptors([{"desc": desc, "timestamp": "now"}]) |
| 1005 | + else: |
| 1006 | + res = self.nodes[0].importmulti([{"desc": desc, "timestamp": "now"}]) |
| 1007 | + assert res[0]["success"] |
| 1008 | + addr = self.nodes[0].deriveaddresses(desc)[0] |
| 1009 | + addr_info = self.nodes[0].getaddressinfo(addr) |
| 1010 | + |
| 1011 | + self.nodes[0].sendtoaddress(addr, 10) |
| 1012 | + self.nodes[0].sendtoaddress(wallet.getnewaddress(), 10) |
| 1013 | + self.nodes[0].generate(6) |
| 1014 | + ext_utxo = self.nodes[0].listunspent(addresses=[addr])[0] |
| 1015 | + |
| 1016 | + # An external input without solving data should result in an error |
| 1017 | + raw_tx = wallet.createrawtransaction([ext_utxo], {self.nodes[0].getnewaddress(): 15}) |
| 1018 | + assert_raises_rpc_error(-4, "Insufficient funds", wallet.fundrawtransaction, raw_tx) |
| 1019 | + |
| 1020 | + # Error conditions |
| 1021 | + assert_raises_rpc_error(-5, "'not a pubkey' is not hex", wallet.fundrawtransaction, raw_tx, {"solving_data": {"pubkeys":["not a pubkey"]}}) |
| 1022 | + assert_raises_rpc_error(-5, "'01234567890a0b0c0d0e0f' is not a valid public key", wallet.fundrawtransaction, raw_tx, {"solving_data": {"pubkeys":["01234567890a0b0c0d0e0f"]}}) |
| 1023 | + assert_raises_rpc_error(-5, "'not a script' is not hex", wallet.fundrawtransaction, raw_tx, {"solving_data": {"scripts":["not a script"]}}) |
| 1024 | + assert_raises_rpc_error(-8, "Unable to parse descriptor 'not a descriptor'", wallet.fundrawtransaction, raw_tx, {"solving_data": {"descriptors":["not a descriptor"]}}) |
| 1025 | + |
| 1026 | + # But funding should work when the solving data is provided |
| 1027 | + funded_tx = wallet.fundrawtransaction(raw_tx, {"solving_data": {"pubkeys": [addr_info['pubkey']], "scripts": [addr_info["embedded"]["scriptPubKey"]]}}) |
| 1028 | + signed_tx = wallet.signrawtransactionwithwallet(funded_tx['hex']) |
| 1029 | + assert not signed_tx['complete'] |
| 1030 | + signed_tx = self.nodes[0].signrawtransactionwithwallet(signed_tx['hex']) |
| 1031 | + assert signed_tx['complete'] |
| 1032 | + |
| 1033 | + funded_tx = wallet.fundrawtransaction(raw_tx, {"solving_data": {"descriptors": [desc]}}) |
| 1034 | + signed_tx = wallet.signrawtransactionwithwallet(funded_tx['hex']) |
| 1035 | + assert not signed_tx['complete'] |
| 1036 | + signed_tx = self.nodes[0].signrawtransactionwithwallet(signed_tx['hex']) |
| 1037 | + assert signed_tx['complete'] |
| 1038 | + self.nodes[2].unloadwallet("extfund") |
986 | 1039 |
|
987 | 1040 | def test_include_unsafe(self):
|
988 | 1041 | self.log.info("Test fundrawtxn with unsafe inputs")
|
@@ -1017,6 +1070,7 @@ def test_include_unsafe(self):
|
1017 | 1070 | assert all((txin["txid"], txin["vout"]) in inputs for txin in tx_dec["vin"])
|
1018 | 1071 | signedtx = wallet.signrawtransactionwithwallet(fundedtx['hex'])
|
1019 | 1072 | assert wallet.testmempoolaccept([signedtx['hex']])[0]["allowed"]
|
| 1073 | + self.nodes[0].unloadwallet("unsafe") |
1020 | 1074 |
|
1021 | 1075 | def test_22670(self):
|
1022 | 1076 | # In issue #22670, it was observed that ApproximateBestSubset may
|
|
0 commit comments