def test_send_multisig_3_change(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) nodes = [self.client.get_public_node(self.client.expand_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=self.client.expand_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=self.client.expand_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.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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'01000000000101fc7901dd033f8c02da14f3ac916b6498036b80b4a0b4dc124e02c2bb408034c90000000000ffffffff01b87518000000000017a914a8655acf68f785125561158b0f4db9b5d0044047870400473044022057b571986c07f8ccb231811334ad06ee6f87b722495def2e9511c1da46f3433202207b6e95bdd99e7fc7d319486437cb930d40a4af3cd753c4cb960b330badbf7f35014730440220517ecc6d0a2544276921d8fc2077aec4285ab83b1b21f5eb73cdb6187a0583e4022043fb5ab942f8981c04a54c66a57c4d291fad8514d4a8afea09f01f2db7a8f32901695221038e81669c085a5846e68e03875113ddb339ecbb7cb11376d4163bca5dc2e2a0c1210348c5c3be9f0e6cf1954ded1c0475beccc4d26aaa9d0cce2dd902538ff1018a112103931140ebe0fbbb7df0be04ed032a54e9589e30339ba7bbb8b0b71b15df1294da53ae00000000'
def test_send_multisig_4_change(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) nodes = [self.client.get_public_node(self.client.expand_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=self.client.expand_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=self.client.expand_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.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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'01000000000101e5918f661488bb7f0a7d04fc1dad61b5d0bad5167a05b3a637e36ace881cbc3100000000232200205b9824093eaf5cdcf8247c00dc0b557a7720957828fcde8384ac11f80a91f403ffffffff01d071180000000000220020e77caf5fbef07b1e461475c02afd4aed877693263d69c81e14617304349b629a040047304402204832553b0da1009da496881e58e8e2e41010cfe5c0161623048093f1b1a817b7022020dad8bf887acf574af80bfe4b39cd24e95019fd5e6b8ae967471e21ddc67354014830450221009e5d60847e7275edcf4619ed8ee462c56a042eef75d17da2d44e6b13d78e50e50220665195492900ef87a5eb8a924fa0ac9afc4fc75ca704ff356dc3a213979970c80169522103f4040006e3561b3e76c6d4113225c84748ab9d55ffd23f9578ab4c18fb0c3b9721020975f2e6922897ff6b80da6412a8d6ebd67e33c9611d081656a53ef967964e5021026b0546f23a6ce6b756c2c30b4176ce6f1c3268744f7aca82668d5116c4f764e453ae00000000'
def test_show_multisig_3(self, client): nodes = [ btc.get_public_node(client, parse_path("999'/1'/%d'" % index)).node for index in range(1, 4) ] multisig1 = proto.MultisigRedeemScriptType( nodes=nodes, address_n=[2, 0], signatures=[b"", b"", b""], m=2 ) multisig2 = proto.MultisigRedeemScriptType( nodes=nodes, address_n=[2, 1], signatures=[b"", b"", b""], m=2 ) for i in [1, 2, 3]: assert ( btc.get_address( client, "Testnet", parse_path("999'/1'/%d'/2/1" % i), False, multisig2, script_type=proto.InputScriptType.SPENDWITNESS, ) == "tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy" ) assert ( btc.get_address( client, "Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDWITNESS, ) == "tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z" )
def test_show_multisig_3(client: Client): nodes = [ btc.get_public_node(client, parse_path(f"m/84h/1h/{index}h"), coin_name="Testnet").node for index in range(1, 4) ] multisig1 = messages.MultisigRedeemScriptType(nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2) multisig2 = messages.MultisigRedeemScriptType(nodes=nodes, address_n=[0, 1], signatures=[b"", b"", b""], m=2) for i in [1, 2, 3]: assert (btc.get_address( client, "Testnet", parse_path(f"m/84h/1h/{i}h/0/1"), False, multisig2, script_type=messages.InputScriptType.SPENDWITNESS, ) == "tb1qauuv4e2pwjkr4ws5f8p20hu562jlqpe5h74whxqrwf7pufsgzcms9y8set") assert (btc.get_address( client, "Testnet", parse_path(f"m/84h/1h/{i}h/0/0"), False, multisig1, script_type=messages.InputScriptType.SPENDWITNESS, ) == "tb1qgvn67p4twmpqhs8c39tukmu9geamtf7x0z3flwf9rrw4ff3h6d2qt0czq3")
def test_attack_ownership_id(client: Client): # Multisig with global suffix specification. # Use account numbers 1, 2 and 3 to create a valid multisig, # but not containing the keys from account 0 used below. nodes = [ btc.get_public_node(client, parse_path(f"m/84h/0h/{i}h")).node for i in range(1, 4) ] multisig1 = messages.MultisigRedeemScriptType( nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2 ) # Multisig with per-node suffix specification. node = btc.get_public_node( client, parse_path("m/84h/0h/0h/0"), coin_name="Bitcoin" ).node multisig2 = messages.MultisigRedeemScriptType( pubkeys=[ messages.HDNodePathType(node=node, address_n=[1]), messages.HDNodePathType(node=node, address_n=[2]), messages.HDNodePathType(node=node, address_n=[3]), ], signatures=[b"", b"", b""], m=2, ) for multisig in (multisig1, multisig2): with pytest.raises(TrezorFailure): btc.get_ownership_id( client, "Bitcoin", parse_path("m/84h/0h/0h/0/0"), multisig=multisig, script_type=messages.InputScriptType.SPENDWITNESS, )
def test_multisig_missing(self, client, show_display): # Multisig with global suffix specification. # Use account numbers 1, 2 and 3 to create a valid multisig, # but not containing the keys from account 0 used below. nodes = [ btc.get_public_node(client, parse_path(f"44'/0'/{i}'")).node for i in range(1, 4) ] multisig1 = messages.MultisigRedeemScriptType( nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2) # Multisig with per-node suffix specification. node = btc.get_public_node(client, parse_path("44h/0h/0h/0"), coin_name="Bitcoin").node multisig2 = messages.MultisigRedeemScriptType( pubkeys=[ messages.HDNodePathType(node=node, address_n=[1]), messages.HDNodePathType(node=node, address_n=[2]), messages.HDNodePathType(node=node, address_n=[3]), ], signatures=[b"", b"", b""], m=2, ) for multisig in (multisig1, multisig2): with pytest.raises(TrezorFailure): btc.get_address( client, "Bitcoin", parse_path("44'/0'/0'/0/0"), show_display=show_display, multisig=multisig, )
def test_show_multisig_3(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, 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 ( btc.get_address( self.client, "Testnet", parse_path("999'/1'/%d'/2/1" % i), False, multisig2, script_type=proto.InputScriptType.SPENDWITNESS, ) == "tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy" ) assert ( btc.get_address( self.client, "Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDWITNESS, ) == "tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z" )
def getmultisig(chain, nr, signatures=[b"", b"", b""], xpubs=xpubs): return proto.MultisigRedeemScriptType( nodes=[deserialize(xpub) for xpub in xpubs], address_n=[chain, nr], signatures=signatures, m=2, )
def getmultisig(chain, nr, xpubs): return messages.MultisigRedeemScriptType( nodes=[bip32.deserialize(xpub) for xpub in xpubs], address_n=[chain, nr], signatures=[b"", b"", b""], m=2, )
def test_show_multisig_3(self): self.setup_mnemonic_allallall() nodes = map( lambda index: btc.get_public_node( self.client, parse_path("999'/1'/%d'" % index)), range(1, 4), ) multisig1 = proto.MultisigRedeemScriptType( nodes=[bip32.deserialize(n.xpub) for n in nodes], address_n=[2, 0], 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 (btc.get_address( self.client, "Testnet", parse_path("999'/1'/%d'/2/0" % i), False, multisig1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) == "2N2MxyAfifVhb3AMagisxaj3uij8bfXqf4Y")
def test_show_multisig_3(client): node = btc.get_public_node( client, tools.parse_path("45h/0/0"), coin_name="Bitcoin" ).node multisig = messages.MultisigRedeemScriptType( pubkeys=[ messages.HDNodePathType(node=node, address_n=[1]), messages.HDNodePathType(node=node, address_n=[2]), messages.HDNodePathType(node=node, address_n=[3]), ], signatures=[b"", b"", b""], m=2, ) for i in [1, 2, 3]: assert ( btc.get_address( client, "Bitcoin", tools.parse_path(f"45h/0/0/{i}"), show_display=True, multisig=multisig, script_type=messages.InputScriptType.SPENDMULTISIG, ) == "35Q3tgZZfr9GhVpaqz7fbDK8WXV1V1KxfD" )
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'0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000'
def test_show_multisig_3(client): node = btc.get_public_node( client, tools.parse_path("44h/0h/0h/0"), coin_name="Bitcoin" ).node multisig = messages.MultisigRedeemScriptType( pubkeys=[ messages.HDNodePathType(node=node, address_n=[1]), messages.HDNodePathType(node=node, address_n=[2]), messages.HDNodePathType(node=node, address_n=[3]), ], signatures=[b"", b"", b""], m=2, ) for i in [1, 2, 3]: assert ( btc.get_address( client, "Bitcoin", tools.parse_path(f"44h/0h/0h/0/{i}"), show_display=True, multisig=multisig, ) == "36AvLYugbb9CsN8sQ5k7kJ2diWF54msYKs" )
def test_15_of_15(self): self.setup_mnemonic_nopin_nopassphrase() """ pubs = [] for x in range(15): pubs.append(self.client.get_public_node([x]).node.public_key.hex())) """ # xpub: # print(bip32.serialize(self.client.get_public_node([]).node)) # xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy node = bip32.deserialize( "xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy" ) 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=bytes.fromhex( "6189e3febb5a21cee8b725aa1ef04ffce7e609448446d3a8d6f483c634ef5315" ), prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) with self.client: sig, serialized_tx = btc.sign_tx( self.client, "Bitcoin", [inp1], [out1], prev_txes=TX_API ) signatures[x] = sig[0] # Accepted as tx id dd320786d1f58c095be0509dc56b277b6de8f2fb5517f519c6e6708414e3300b assert ( serialized_tx.hex() == "01000000011553ef34c683f4d6a8d346844409e6e7fc4ff01eaa25b7e8ce215abbfee3896101000000fd43060048304502210098e23085ad7282de988bf98afa1e9add9c9830009132f8902a9fa4624d5dc98b0220733216e70ab67791aa64be5c83d2050cb4ed9ff7eda2a1acc35da024d2ab2a670147304402201f8c11fb6e90fd616e484986e9451929797eba039882a9abcc203210948060b9022044da031530de7d9747d3c5a8e7cec04b04b7af495c9120b854ce7362af7fa05a01483045022100ea67c70186acef019bdf1551881bf38e6f88186501b64d3a756a2ce18e4ba18002201c35110325653e21e448b60053a4b5dda46b61096faf701a1faca61fcde91f00014730440220315598992f156d2f9d7b4275395fa067aa61ea95829fa17730885c86df4de70d02203eda9ade1656e2198c668603b17e197acb0969ed183ab0841303ea261205618901473044022060fdd6621edde9b8cf6776bc4eef26ace9b57514d725b7214ba11d333520a30e022044c30744f94484aec0f896233c5613a3256878ec0379f566226906b6d1b6061401483045022100b1d907e3574f60f7834c7e9f2e367998ce0461dad7d742d84ef8917d713f41f902203b3ac54f7bb2f7fb8685f582d2a94f7213a37cb508acffe29090cc06ae01588b01483045022100e3bf90ff3ad6395e42f46002f253f94ca0e8ffaa0620f2ceb4fa21493abdca4d02201d4c28b10b740bb2dc4b3695b4205c18f8c0dad2bb69540eb8a36576463cd5280147304402202cfaf9fab7dc1c9f0c3c23bd46bd6d5cea0664d914139fc9add80766ce998808022012db2802c07853e4cbe147afdf0b47e60bdcbcd31f9df19e04c177ed9aa66c6d0147304402207cbc2d83f351eee5ee91df26bb0c7e1cb07fe328cbbcdb0bb9656d37922c497302201b3435d4c71ffd1b34d45892f2a487bd79c8c7f57cc04373287642bb9610cb840147304402202dc3eab30ccb06553703e794212f43ee9a659f5e787a8374e9ea0bf6de0def7402201a70e970c21a807783313ed102bf4f0a3406ac7c84f94bc8194c5e209464d7230147304402206b04530c190c46a879d7771a6ad53acd33547e0d7fd320d5ad0b5b1fdeb5d4c202207b812be81c3419daadc942cca0c55aa32c7759fa7566c6dc35f030ca87a1c5be01483045022100ce523dddd6eef73d5ae7c44c870466e1ac5a7a77d43475e8def024af68977a1e022028be0276435bfa2ea887d6cf89fa829f96c1c7a55edc57bb3fd667d523fd3bf601473044022019410b20ebcd8eb3ee7ec1eff6bf0f9cbfaea82116811c61f3cf24af7e4434b1022009e5823f3349f695be09ae40754185300d8442a22715ddb5ffa17c4213140e7201483045022100964ef26a9074c3cdafffcfbe4bd445933f8c842ba11fd887922adcf7fabe0c82022023055d94c75ab223c767fbaa825c917e9beecbc7d5758cccf20d886c63d4b72a0147304402207aa3a98197697d258a8baae681f0b4c0ee682982f4205534e6c95a37dabaddd60220517a7ed5c03da2f242e17ccfdae0d81d6f454d7f9ea931fc62df6c0eab922186014d01025f21023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43d210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a621038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e32103477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a79022103fe91eca10602d7dad4c9dab2b2a0858f71e25a219a6940749ce7a48118480dae210234716c01c2dd03fa7ee302705e2b8fbd1311895d94b1dca15e62eedea9b0968f210341fb2ead334952cf60f4481ba435c4693d0be649be01d2cfe9b02018e483e7bd2102dad8b2bce360a705c16e74a50a36459b4f8f4b78f9cd67def29d54ef6f7c7cf9210222dbe3f5f197a34a1d50e2cbe2a1085cac2d605c9e176f9a240e0fd0c669330d2103fb41afab56c9cdb013fda63d777d4938ddc3cb2ad939712da688e3ed333f95982102435f177646bdc717cb3211bf46656ca7e8d642726144778c9ce816b8b8c36ccf2102158d8e20095364031d923c7e9f7f08a14b1be1ddee21fe1a5431168e31345e5521026259794892428ca0818c8fb61d2d459ddfe20e57f50803c7295e6f4e2f5586652102815f910a8689151db627e6e262e0a2075ad5ec2993a6bc1b876a9d420923d681210318f54647f645ff01bd49fedc0219343a6a22d3ea3180a3c3d3097e4b888a8db45faeffffffff0110270000000000001976a9144a087d89f8ad16ca029c675b037c02fd1c5f9aec88ac00000000" )
def test_signtx_multisig(client, paths, address_index): pubs = [ messages.HDNodePathType( node=btc.get_public_node( client, parse_path(path), coin_name="Bitcoin" ).node, address_n=address_index, ) for path in paths ] signatures = [b""] * 3 multisig = messages.MultisigRedeemScriptType( pubkeys=pubs, signatures=signatures, m=2 ) out1 = messages.TxOutputType( address="17kTB7qSk3MupQxWdiv5ZU3zcrZc2Azes1", amount=10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) inp1 = messages.TxInputType( address_n=parse_path(paths[0]) + address_index, amount=20000, prev_hash=TXHASH_6189e3, prev_index=1, script_type=messages.InputScriptType.SPENDMULTISIG, multisig=multisig, ) sig, _ = btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET) assert sig[0]
def test_multisig_change_match_second(client): multisig_out2 = messages.MultisigRedeemScriptType( nodes=[NODE_EXT1, NODE_EXT2, NODE_INT], address_n=[1, 1], signatures=[b"", b"", b""], m=2, ) out1 = messages.TxOutputType( address="3B23k4kFBRtu49zvpG3Z9xuFzfpHvxBcwt", amount=40000000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address_n=[H_(45), 0, 1, 1], multisig=multisig_out2, amount=44000000, script_type=messages.OutputScriptType.PAYTOMULTISIG, ) with client: client.set_expected_responses(_responses(INP1, INP2, change=2)) _, serialized_tx = btc.sign_tx( client, "Bitcoin", [INP1, INP2], [out1, out2], prev_txes=TX_API, ) assert ( serialized_tx.hex() == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" )
def create_multisig(index, address, signatures=None): address_n = parse_path(address) multisig = proto.MultisigRedeemScriptType( nodes=nodes, address_n=address_n, signatures=signatures, m=2 ) return (paths[index] + address_n), multisig
def test_show_multisig_3(self, client): nodes = [ btc.get_public_node( client, parse_path(f"49'/1'/{i}'"), coin_name="Testnet" ).node for i in range(1, 4) ] multisig1 = proto.MultisigRedeemScriptType( nodes=nodes, address_n=[0, 7], 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 ( btc.get_address( client, "Testnet", parse_path(f"49'/1'/{i}'/0/7"), False, multisig1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) == "2MwuUwUzPG17wiKQpfXmzfxJEoe7RXZDRad" )
def test_multisig_mismatch_inputs(self, client): multisig_out1 = proto.MultisigRedeemScriptType( nodes=[self.node_ext2, self.node_ext1, self.node_int], address_n=[1, 0], signatures=[b"", b"", b""], m=2, ) out1 = proto.TxOutputType( address_n=[H_(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 client: client.set_expected_responses(self._responses(self.inp1, self.inp3)) _, serialized_tx = btc.sign_tx( client, "Testnet", [self.inp1, self.inp3], [out1, out2], prev_txes=TX_API, ) assert ( serialized_tx.hex() == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100d907b9339951c96ef4515ef7aff8b3c28c4c8c5875d7421aa1de9f3a94e3508302205cdc311a6c91dfbb74f1a9a940a994a65dbfb0cf6dedcaaaeee839e0b8fd016d014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff39f756d82082b580b0d69ae8798ff10a981820ccfe1ab149a708a37bc26d94b000000000b500483045022100fdad4a47d15f47cc364fe0cbed11b1ced1f9ef210bc1bd413ec4384f630c63720220752e4f09ea4e5e6623f5ebe89b3983ec6e5702f63f9bce696f10b2d594d23532014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103b6321a1194e5cc47b6b7edc3f67a096e6f71ccb72440f84f390b6e98df0ea8ec2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948740d2df030000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" )
def test_multisig_mismatch_change(self, client): multisig_out2 = proto.MultisigRedeemScriptType( nodes=[self.node_ext1, self.node_int, 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=[H_(45), 0, 1, 0], multisig=multisig_out2, amount=44000000, script_type=proto.OutputScriptType.PAYTOMULTISIG, ) with client: client.set_expected_responses(self._responses(self.inp1, self.inp2)) _, serialized_tx = btc.sign_tx( client, "Testnet", [self.inp1, self.inp2], [out1, out2], prev_txes=TX_API, ) assert ( serialized_tx.hex() == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b40047304402207f9992cc0230527faf54ec6bd233307db82bc8fac039dcee418bc6feb4e96a3a02206bb4cb157ad27c123277328a877572563a45d70b844d9ab07cc42238112f8c2a014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b400473044022078a41bfa87d72d6ba810d84bf568b5a29acf8b851ba6c3a8dbff079b34a7feb0022037b770c776db0b6c883c38a684a121b90a59ed1958774cbf64de70e53e29639f014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914e6a3e2fbadb7f559f8d20c46aceae78c96fcf1d18700000000" )
def test_missing_pubkey(self, client): node = btc.get_public_node( client, parse_path("48h/0h/1h/0h/0"), coin_name="Bitcoin" ).node 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=parse_path("48h/0h/1h/0h/0/10"), amount=100000, 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(TrezorFailure, match="Pubkey not found in multisig script"): btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API)
def test_missing_pubkey(self, client): 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(TrezorFailure, match="Pubkey not found in multisig script"): btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API)
def getmultisig(chain, nr, xpubs, signatures=[b"", b"", b""]): return proto.MultisigRedeemScriptType( pubkeys=[ proto.HDNodePathType(node=bip32.deserialize(xpub), address_n=[chain, nr]) for xpub in xpubs ], signatures=signatures, m=2, )
def create_multisig(index, address, signatures=None): address_n = parse_path(address) multisig = proto.MultisigRedeemScriptType( pubkeys=[proto.HDNodePathType(node=node, address_n=address_n) for node in nodes], signatures=signatures, m=2, ) return (paths[index] + address_n), multisig
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) try: self.client.sign_tx('Bitcoin', [ inp1, ], [ out1, ]) except CallException as exc: assert exc.args[0] == proto.FailureType.DataError assert exc.args[1] == 'Pubkey not found in multisig script' else: assert False # exception expected
def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs): return proto.MultisigRedeemScriptType( pubkeys=list( map( lambda xpub: proto.HDNodePathType( node=deserialize(xpub), address_n=[chain, nr]), xpubs)), signatures=signatures, m=2, )
def test_send_multisig_1(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) nodes = [self.client.get_public_node(self.client.expand_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=self.client.expand_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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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'01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1ffffffff01887d180000000000220020c5f4a0a4ea7c0392efe0a9670a73264cffa90b19107cd8a8e9750ff93c77fdfb0400483045022100a9b681f324ff4cf419ab06820d07248cc4e359c77334bf448ae7b5cdf3995ddf022039811f91f55b602368b4ba08a217b82bfd62d1a97dc635deb1457e7cfcc1550b0147304402201ad86a795c3d26881d696fa0a0619c24c4d505718132a82965cc2a609c9d8798022067cd490ce1366cde77e307ced5b13040bbc04991619ea6f49e06cece9a83268b01695221038e81669c085a5846e68e03875113ddb339ecbb7cb11376d4163bca5dc2e2a0c1210348c5c3be9f0e6cf1954ded1c0475beccc4d26aaa9d0cce2dd902538ff1018a112103931140ebe0fbbb7df0be04ed032a54e9589e30339ba7bbb8b0b71b15df1294da53ae00000000'
def test_send_multisig_2(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) nodes = [self.client.get_public_node(self.client.expand_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=self.client.expand_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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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'010000000001012812fe3916f228cda6c7b57d5464541265a63ad118f430a805eeec8bddbe1cf40000000000ffffffff01a0791800000000002200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a10400483045022100cc97f21a7cabc543a9b4ac52424e8f7e420622903f2417a1c08a6af68058ec4a02200baca0b222fc825078d94e8e1b55f174c4828bed16697e4281cda2a0c799eecf01473044022009b8058dc30fa7a13310dd8f1a99c4341c4cd95f771c5a41c4381f956e2344c102205e829c560c0184fd4b4db8971f99711e2a87409afa4df0840b4f12a87b2c8afc0169522102740ec30d0af8591a0dd4a3e3b274e57f3f73bdc0638a9603f9ee6ade0475ba57210311aada919974e882abf0c67b5c0fba00000b26997312ca00345027d22359443021029382591271a79d4b12365fa27c67fad3753150d8eaa987e5a12dc5ba1bb2fa1653ae00000000'
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(self.client.expand_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=self.client.expand_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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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'01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1ffffffff01887d1800000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac040047304402205b44c20cf2681690edaaf7cd2e30d4704124dd8b7eb1fb7f459d3906c3c374a602205ca359b6544ce2c101c979899c782f7d141c3b0454ea69202b1fb4c09d3b715701473044022052fafa64022554ae436dbf781e550bf0d326fef31eea1438350b3ff1940a180102202851bd19203b7fe8582a9ef52e82aa9f61cd52d4bcedfe6dcc0cf782468e6a8e01695221038e81669c085a5846e68e03875113ddb339ecbb7cb11376d4163bca5dc2e2a0c1210348c5c3be9f0e6cf1954ded1c0475beccc4d26aaa9d0cce2dd902538ff1018a112103931140ebe0fbbb7df0be04ed032a54e9589e30339ba7bbb8b0b71b15df1294da53ae00000000'
def test_send_bch_multisig_wrongchange(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiBitcoinCash) xpubs = [] for n in map(lambda index: self.client.get_public_node(self.client.expand_path("44'/145'/" + str(index) + "'")), range(1, 4)): xpubs.append(n.xpub) def getmultisig(chain, nr, signatures=[b'', b'', b''], xpubs=xpubs): return proto.MultisigRedeemScriptType( pubkeys=list(map(lambda xpub: proto.HDNodePathType(node=deserialize(xpub), address_n=[chain, nr]), xpubs)), signatures=signatures, m=2, ) correcthorse = proto.HDNodeType( depth=1, fingerprint=0, child_num=0, chain_code=unhexlify('0000000000000000000000000000000000000000000000000000000000000000'), public_key=unhexlify('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71')) sig = unhexlify(b'304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae') inp1 = proto.TxInputType( address_n=self.client.expand_path("44'/145'/1'/1/0"), multisig=getmultisig(1, 0, [b'', sig, b'']), # 3CPtPpL5mGAPdxUeUDfm2RNdWoSN9dKpXE amount=24000, prev_hash=unhexlify('f68caf10df12d5b07a34601d88fa6856c6edcbf4d05ebef3486510ae1c293d5f'), prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, ) out1 = proto.TxOutputType( address_n=self.client.expand_path("44'/145'/1'/1/1"), multisig=proto.MultisigRedeemScriptType( pubkeys=[proto.HDNodePathType(node=deserialize(xpubs[0]), address_n=[1, 1]), proto.HDNodePathType(node=correcthorse, address_n=[]), proto.HDNodePathType(node=correcthorse, address_n=[])], signatures=[b'', b'', b''], m=2, ), script_type=proto.OutputScriptType.PAYTOMULTISIG, amount=23000 ) 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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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.TXFINISHED), ]) (signatures1, serialized_tx) = self.client.sign_tx('Bcash', [inp1], [out1]) assert hexlify(signatures1[0]) == b'3044022052ccf022b3684ecce9f961ce8828387b97267c86bedf0ce16a24bf014e62e42c022035d315ddbeeef7ab3456bd09aed8b625ea58852216b60e4b84ba9f85827d305c' assert hexlify(serialized_tx) == b'01000000015f3d291cae106548f3be5ed0f4cbedc65668fa881d60347ab0d512df10af8cf601000000fc00473044022052ccf022b3684ecce9f961ce8828387b97267c86bedf0ce16a24bf014e62e42c022035d315ddbeeef7ab3456bd09aed8b625ea58852216b60e4b84ba9f85827d305c4147304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae414c69522103d62b2af2272bbd67cbe30eeaf4226c7f2d57d2a0ed1aab5ab736fb40bb2f5ffe21036d5e0d7ca3589465711eec91436249d7234d3a994c219024fc75cec98fc02ae221024f58378a69b68e89301a6ff882116e0fa35446ec9bfd86532eeb05941ec1f8c853aeffffffff01d85900000000000017a9140bb11de6558871f49fc241341992ece9986f7c5c8700000000'