def test_show_segwit(self): self.setup_mnemonic_allallall() assert self.client.get_address( "Testnet", parse_path("49'/1'/0'/0/0"), True, None, script_type=proto.InputScriptType.SPENDWITNESS ) == 'tb1qnkeww24u2z6q92n7exrn2zwsy8q3yhtw5v5gfn' assert self.client.get_address( "Testnet", parse_path("49'/1'/0'/1/0"), False, None, script_type=proto.InputScriptType.SPENDWITNESS ) == 'tb1qsf8mzqm4226t62acf4l383dz4f9j4vxjmefmck' assert self.client.get_address( "Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDWITNESS ) == 'tb1qa699g92dtfpwwmtcjq44rkcrm3dshhfrxyx97z' assert self.client.get_address( "Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS ) == 'n3GEpwQbivawYe9Hb6rfNsAdgn76qUJnuM'
def test_show_segwit(self): self.setup_mnemonic_allallall() assert self.client.get_address( "Testnet", parse_path("49'/1'/0'/1/0"), True, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS ) == '2MziCCH1NDzJtJxZ4apXhZ3TPoWycYqZA5v' assert self.client.get_address( "Testnet", parse_path("49'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS ) == '2N8xnYHWiPxw9e58HQ8eaXquhHRnCYq3hHD' assert self.client.get_address( "Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDP2SHWITNESS ) == '2NFmA5TjpCjasB2jnGSWrrSm4ThKwMyFm9E' assert self.client.get_address( "Testnet", parse_path("44'/1'/0'/0/0"), False, None, script_type=proto.InputScriptType.SPENDADDRESS ) == 'n3GEpwQbivawYe9Hb6rfNsAdgn76qUJnuM'
def test_send_p2sh_change(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=123456789, prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'), prev_index=0, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) out1 = proto.TxOutputType( address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC', amount=12300000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("49'/1'/0'/1/0"), script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, amount=123456789 - 11000 - 12300000, ) 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.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.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.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1, out2]) assert hexlify(serialized_tx) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014824fb1037552b4bd2bb84d7f13c5a2aa4b2ab0d2ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91451e29d52c5b62da357b34fdbec72b4a150a0fd398702483045022100fbb9dfbf0c9ab350bd8e0a3f19254d2a4afffb5b1169121bb81eb5feb2d9160602202c110061c86af375152085a0787d1efd5aab35e5345b20a3b4b4c4c991684fec012103fea49c7079e5de753d11cd49ac47938cc95fcb1a40cb50ee41cce82e2283c51900000000'
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'
def test_bch_multisig(self): self.setup_mnemonic_allallall() xpubs = [] for n in map( lambda index: self.client.get_public_node( parse_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=bip32.deserialize(xpub), address_n=[chain, nr]), xpubs)), signatures=signatures, m=2, ) for nr in range(1, 4): assert self.client.get_address( 'Bcash', parse_path("44'/145'/" + str(nr) + "'/0/0"), show_display=(nr == 1), multisig=getmultisig(0, 0) ) == 'bitcoincash:ppvepa7y0ek8p2f2gm4pmeatvxev9u2vmsfvj2ktxg' assert self.client.get_address( 'Bcash', parse_path("44'/145'/" + str(nr) + "'/1/0"), show_display=(nr == 1), multisig=getmultisig(1, 0) ) == 'bitcoincash:pr8hvff8m8hwrlg389mr4c40qjhf8zw6vulhlj3emm'
def test_send_p2sh_change(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=123456789, prev_hash=unhexlify( '20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337' ), prev_index=0, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) out1 = proto.TxOutputType( address='tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s', amount=12300000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("49'/1'/0'/1/0"), script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, amount=123456789 - 11000 - 12300000, ) 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.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.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.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1, out2]) assert hexlify( serialized_tx ) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014824fb1037552b4bd2bb84d7f13c5a2aa4b2ab0d2ffffffff02e0aebb00000000001600140099a7ecbd938ed1839f5f6bf6d50933c6db9d5c3df39f060000000017a91451e29d52c5b62da357b34fdbec72b4a150a0fd398702483045022100d95d31aad21f2a5210a2a984e1d039fdb24d0b46ac404d40715222eb43a7364d022029709b28a15162c9f2042529c0b872fd91bf7fccb57481a65a6dbccbb4e65a55012103fea49c7079e5de753d11cd49ac47938cc95fcb1a40cb50ee41cce82e2283c51900000000'
def test_send_native_change(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/0/0"), # tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s amount=12300000, prev_hash=unhexlify( '09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a' ), prev_index=0, script_type=proto.InputScriptType.SPENDWITNESS, ) out1 = proto.TxOutputType( address='2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp', amount=5000000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("49'/1'/0'/1/0"), script_type=proto.OutputScriptType.PAYTOWITNESS, amount=12300000 - 11000 - 5000000, ) 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.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.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.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1, out2]) assert hexlify( serialized_tx ) == b'010000000001018a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014824fb1037552b4bd2bb84d7f13c5a2aa4b2ab0d202473044022059b0adc1b30f8abed085b75cbe3144c01e40fd2e2d2622cc01c3488c202e160002200383f27e478784c3e93d9dcab9b1781a274c103244f64f4c7f74ac1540a7ef61012102d96aa150a2a60cc2c2c640816567945289feaadd68abeec410386846cb14147a00000000'
def test_bch(self): self.setup_mnemonic_allallall() assert self.client.get_address( 'Bcash', parse_path("44'/145'/0'/0/0") ) == 'bitcoincash:qp68396zpxkvcnqjtesk5fsa2kuw6ltresw9cjdlx0' assert self.client.get_address( 'Bcash', parse_path("44'/145'/0'/0/1") ) == 'bitcoincash:qpzk3hufhgl5tj3cgzefppjpe832mfv6tsrtlhdpae' assert self.client.get_address( 'Bcash', parse_path("44'/145'/0'/1/0") ) == 'bitcoincash:qpknzn0ltugd0475z3z6pscuazldvgtyqvurcqwxs6'
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_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'
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'
def test_send_p2sh(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=123456789, prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'), prev_index=0, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) out1 = proto.TxOutputType( address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC', amount=12300000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address='2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX', script_type=proto.OutputScriptType.PAYTOADDRESS, amount=123456789 - 11000 - 12300000, ) 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.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.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.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1, out2]) assert hexlify(serialized_tx) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014824fb1037552b4bd2bb84d7f13c5a2aa4b2ab0d2ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100fe67c24bcd8fc7ab544c66b744ecfc0ea5bca1950618d4659d890cb6d5273f9002202db1b67d63a6d34bd701d36c7f985bfd755962214787894ed23ce0559ed934c9012103fea49c7079e5de753d11cd49ac47938cc95fcb1a40cb50ee41cce82e2283c51900000000'
def test_send_p2sh(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=123456789, prev_hash=unhexlify( '20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337' ), prev_index=0, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) out1 = proto.TxOutputType( address='tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s', amount=12300000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address='2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX', script_type=proto.OutputScriptType.PAYTOADDRESS, amount=123456789 - 11000 - 12300000, ) 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.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.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.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1, out2]) assert hexlify( serialized_tx ) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014824fb1037552b4bd2bb84d7f13c5a2aa4b2ab0d2ffffffff02e0aebb00000000001600140099a7ecbd938ed1839f5f6bf6d50933c6db9d5c3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca870247304402206625dab306dc21345b7efc382817e0825624d66d886b2fd5e47b52c33c88dc10022071da5b080e72e3424ff8b4dc358015200bae8d71569810e39a2ab773c3295993012103fea49c7079e5de753d11cd49ac47938cc95fcb1a40cb50ee41cce82e2283c51900000000'
def test_send_native(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/0/0"), # tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s amount=12300000, prev_hash=unhexlify( '09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a' ), prev_index=0, script_type=proto.InputScriptType.SPENDWITNESS, ) out1 = proto.TxOutputType( address='2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp', amount=5000000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address='tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu', script_type=proto.OutputScriptType.PAYTOADDRESS, amount=12300000 - 11000 - 5000000, ) 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.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.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.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1, out2]) assert hexlify( serialized_tx ) == b'010000000001018a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014d16b8c0680c61fc6ed2e407455715055e41052f502483045022100cdff526cbb19c26e52d3ef0d43039c8662f4144bcbe9688a4bb88fcf0edf37d6022041347e1eabb5c14c7676282f56c6dd9d93c02de810cc59ba5156efdb19e0a2d1012102d96aa150a2a60cc2c2c640816567945289feaadd68abeec410386846cb14147a00000000'
def test_cosi_commit(self): self.setup_mnemonic_nopin_nopassphrase() digest = sha256(b'this is a message').digest() c0 = self.client.cosi_commit(parse_path("10018'/0'"), digest) c1 = self.client.cosi_commit(parse_path("10018'/1'"), digest) c2 = self.client.cosi_commit(parse_path("10018'/2'"), digest) assert c0.pubkey != c1.pubkey assert c0.pubkey != c2.pubkey assert c1.pubkey != c2.pubkey assert c0.commitment != c1.commitment assert c0.commitment != c2.commitment assert c1.commitment != c2.commitment digestb = sha256(b'this is a different message').digest() c0b = self.client.cosi_commit(parse_path("10018'/0'"), digestb) c1b = self.client.cosi_commit(parse_path("10018'/1'"), digestb) c2b = self.client.cosi_commit(parse_path("10018'/2'"), digestb) assert c0.pubkey == c0b.pubkey assert c1.pubkey == c1b.pubkey assert c2.pubkey == c2b.pubkey assert c0.commitment != c0b.commitment assert c1.commitment != c1b.commitment assert c2.commitment != c2b.commitment
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'
def test_cosi_compat(self): self.setup_mnemonic_nopin_nopassphrase() digest = sha256(b'this is not a pipe').digest() remote_commit = self.client.cosi_commit(parse_path("10018'/0'"), digest) local_privkey = sha256(b'private key').digest()[:32] local_pubkey = cosi.pubkey_from_privkey(local_privkey) local_nonce, local_commitment = cosi.get_nonce(local_privkey, digest, 42) global_pk = cosi.combine_keys([remote_commit.pubkey, local_pubkey]) global_R = cosi.combine_keys( [remote_commit.commitment, local_commitment]) remote_sig = self.client.cosi_sign(parse_path("10018'/0'"), digest, global_R, global_pk) local_sig = cosi.sign_with_privkey(digest, local_privkey, global_pk, local_nonce, global_R) sig = cosi.combine_sig(global_R, [remote_sig.signature, local_sig]) cosi.verify(sig, digest, global_pk)
def test_cosi_sign(self): self.setup_mnemonic_nopin_nopassphrase() digest = sha256(b'this is a message').digest() c0 = self.client.cosi_commit(parse_path("10018'/0'"), digest) c1 = self.client.cosi_commit(parse_path("10018'/1'"), digest) c2 = self.client.cosi_commit(parse_path("10018'/2'"), digest) global_pk = cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey]) global_R = cosi.combine_keys( [c0.commitment, c1.commitment, c2.commitment]) sig0 = self.client.cosi_sign(parse_path("10018'/0'"), digest, global_R, global_pk) sig1 = self.client.cosi_sign(parse_path("10018'/1'"), digest, global_R, global_pk) sig2 = self.client.cosi_sign(parse_path("10018'/2'"), digest, global_R, global_pk) sig = cosi.combine_sig( global_R, [sig0.signature, sig1.signature, sig2.signature]) cosi.verify(sig, digest, global_pk)
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_both(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=111145789, prev_hash=unhexlify( '09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a' ), prev_index=1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) inp2 = proto.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu amount=7289000, prev_hash=unhexlify( '65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b' ), prev_index=1, script_type=proto.InputScriptType.SPENDWITNESS, ) out1 = proto.TxOutputType( address='tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc', amount=12300000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( # address_n=parse_path("44'/1'/0'/0/0"), # script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, address='2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc', script_type=proto.OutputScriptType.PAYTOADDRESS, amount=45600000, ) out3 = proto.TxOutputType( address='mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q', amount=111145789 + 7289000 - 11000 - 12300000 - 45600000, 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.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=2)), 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=2)), 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.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1, inp2], [out1, out2, out3]) # 0e480a97c7a545c85e101a2f13c9af0e115d43734e1448f0cac3e55fe8e7399d assert hexlify( serialized_tx ) == b'010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090100000017160014824fb1037552b4bd2bb84d7f13c5a2aa4b2ab0d2ffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff03e0aebb0000000000160014a579388225827d9f2fe9014add644487808c695d00cdb7020000000017a91491233e24a9bf8dbb19c1187ad876a9380c12e787870d859b03000000001976a914a579388225827d9f2fe9014add644487808c695d88ac024730440220685a8bd6321cdd279c811a87352ebe42720c0a723cbb9a2562cc88756a14a97802203c546b433d073df26244db4762c82ce12049e48fb9dcf7ecf9dec9c340b55cca012103fea49c7079e5de753d11cd49ac47938cc95fcb1a40cb50ee41cce82e2283c5190248304502210089ed4a2756995190534911c575f9e119cc8be00f5d13b84f43f654885961c7a402202c1e3997a53331d087eb1c9fa156cf6921c00244f80d1cb19453ac0907cb8d99012103fea49c7079e5de753d11cd49ac47938cc95fcb1a40cb50ee41cce82e2283c51900000000'
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'
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_attack_change_input_address(self): # This unit test attempts to modify input address after the Trezor checked # that it matches the change output self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=123456789, prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'), prev_index=0, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) out1 = proto.TxOutputType( address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC', amount=12300000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("49'/1'/12345'/1/0"), script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, amount=123456789 - 11000 - 12300000, ) global run_attack run_attack = True def attack_processor(req, msg): global run_attack if req.details.tx_hash is not None: return msg if req.request_type != proto.RequestType.TXINPUT: return msg if req.details.request_index != 0: return msg if not run_attack: return msg msg.inputs[0].address_n[2] = 12345 + 0x80000000 run_attack = False return msg # Test if the transaction can be signed normally 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.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.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.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1, out2]) assert hexlify(serialized_tx) == b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014824fb1037552b4bd2bb84d7f13c5a2aa4b2ab0d2ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a914ec45708fdebe5993e301bb580077988cf47e246987024830450221008dfdba08ae05346119cba6f31029b4fa2e1fbf8a227367b726de4efd9971982d02200e594d84a4334aaa689235adc867fb1440be695d771bd94231cb5ea9807b9dda012103fea49c7079e5de753d11cd49ac47938cc95fcb1a40cb50ee41cce82e2283c51900000000' # Now run the attack, must trigger the exception 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.Failure(code=proto.FailureType.ProcessError), ]) with pytest.raises(CallException) as exc: self.client.sign_tx('Testnet', [inp1], [out1, out2], debug_processor=attack_processor) assert exc.value.args[0] == proto.FailureType.ProcessError assert exc.value.args[1].endswith("Failed to compile input")
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'