def test_send_dash_dip2_input(self): self.setup_mnemonic_allallall() inp1 = proto.TxInputType( address_n=parse_path("44'/5'/0'/0/0"), # dash:XdTw4G5AWW4cogGd7ayybyBNDbuB45UpgH amount=4095000260, prev_hash=bytes.fromhex( "15575a1c874bd60a819884e116c42e6791c8283ce1fc3b79f0d18531a61bbb8a" ), prev_index=1, script_type=proto.InputScriptType.SPENDADDRESS, ) out1 = proto.TxOutputType( address_n=parse_path("44'/5'/0'/1/0"), amount=4000000000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address="XrEFMNkxeipYHgEQKiJuqch8XzwrtfH5fm", amount=95000000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=inp1.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.TXEXTRADATA, details=proto.TxRequestDetailsType( extra_data_len=39, extra_data_offset=0, tx_hash=inp1.prev_hash, ), ), 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.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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) _, serialized_tx = btc.sign_tx(self.client, "Dash", [inp1], [out1, out2], prev_txes=TX_API) assert ( serialized_tx.hex() == "01000000018abb1ba63185d1f0793bfce13c28c891672ec416e18498810ad64b871c5a5715010000006b483045022100f0442b6d9c7533cd6f74afa993b280ed9475276d69df4dac631bc3b5591ba71b022051daf125372c1c477681bbd804a6445d8ff6840901854fb0b485b1c6c7866c44012102936f80cac2ba719ddb238646eb6b78a170a55a52a9b9f08c43523a4a6bd5c896ffffffff0200286bee000000001976a914fd61dd017dad1f505c0511142cc9ac51ef3a5beb88acc095a905000000001976a914aa7a6a1f43dfc34d17e562ce1845b804b73fc31e88ac00000000" )
def test_attack_change_input(self): self.setup_mnemonic_allallall() inp1 = proto.TxInputType( address_n=parse_path("44'/145'/10'/0/0"), amount=1995344, prev_hash=bytes.fromhex( "bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78" ), prev_index=0, script_type=proto.InputScriptType.SPENDADDRESS, ) out1 = proto.TxOutputType( address_n=parse_path("44'/145'/10'/1/0"), amount=1896050, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address="bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4", amount=73452, script_type=proto.OutputScriptType.PAYTOADDRESS, ) run_attack = False def attack_processor(msg): nonlocal run_attack if msg.tx.inputs and msg.tx.inputs[0] == inp1: if not run_attack: run_attack = True else: msg.tx.inputs[0].address_n[2] = H_(1) return msg self.client.set_filter(proto.TxAck, attack_processor) 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.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.Failure(code=proto.FailureType.ProcessError), ]) with pytest.raises(CallException): btc.sign_tx(self.client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API)
def test_send_bch_multisig_change(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, parse_path("48'/145'/%d'" % i)).node for i in range(1, 4) ] def getmultisig(chain, nr, signatures=[b"", b"", b""], nodes=nodes): return proto.MultisigRedeemScriptType(nodes=nodes, address_n=[chain, nr], signatures=signatures, m=2) inp1 = proto.TxInputType( address_n=parse_path("48'/145'/3'/0/0"), multisig=getmultisig(0, 0), amount=48490, prev_hash=bytes.fromhex( "8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0" ), prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, ) out1 = proto.TxOutputType( address="bitcoincash:qqq8gx2j76nw4dfefumxmdwvtf2tpsjznusgsmzex9", amount=24000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("48'/145'/3'/1/0"), multisig=getmultisig(1, 0), script_type=proto.OutputScriptType.PAYTOMULTISIG, amount=24000, ) 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.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) (signatures1, serialized_tx) = btc.sign_tx(self.client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API) assert ( signatures1[0].hex() == "3045022100a05f77bb39515c21c43e6c4ba401f39ed5d409dc3cfcd90f9a8345a08cc4bc8202205faf8f3b0775748278495324fdd60f370460452e4995e546450209ec4804a0f3" ) inp1 = proto.TxInputType( address_n=parse_path("48'/145'/1'/0/0"), multisig=getmultisig(0, 0, [b"", b"", signatures1[0]]), # bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw amount=48490, prev_hash=bytes.fromhex( "8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0" ), prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, ) out2.address_n[2] = H_(1) 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.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) (signatures1, serialized_tx) = btc.sign_tx(self.client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API) assert ( signatures1[0].hex() == "3044022006f239ef1f065a70873ab9d2c81a623a04ec7a37a0ec5299d3c585668f441f49022032b2f9ef13bc61230d14f6d79b9ad1bbebdf47b95e4757e9af1b1dcdf520d3ab" ) assert ( serialized_tx.hex() == "0100000001a07660b10df9868df9393c9cf8962bc34f48cb2cea53b0865d2324bab8b96d8b00000000fdfd0000473044022006f239ef1f065a70873ab9d2c81a623a04ec7a37a0ec5299d3c585668f441f49022032b2f9ef13bc61230d14f6d79b9ad1bbebdf47b95e4757e9af1b1dcdf520d3ab41483045022100a05f77bb39515c21c43e6c4ba401f39ed5d409dc3cfcd90f9a8345a08cc4bc8202205faf8f3b0775748278495324fdd60f370460452e4995e546450209ec4804a0f3414c69522102f8ca0d9665af03de32a7c19a167a4f6e97e4e0ed9505f75d11f7a45ab60b1f4d2103263d87cefd687bc15b4ef7801f9f538267b66d46f18e9fccc41d54071cfdd1ce210388568bf42f02298308eb6fa2fa4b446d544600253b4409be27e2c0c1a71c424853aeffffffff02c05d0000000000001976a91400741952f6a6eab5394f366db5cc5a54b0c2429f88acc05d00000000000017a91478574751407449b97f8054be2e40e684ad07d3738700000000" )
def test_signtx(self, client): inp1 = proto.TxInputType( address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e prev_hash=TXHASH_d5f65e, prev_index=0, ) out1 = proto.TxOutputType( address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", amount=390000 - 10000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses([ proto.PinMatrixRequest(), proto.PassphraseRequest(), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_d5f65e), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_d5f65e), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_d5f65e), ), 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=tx_cache("Bitcoin"))
def test_attack_amount(self): self.setup_mnemonic_allallall() inp1 = proto.TxInputType( address_n=parse_path("44'/145'/0'/1/0"), # bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw amount=300, prev_hash=bytes.fromhex( "502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c" ), prev_index=0, script_type=proto.InputScriptType.SPENDADDRESS, ) inp2 = proto.TxInputType( address_n=parse_path("44'/145'/0'/0/1"), # bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4 amount=70, prev_hash=bytes.fromhex( "502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c" ), prev_index=1, script_type=proto.InputScriptType.SPENDADDRESS, ) out1 = proto.TxOutputType( address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4", amount=200, script_type=proto.OutputScriptType.PAYTOADDRESS, ) # test if passes without modifications 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.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.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.TXFINISHED), ]) btc.sign_tx(self.client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API) run_attack = True def attack_processor(msg): nonlocal run_attack if run_attack and msg.tx.inputs and msg.tx.inputs[0] == inp1: # 300 is lowered to 280 at the first run # the user confirms 280 but the transaction # is spending 300 => larger fee without the user knowing msg.tx.inputs[0].amount = 280 run_attack = False return msg # now fails self.client.set_filter(proto.TxAck, attack_processor) 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.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.TXINPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.Failure(), ]) with pytest.raises(CallException) as exc: btc.sign_tx(self.client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API) assert exc.value.args[0] in ( proto.FailureType.ProcessError, proto.FailureType.DataError, ) assert exc.value.args[1].endswith( "Transaction has changed during signing")
def test_one_one_rewards_claim(self, client): # prevout: 7b28bd91119e9776f0d4ebd80e570165818a829bbf4477cd1afe5149dbcd34b1:0 # input 1: 10.9997 KMD inp1 = proto.TxInputType( address_n=parse_path( "44'/141'/0'/0/0"), # R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi amount=1099970000, prev_hash=TXHASH_7b28bd, prev_index=0, ) out1 = proto.TxOutputType( address="R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi", amount=1099970000 - 10000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) # kmd interest, vout sum > vin sum out2 = proto.TxOutputType( address="R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi", amount=79605, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: er = [ 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.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.ButtonRequest( code=proto.ButtonRequestType.ConfirmOutput), ] if TREZOR_VERSION != 1: # extra screen for lock_time er += [ proto.ButtonRequest(code=proto.ButtonRequestType.SignTx) ] er += [ 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] client.set_expected_responses(er) details = proto.SignTx( version=4, overwintered=True, version_group_id=0x892F2085, branch_id=0x76B809BB, lock_time=0x5D2AF1F2, ) _, serialized_tx = btc.sign_tx( client, "Komodo", [inp1], [out1, out2], details=details, prev_txes=TX_API, ) # Accepted by network: tx c775678ceb18277729b427c7acf2f8ce63ac02fc2366f47ce08a3f443ff0e059 assert ( serialized_tx.hex() == "0400008085202f8901b134cddb4951fe1acd7744bf9b828a816501570ed8ebd4f076979e1191bd287b000000006a4730440220483a58f5be3a147c773c663008c992a7fcea4d03bdf4c1d4bc0535c0d98ddf0602207b19d69140dd00c7a94f048c712aeaed55dfd27f581c7212d9cc5e476fe1dc9f012102a87aef7b1a8f676e452d6240767699719cd58b0261c822472c25df146938bca5ffffffff02c00e9041000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acf5360100000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acf2f12a5d000000000000000000000000000000" )
def _responses(self, inp1, inp2, change=0): resp = [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=inp1.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=inp1.prev_hash ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=inp1.prev_hash ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=1, tx_hash=inp1.prev_hash ), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=inp2.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=inp2.prev_hash ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=inp2.prev_hash ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=1, tx_hash=inp2.prev_hash ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), ] if change != 1: resp.append(proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput)) resp.append( proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ) ) if change != 2: resp.append(proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput)) resp += [ 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.TXINPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] return resp
def test_send_p2sh(self, client): inp1 = proto.TxInputType( address_n=parse_path("49'/156'/0'/1/0"), amount=123456789, prev_hash=bytes.fromhex( "25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985" ), prev_index=0, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) out1 = proto.TxOutputType( address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", amount=12300000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address="GZFLExxrvWFuFT1xRzhfwQWSE2bPDedBfn", script_type=proto.OutputScriptType.PAYTOADDRESS, amount=123456789 - 11000 - 12300000, ) with client: 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.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.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), ]) _, serialized_tx = btc.sign_tx(client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API) assert ( serialized_tx.hex() == "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f06000000001976a914a8f757819ec6779409f45788f7b4a0e8f51ec50488ac02473044022073fcbf2876f073f78923ab427f14de5b2a0fbeb313a9b2b650b3567061f242a702202f45fc22c501108ff6222afe3aca7da9d8c7dc860f9cda335bef31fa184e7bef412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000" )
def test_send_p2sh_witness_change(self, client): inp1 = proto.TxInputType( address_n=parse_path("49'/156'/0'/1/0"), amount=123456789, prev_hash=bytes.fromhex( "25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985" ), prev_index=0, script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) out1 = proto.TxOutputType( address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", amount=12300000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("49'/156'/0'/1/0"), script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, amount=123456789 - 11000 - 12300000, ) with client: 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.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.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), ]) _, serialized_tx = btc.sign_tx(client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API) assert ( serialized_tx.hex() == "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f060000000017a9140cd03822b799a452c106d1b3771844a067b17f118702483045022100d79b33384c686d8dd40ad5f84f46691d30994992c1cb42e934c2a625d86cb2f902206859805a9a98ba140b71a9d4b9a6b8df94a9424f9c40f3bd804149fd6e278d63412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000" )
def test_attack_change_input(self, client): inp1 = proto.TxInputType( address_n=parse_path("44'/156'/11'/0/0"), amount=1995344, prev_hash=bytes.fromhex( "25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985" ), prev_index=0, script_type=proto.InputScriptType.SPENDADDRESS, ) out1 = proto.TxOutputType( address_n=parse_path("44'/156'/11'/1/0"), amount=1896050, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", amount=73452, script_type=proto.OutputScriptType.PAYTOADDRESS, ) run_attack = False def attack_processor(msg): nonlocal run_attack if msg.tx.inputs and msg.tx.inputs[0] == inp1: if run_attack: msg.tx.inputs[0].address_n[2] = H_(1) else: run_attack = True return msg client.set_filter(proto.TxAck, attack_processor) with client: 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.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.Failure(code=proto.FailureType.ProcessError), ]) with pytest.raises(CallException): btc.sign_tx(client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API)
def test_send_btg_multisig_change(self, client): nodes = [ btc.get_public_node(client, parse_path("48'/156'/%d'" % i)).node for i in range(1, 4) ] def getmultisig(chain, nr, signatures=[b"", b"", b""], nodes=nodes): return proto.MultisigRedeemScriptType(nodes=nodes, address_n=[chain, nr], signatures=signatures, m=2) inp1 = proto.TxInputType( address_n=parse_path("48'/156'/3'/0/0"), multisig=getmultisig(0, 0), # 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R amount=48490, prev_hash=bytes.fromhex( "25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985" ), prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, ) out1 = proto.TxOutputType( address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", amount=24000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("48'/156'/3'/1/0"), multisig=getmultisig(1, 0), script_type=proto.OutputScriptType.PAYTOMULTISIG, amount=24000, ) with client: 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.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) signatures, serialized_tx = btc.sign_tx(client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API) assert ( signatures[0].hex() == "3045022100d954f341ddd3ec96e4bc6cdb90f2df9b2032723f85e4a0187346dd743130bfca0220105ce08b795c70dc09a55569d7874bff684a877219ec2fc37c88cdffe12f332c" ) inp1 = proto.TxInputType( address_n=parse_path("48'/156'/1'/0/0"), multisig=getmultisig(0, 0, [b"", b"", signatures[0]]), amount=48490, prev_hash=bytes.fromhex( "25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985" ), prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, ) out2.address_n[2] = H_(1) with client: 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.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) signatures, serialized_tx = btc.sign_tx(client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API) assert ( signatures[0].hex() == "30440220614f9a18695365a2edba0d930404a77cae970d3430ad86c5b5239a96fd54bf84022030bc76a322e3b2b1c987622b5eb6da23ac1e6c905ee9b3b6405a4e4edd5bbb87" ) assert ( serialized_tx.hex() == "010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522500000000fdfd00004730440220614f9a18695365a2edba0d930404a77cae970d3430ad86c5b5239a96fd54bf84022030bc76a322e3b2b1c987622b5eb6da23ac1e6c905ee9b3b6405a4e4edd5bbb8741483045022100d954f341ddd3ec96e4bc6cdb90f2df9b2032723f85e4a0187346dd743130bfca0220105ce08b795c70dc09a55569d7874bff684a877219ec2fc37c88cdffe12f332c414c695221035a8db79c0ef57a202664a3da60ca41e8865c6d86ed0aafc03f8e75173341b58021037fba152d8fca660cc49973d8bc9421ff49a75b44ea200873d70d3990f763ed4c210348cbcbd93e069416e0d5db93e86b5698852d9fd54502ad0bed9722fa83f90e4b53aeffffffff02c05d0000000000001976a914ea5f904d195079a350b534db4446433b3cec222e88acc05d00000000000017a914623c803f7fb654dac8dda7786fbf9bc38cd867f48700000000" )
def tx_request(request_type, **kwargs): if kwargs: details = proto.TxRequestDetailsType(**kwargs) else: details = None return proto.TxRequest(request_type=request_type, details=details)
def test_attack_change_input_address(self, client): inp1 = proto.TxInputType( address_n=parse_path("44'/1'/4'/0/0"), # moUJnmge8SRXuediK7bW6t4YfrPqbE6hD7 prev_hash=TXHASH_d2dcda, prev_index=1, script_type=proto.InputScriptType.SPENDADDRESS, ) out1 = proto.TxOutputType( address="mwue7mokpBRAsJtHqEMcRPanYBmsSmYKvY", amount=100000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("44'/1'/4'/1/0"), amount=123400000 - 5000 - 100000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) # Test if the transaction can be signed normally _, serialized_tx = check_sign_tx(client, "Testnet", [inp1], [out1, out2]) assert ( serialized_tx.hex() == "0100000001243e15b53cc553d93ec4e27e16984adc3d885ef107c613a7577fea47f5dadcd2010000006b483045022100eedaadde3a771967beee39f1daa9e9450f72fccdec63488a96d71eeae4224b4002203a22be3c1677d3451c93a49550b69e8f8fc06328823c7e0f633dde13d67ef96b01210364430c9122948e525e2f1c6d88f00f47679274f0810fd8c63754954f310995c1ffffffff02a0860100000000001976a914b3cc67f3349974d0f1b50e9bb5dfdf226f888fa088ac18555907000000001976a914f80fb232a1e54b1fa732bc120cae72eabd7fcf6888ac00000000" ) run_attack = False def attack_processor(msg): nonlocal run_attack if msg.tx.inputs and msg.tx.inputs[0] == inp1: if not run_attack: run_attack = True else: msg.tx.inputs[0].address_n[2] = H_(12) return msg client.set_filter(proto.TxAck, attack_processor) # Now run the attack, must trigger the exception with client: client.set_expected_responses( [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_d2dcda), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_d2dcda ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=0, tx_hash=TXHASH_d2dcda ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType( request_index=1, tx_hash=TXHASH_d2dcda ), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.Failure(code=proto.FailureType.ProcessError), ] ) # Now run the attack, must trigger the exception with pytest.raises(CallException) as exc: btc.sign_tx( client, "Testnet", [inp1], [out1, out2], prev_txes=tx_cache("Testnet"), ) assert exc.value.args[0] == proto.FailureType.ProcessError if client.features.model == "1": assert exc.value.args[1].endswith("Failed to compile input") else: assert exc.value.args[1].endswith( "Transaction has changed during signing" )
def test_send_dash(self): self.setup_mnemonic_allallall() inp1 = proto.TxInputType( address_n=parse_path("44'/5'/0'/0/0"), # dash:XdTw4G5AWW4cogGd7ayybyBNDbuB45UpgH amount=1000000000, prev_hash=bytes.fromhex( "5579eaa64b2a0233e7d8d037f5a5afc957cedf48f1c4067e9e33ca6df22ab04f" ), prev_index=1, script_type=proto.InputScriptType.SPENDADDRESS, ) out1 = proto.TxOutputType( address="XpTc36DPAeWmaueNBA9JqCg2GC8XDLKSYe", amount=999999000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=inp1.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), ), proto.TxRequest( request_type=proto.RequestType.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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) _, serialized_tx = btc.sign_tx(self.client, "Dash", [inp1], [out1], prev_txes=TX_API) assert ( serialized_tx.hex() == "01000000014fb02af26dca339e7e06c4f148dfce57c9afa5f537d0d8e733022a4ba6ea7955010000006a4730440220387be4d1e4b5e355614091416373e99e1a3532b8cc9a8629368060aff2681bdb02200a0c4a5e9eb2ce6adb6c2e01ec8f954463dcc04f531ed8a89a2b40019d5aeb0b012102936f80cac2ba719ddb238646eb6b78a170a55a52a9b9f08c43523a4a6bd5c896ffffffff0118c69a3b000000001976a9149710d6545407e78c326aa8c8ae386ec7f883b0af88ac00000000" )
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() inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=123456789, prev_hash=bytes.fromhex( "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'/12'/1/0"), script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, amount=123456789 - 11000 - 12300000, ) # 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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.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), ] ) _, serialized_tx = btc.sign_tx( self.client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) assert ( serialized_tx.hex() == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a9142f98413cb83ff8b3eaf1926192e68973cbd68a3a8702473044022013cbce7c575337ca05dbe03b5920a0805b510cd8dfd3180bd7c5d01cec6439cd0220050001be4bcefb585caf973caae0ffec682347f2127cc22f26efd93ee54fd852012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" ) run_attack = True def attack_processor(msg): nonlocal run_attack if run_attack and msg.tx.inputs and msg.tx.inputs[0] == inp1: run_attack = False msg.tx.inputs[0].address_n[2] = H_(12) return msg # Now run the attack, must trigger the exception self.client.set_filter(proto.TxAck, attack_processor) 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.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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: btc.sign_tx( self.client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) assert exc.value.args[0] == proto.FailureType.ProcessError if TREZOR_VERSION == 1: assert exc.value.args[1].endswith("Failed to compile input") else: assert exc.value.args[1].endswith( "Transaction has changed during signing" )
def test_send_multisig_1(self, client): nodes = [ btc.get_public_node(client, parse_path("49'/156'/%d'" % i)).node for i in range(1, 4) ] multisig = proto.MultisigRedeemScriptType(nodes=nodes, address_n=[1, 0], signatures=[b"", b"", b""], m=2) inp1 = proto.TxInputType( address_n=parse_path("49'/156'/1'/1/0"), prev_hash=bytes.fromhex( "25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985" ), prev_index=1, script_type=proto.InputScriptType.SPENDP2SHWITNESS, multisig=multisig, amount=1610436, ) out1 = proto.TxOutputType( address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", amount=1605000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: 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), ]) signatures, _ = btc.sign_tx(client, "Bgold", [inp1], [out1], prev_txes=TX_API) # store signature inp1.multisig.signatures[0] = signatures[0] # sign with third key inp1.address_n[2] = H_(3) 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), ]) _, serialized_tx = btc.sign_tx(client, "Bgold", [inp1], [out1], prev_txes=TX_API) assert ( serialized_tx.hex() == "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250100000023220020ea9ec48498c451286c2ebaf9e19255e2873b0fb517d67b2f2005298c7e437829ffffffff01887d1800000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0400473044022077cb8b2a534f79328810ca8c330539ae9ffa086c359ddb7da11026557b04eef202201d95be0dd1da0aa01720953e52d5dabffd19a998d1490c13a21b8e52e4ead2e041483045022100e41cbd6a501ba8fe6f65554420e23e950d35af0da9b052da54a087463b0717ca02206c695c8d1f74f9535b5d89a2fd1f9326a0ef20e5400137f1e1daeee992b62b594169522103279aea0b253b144d1b2bb8532280001a996dcddd04f86e5e13df1355032cbc1321032c6465c956c0879663fa8be974c912d229c179a5cdedeb29611a1bec1f951eb22103494480a4b72101cbd2eadac8e18c7a3a7589a7f576bf46b8971c38c51e5eceeb53ae00000000" )
def test_send_p2sh_change(self): self.setup_mnemonic_allallall() inp1 = proto.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=123456789, prev_hash=bytes.fromhex( "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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.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), ] ) _, serialized_tx = btc.sign_tx( self.client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) assert ( serialized_tx.hex() == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" )
def test_send_bitcoin_gold_nochange(self, client): inp1 = proto.TxInputType( address_n=parse_path("44'/156'/0'/1/0"), amount=1896050, prev_hash=bytes.fromhex( "25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985" ), prev_index=0, script_type=proto.InputScriptType.SPENDADDRESS, ) inp2 = proto.TxInputType( address_n=parse_path("44'/156'/0'/0/1"), # 1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3 amount=73452, prev_hash=bytes.fromhex( "db77c2461b840e6edbe7f9280043184a98e020d9795c1b65cb7cef2551a8fb18" ), prev_index=1, script_type=proto.InputScriptType.SPENDADDRESS, ) out1 = proto.TxOutputType( address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", amount=1934960, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: 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.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.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.TXFINISHED), ]) _, serialized_tx = btc.sign_tx(client, "Bgold", [inp1, inp2], [out1], prev_txes=TX_API) assert ( serialized_tx.hex() == "010000000285c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100928852076c9fab160c07564cd54691af1cbc37fb28f0b7bee7299c7925ef62f0022058856387afecc6508f2f04ecdfd292a13026a5b2107ebdd2cc789bdf8820d552412102a6c3998d0d4e5197ff41aab5c53580253b3b91f583f4c31f7624be7dc83ce15fffffffff18fba85125ef7ccb651b5c79d920e0984a18430028f9e7db6e0e841b46c277db010000006b483045022100faa2f4f01cc95e680349a093923aae0aa2ea01429873555aa8a84bf630ef33a002204c3f4bf567e2d20540c0f71dc278481d6ccb6b95acda2a2f87ce521c79d6b872412102d54a7e5733b1635e5e9442943f48179b1700206b2d1925250ba10f1c86878be8ffffffff0170861d00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000" )
def test_one_one_fee_sapling(self, client): # prevout: 2807c5b126ec8e2b078cab0f12e4c8b4ce1d7724905f8ebef8dca26b0c8e0f1d:0 # input 1: 10.9998 KMD inp1 = proto.TxInputType( address_n=parse_path( "44'/141'/0'/0/0"), # R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi amount=1099980000, prev_hash=TXHASH_2807c, prev_index=0, ) out1 = proto.TxOutputType( address="R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi", amount=1099980000 - 10000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: er = [ 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), ] if TREZOR_VERSION != 1: # extra screen for lock_time er += [ proto.ButtonRequest(code=proto.ButtonRequestType.SignTx) ] er += [ 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), ] client.set_expected_responses(er) details = proto.SignTx( version=4, overwintered=True, version_group_id=0x892F2085, branch_id=0x76B809BB, lock_time=0x5D2A30B8, ) _, serialized_tx = btc.sign_tx(client, "Komodo", [inp1], [out1], details=details, prev_txes=TX_API) # Accepted by network: tx 7b28bd91119e9776f0d4ebd80e570165818a829bbf4477cd1afe5149dbcd34b1 assert ( serialized_tx.hex() == "0400008085202f89011d0f8e0c6ba2dcf8be8e5f9024771dceb4c8e4120fab8c072b8eec26b1c50728000000006a4730440220158c970ca2fc6bcc33026eb5366f0342f63b35d178f7efb334b1df78fe90b67202207bc4ff69f67cf843b08564a5adc77bf5593e28ab4d5104911824ac13fe885d8f012102a87aef7b1a8f676e452d6240767699719cd58b0261c822472c25df146938bca5ffffffff01d0359041000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acb8302a5d000000000000000000000000000000" )
def test_one_one_fee_overwinter(self, client): # prevout: aaf51e4606c264e47e5c42c958fe4cf1539c5172684721e38e69f4ef634d75dc:1 # input 1: 3.0 TAZ inp1 = proto.TxInputType( # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu address_n=parse_path("m/44h/1h/0h/0/0"), amount=300000000, prev_hash=TXHASH_aaf51e, prev_index=1, ) out1 = proto.TxOutputType( address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z", amount=300000000 - 1940, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: 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), ]) details = proto.SignTx( version=3, version_group_id=0x03C48270, branch_id=0x5BA81B19, ) _, serialized_tx = btc.sign_tx( client, "Zcash Testnet", [inp1], [out1], details=details, prev_txes=TX_API, ) # Accepted by network: tx eda9b772c47f0c29310759960e0081c98707aa67a0a2738bcc71439fcf360675 assert ( serialized_tx.hex() == "030000807082c40301dc754d63eff4698ee321476872519c53f14cfe58c9425c7ee464c206461ef5aa010000006a47304402207e45f303b4e42be824513855eb21653e1d2749cd94dcd0f0613d3f85d4efd1e20220699ffbdbcad889af7ede5ce9febf7a5ef8f5619b2464824529974c400cffaebc0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac000000000000000000" )
def test_2_of_3(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, parse_path("48'/0'/%d'" % index)) for index in range(1, 4) ] multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[0, 0], signatures=[b"", b"", b""], m=2, ) # Let's go to sign with key 1 inp1 = proto.TxInputType( address_n=parse_path("48'/0'/1'/0/0"), prev_hash=TXHASH_c6091a, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) out1 = proto.TxOutputType( address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss", amount=100000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) # Now we have first signature signatures1, _ = btc.sign_tx(self.client, "Bitcoin", [inp1], [out1], prev_txes=TX_API) assert ( signatures1[0].hex() == "3044022052f4a3dc5ca3e86ed66abb1e2b4d9b9ace7d96f5615944beea19e58280847c2902201bd3ff32a38366a4eed0373e27da26ebc0d2a4c2bbeffd83e8a60e313d95b9e3" ) # --------------------------------------- # Let's do second signature using 3rd key multisig = proto.MultisigRedeemScriptType( nodes=[deserialize(n.xpub) for n in nodes], address_n=[0, 0], signatures=[ signatures1[0], b"", b"", ], # Fill signature from previous signing process m=2, ) # Let's do a second signature with key 3 inp3 = proto.TxInputType( address_n=parse_path("48'/0'/3'/0/0"), prev_hash=TXHASH_c6091a, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_c6091a), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) signatures2, serialized_tx = btc.sign_tx(self.client, "Bitcoin", [inp3], [out1], prev_txes=TX_API) assert ( signatures2[0].hex() == "304402203828fd48540811be6a1b12967e7012587c46e6f05c78d42471e7b25c06bc7afc0220749274bc1aa698335b00400c5ba946a70b6b46c711324fbc4989279737a57f49" ) assert ( serialized_tx.hex() == "010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fc00473044022052f4a3dc5ca3e86ed66abb1e2b4d9b9ace7d96f5615944beea19e58280847c2902201bd3ff32a38366a4eed0373e27da26ebc0d2a4c2bbeffd83e8a60e313d95b9e30147304402203828fd48540811be6a1b12967e7012587c46e6f05c78d42471e7b25c06bc7afc0220749274bc1aa698335b00400c5ba946a70b6b46c711324fbc4989279737a57f49014c6952210203ed6187880ae932660086e55d4561a57952dd200aa3ed2aa66b73e5723a0ce7210360e7f32fd3c8dee27a166f6614c598929699ee66acdcbda5fb24571bf2ae1ca021037c4c7e5d3293ab0f97771dcfdf83caadab341f427f54713da8b2c590a834f03b53aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000" )
def test_one_one_fee_sapling(self, client): # prevout: e3820602226974b1dd87b7113cc8aea8c63e5ae29293991e7bfa80c126930368:0 # input 1: 3.0 TAZ inp1 = proto.TxInputType( # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu address_n=parse_path("m/44h/1h/0h/0/0"), amount=300000000, prev_hash=TXHASH_e38206, prev_index=0, ) out1 = proto.TxOutputType( address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z", amount=300000000 - 1940, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: 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), ]) details = proto.SignTx( version=4, version_group_id=0x892F2085, branch_id=0x76B809BB, ) _, serialized_tx = btc.sign_tx( client, "Zcash Testnet", [inp1], [out1], details=details, prev_txes=TX_API, ) # Accepted by network: tx 0cef132c1d6d67f11cfa48f7fca3209da29cf872ac782354bedb686e61a17a78 assert ( serialized_tx.hex() == "0400008085202f890168039326c180fa7b1e999392e25a3ec6a8aec83c11b787ddb1746922020682e3000000006b483045022100f28298891f48706697a6f898ac18e39ce2c7cebe547b585d51cc22d80b1b21a602201a807b8a18544832d95d1e3ada82c0617bc6d97d3f24d1fb4801ac396647aa880121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000000000000000000000000000000000" )
def test_one_one_fee(self): self.setup_mnemonic_allallall() # tx: 93373e63cc626c4a7d049ad775d6511bb5eba985f142db660c9b9f955c722f5c # input 0: 1.234567 TAZ inp1 = proto.TxInputType( address_n=[2147483692, 2147483649, 2147483648, 0, 0], # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu # amount=123456700, prev_hash=TXHASH_93373e, prev_index=0, ) out1 = proto.TxOutputType( address='tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z', amount=123456700 - 1940, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with self.client: self.client.set_tx_api(TxApiZcash) self.client.set_expected_responses([ proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto.RequestType.TXMETA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_93373e)), proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_93373e)), proto.TxRequest(request_type=proto.RequestType.TXEXTRADATA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_93373e, extra_data_offset=0, extra_data_len=1024)), proto.TxRequest(request_type=proto.RequestType.TXEXTRADATA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_93373e, extra_data_offset=1024, extra_data_len=1024)), proto.TxRequest(request_type=proto.RequestType.TXEXTRADATA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_93373e, extra_data_offset=2048, extra_data_len=1024)), proto.TxRequest(request_type=proto.RequestType.TXEXTRADATA, details=proto.TxRequestDetailsType(tx_hash=TXHASH_93373e, extra_data_offset=3072, extra_data_len=629)), 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Zcash', [inp1, ], [out1, ]) # Accepted by network: tx dcc2a10894e0e8a785c2afd4de2d958207329b9acc2b987fd768a09c5efc4547 assert hexlify(serialized_tx) == b'01000000015c2f725c959f9b0c66db42f185a9ebb51b51d675d79a047d4a6c62cc633e3793000000006a4730440220670b2b63d749a7038f9aea6ddf0302fe63bdcad93dafa4a89a1f0e7300ae2484022002c50af43fd867490cea0c527273c5828ff1b9a5115678f155a1830737cf29390121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff0128c55b07000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000'
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_change(self): self.setup_mnemonic_allallall() inp1 = proto.TxInputType( address_n=parse_path("44'/145'/0'/0/0"), # bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv amount=1995344, prev_hash=bytes.fromhex( "bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78" ), prev_index=0, script_type=proto.InputScriptType.SPENDADDRESS, ) out1 = proto.TxOutputType( address_n=parse_path("44'/145'/0'/1/0"), amount=1896050, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address="bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4", amount=73452, 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) _, serialized_tx = btc.sign_tx(self.client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API) assert ( serialized_tx.hex() == "0100000001781a716b1e15b41b07157933e5d777392a75bf87132650cb2e7d46fb8dc237bc000000006a473044022061aee4f17abe044d5df8c52c9ffd3b84e5a29743517e488b20ecf1ae0b3e4d3a02206bb84c55e407f3b684ff8d9bea0a3409cfd865795a19d10b3d3c31f12795c34a412103a020b36130021a0f037c1d1a02042e325c0cb666d6478c1afdcd9d913b9ef080ffffffff0272ee1c00000000001976a914b1401fce7e8bf123c88a0467e0ed11e3b9fbef5488acec1e0100000000001976a914d51eca49695cdf47e7f4b55507893e3ad53fe9d888ac00000000" )
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=self.client.expand_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=self.client.expand_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): import sys 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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), 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.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'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a914dae9e09a7fc3bbe5a716fffec1bbb340b82a4fb9870248304502210099b5c4f8fd4402c9c0136fee5f711137d64fc9f14587e01bfa7798f5428f845d0220253e21c98f5b1b64efae69bc2ea9799c5620a43450baa6762a0c3cf4fdc886e5012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000' # 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.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), 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 if TREZOR_VERSION == 1: assert exc.value.args[1].endswith("Failed to compile input") else: assert exc.value.args[1].endswith('Transaction has changed during signing')
def test_send_bch_multisig_wrongchange(self): self.setup_mnemonic_allallall() nodes = [ btc.get_public_node(self.client, parse_path("48'/145'/%d'" % i)).node for i in range(1, 4) ] def getmultisig(chain, nr, signatures=[b"", b"", b""], nodes=nodes): return proto.MultisigRedeemScriptType(nodes=nodes, address_n=[chain, nr], signatures=signatures, m=2) correcthorse = proto.HDNodeType( depth=1, fingerprint=0, child_num=0, chain_code=bytes.fromhex( "0000000000000000000000000000000000000000000000000000000000000000" ), public_key=bytes.fromhex( "0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71" ), ) sig = bytes.fromhex( "304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae" ) inp1 = proto.TxInputType( address_n=parse_path("48'/145'/1'/1/0"), multisig=getmultisig(1, 0, [b"", sig, b""]), # bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a amount=24000, prev_hash=bytes.fromhex( "f68caf10df12d5b07a34601d88fa6856c6edcbf4d05ebef3486510ae1c293d5f" ), prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, ) out1 = proto.TxOutputType( address_n=parse_path("48'/145'/1'/1/1"), multisig=proto.MultisigRedeemScriptType( pubkeys=[ proto.HDNodePathType(node=nodes[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) = btc.sign_tx(self.client, "Bcash", [inp1], [out1], prev_txes=TX_API) assert ( signatures1[0].hex() == "304402201badcdcafef4855ed58621f95935efcbc72068510472140f4ec5e252faa0af93022003310a43488288f70aedee96a5af2643a255268a6858cda9ae3001ea5e3c7557" ) assert ( serialized_tx.hex() == "01000000015f3d291cae106548f3be5ed0f4cbedc65668fa881d60347ab0d512df10af8cf601000000fc0047304402201badcdcafef4855ed58621f95935efcbc72068510472140f4ec5e252faa0af93022003310a43488288f70aedee96a5af2643a255268a6858cda9ae3001ea5e3c75574147304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae414c69522102245739b55787a27228a4fe78b3a324366cc645fbaa708cad45da351a334341192102debbdcb0b6970d5ade84a50fdbda1c701cdde5c9925d9b6cd8e05a9a15dbef352102ffe5fa04547b2b0c3cfbc21c08a1ddfb147025fee10274cdcd5c1bdeee88eae253aeffffffff01d85900000000000017a914a23eb2a1ed4003d357770120f5c370e199ee55468700000000" )
def test_send_multisig_1(self): self.setup_mnemonic_allallall() nodes = map( lambda index: btc.get_public_node( self.client, parse_path("49'/1'/%d'" % index) ), range(1, 4), ) multisig = proto.MultisigRedeemScriptType( pubkeys=list( map( lambda n: proto.HDNodePathType( node=deserialize(n.xpub), address_n=[1, 0] ), nodes, ) ), signatures=[b"", b"", b""], m=2, ) inp1 = proto.TxInputType( address_n=parse_path("49'/1'/1'/1/0"), prev_hash=bytes.fromhex( "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), ] ) signatures, _ = btc.sign_tx( self.client, "Testnet", [inp1], [out1], prev_txes=TX_API ) # store signature inp1.multisig.signatures[0] = signatures[0] # sign with third key inp1.address_n[2] = H_(3) 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), ] ) _, serialized_tx = btc.sign_tx( self.client, "Testnet", [inp1], [out1], prev_txes=TX_API ) assert ( serialized_tx.hex() == "01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c0100000023220020cf28684ff8a6dda1a7a9704dde113ddfcf236558da5ce35ad3f8477474dbdaf7ffffffff01887d1800000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac040047304402203fc3fbe6cd6250d82ace4a585debc07587c07d2efc8bb56558c91e1f810fe65402206025bd9a4e80960f617b6e5bfdd568e34aa085d093471b7976e6b14c2a2402a7014730440220327abf491a57964d75c67fad204eb782fa74aa4abde40e5ad30fb0b7696102b7022049e31f2302417be0a87e2f818b93a862a7e67d4178b7cbeee680264f0882113f0169522103d54ab3c8b81cb7f8f8088df4c62c105e8acaa2fb53b180f6bc6f922faecf3fdc21036aa47994f3f18f0976d6073ca79997003c3fa29c4f93907998fefc1151b4529b2102a092580f2828272517c402da9461425c5032860ab40180e041fbbb88ea2a520453ae00000000" )
def test_send_bch_nochange(self): self.setup_mnemonic_allallall() inp1 = proto.TxInputType( address_n=parse_path("44'/145'/0'/1/0"), # bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw amount=1896050, prev_hash=bytes.fromhex( "502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c" ), prev_index=0, script_type=proto.InputScriptType.SPENDADDRESS, ) inp2 = proto.TxInputType( address_n=parse_path("44'/145'/0'/0/1"), # bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4 amount=73452, prev_hash=bytes.fromhex( "502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c" ), prev_index=1, script_type=proto.InputScriptType.SPENDADDRESS, ) out1 = proto.TxOutputType( address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4", amount=1934960, 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.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.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.TXFINISHED), ]) _, serialized_tx = btc.sign_tx(self.client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API) assert ( serialized_tx.hex() == "01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000" )
def test_send_bch_multisig_change(self): self.setup_mnemonic_allallall() xpubs = [] for n in map( lambda index: btc.get_public_node( self.client, parse_path("44'/145'/%d'" % 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, ) inp1 = proto.TxInputType( address_n=parse_path("44'/145'/3'/0/0"), multisig=getmultisig(0, 0), # bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw amount=48490, prev_hash=bytes.fromhex( "8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0" ), prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, ) out1 = proto.TxOutputType( address="bitcoincash:qqq8gx2j76nw4dfefumxmdwvtf2tpsjznusgsmzex9", amount=24000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) out2 = proto.TxOutputType( address_n=parse_path("44'/145'/3'/1/0"), multisig=getmultisig(1, 0), script_type=proto.OutputScriptType.PAYTOMULTISIG, amount=24000, ) 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.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) (signatures1, serialized_tx) = btc.sign_tx(self.client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API) assert ( signatures1[0].hex() == "3045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85" ) inp1 = proto.TxInputType( address_n=parse_path("44'/145'/1'/0/0"), multisig=getmultisig(0, 0, [b"", b"", signatures1[0]]), # bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw amount=48490, prev_hash=bytes.fromhex( "8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0" ), prev_index=0, script_type=proto.InputScriptType.SPENDMULTISIG, ) out2.address_n[2] = H_(1) 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.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), 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.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) (signatures1, serialized_tx) = btc.sign_tx(self.client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API) assert ( signatures1[0].hex() == "3045022100f1153636371ba1f84389460e1265a8fa296569bc18e117c31f4e8f0fc0650c01022022932cc84766ff0c0f65ed9633ad311ae90d4c8fe71f5e1890b1e8f74dd516fa" ) assert ( serialized_tx.hex() == "0100000001a07660b10df9868df9393c9cf8962bc34f48cb2cea53b0865d2324bab8b96d8b00000000fdfe0000483045022100f1153636371ba1f84389460e1265a8fa296569bc18e117c31f4e8f0fc0650c01022022932cc84766ff0c0f65ed9633ad311ae90d4c8fe71f5e1890b1e8f74dd516fa41483045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85414c69522102fcf63419c319ce1a42d69120a3599d6da8c5dd4caf2888220eccde5a1ff7c5d021036d7d5ef79370b7fabe2c058698a20219e97fc70868e65ecdd6b37cc18e8a88bd2103505dc649dab8cd1655a4c0daf0ec5f955881c9d7011478ea881fac11cab1e49953aeffffffff02c05d0000000000001976a91400741952f6a6eab5394f366db5cc5a54b0c2429f88acc05d00000000000017a914756c06d7e77de3950a6124f026d8e1a2464b3ecf8700000000" )