aboutsummaryrefslogtreecommitdiff
path: root/test/functional/rpc_psbt.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/rpc_psbt.py')
-rwxr-xr-xtest/functional/rpc_psbt.py65
1 files changed, 58 insertions, 7 deletions
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index cf4d8a134c..b132ac3d31 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -8,6 +8,8 @@
from decimal import Decimal
from itertools import product
+from test_framework.descriptors import descsum_create
+from test_framework.key import ECKey
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_approx,
@@ -16,6 +18,7 @@ from test_framework.util import (
assert_raises_rpc_error,
find_output,
)
+from test_framework.wallet_util import bytes_to_wif
import json
import os
@@ -57,7 +60,7 @@ class PSBTTest(BitcoinTestFramework):
online_addr = w2.getnewaddress(address_type="p2sh-segwit")
wonline.importaddress(offline_addr, "", False)
mining_node.sendtoaddress(address=offline_addr, amount=1.0)
- mining_node.generate(nblocks=1)
+ self.generate(mining_node, nblocks=1)
self.sync_blocks([mining_node, online_node])
# Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO)
@@ -72,7 +75,7 @@ class PSBTTest(BitcoinTestFramework):
# Make sure we can mine the resulting transaction
txid = mining_node.sendrawtransaction(mining_node.finalizepsbt(signed_psbt)["hex"])
- mining_node.generate(1)
+ self.generate(mining_node, 1)
self.sync_blocks([mining_node, online_node])
assert_equal(online_node.gettxout(txid,0)["confirmations"], 1)
@@ -108,6 +111,16 @@ class PSBTTest(BitcoinTestFramework):
psbtx = self.nodes[1].walletprocesspsbt(psbtx1)['psbt']
assert_equal(psbtx1, psbtx)
+ # Node 0 should not be able to sign the transaction with the wallet is locked
+ self.nodes[0].encryptwallet("password")
+ assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].walletprocesspsbt, psbtx)
+
+ # Node 0 should be able to process without signing though
+ unsigned_tx = self.nodes[0].walletprocesspsbt(psbtx, False)
+ assert_equal(unsigned_tx['complete'], False)
+
+ self.nodes[0].walletpassphrase(passphrase="password", timeout=1000000)
+
# Sign the transaction and send
signed_tx = self.nodes[0].walletprocesspsbt(psbtx)['psbt']
final_tx = self.nodes[0].finalizepsbt(signed_tx)['hex']
@@ -148,7 +161,7 @@ class PSBTTest(BitcoinTestFramework):
rawtx = self.nodes[0].fundrawtransaction(rawtx, {"changePosition":3})
signed_tx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])['hex']
txid = self.nodes[0].sendrawtransaction(signed_tx)
- self.nodes[0].generate(6)
+ self.generate(self.nodes[0], 6)
self.sync_all()
# Find the output pos
@@ -307,7 +320,7 @@ class PSBTTest(BitcoinTestFramework):
node2_addr = self.nodes[2].getnewaddress()
txid1 = self.nodes[0].sendtoaddress(node1_addr, 13)
txid2 = self.nodes[0].sendtoaddress(node2_addr, 13)
- blockhash = self.nodes[0].generate(6)[0]
+ blockhash = self.generate(self.nodes[0], 6)[0]
self.sync_all()
vout1 = find_output(self.nodes[1], txid1, 13, blockhash=blockhash)
vout2 = find_output(self.nodes[2], txid2, 13, blockhash=blockhash)
@@ -335,7 +348,7 @@ class PSBTTest(BitcoinTestFramework):
combined = self.nodes[0].combinepsbt([psbt1, psbt2])
finalized = self.nodes[0].finalizepsbt(combined)['hex']
self.nodes[0].sendrawtransaction(finalized)
- self.nodes[0].generate(6)
+ self.generate(self.nodes[0], 6)
self.sync_all()
# Test additional args in walletcreatepsbt
@@ -530,7 +543,7 @@ class PSBTTest(BitcoinTestFramework):
addr4 = self.nodes[1].getnewaddress("", "p2sh-segwit")
txid4 = self.nodes[0].sendtoaddress(addr4, 5)
vout4 = find_output(self.nodes[0], txid4, 5)
- self.nodes[0].generate(6)
+ self.generate(self.nodes[0], 6)
self.sync_all()
psbt2 = self.nodes[1].createpsbt([{"txid":txid4, "vout":vout4}], {self.nodes[0].getnewaddress():Decimal('4.999')})
psbt2 = self.nodes[1].walletprocesspsbt(psbt2)['psbt']
@@ -554,7 +567,7 @@ class PSBTTest(BitcoinTestFramework):
addr = self.nodes[1].getnewaddress("", "p2sh-segwit")
txid = self.nodes[0].sendtoaddress(addr, 7)
addrinfo = self.nodes[1].getaddressinfo(addr)
- blockhash = self.nodes[0].generate(6)[0]
+ blockhash = self.generate(self.nodes[0], 6)[0]
self.sync_all()
vout = find_output(self.nodes[0], txid, 7, blockhash=blockhash)
psbt = self.nodes[1].createpsbt([{"txid":txid, "vout":vout}], {self.nodes[0].getnewaddress("", "p2sh-segwit"):Decimal('6.999')})
@@ -598,5 +611,43 @@ class PSBTTest(BitcoinTestFramework):
assert_raises_rpc_error(-25, 'Inputs missing or spent', self.nodes[0].walletprocesspsbt, 'cHNidP8BAJoCAAAAAkvEW8NnDtdNtDpsmze+Ht2LH35IJcKv00jKAlUs21RrAwAAAAD/////S8Rbw2cO1020OmybN74e3Ysffkglwq/TSMoCVSzbVGsBAAAAAP7///8CwLYClQAAAAAWABSNJKzjaUb3uOxixsvh1GGE3fW7zQD5ApUAAAAAFgAUKNw0x8HRctAgmvoevm4u1SbN7XIAAAAAAAEAnQIAAAACczMa321tVHuN4GKWKRncycI22aX3uXgwSFUKM2orjRsBAAAAAP7///9zMxrfbW1Ue43gYpYpGdzJwjbZpfe5eDBIVQozaiuNGwAAAAAA/v///wIA+QKVAAAAABl2qRT9zXUVA8Ls5iVqynLHe5/vSe1XyYisQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAAAAAQEfQM0ClQAAAAAWABRmWQUcjSjghQ8/uH4Bn/zkakwLtAAAAA==')
+ # Test that we can fund psbts with external inputs specified
+ eckey = ECKey()
+ eckey.generate()
+ privkey = bytes_to_wif(eckey.get_bytes())
+
+ # Make a weird but signable script. sh(pkh()) descriptor accomplishes this
+ desc = descsum_create("sh(pkh({}))".format(privkey))
+ if self.options.descriptors:
+ res = self.nodes[0].importdescriptors([{"desc": desc, "timestamp": "now"}])
+ else:
+ res = self.nodes[0].importmulti([{"desc": desc, "timestamp": "now"}])
+ assert res[0]["success"]
+ addr = self.nodes[0].deriveaddresses(desc)[0]
+ addr_info = self.nodes[0].getaddressinfo(addr)
+
+ self.nodes[0].sendtoaddress(addr, 10)
+ self.generate(self.nodes[0], 6)
+ self.sync_all()
+ ext_utxo = self.nodes[0].listunspent(addresses=[addr])[0]
+
+ # An external input without solving data should result in an error
+ assert_raises_rpc_error(-4, "Insufficient funds", self.nodes[1].walletcreatefundedpsbt, [ext_utxo], {self.nodes[0].getnewaddress(): 10 + ext_utxo['amount']}, 0, {'add_inputs': True})
+
+ # But funding should work when the solving data is provided
+ psbt = self.nodes[1].walletcreatefundedpsbt([ext_utxo], {self.nodes[0].getnewaddress(): 15}, 0, {'add_inputs': True, "solving_data": {"pubkeys": [addr_info['pubkey']], "scripts": [addr_info["embedded"]["scriptPubKey"]]}})
+ signed = self.nodes[1].walletprocesspsbt(psbt['psbt'])
+ assert not signed['complete']
+ signed = self.nodes[0].walletprocesspsbt(signed['psbt'])
+ assert signed['complete']
+ self.nodes[0].finalizepsbt(signed['psbt'])
+
+ psbt = self.nodes[1].walletcreatefundedpsbt([ext_utxo], {self.nodes[0].getnewaddress(): 15}, 0, {'add_inputs': True, "solving_data":{"descriptors": [desc]}})
+ signed = self.nodes[1].walletprocesspsbt(psbt['psbt'])
+ assert not signed['complete']
+ signed = self.nodes[0].walletprocesspsbt(signed['psbt'])
+ assert signed['complete']
+ self.nodes[0].finalizepsbt(signed['psbt'])
+
if __name__ == '__main__':
PSBTTest().main()