From 5767c717b6888587aac9cde00c4e359ec4595161 Mon Sep 17 00:00:00 2001 From: Ava Chow Date: Wed, 8 Jan 2025 15:49:15 -0500 Subject: [PATCH] tests: Test PSBT sighash type mismatch --- test/functional/rpc_psbt.py | 39 ++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index 8042bdf0715..ebf618332c3 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -27,13 +27,14 @@ from test_framework.psbt import ( PSBT_GLOBAL_UNSIGNED_TX, PSBT_IN_RIPEMD160, PSBT_IN_SHA256, + PSBT_IN_SIGHASH_TYPE, PSBT_IN_HASH160, PSBT_IN_HASH256, PSBT_IN_NON_WITNESS_UTXO, PSBT_IN_WITNESS_UTXO, PSBT_OUT_TAP_TREE, ) -from test_framework.script import CScript, OP_TRUE +from test_framework.script import CScript, OP_TRUE, SIGHASH_ALL, SIGHASH_ANYONECANPAY from test_framework.script_util import MIN_STANDARD_TX_NONWITNESS_SIZE from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( @@ -201,6 +202,41 @@ class PSBTTest(BitcoinTestFramework): wallet.unloadwallet() + def test_sighash_mismatch(self): + self.log.info("Test sighash type mismatches") + self.nodes[0].createwallet("sighash_mismatch") + wallet = self.nodes[0].get_wallet_rpc("sighash_mismatch") + def_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name) + + addr = wallet.getnewaddress(address_type="bech32") + def_wallet.sendtoaddress(addr, 5) + self.generate(self.nodes[0], 6) + + # Make a PSBT + psbt = wallet.walletcreatefundedpsbt([], [{def_wallet.getnewaddress(): 1}])["psbt"] + + # Modify the PSBT and insert a sighash field for ALL|ANYONECANPAY on input 0 + mod_psbt = PSBT.from_base64(psbt) + mod_psbt.i[0].map[PSBT_IN_SIGHASH_TYPE] = (SIGHASH_ALL | SIGHASH_ANYONECANPAY).to_bytes(4, byteorder="little") + psbt = mod_psbt.to_base64() + + # Mismatching sighash type fails + assert_raises_rpc_error(-22, "Specified sighash value does not match value stored in PSBT", wallet.walletprocesspsbt, psbt, True, "DEFAULT") + assert_raises_rpc_error(-22, "Specified sighash value does not match value stored in PSBT", wallet.walletprocesspsbt, psbt, True, "ALL") + assert_raises_rpc_error(-22, "Specified sighash value does not match value stored in PSBT", wallet.walletprocesspsbt, psbt, True, "NONE") + assert_raises_rpc_error(-22, "Specified sighash value does not match value stored in PSBT", wallet.walletprocesspsbt, psbt, True, "SINGLE") + assert_raises_rpc_error(-22, "Specified sighash value does not match value stored in PSBT", wallet.walletprocesspsbt, psbt, True, "NONE|ANYONECANPAY") + assert_raises_rpc_error(-22, "Specified sighash value does not match value stored in PSBT", wallet.walletprocesspsbt, psbt, True, "SINGLE|ANYONECANPAY") + + # No sighash type specified fails + assert_raises_rpc_error(-22, "Specified sighash value does not match value stored in PSBT", wallet.walletprocesspsbt, psbt, True) + + # Matching sighash type succeeds + proc = wallet.walletprocesspsbt(psbt, True, "ALL|ANYONECANPAY") + assert_equal(proc["complete"], True) + + wallet.unloadwallet() + def assert_change_type(self, psbtx, expected_type): """Assert that the given PSBT has a change output with the given type.""" @@ -1051,6 +1087,7 @@ class PSBTTest(BitcoinTestFramework): self.log.info("Test descriptorprocesspsbt raises if an invalid sighashtype is passed") assert_raises_rpc_error(-8, "'all' is not a valid sighash parameter.", self.nodes[2].descriptorprocesspsbt, psbt, [descriptor], sighashtype="all") + self.test_sighash_mismatch() if __name__ == '__main__': PSBTTest(__file__).main()