Ejemplo n.º 1
0
    def test_missing_pubkey(self):
        self.setup_mnemonic_nopin_nopassphrase()

        # key1 = self.client.get_public_node([1])
        # key2 = self.client.get_public_node([2])
        # key3 = self.client.get_public_node([3])

        # pubkeys:
        #    0338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6
        #    038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3
        #    03477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a7902

        # multisig address: 3E7GDtuHqnqPmDgwH59pVC7AvySiSkbibz

        # xpub:
        # print(bip32.serialize(self.client.get_public_node([]).node))
        # xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy
        node = bip32.deserialize('xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy')

        multisig = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=node, address_n=[1]),
                proto.HDNodePathType(node=node, address_n=[2]),
                proto.HDNodePathType(node=node, address_n=[3])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        # Let's go to sign with key 10, which is NOT in pubkeys
        inp1 = proto.TxInputType(
            address_n=[10],
            prev_hash=TXHASH_c6091a,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDMULTISIG,
            multisig=multisig,
        )

        out1 = proto.TxOutputType(
            address='12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss',
            amount=100000,
            script_type=proto.OutputScriptType.PAYTOADDRESS
        )

        with pytest.raises(CallException) as exc:
            self.client.sign_tx('Bitcoin', [inp1, ], [out1, ])

        assert exc.value.args[0] == proto.FailureType.DataError
        assert exc.value.args[1].endswith('Pubkey not found in multisig script')
 def test_show_multisig_3(self):
     self.setup_mnemonic_allallall()
     nodes = map(
         lambda index: self.client.get_public_node(
             parse_path("999'/1'/%d'" % index)), range(1, 4))
     multisig1 = proto.MultisigRedeemScriptType(
         pubkeys=list(
             map(
                 lambda n: proto.HDNodePathType(
                     node=bip32.deserialize(n.xpub), address_n=[2, 0]),
                 nodes)),
         signatures=[b'', b'', b''],
         m=2,
     )
     # multisig2 = proto.MultisigRedeemScriptType(
     #     pubkeys=map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 1]), nodes),
     #     signatures=[b'', b'', b''],
     #     m=2,
     # )
     for i in [1, 2, 3]:
         assert self.client.get_address(
             "Testnet",
             parse_path("999'/1'/%d'/2/0" % i),
             False,
             multisig1,
             script_type=proto.InputScriptType.SPENDP2SHWITNESS
         ) == '2N8BM8wXhiSAZCX8ZxSaV9hENtq21U7QuSd'
Ejemplo n.º 3
0
 def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs):
     return proto.MultisigRedeemScriptType(
         pubkeys=list(
             map(
                 lambda xpub: proto.HDNodePathType(
                     node=bip32.deserialize(xpub),
                     address_n=[chain, nr]), xpubs)),
         signatures=signatures,
         m=2,
     )
    def test_show_multisig_3(self):
        self.setup_mnemonic_nopin_nopassphrase()

        node = bip32.deserialize(
            'xpub661MyMwAqRbcFW3NvPPCXr3RKSnks2UPNj543xvx3zKaWMTDH7rifpbTxgRbeavHFgke9vrfGZSb16ePwqWpguRYquYo8QtNRKcnVnPdmMp'
        )
        multisig = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=node, address_n=[1]),
                proto.HDNodePathType(node=node, address_n=[2]),
                proto.HDNodePathType(node=node, address_n=[3])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        for i in [1, 2, 3]:
            assert self.client.get_address(
                'Bitcoin', [i], show_display=True,
                multisig=multisig) == '33JHGqGsPuAgfYyNK5rw9tyzB7D7gjM9VZ'
Ejemplo n.º 5
0
    def test_15_of_15(self):
        self.setup_mnemonic_nopin_nopassphrase()

        """
        pubs = []
        for x in range(15):
            pubs.append(hexlify(self.client.get_public_node([x]).node.public_key))
        """

        # xpub:
        # print(bip32.serialize(self.client.get_public_node([]).node))
        # xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy
        node = bip32.deserialize('xpub661MyMwAqRbcFW3NvPPCXr3RKSnks2UPNj543xvx3zKaWMTDH7rifpbTxgRbeavHFgke9vrfGZSb16ePwqWpguRYquYo8QtNRKcnVnPdmMp')

        pubs = []
        for x in range(15):
            pubs.append(proto.HDNodePathType(node=node, address_n=[x]))

        # redeeemscript
        # 5f21023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43d210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a79022103fe91eca10602d7dad4c9dab2b2a0858f71e25a219a6940749ce7a48118480dae210234716c01c2dd03fa7ee302705e2b8fbd1311895d94b1dca15e62eedea9b0968f210341fb2ead334952cf60f4481ba435c4693d0be649be01d2cfe9b02018e483e7bd2102dad8b2bce360a705c16e74a50a36459b4f8f4b78f9cd67def29d54ef6f7c7cf9210222dbe3f5f197a34a1d50e2cbe2a1085cac2d605c9e176f9a240e0fd0c669330d2103fb41afab56c9cdb013fda63d777d4938ddc3cb2ad939712da688e3ed333f95982102435f177646bdc717cb3211bf46656ca7e8d642726144778c9ce816b8b8c36ccf2102158d8e20095364031d923c7e9f7f08a14b1be1ddee21fe1a5431168e31345e5521026259794892428ca0818c8fb61d2d459ddfe20e57f50803c7295e6f4e2f5586652102815f910a8689151db627e6e262e0a2075ad5ec2993a6bc1b876a9d420923d681210318f54647f645ff01bd49fedc0219343a6a22d3ea3180a3c3d3097e4b888a8db45fae

        # multisig address
        # 3QaKF8zobqcqY8aS6nxCD5ZYdiRfL3RCmU

        signatures = [b''] * 15

        out1 = proto.TxOutputType(
            address='17kTB7qSk3MupQxWdiv5ZU3zcrZc2Azes1',
            amount=10000,
            script_type=proto.OutputScriptType.PAYTOADDRESS
        )

        for x in range(15):
            multisig = proto.MultisigRedeemScriptType(
                pubkeys=pubs,
                signatures=signatures,
                m=15,
            )

            inp1 = proto.TxInputType(
                address_n=[x],
                prev_hash=unhexlify('6189e3febb5a21cee8b725aa1ef04ffce7e609448446d3a8d6f483c634ef5315'),
                prev_index=1,
                script_type=proto.InputScriptType.SPENDMULTISIG,
                multisig=multisig,
            )

            with self.client:
                (sig, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, ])
                signatures[x] = sig[0]

        # Accepted as tx id dd320786d1f58c095be0509dc56b277b6de8f2fb5517f519c6e6708414e3300b
        assert hexlify(serialized_tx) == b'01000000011553ef34c683f4d6a8d346844409e6e7fc4ff01eaa25b7e8ce215abbfee3896101000000fd440600473044022069759a1f82ba3eb3577e13e36b199aa54939a097accb085766b8e3796b98afaa022024bb93a30fa66d90930f5b3b5f37411a850e4a84d3c9b0d6522014ea37d3a66301473044022017de2986c48dc9f3227d95c93d04b75061f038076459af9ae0f61ba46fa8f6a6022061ec4d4a2a99e67934946ea76619e14ecad90631089daabca5b8c0eab17b168b014830450221008ea5fb5e6555ac745988baaf1beccad1f21957ce4b8769424c0d9856ee6b2ed902204c2ce90bae9a478a7e3d9b2d9c22b6136026fc653d677a74e6c6600696af3a96014730440220567ee5c2027841e21c5597b648eea192b4a12eed7182f940b896770cffa87ed30220607023fafed86a1373ccd4c8de6b223cd226a3c0bdf669b06fa66c905afdd24b01483045022100cd664977973c0f51384b6feb2eb651cca52377c7c91ec96b4838d1a96084b03102205cf95ea28b4f4dfb6abceb02ee517ff8e03ddce9fe40434b0d70896f24c2e234014730440220059a86bffc16ebfd958aa6b0e347807a839a65159bf8a12605fbfa30aee9b61c022053dfda65277510f55aea29175e1924dfb97d7a2366127d8a2ee2a2b4f4047e4e01473044022042b425ee8c87131533f768082ff6a71a7f925584b5cb74c035c57835eb06341502203e8377f7cec26f2f1caeff25b839e546822b6afdd622e1c87ccc1518c112fb7a01483045022100b77d30ec7d764c419386fc275ec3e93e8cb6a266959086b8d86a93c0044a91af02201201982a9f5cac00178df3bce02d82d46457772a7fa8c532fc4c9b6bf245c51d0147304402204aa6268dbafcea94e29c61fdcb5b88b2d5a95ccf7101ae81c0534c4db159676f02203ade8e9ebecbd0ffba249450fa6dd993f28a83d2ef0b422d5fc18495d5a693aa01483045022100de920a940de7035d34e60cdfcc8f2ed794498fb5fbc807a0f53339da35e5628502207f869279372b9051e8443e4159fa720c352870758b5e5cdc364a3d66aa768d5701473044022026121b6c5c99c94d85815c56f586f77f74f56bf49731e891a2d4fba1ad4d31c1022045fa621c1bd25209a91951c1e7638ec87c311b450299b19c264c9887e617e40b01473044022068300807e73176ae94f9352ec3051f23bcc6a131f449061a33c2925ffffcfc480220483e63ae743d14a9472dd861bf5f79f15a7cc12f00e8bad61f5cf49a7e2cf61201483045022100d06cce8c8ae2e3ab382dd62159d222bb77040beaa7a19f8f2b21b24b699e12e302201027ca2f03aeaa1414cbb8969e9acf63814129872c9a94d0a4e55342cf456c5601483045022100b24778fa3a1f87fb5dd164454514ad8f97dc507e4bcb50d1fc68cd4f44ecd24d02200e5720e4e941cfe39d8e43ef77db5b4497dfca4327ecaae62ebbd9c0515c878201483045022100979c49b69c006dd7d0d6a0f18f05d87f40c8cbb513530580d20c6511e86e0e88022029b9ef179ad3fdeaec91f90fcda2a44dc95b839e67528ebe2e3826b11b4871de014d01025f2103bb20b056809acb091b3e3d1833681cb80f7b5f09bd9c5a229f5ff00edfcdee112103912a8f07b60de8f0b2800f1088f9b016059219cc63beeb4bf26e1bd5e7da5319210309b80e44b9ee837a2ef8e839cce1d6bb7c1408646143fb9b59569f39669e3049210262f6426d6942332874d20899b44c136b0b56c66b876de9658a97182ad1cafc79210201d07233d7c1c63d2004ba28e11a0cbab4802b7d70fce644564c3067e8100b712103c86a1fe7530c538d640692ebe24eefdec35d64759952ec69ffb616f1bc73fbcd2102f1404a0a192ce18c471448cc4f26f80252aaed299854c3b86dc4b90167493df0210234f078300980ffcb54957386634300660f84519a9731b5ffd9b1b629a0c0f6d42103ba77c9108cf392030d4ef801cc7ee1bc404acd704ed61eb945622f8377c76e55210332881699bec210e2e0e15cb861864e88a27195f84855df789f44c9e68ae763bc21025007b55de10f834b1b7b75d02ebed4ddf2df8f2a370a883290daf2cbf40fd612210321ea75cc48cb17e35b8d2b2e0383181fc85950f896ef7ffe6658c3b2f3f6872821021ea187ea5868b053a1a91e4e7135f6cf4f9caf0a8cada43b8ff14c87d4cadce02102f164a27945a02a791f682a7f5cef88f95b2f8e273d75fb94b39d3fb17284a6db210294db8e8e09ee6d70436e9a01246cf94db741f0cd14fcb8f37964281a3bcb60d05faeffffffff0110270000000000001976a9144a087d89f8ad16ca029c675b037c02fd1c5f9aec88ac00000000'
Ejemplo n.º 6
0
 def test_show_multisig_3(self):
     self.setup_mnemonic_allallall()
     nodes = [
         self.client.get_public_node(parse_path("999'/1'/%d'" % index))
         for index in range(1, 4)
     ]
     multisig1 = proto.MultisigRedeemScriptType(
         pubkeys=list(
             map(
                 lambda n: proto.HDNodePathType(
                     node=bip32.deserialize(n.xpub), address_n=[2, 0]),
                 nodes)),
         signatures=[b'', b'', b''],
         m=2,
     )
     multisig2 = proto.MultisigRedeemScriptType(
         pubkeys=list(
             map(
                 lambda n: proto.HDNodePathType(
                     node=bip32.deserialize(n.xpub), address_n=[2, 1]),
                 nodes)),
         signatures=[b'', b'', b''],
         m=2,
     )
     for i in [1, 2, 3]:
         assert self.client.get_address(
             "Testnet",
             parse_path("999'/1'/%d'/2/1" % i),
             False,
             multisig2,
             script_type=proto.InputScriptType.SPENDWITNESS
         ) == 'tb1qr60gl0vt6nrduwrhl32jqcefce8zw0ewfr8y6n4h0mqe9xwa4z0svt3rk7'
         assert self.client.get_address(
             "Testnet",
             parse_path("999'/1'/%d'/2/0" % i),
             False,
             multisig1,
             script_type=proto.InputScriptType.SPENDWITNESS
         ) == 'tb1qsvhqde0wme09er327gdn806af22nh908g47qxnctc8acq2xvtwdstc34v7'
Ejemplo n.º 7
0
    def test_multisig_mismatch_inputs(self):
        self.setup_mnemonic_nopin_nopassphrase()

        multisig_out1 = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=self.node_ext2, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_int, address_n=[1, 0])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        out1 = proto.TxOutputType(
            address_n=[0x80000000 | 45, 0, 1, 0],
            multisig=multisig_out1,
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOMULTISIG)

        out2 = proto.TxOutputType(
            address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw',
            amount=65000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp3))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp3,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100b7f49a255464bc69a5ea576bc5512084561d527d6cb2cd056cfa6350c51c21a8022017bb0b4eeb4dfd28646c234b3c7c49e535378675caa60b83bbdc629baeb94d28014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff39f756d82082b580b0d69ae8798ff10a981820ccfe1ab149a708a37bc26d94b000000000b500483045022100a9ca27e9943ba7bfbf5b654f38982d62cf2cb82c0b99156ab739b472e31cd580022074b564cf50ad8078bbae89b86af8e31a098eddc61b1a91697ea9b8c52acece7d014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103b6321a1194e5cc47b6b7edc3f67a096e6f71ccb72440f84f390b6e98df0ea8ec21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a62020000000017a914705d4f1d91c05ee5bde07e8e81fe878c2a2d48a68740d2df030000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000'
Ejemplo n.º 8
0
    def test_multisig_mismatch_change(self):
        self.setup_mnemonic_nopin_nopassphrase()

        multisig_out2 = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_int, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_ext3, address_n=[1, 0])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        out1 = proto.TxOutputType(
            address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR',
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        out2 = proto.TxOutputType(
            address_n=[0x80000000 | 45, 0, 1, 0],
            multisig=multisig_out2,
            amount=44000000,
            script_type=proto.OutputScriptType.PAYTOMULTISIG)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp2))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp2,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b40047304402205a647596f2ba4746a07dbcb8c3efed1ccbe3b29212ffe6493a8763c0e7227ff302205c7897deaa1183fea95a6b6b97c00c7460aa0219413c7329fc624b98d366ef21014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b500483045022100fcc5b14240541914824c79c1f1d760cf9b61d2802c99ee1c4d3b449fa7b2fca502206e368c03813ef0a4b2ac32a6e5ea6ac52b0f6deb9dbf0c45198f1d3abcafc7f0014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a9146169c87e30105747aafd636bfd35bc9e3a5e13ea8700000000'
Ejemplo n.º 9
0
    def test_multisig_change_match_second(self):
        self.setup_mnemonic_nopin_nopassphrase()

        multisig_out2 = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=self.node_ext1, address_n=[1, 1]),
                proto.HDNodePathType(node=self.node_ext2, address_n=[1, 1]),
                proto.HDNodePathType(node=self.node_int, address_n=[1, 1])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        out1 = proto.TxOutputType(
            address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR',
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        out2 = proto.TxOutputType(
            address_n=[0x80000000 | 45, 0, 1, 1],
            multisig=multisig_out2,
            amount=44000000,
            script_type=proto.OutputScriptType.PAYTOMULTISIG)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp2, change=2))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp2,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022027cd3f397e006922a45978dffde57ad87fca656372526c1c494726c9dd216d7502206674ad0281f4210d32b37da1651921750f8c66c1e6d2b69c8909b701f602901a014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b500483045022100b24ca91c00574e1ed3d7370a4cdc52f004040ea308d18977450bc428477eb62002203e1be7e1a990a29c019202a5f9631dd7a94d603f8ca77834740b3be814718172014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914a13fc6db7be0606fb301567d90c9f89d05cd3a1b8700000000'
Ejemplo n.º 10
0
    def test_multisig_change_match_first(self):
        self.setup_mnemonic_nopin_nopassphrase()

        multisig_out1 = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=self.node_ext2, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_int, address_n=[1, 0])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        out1 = proto.TxOutputType(
            address_n=[0x80000000 | 45, 0, 1, 0],
            multisig=multisig_out1,
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOMULTISIG)

        out2 = proto.TxOutputType(
            address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw',
            amount=44000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp2, change=1))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp2,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100a0c9c923a27f9852ced3064ec8183ba2f7d9897b1a416357f1e8bf242f194c1d02202cebe99b428d2ff539fad2ba428e821de9a6a1891eaf941b921ad98534513626014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b500483045022100c5c59484926e1b2560d964f28c6fd62a44fb01fb895cad23978f5940b53b2509022072338a2621f6e5a078994a57095a28397348812f0ea46e1a5ded117afb89a0a3014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a62020000000017a914705d4f1d91c05ee5bde07e8e81fe878c2a2d48a68700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000'
Ejemplo n.º 11
0
    def test_send_multisig_1(self):
        self.setup_mnemonic_allallall()
        self.client.set_tx_api(TxApiTestnet)
        nodes = map(lambda index: self.client.get_public_node(parse_path("999'/1'/%d'" % index)), range(1, 4))
        multisig = proto.MultisigRedeemScriptType(
            pubkeys=list(map(lambda n: proto.HDNodePathType(node=deserialize(n.xpub), address_n=[2, 0]), nodes)),
            signatures=[b'', b'', b''],
            m=2,
        )

        inp1 = proto.TxInputType(
            address_n=parse_path("999'/1'/1'/2/0"),
            prev_hash=unhexlify('9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be'),
            prev_index=1,
            script_type=proto.InputScriptType.SPENDP2SHWITNESS,
            multisig=multisig,
            amount=1610436
        )

        out1 = proto.TxOutputType(address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC',
                                  amount=1605000,
                                  script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures1, _) = self.client.sign_tx('Testnet', [inp1], [out1])
            # store signature
            inp1.multisig.signatures[0] = signatures1[0]
            # sign with third key
            inp1.address_n[2] = 0x80000003
            self.client.set_expected_responses([
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures2, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1])

        assert hexlify(serialized_tx) == b'01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c0100000023220020832e06e5eede5e5c8e2af21b33bf5d4a953b95e7457c034f0bc1fb8028cc5b9bffffffff01887d1800000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac04004730440220236afb6d9ee8c86ff7b0b5c8003a92eabcd08f60b66fad5e43a4ba39e56d623802203aeca56ddb50ece8978b19e71a635d4fd50296008f363a0fdeeb7d42fc9e32b601483045022100d496d1ef47a9be472bf1d556f55f43f32214d923a39e69654212d0740f533c1302203f5b12e05c4c7e2d7c6dc367953e97f0115b139ae12bbf9a1f5e0bfd4d7e997c0169522102cea51fb0aa19715665ac367725c4ea0bac2b7f3371df16e58c3538b788260fe12102cd496a185be36b20cf1400d296a221fd05bfc46adc04e7ba4ebd8f47f037ae682103caaabaa9876547cf014dcb93a73af348e32af5cbf29d436b9fa922232432f03153ae00000000'
    def test_show_multisig_15(self):
        self.setup_mnemonic_nopin_nopassphrase()

        node = bip32.deserialize(
            'xpub661MyMwAqRbcFW3NvPPCXr3RKSnks2UPNj543xvx3zKaWMTDH7rifpbTxgRbeavHFgke9vrfGZSb16ePwqWpguRYquYo8QtNRKcnVnPdmMp'
        )

        pubs = []
        for x in range(15):
            pubs.append(proto.HDNodePathType(node=node, address_n=[x]))

        multisig = proto.MultisigRedeemScriptType(
            pubkeys=pubs,
            signatures=[b''] * 15,
            m=15,
        )

        for i in range(15):
            assert self.client.get_address(
                'Bitcoin', [i], show_display=True,
                multisig=multisig) == '3DTbMcL2LFgDwGY3M2YLVev1Kvata3x1Ws'
    def test_send_multisig_1(self):
        self.setup_mnemonic_allallall()
        self.client.set_tx_api(TxApiTestnet)
        nodes = [
            self.client.get_public_node(parse_path("999'/1'/%d'" % index))
            for index in range(1, 4)
        ]
        multisig = proto.MultisigRedeemScriptType(
            pubkeys=list(
                map(
                    lambda n: proto.HDNodePathType(node=deserialize(n.xpub),
                                                   address_n=[2, 0]), nodes)),
            signatures=[b'', b'', b''],
            m=2,
        )

        inp1 = proto.TxInputType(
            address_n=parse_path("999'/1'/1'/2/0"),
            prev_hash=unhexlify(
                '9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be'
            ),
            prev_index=1,
            script_type=proto.InputScriptType.SPENDP2SHWITNESS,
            multisig=multisig,
            amount=1610436)

        out1 = proto.TxOutputType(
            address=
            'tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy',
            amount=1605000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures1, _) = self.client.sign_tx('Testnet', [inp1], [out1])
            # store signature
            inp1.multisig.signatures[0] = signatures1[0]
            # sign with third key
            inp1.address_n[2] = 0x80000003
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures2,
             serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1])

        # f41cbedd8becee05a830f418d13aa665125464547db5c7a6cd28f21639fe1228
        assert hexlify(
            serialized_tx
        ) == b'01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c0100000023220020832e06e5eede5e5c8e2af21b33bf5d4a953b95e7457c034f0bc1fb8028cc5b9bffffffff01887d180000000000220020c5f4a0a4ea7c0392efe0a9670a73264cffa90b19107cd8a8e9750ff93c77fdfb0400483045022100b4c59881e3e9491aa40a1d2bb4932e1fc7ffcc90c5150270e5ef2f95376c77c302203c9cf4b0ed841135aee07c84357b4e8550f14fad87c44b8ee58952acc177a82e0147304402204c100f179c99fab2a2f510652b717debfdeba5cd4a1dc22d3e7ab1b58902deda0220018bc0129026920c8757ba7de9a1c7fb50bd16d7ca5e22c6af75c31afe993cb60169522102cea51fb0aa19715665ac367725c4ea0bac2b7f3371df16e58c3538b788260fe12102cd496a185be36b20cf1400d296a221fd05bfc46adc04e7ba4ebd8f47f037ae682103caaabaa9876547cf014dcb93a73af348e32af5cbf29d436b9fa922232432f03153ae00000000'
Ejemplo n.º 14
0
    def test_2_of_3(self):
        self.setup_mnemonic_nopin_nopassphrase()

        # key1 = self.client.get_public_node([1])
        # key2 = self.client.get_public_node([2])
        # key3 = self.client.get_public_node([3])

        # xpub:
        # print(bip32.serialize(self.client.get_public_node([]).node))
        # xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy

        # pubkeys:
        #    xpub/1: 0338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6
        #    xpub/2: 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3
        #    xpub/3: 03477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a7902

        # redeem script:
        # 52210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a790253ae

        # multisig address: 3E7GDtuHqnqPmDgwH59pVC7AvySiSkbibz

        # tx: c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52
        # input 1: 0.001 BTC

        node = bip32.deserialize('xpub661MyMwAqRbcFW3NvPPCXr3RKSnks2UPNj543xvx3zKaWMTDH7rifpbTxgRbeavHFgke9vrfGZSb16ePwqWpguRYquYo8QtNRKcnVnPdmMp')

        multisig = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=node, address_n=[1]),
                proto.HDNodePathType(node=node, address_n=[2]),
                proto.HDNodePathType(node=node, address_n=[3])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        # Let's go to sign with key 1
        inp1 = proto.TxInputType(
            address_n=[1],
            prev_hash=TXHASH_c6091a,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDMULTISIG,
            multisig=multisig,
        )

        out1 = proto.TxOutputType(
            address='12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss',
            amount=100000,
            script_type=proto.OutputScriptType.PAYTOADDRESS
        )

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])

            # Now we have first signature
            (signatures1, _) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, ])

        assert hexlify(signatures1[0]) == b'30440220650a2b065231511223a200afbd39dbe31e217de71443f3e1bf6f16184ffb454102207363a9991104273be3bacb51d77e53055f32a6c324e296567705d53ad1266f04'

        # ---------------------------------------
        # Let's do second signature using 3rd key

        multisig = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=node, address_n=[1]),
                proto.HDNodePathType(node=node, address_n=[2]),
                proto.HDNodePathType(node=node, address_n=[3])
            ],
            signatures=[signatures1[0], b'', b''],  # Fill signature from previous signing process
            m=2,
        )

        # Let's do a second signature with key 3
        inp3 = proto.TxInputType(
            address_n=[3],
            prev_hash=TXHASH_c6091a,
            prev_index=1,
            script_type=proto.InputScriptType.SPENDMULTISIG,
            multisig=multisig,
        )

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_c6091a)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures2, serialized_tx) = self.client.sign_tx('Bitcoin', [inp3, ], [out1, ])

        assert hexlify(signatures2[0]) == b'30450221009181106fe1ac79dd86b84e349cdc46d6c842018bbad4a0d0464590d380f9466c02207dc0c6678dbd2df7d8560239dfe9db6dda35483870f8db3f3ff2534e15b4da6d'

        # Accepted by network: tx 8382a2b2e3ec8788800c1d46d285dfa9dd4051edddd75982fad166b9273e5ac6
        assert hexlify(serialized_tx) == b'010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fdfd00004730440220650a2b065231511223a200afbd39dbe31e217de71443f3e1bf6f16184ffb454102207363a9991104273be3bacb51d77e53055f32a6c324e296567705d53ad1266f04014830450221009181106fe1ac79dd86b84e349cdc46d6c842018bbad4a0d0464590d380f9466c02207dc0c6678dbd2df7d8560239dfe9db6dda35483870f8db3f3ff2534e15b4da6d014c69522103912a8f07b60de8f0b2800f1088f9b016059219cc63beeb4bf26e1bd5e7da5319210309b80e44b9ee837a2ef8e839cce1d6bb7c1408646143fb9b59569f39669e3049210262f6426d6942332874d20899b44c136b0b56c66b876de9658a97182ad1cafc7953aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000'
Ejemplo n.º 15
0
class TestMultisigChange(HideezTest):
    def setup_method(self, method):
        super(TestMultisigChange, self).setup_method(method)
        self.client.set_tx_api(tx_api['Testnet'])

    node_ext1 = bip32.deserialize(
        'tpubDADHV9u9Y6gkggintTdMjJE3be58zKNLhpxBQyuEM6Pwx3sN9JVLmMCMN4DNVwL9AKec27z5TaWcWuHzMXiGAtcra5DjwWbvppGX4gaEGVN'
    )
    # m/1 => 02c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e
    # m/2 => 0375b9dfaad928ce1a7eed88df7c084e67d99e9ab74332419458a9a45779706801

    node_ext2 = bip32.deserialize(
        'tpubDADHV9u9Y6gkhWXBmDJ6TUhZajLWjvKukRe2w9FfhdbQpUux8Z8jnPHNAZqFRgHPg9sR7YR93xThM32M7NfRu8S5WyDtext7S62sqxeJNkd'
    )
    # m/1 => 0388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c1
    # m/2 => 03a04f945d5a3685729dde697d574076de4bdf38e904f813b22a851548e1110fc0

    node_ext3 = bip32.deserialize(
        'tpubDADHV9u9Y6gkmM5ohWRGTswrc6fr7soH7e2D2ic5a86PDUaHc5Ln9EbER69cEr5bDZPa7EXguJ1MhWVzPZpZWVdG5fvoF3hfirXvRbpCCBg'
    )
    # m/1 => 02e0c21e2a7cf00b94c5421725acff97f9826598b91f2340c5ddda730caca7d648
    # m/2 => 03928301ffb8c0d7a364b794914c716ba3107cc78a6fe581028b0d8638b22e8573

    # m/45'/0
    node_int = bip32.deserialize(
        'tpubDAr57pLnvN3Z6VjGJvqULNdJig1QKVh87QnNuDymu11WfGSTMbcDtrTU66GAqF9yAdLgiYFSfPdp6LXPWQC6S3iFBRaYNzXPfKy1jvS8NSm'
    )
    # m/1 => 03f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff35
    # m/2 => 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3

    # ext1 + ext2 + int
    #   redeemscript (2 of 3): 522102c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e210388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c1210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a653ae
    #   multisig address: 3Gj7y1FdTppx2JEDqYqAEZFnKCA4GRysKF
    #   tx: d1d08ea63255af4ad16b098e9885a252632086fa6be53301521d05253ce8a73d
    #   input 0: 0.001 BTC

    # ext1 + int + ext2
    #   redeemscript (2 of 3): 522102c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6210388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c153ae
    #   multisig address: 3QsvfB6d1LzYcpm8xyhS1N1HBRrzHTgLHB
    #   tx: a6e2829d089cee47e481b1a753a53081b40738cc87e38f1d9b23ab57d9ad4396
    #   input 0: 0.001 BTC

    # ext1 + ext3 + int
    #   redeemscript (2 of 3): 522102c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e2102e0c21e2a7cf00b94c5421725acff97f9826598b91f2340c5ddda730caca7d648210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a653ae
    #   multisig address: 37LvC1Q5CyKbMbKMncEJdXxqGhHxrBEgPE
    #   tx: e4bc1ae5e5007a08f2b3926fe11c66612e8f73c6b00c69c7027213b84d259be3
    #   input 1: 0.001 BTC

    multisig_in1 = proto.MultisigRedeemScriptType(
        pubkeys=[
            proto.HDNodePathType(node=node_ext2, address_n=[0, 0]),
            proto.HDNodePathType(node=node_ext1, address_n=[0, 0]),
            proto.HDNodePathType(node=node_int, address_n=[0, 0])
        ],
        signatures=[b'', b'', b''],
        m=2,
    )

    multisig_in2 = proto.MultisigRedeemScriptType(
        pubkeys=[
            proto.HDNodePathType(node=node_ext1, address_n=[0, 1]),
            proto.HDNodePathType(node=node_ext2, address_n=[0, 1]),
            proto.HDNodePathType(node=node_int, address_n=[0, 1]),
        ],
        signatures=[b'', b'', b''],
        m=2,
    )

    multisig_in3 = proto.MultisigRedeemScriptType(
        pubkeys=[
            proto.HDNodePathType(node=node_ext1, address_n=[0, 1]),
            proto.HDNodePathType(node=node_ext3, address_n=[0, 1]),
            proto.HDNodePathType(node=node_int, address_n=[0, 1])
        ],
        signatures=[b'', b'', b''],
        m=2,
    )

    # 2N9W4z9AhAPaHghtqVQPbaTAGHdbrhKeBQw
    inp1 = proto.TxInputType(
        address_n=[45 | 0x80000000, 0, 0, 0],
        prev_hash=unhexlify(
            '16c6c8471b8db7a628f2b2bb86bfeefae1766463ce8692438c7fd3fce3f43ce5'
        ),
        prev_index=1,
        script_type=proto.InputScriptType.SPENDMULTISIG,
        multisig=multisig_in1,
    )

    # 2NDBG6QXQLtnQ3jRGkrqo53BiCeXfQXLdj4
    inp2 = proto.TxInputType(
        address_n=[45 | 0x80000000, 0, 0, 1],
        prev_hash=unhexlify(
            'd80c34ee14143a8bf61125102b7ef594118a3796cad670fa8ee15080ae155318'
        ),
        prev_index=0,
        script_type=proto.InputScriptType.SPENDMULTISIG,
        multisig=multisig_in2,
    )

    # 2MvwPWfp2XPU3S1cMwgEMKBPUw38VP5SBE4
    inp3 = proto.TxInputType(
        address_n=[45 | 0x80000000, 0, 0, 1],
        prev_hash=unhexlify(
            'b0946dc27ba308a749b11afecc2018980af18f79e89ad6b080b58220d856f739'
        ),
        prev_index=0,
        script_type=proto.InputScriptType.SPENDMULTISIG,
        multisig=multisig_in3,
    )

    def _responses(self, inp1, inp2, change=0):
        resp = [
            proto.TxRequest(
                request_type=proto.RequestType.TXINPUT,
                details=proto.TxRequestDetailsType(request_index=0)),
            proto.TxRequest(
                request_type=proto.RequestType.TXMETA,
                details=proto.TxRequestDetailsType(tx_hash=inp1.prev_hash)),
            proto.TxRequest(request_type=proto.RequestType.TXINPUT,
                            details=proto.TxRequestDetailsType(
                                request_index=0, tx_hash=inp1.prev_hash)),
            proto.TxRequest(request_type=proto.RequestType.TXOUTPUT,
                            details=proto.TxRequestDetailsType(
                                request_index=0, tx_hash=inp1.prev_hash)),
            proto.TxRequest(request_type=proto.RequestType.TXOUTPUT,
                            details=proto.TxRequestDetailsType(
                                request_index=1, tx_hash=inp1.prev_hash)),
            proto.TxRequest(
                request_type=proto.RequestType.TXINPUT,
                details=proto.TxRequestDetailsType(request_index=1)),
            proto.TxRequest(
                request_type=proto.RequestType.TXMETA,
                details=proto.TxRequestDetailsType(tx_hash=inp2.prev_hash)),
            proto.TxRequest(request_type=proto.RequestType.TXINPUT,
                            details=proto.TxRequestDetailsType(
                                request_index=0, tx_hash=inp2.prev_hash)),
            proto.TxRequest(request_type=proto.RequestType.TXOUTPUT,
                            details=proto.TxRequestDetailsType(
                                request_index=0, tx_hash=inp2.prev_hash)),
            proto.TxRequest(request_type=proto.RequestType.TXOUTPUT,
                            details=proto.TxRequestDetailsType(
                                request_index=1, tx_hash=inp2.prev_hash)),
            proto.TxRequest(
                request_type=proto.RequestType.TXOUTPUT,
                details=proto.TxRequestDetailsType(request_index=0)),
        ]
        resp.append(
            proto.TxRequest(
                request_type=proto.RequestType.TXOUTPUT,
                details=proto.TxRequestDetailsType(request_index=1)))
        resp += [
            proto.TxRequest(
                request_type=proto.RequestType.TXINPUT,
                details=proto.TxRequestDetailsType(request_index=0)),
            proto.TxRequest(
                request_type=proto.RequestType.TXINPUT,
                details=proto.TxRequestDetailsType(request_index=1)),
            proto.TxRequest(
                request_type=proto.RequestType.TXOUTPUT,
                details=proto.TxRequestDetailsType(request_index=0)),
            proto.TxRequest(
                request_type=proto.RequestType.TXOUTPUT,
                details=proto.TxRequestDetailsType(request_index=1)),
            proto.TxRequest(
                request_type=proto.RequestType.TXINPUT,
                details=proto.TxRequestDetailsType(request_index=0)),
            proto.TxRequest(
                request_type=proto.RequestType.TXINPUT,
                details=proto.TxRequestDetailsType(request_index=1)),
            proto.TxRequest(
                request_type=proto.RequestType.TXOUTPUT,
                details=proto.TxRequestDetailsType(request_index=0)),
            proto.TxRequest(
                request_type=proto.RequestType.TXOUTPUT,
                details=proto.TxRequestDetailsType(request_index=1)),
            proto.TxRequest(
                request_type=proto.RequestType.TXOUTPUT,
                details=proto.TxRequestDetailsType(request_index=0)),
            proto.TxRequest(
                request_type=proto.RequestType.TXOUTPUT,
                details=proto.TxRequestDetailsType(request_index=1)),
            proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
        ]
        return resp

    # both outputs are external
    def test_external_external(self):
        self.setup_mnemonic_nopin_nopassphrase()

        out1 = proto.TxOutputType(
            address='muevUcG1Bb8eM2nGUGhqmeujHRX7YXjSEu',
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        out2 = proto.TxOutputType(
            address='mwdrpMVSJxxsM8f8xbnCHn9ERaRT1NG1UX',
            amount=44000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp2))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp2,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100b83f55b5909d5d368ad53f016586b49cf6d64189089efc1eeba2f1f316541e7f02201d41be646e08de2af07db9b4880a5ddc9f460c32d75dd3c4666dc602bae2dfb1014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402207d9a207b6139ea1fcc7c10d02db2b6d671f39d46ef3644f75ba9e45b728076fa02202d1cab6cb8303e89fd79dbc646cb819dc63e315a6ab7a1daa9d14369107824fe014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000'

    # first external, second internal
    def test_external_internal(self):
        self.setup_mnemonic_nopin_nopassphrase()

        out1 = proto.TxOutputType(
            address='muevUcG1Bb8eM2nGUGhqmeujHRX7YXjSEu',
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        out2 = proto.TxOutputType(
            address_n=parse_path("45'/0/1/1"),
            amount=44000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp2, change=2))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp2,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b40047304402200c4fa6e53961b88ce8319924dc07b23feb931923b8e8d0625028ee408d6f6a970220360b7bd8e585a331a2b2c87f9c1f36197f351f9fc4949068cf3359a7f2b6d73f014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402206c612fe0e17cf37f7e035be7faa5c5df721e7463de621bb953f099ac3f3a828902206b86dad2bb4377f4a2d77a248e3d5d5c69abdcb544f40bd261e12b7cd67f9456014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914794659b1482d713ae4facfc09cf45466eed7dd3e88ac00000000'

    # first internal, second external
    def test_internal_external(self):
        self.setup_mnemonic_nopin_nopassphrase()

        out1 = proto.TxOutputType(
            address_n=parse_path("45'/0/1/0"),
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        out2 = proto.TxOutputType(
            address='mwdrpMVSJxxsM8f8xbnCHn9ERaRT1NG1UX',
            amount=44000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp2, change=1))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp2,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100aa0a1b8e97e62d63b02cb7a714c3dbb816cd7b56304c36ca91e4b59e48627b650220527b412cb1f71ac208cf1f4c25c3174fe13297cd0299a1071170d58bbea387ba014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b5004830450221009036e6bbb0a7af02f5993525b9e4e63ddfadd17a645f40fc46fb4d517d38f99402206f13e81596b10eab8e0c81a59830ae4ad3a82c43c177dc6d5c40a757e42254fd014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a6202000000001976a914c5d93a7fc535d6a9f6668830b33fa68b14b250ae88ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000'

    # both outputs are external
    def test_multisig_external_external(self):
        self.setup_mnemonic_nopin_nopassphrase()

        out1 = proto.TxOutputType(
            address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR',
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        out2 = proto.TxOutputType(
            address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw',
            amount=44000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp2))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp2,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b40047304402204248374f704cee8ac074577a107f7445d49a4ec0f4f323b74a49e1939a88484602203e5024b1e8c57a8146281f87bef81b8b860db6b3bef95df1aac0760ace0ab62e014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205818d7f6be68dbd75e2e14a5264c5de00b4259483912d77fd549b8721c9b2a360220214ea606137980f12dd14a69f8a62533f380da9422021b9cdde662be4694e82e014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000'

    # inputs match, change matches (first is change)
    def test_multisig_change_match_first(self):
        self.setup_mnemonic_nopin_nopassphrase()

        multisig_out1 = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=self.node_ext2, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_int, address_n=[1, 0])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        out1 = proto.TxOutputType(
            address_n=[0x80000000 | 45, 0, 1, 0],
            multisig=multisig_out1,
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOMULTISIG)

        out2 = proto.TxOutputType(
            address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw',
            amount=44000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp2, change=1))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp2,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100a0c9c923a27f9852ced3064ec8183ba2f7d9897b1a416357f1e8bf242f194c1d02202cebe99b428d2ff539fad2ba428e821de9a6a1891eaf941b921ad98534513626014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b500483045022100c5c59484926e1b2560d964f28c6fd62a44fb01fb895cad23978f5940b53b2509022072338a2621f6e5a078994a57095a28397348812f0ea46e1a5ded117afb89a0a3014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a62020000000017a914705d4f1d91c05ee5bde07e8e81fe878c2a2d48a68700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000'

    # inputs match, change matches (second is change)
    def test_multisig_change_match_second(self):
        self.setup_mnemonic_nopin_nopassphrase()

        multisig_out2 = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=self.node_ext1, address_n=[1, 1]),
                proto.HDNodePathType(node=self.node_ext2, address_n=[1, 1]),
                proto.HDNodePathType(node=self.node_int, address_n=[1, 1])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        out1 = proto.TxOutputType(
            address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR',
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        out2 = proto.TxOutputType(
            address_n=[0x80000000 | 45, 0, 1, 1],
            multisig=multisig_out2,
            amount=44000000,
            script_type=proto.OutputScriptType.PAYTOMULTISIG)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp2, change=2))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp2,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022027cd3f397e006922a45978dffde57ad87fca656372526c1c494726c9dd216d7502206674ad0281f4210d32b37da1651921750f8c66c1e6d2b69c8909b701f602901a014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b500483045022100b24ca91c00574e1ed3d7370a4cdc52f004040ea308d18977450bc428477eb62002203e1be7e1a990a29c019202a5f9631dd7a94d603f8ca77834740b3be814718172014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914a13fc6db7be0606fb301567d90c9f89d05cd3a1b8700000000'

    # inputs match, change mismatches (second tries to be change but isn't)
    def test_multisig_mismatch_change(self):
        self.setup_mnemonic_nopin_nopassphrase()

        multisig_out2 = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_int, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_ext3, address_n=[1, 0])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        out1 = proto.TxOutputType(
            address='2N2aFoogGntQFFwdUVPfRmutXD22ThcNTsR',
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        out2 = proto.TxOutputType(
            address_n=[0x80000000 | 45, 0, 1, 0],
            multisig=multisig_out2,
            amount=44000000,
            script_type=proto.OutputScriptType.PAYTOMULTISIG)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp2))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp2,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b40047304402205a647596f2ba4746a07dbcb8c3efed1ccbe3b29212ffe6493a8763c0e7227ff302205c7897deaa1183fea95a6b6b97c00c7460aa0219413c7329fc624b98d366ef21014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b500483045022100fcc5b14240541914824c79c1f1d760cf9b61d2802c99ee1c4d3b449fa7b2fca502206e368c03813ef0a4b2ac32a6e5ea6ac52b0f6deb9dbf0c45198f1d3abcafc7f0014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a9146169c87e30105747aafd636bfd35bc9e3a5e13ea8700000000'

    # inputs mismatch, change matches with first input
    def test_multisig_mismatch_inputs(self):
        self.setup_mnemonic_nopin_nopassphrase()

        multisig_out1 = proto.MultisigRedeemScriptType(
            pubkeys=[
                proto.HDNodePathType(node=self.node_ext2, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_ext1, address_n=[1, 0]),
                proto.HDNodePathType(node=self.node_int, address_n=[1, 0])
            ],
            signatures=[b'', b'', b''],
            m=2,
        )

        out1 = proto.TxOutputType(
            address_n=[0x80000000 | 45, 0, 1, 0],
            multisig=multisig_out1,
            amount=40000000,
            script_type=proto.OutputScriptType.PAYTOMULTISIG)

        out2 = proto.TxOutputType(
            address='2NFJjQcU8mw4Z3ywpbek8HL1VoJ27GDrkHw',
            amount=65000000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses(
                self._responses(self.inp1, self.inp3))
            (_, serialized_tx) = self.client.sign_tx('Testnet', [
                self.inp1,
                self.inp3,
            ], [
                out1,
                out2,
            ])

        assert hexlify(
            serialized_tx
        ) == b'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100b7f49a255464bc69a5ea576bc5512084561d527d6cb2cd056cfa6350c51c21a8022017bb0b4eeb4dfd28646c234b3c7c49e535378675caa60b83bbdc629baeb94d28014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c21038c124bfafc58ba5de8f3e2200ad904e11b66a1ffafd0ceb2ea26da187d68e02853aeffffffff39f756d82082b580b0d69ae8798ff10a981820ccfe1ab149a708a37bc26d94b000000000b500483045022100a9ca27e9943ba7bfbf5b654f38982d62cf2cb82c0b99156ab739b472e31cd580022074b564cf50ad8078bbae89b86af8e31a098eddc61b1a91697ea9b8c52acece7d014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103b6321a1194e5cc47b6b7edc3f67a096e6f71ccb72440f84f390b6e98df0ea8ec21025b464f5a3068dce6dbdbd30c099e9e9e213967db0e0add273d386ba1d767bbe753aeffffffff02005a62020000000017a914705d4f1d91c05ee5bde07e8e81fe878c2a2d48a68740d2df030000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000'
    def test_send_multisig_2(self):
        self.setup_mnemonic_allallall()
        self.client.set_tx_api(TxApiTestnet)
        nodes = [
            self.client.get_public_node(parse_path("999'/1'/%d'" % index))
            for index in range(1, 4)
        ]
        multisig = proto.MultisigRedeemScriptType(
            pubkeys=list(
                map(
                    lambda n: proto.HDNodePathType(node=deserialize(n.xpub),
                                                   address_n=[2, 1]), nodes)),
            signatures=[b'', b'', b''],
            m=2,
        )

        inp1 = proto.TxInputType(
            address_n=parse_path("999'/1'/2'/2/1"),
            prev_hash=unhexlify(
                'f41cbedd8becee05a830f418d13aa665125464547db5c7a6cd28f21639fe1228'
            ),
            prev_index=0,
            script_type=proto.InputScriptType.SPENDWITNESS,
            multisig=multisig,
            amount=1605000)

        out1 = proto.TxOutputType(
            address=
            'tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z',
            amount=1604000,
            script_type=proto.OutputScriptType.PAYTOADDRESS)

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures1, _) = self.client.sign_tx('Testnet', [inp1], [out1])
            # store signature
            inp1.multisig.signatures[1] = signatures1[0]
            # sign with first key
            inp1.address_n[2] = 0x80000001
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures2,
             serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1])

        # c9348040bbc2024e12dcb4a0b4806b0398646b91acf314da028c3f03dd0179fc
        assert hexlify(
            serialized_tx
        ) == b'010000000001012812fe3916f228cda6c7b57d5464541265a63ad118f430a805eeec8bddbe1cf40000000000ffffffff01a0791800000000002200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a10400483045022100ed4a2a483f65888a1f3c705ce602d0a2d49e1de07c135fe3ffc1d434ed8df7cc02201fdfae3cab18cce2bb45b4951524e59c531a545d8d4130744724a1da747ffed60147304402202aa1ea471f5bf86cd817fa8def692afc93948604eb9d81b3e8f79a88e5cd313902201005f28a55f309021f86100c37e22f8f2aff72d11e6ebbb81e37e34faa22557d016952210344dedfd45a83764a830caa704e1d08e72a7fca35e05567bf1bc055381bf5ca3b21026a56ffbb409323325e6ad1da94793affc1fe7783579ed0bdb19361c723414a702103b6ef0db28a5bf481c4d89b3b48208765de1bee59351e86134c8c8167406101d153ae00000000'
    def test_send_multisig_3_change(self):
        self.setup_mnemonic_allallall()
        self.client.set_tx_api(TxApiTestnet)
        nodes = [
            self.client.get_public_node(parse_path("999'/1'/%d'" % index))
            for index in range(1, 4)
        ]
        multisig = proto.MultisigRedeemScriptType(
            pubkeys=list(
                map(
                    lambda n: proto.HDNodePathType(node=deserialize(n.xpub),
                                                   address_n=[2, 0]), nodes)),
            signatures=[b'', b'', b''],
            m=2,
        )
        multisig2 = proto.MultisigRedeemScriptType(
            pubkeys=list(
                map(
                    lambda n: proto.HDNodePathType(node=deserialize(n.xpub),
                                                   address_n=[1, 1]), nodes)),
            signatures=[b'', b'', b''],
            m=2,
        )

        inp1 = proto.TxInputType(
            address_n=parse_path("999'/1'/1'/2/0"),
            prev_hash=unhexlify(
                'c9348040bbc2024e12dcb4a0b4806b0398646b91acf314da028c3f03dd0179fc'
            ),
            prev_index=0,
            script_type=proto.InputScriptType.SPENDWITNESS,
            multisig=multisig,
            amount=1604000)

        out1 = proto.TxOutputType(
            address_n=parse_path("999'/1'/1'/1/1"),
            amount=1603000,
            multisig=multisig2,
            script_type=proto.OutputScriptType.PAYTOP2SHWITNESS)

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures1, _) = self.client.sign_tx('Testnet', [inp1], [out1])
            # store signature
            inp1.multisig.signatures[0] = signatures1[0]
            # sign with third key
            inp1.address_n[2] = 0x80000003
            out1.address_n[2] = 0x80000003
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures2,
             serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1])

        # 31bc1c88ce6ae337a6b3057a16d5bad0b561ad1dfc047d0a7fbb8814668f91e5
        assert hexlify(
            serialized_tx
        ) == b'01000000000101fc7901dd033f8c02da14f3ac916b6498036b80b4a0b4dc124e02c2bb408034c90000000000ffffffff01b87518000000000017a9149ac59a48a4403831984629e6cef243874295e25f8704004830450221008c02ac568cb1acabf7a1f2004bd20f2af0f624662199d962e7fdadf55448f8c3022073da0769479fe983dcca7317e2280cbdf3add9a4380e927b2c525faf689ae96701473044022067cbd98e86f22d2d6f4cd82926b28a51900a331aeb2c7b38c71ce2988e08af6102203c3cbf04944439bd898a16f3ca7526895329c3169cf9a81992242f23a79208a20169522102cea51fb0aa19715665ac367725c4ea0bac2b7f3371df16e58c3538b788260fe12102cd496a185be36b20cf1400d296a221fd05bfc46adc04e7ba4ebd8f47f037ae682103caaabaa9876547cf014dcb93a73af348e32af5cbf29d436b9fa922232432f03153ae00000000'
    def test_send_multisig_4_change(self):
        self.setup_mnemonic_allallall()
        self.client.set_tx_api(TxApiTestnet)
        nodes = [
            self.client.get_public_node(parse_path("999'/1'/%d'" % index))
            for index in range(1, 4)
        ]
        multisig = proto.MultisigRedeemScriptType(
            pubkeys=list(
                map(
                    lambda n: proto.HDNodePathType(node=deserialize(n.xpub),
                                                   address_n=[1, 1]), nodes)),
            signatures=[b'', b'', b''],
            m=2,
        )
        multisig2 = proto.MultisigRedeemScriptType(
            pubkeys=list(
                map(
                    lambda n: proto.HDNodePathType(node=deserialize(n.xpub),
                                                   address_n=[1, 2]), nodes)),
            signatures=[b'', b'', b''],
            m=2,
        )

        inp1 = proto.TxInputType(
            address_n=parse_path("999'/1'/1'/1/1"),
            prev_hash=unhexlify(
                '31bc1c88ce6ae337a6b3057a16d5bad0b561ad1dfc047d0a7fbb8814668f91e5'
            ),
            prev_index=0,
            script_type=proto.InputScriptType.SPENDP2SHWITNESS,
            multisig=multisig,
            amount=1603000)

        out1 = proto.TxOutputType(
            address_n=parse_path("999'/1'/1'/1/2"),
            amount=1602000,
            multisig=multisig2,
            script_type=proto.OutputScriptType.PAYTOWITNESS)

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures1, _) = self.client.sign_tx('Testnet', [inp1], [out1])
            # store signature
            inp1.multisig.signatures[0] = signatures1[0]
            # sign with third key
            inp1.address_n[2] = 0x80000003
            out1.address_n[2] = 0x80000003
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
            ])
            (signatures2,
             serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1])

        # c0bf56060a109624b4635222696d94a7d533cacea1b3f8245417a4348c045829
        assert hexlify(
            serialized_tx
        ) == b'01000000000101e5918f661488bb7f0a7d04fc1dad61b5d0bad5167a05b3a637e36ace881cbc310000000023220020a4bd311ad9f0c99fd00dae2073c708f37999d4fb25bc8a39b9ccfbb43917c570ffffffff01d071180000000000220020041c9609b4d7003148fb714a8e2a1002fcf582cc2867d331e787d1658f0eee2e0400473044022033845a1a36f30acfda8bc29834bdb7b2ac6214968c749773ccef8fb097b3815c022060c7d56cf6e8d6f83ec3b3dfcf3e0bfecc9f3c9dba910ab27605763c3e2a53a101483045022100c44552abccdea92ae9af4bacf30788d78a9bd24729f1f3d8cef422f2a71ba89702200969d28cc9ea49bcb3113979b90050a44d0f41122fce5c4379da31bf66e6157f01695221022af8e5bbb3091ae655d64f2444776eb9bd4ab750dbbec1f50a8a779bef97e19821029d7f2e3cdcd413b7423a7f5ffbdce524c177e3bf995b4b9d2b50c291e661d4902102663d3ba942719a6ef3a25427c908e653fba13056388b989cdd912e82cd68baa253ae00000000'