<commit_before>#!/usr/bin/env python3
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the Partially Signed Transaction RPCs.
"""

import json
import os

from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
    assert_equal,
    assert_greater_than,
    assert_raises_rpc_error,
    find_output,
)

# Create one-input, one-output, no-fee transaction:


class PSBTTest(BitcoinTestFramework):

    def set_test_params(self):
        self.setup_clean_chain = False
        self.num_nodes = 3

    def skip_test_if_missing_module(self):
        self.skip_if_no_wallet()

    def run_test(self):
        # Create and fund a raw tx for sending 10 BTC
        psbtx1 = self.nodes[0].walletcreatefundedpsbt(
            [], {self.nodes[2].getnewaddress(): 10})['psbt']

        # Node 1 should not be able to add anything to it but still return the
        # psbtx same as before
        psbtx = self.nodes[1].walletprocesspsbt(psbtx1)['psbt']
        assert_equal(psbtx1, psbtx)

        # Sign the transaction and send
        signed_tx = self.nodes[0].walletprocesspsbt(psbtx)['psbt']
        final_tx = self.nodes[0].finalizepsbt(signed_tx)['hex']
        self.nodes[0].sendrawtransaction(final_tx)

        # Create p2sh, p2pkh addresses
        pubkey0 = self.nodes[0].getaddressinfo(
            self.nodes[0].getnewaddress())['pubkey']
        pubkey1 = self.nodes[1].getaddressinfo(
            self.nodes[1].getnewaddress())['pubkey']
        pubkey2 = self.nodes[2].getaddressinfo(
            self.nodes[2].getnewaddress())['pubkey']
        p2sh = self.nodes[1].addmultisigaddress(
            2, [pubkey0, pubkey1, pubkey2], "")['address']
        p2pkh = self.nodes[1].getnewaddress("")

        # fund those addresses
        rawtx = self.nodes[0].createrawtransaction([], {p2sh: 10, p2pkh: 10})
        rawtx = self.nodes[0].fundrawtransaction(rawtx, {"changePosition": 0})
        signed_tx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])[
            'hex']
        txid = self.nodes[0].sendrawtransaction(signed_tx)
        self.nodes[0].generate(6)
        self.sync_all()

        # Find the output pos
        p2sh_pos = -1
        p2pkh_pos = -1
        decoded = self.nodes[0].decoderawtransaction(signed_tx)
        for out in decoded['vout']:
            if out['scriptPubKey']['addresses'][0] == p2sh:
                p2sh_pos = out['n']
            elif out['scriptPubKey']['addresses'][0] == p2pkh:
                p2pkh_pos = out['n']

        # spend single key from node 1
        rawtx = self.nodes[1].walletcreatefundedpsbt([{"txid": txid, "vout": p2pkh_pos}], {
                                                     self.nodes[1].getnewaddress(): 9.99})['psbt']
        walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(rawtx)
        assert_equal(walletprocesspsbt_out['complete'], True)
        self.nodes[1].sendrawtransaction(
            self.nodes[1].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'])

        # feeRate of 0.1 BCH / KB produces a total fee slightly below -maxtxfee
        res = self.nodes[1].walletcreatefundedpsbt([
            {"txid": txid, "vout": p2sh_pos},
            {"txid": txid, "vout": p2pkh_pos}
        ], {self.nodes[1].getnewaddress(): 29.99}, 0, {"feeRate": 0.1})
        assert_greater_than(res["fee"], 0.06)
        assert_greater_than(0.07, res["fee"])

        # feeRate of 10 BCH / KB produces a total fee well above -maxtxfee
        # previously this was silenty capped at -maxtxfee
        assert_raises_rpc_error(
            -4,
            "Fee exceeds maximum configured by -maxtxfee",
            self.nodes[1].walletcreatefundedpsbt,
            [
                {"txid": txid, "vout": p2sh_pos},
                {"txid": txid, "vout": p2pkh_pos},
            ],
            {self.nodes[1].getnewaddress(): 29.99},
            0,
            {"feeRate": 10})

        # partially sign multisig things with node 1
        psbtx = self.nodes[1].walletcreatefundedpsbt([{"txid": txid, "vout": p2sh_pos}], {
                                                     self.nodes[1].getnewaddress(): 9.99})['psbt']
        walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(psbtx)
        psbtx = walletprocesspsbt_out['psbt']
        assert_equal(walletprocesspsbt_out['complete'], False)

        # partially sign with node 2. This should be complete and sendable
        walletprocesspsbt_out = self.nodes[2].walletprocesspsbt(psbtx)
        assert_equal(walletprocesspsbt_out['complete'], True)
        self.nodes[2].sendrawtransaction(
            self.nodes[2].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'])

        # check that walletprocesspsbt fails to decode a non-psbt
        rawtx = self.nodes[1].createrawtransaction([{"txid": txid, "vout": p2pkh_pos}], {
                                                   self.nodes[1].getnewaddress(): 9.99})
        assert_raises_rpc_error(-22, "TX decode failed",
                                self.nodes[1].walletprocesspsbt, rawtx)

        # Convert a non-psbt to psbt and make sure we can decode it
        rawtx = self.nodes[0].createrawtransaction(
            [], {self.nodes[1].getnewaddress(): 10})
        rawtx = self.nodes[0].fundrawtransaction(rawtx)
        new_psbt = self.nodes[0].converttopsbt(rawtx['hex'])
        self.nodes[0].decodepsbt(new_psbt)

        # Make sure that a psbt with signatures cannot be converted
        signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])
        assert_raises_rpc_error(-22, "Inputs must not have scriptSigs",
                                self.nodes[0].converttopsbt, signedtx['hex'])
        # Unless we allow it to convert and strip signatures
        self.nodes[0].converttopsbt(signedtx['hex'], True)<commit_msg>[backport#14818] Bugfix: test/functional/rpc_psbt: Remove check for specific error message that depends on uncertain assumptions<commit_after>#!/usr/bin/env python3
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the Partially Signed Transaction RPCs.
"""

import json
import os

from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
    assert_equal,
    assert_greater_than,
    assert_raises_rpc_error,
    find_output,
)

# Create one-input, one-output, no-fee transaction:


class PSBTTest(BitcoinTestFramework):

    def set_test_params(self):
        self.setup_clean_chain = False
        self.num_nodes = 3

    def skip_test_if_missing_module(self):
        self.skip_if_no_wallet()

    def run_test(self):
        # Create and fund a raw tx for sending 10 BTC
        psbtx1 = self.nodes[0].walletcreatefundedpsbt(
            [], {self.nodes[2].getnewaddress(): 10})['psbt']

        # Node 1 should not be able to add anything to it but still return the
        # psbtx same as before
        psbtx = self.nodes[1].walletprocesspsbt(psbtx1)['psbt']
        assert_equal(psbtx1, psbtx)

        # Sign the transaction and send
        signed_tx = self.nodes[0].walletprocesspsbt(psbtx)['psbt']
        final_tx = self.nodes[0].finalizepsbt(signed_tx)['hex']
        self.nodes[0].sendrawtransaction(final_tx)

        # Create p2sh, p2pkh addresses
        pubkey0 = self.nodes[0].getaddressinfo(
            self.nodes[0].getnewaddress())['pubkey']
        pubkey1 = self.nodes[1].getaddressinfo(
            self.nodes[1].getnewaddress())['pubkey']
        pubkey2 = self.nodes[2].getaddressinfo(
            self.nodes[2].getnewaddress())['pubkey']
        p2sh = self.nodes[1].addmultisigaddress(
            2, [pubkey0, pubkey1, pubkey2], "")['address']
        p2pkh = self.nodes[1].getnewaddress("")

        # fund those addresses
        rawtx = self.nodes[0].createrawtransaction([], {p2sh: 10, p2pkh: 10})
        rawtx = self.nodes[0].fundrawtransaction(rawtx, {"changePosition": 0})
        signed_tx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])[
            'hex']
        txid = self.nodes[0].sendrawtransaction(signed_tx)
        self.nodes[0].generate(6)
        self.sync_all()

        # Find the output pos
        p2sh_pos = -1
        p2pkh_pos = -1
        decoded = self.nodes[0].decoderawtransaction(signed_tx)
        for out in decoded['vout']:
            if out['scriptPubKey']['addresses'][0] == p2sh:
                p2sh_pos = out['n']
            elif out['scriptPubKey']['addresses'][0] == p2pkh:
                p2pkh_pos = out['n']

        # spend single key from node 1
        rawtx = self.nodes[1].walletcreatefundedpsbt([{"txid": txid, "vout": p2pkh_pos}], {
                                                     self.nodes[1].getnewaddress(): 9.99})['psbt']
        walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(rawtx)
        assert_equal(walletprocesspsbt_out['complete'], True)
        self.nodes[1].sendrawtransaction(
            self.nodes[1].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'])

        # feeRate of 0.1 BCH / KB produces a total fee slightly below -maxtxfee
        res = self.nodes[1].walletcreatefundedpsbt([
            {"txid": txid, "vout": p2sh_pos},
            {"txid": txid, "vout": p2pkh_pos}
        ], {self.nodes[1].getnewaddress(): 29.99}, 0, {"feeRate": 0.1})
        assert_greater_than(res["fee"], 0.06)
        assert_greater_than(0.07, res["fee"])

        # feeRate of 10 BCH / KB produces a total fee well above -maxtxfee
        # previously this was silenty capped at -maxtxfee
        assert_raises_rpc_error(
            -4,
            "Fee exceeds maximum configured by -maxtxfee",
            self.nodes[1].walletcreatefundedpsbt,
            [
                {"txid": txid, "vout": p2sh_pos},
                {"txid": txid, "vout": p2pkh_pos},
            ],
            {self.nodes[1].getnewaddress(): 29.99},
            0,
            {"feeRate": 10})

        # partially sign multisig things with node 1
        psbtx = self.nodes[1].walletcreatefundedpsbt([{"txid": txid, "vout": p2sh_pos}], {
                                                     self.nodes[1].getnewaddress(): 9.99})['psbt']
        walletprocesspsbt_out = self.nodes[1].walletprocesspsbt(psbtx)
        psbtx = walletprocesspsbt_out['psbt']
        assert_equal(walletprocesspsbt_out['complete'], False)

        # partially sign with node 2. This should be complete and sendable
        walletprocesspsbt_out = self.nodes[2].walletprocesspsbt(psbtx)
        assert_equal(walletprocesspsbt_out['complete'], True)
        self.nodes[2].sendrawtransaction(
            self.nodes[2].finalizepsbt(walletprocesspsbt_out['psbt'])['hex'])

        # check that walletprocesspsbt fails to decode a non-psbt
        rawtx = self.nodes[1].createrawtransaction([{"txid": txid, "vout": p2pkh_pos}], {
                                                   self.nodes[1].getnewaddress(): 9.99})
        assert_raises_rpc_error(-22, "TX decode failed",
                                self.nodes[1].walletprocesspsbt, rawtx)

        # Convert a non-psbt to psbt and make sure we can decode it
        rawtx = self.nodes[0].createrawtransaction(
            [], {self.nodes[1].getnewaddress(): 10})
        rawtx = self.nodes[0].fundrawtransaction(rawtx)
        new_psbt = self.nodes[0].converttopsbt(rawtx['hex'])
        self.nodes[0].decodepsbt(new_psbt)

        # Make sure that a non-psbt with signatures cannot be converted
        # Error is "Inputs must not have scriptSigs"
        signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])
        assert_raises_rpc_error(-22,
                                "",
                                self.nodes[0].converttopsbt,
                                signedtx['hex'])
        assert_raises_rpc_error(-22,
                                "",
                                self.nodes[0].converttopsbt,
                                signedtx['hex'],
                                False)
        # Unless we allow it to convert and strip signatures
        self.nodes[0].converttopsbt(signedtx['hex'], True)
{'fraction_non_alphanumeric': 0.12169269358362327, 'fraction_numerical': 0.023141030827736872, 'mean_word_length': 2.404020930873038, 'pattern_counts': {'":': 34, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4910106', 'n_tokens_mistral': 3942, 'n_tokens_neox': 3814, 'n_words': 778}