def test_attack_change_outputs(self): # This unit test attempts to modify data sent during ping-pong of streaming signing. # Because device is asking for human confirmation only during first pass (first input), # device must detect that data has been modified during other passes and fail to sign # such modified data (which has not been confirmed by the user). # Test firstly prepare normal transaction and send it to device. Then it send the same # transaction again, but change amount of output 1 during signing the second input. self.setup_mnemonic_nopin_nopassphrase() inp1 = proto_types.TxInputType(address_n=[1], # 1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb # amount=100000, prev_hash=binascii.unhexlify('c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c'), prev_index=1, ) inp2 = proto_types.TxInputType(address_n=[2], # 15AeAhtNJNKyowK8qPHwgpXkhsokzLtUpG # amount=110000, prev_hash=binascii.unhexlify('58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e'), prev_index=1, ) out1 = proto_types.TxOutputType(address='15Jvu3nZNP7u2ipw2533Q9VVgEu2Lu9F2B', amount=210000 - 100000 - 10000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType(address_n=[3], # 1CmzyJp9w3NafXMSEFH4SLYUPAVCSUrrJ5 amount=100000, script_type=proto_types.PAYTOADDRESS, ) global run_attack run_attack = False def attack_processor(req, msg): global run_attack if req.details.tx_hash != b'': return msg if req.details.request_index != 1: return msg if not run_attack: run_attack = True return msg msg.outputs[0].amount = 9999999 # Sign output with another amount return msg # Test if the transaction can be signed normally (_, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, inp2], [out1, out2]) # Accepted by network: tx c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb self.assertEqual(binascii.hexlify(serialized_tx), '01000000021c032e5715d1da8115a2fe4f57699e15742fe113b0d2d1ca3b594649d322bec6010000006b483045022100f773c403b2f85a5c1d6c9c4ad69c43de66930fff4b1bc818eb257af98305546a0220443bde4be439f276a6ce793664b463580e210ec6c9255d68354449ac0443c76501210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6ffffffff6ea42cd8d9c8e5441c4c5f85bfe50311078730d2881494f11f4d2257777a4958010000006b48304502210090cff1c1911e771605358a8cddd5ae94c7b60cc96e50275908d9bf9d6367c79f02202bfa72e10260a146abd59d0526e1335bacfbb2b4401780e9e3a7441b0480c8da0121038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3ffffffff02a0860100000000001976a9142f4490d5263906e4887ca2996b9e207af3e7824088aca0860100000000001976a914812c13d97f9159e54e326b481b8f88a73df8507a88ac00000000') # Now run the attack, must trigger the exception self.assertRaises(CallException, self.client.sign_tx, 'Bitcoin', [inp1, inp2], [out1, out2], debug_processor=attack_processor)
def test_attack_change_outputs(self): # This unit test attempts to modify data sent during ping-pong of streaming signing. # Because device is asking for human confirmation only during first pass (first input), # device must detect that data has been modified during other passes and fail to sign # such modified data (which has not been confirmed by the user). # Test firstly prepare normal transaction and send it to device. Then it send the same # transaction again, but change amount of output 1 during signing the second input. self.setup_mnemonic_nopin_nopassphrase() inp1 = proto_types.TxInputType(address_n=[1], # 1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb # amount=100000, prev_hash=binascii.unhexlify('c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c'), prev_index=1, ) inp2 = proto_types.TxInputType(address_n=[2], # 15AeAhtNJNKyowK8qPHwgpXkhsokzLtUpG # amount=110000, prev_hash=binascii.unhexlify('58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e'), prev_index=1, ) out1 = proto_types.TxOutputType(address='15Jvu3nZNP7u2ipw2533Q9VVgEu2Lu9F2B', amount=210000 - 100000 - 10000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType(address_n=[3], # 1CmzyJp9w3NafXMSEFH4SLYUPAVCSUrrJ5 amount=100000, script_type=proto_types.PAYTOADDRESS, ) global run_attack run_attack = False def attack_processor(req, msg): global run_attack if req.details.tx_hash != b'': return msg if req.details.request_index != 1: return msg if not run_attack: run_attack = True return msg msg.outputs[0].amount = 9999999 # Sign output with another amount return msg # Test if the transaction can be signed normally (_, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, inp2], [out1, out2], None, True) # Accepted by network: tx c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb # Now run the attack, must trigger the exception pytest.raises(CallException, self.client.sign_tx, 'Bitcoin', [inp1, inp2], [out1, out2], 1, 0, attack_processor)
def test_two_two(self): self.setup_mnemonic_nopin_nopassphrase() # tx: c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c # input 1: 0.0010 BTC # tx: 58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e # input 1: 0.0011 BTC inp1 = proto_types.TxInputType(address_n=[1], # 1CK7SJdcb8z9HuvVft3D91HLpLC6KSsGb # amount=100000, prev_hash=binascii.unhexlify('c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c'), prev_index=1, ) inp2 = proto_types.TxInputType(address_n=[2], # 15AeAhtNJNKyowK8qPHwgpXkhsokzLtUpG # amount=110000, prev_hash=binascii.unhexlify('58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e'), prev_index=1, ) out1 = proto_types.TxOutputType(address='15Jvu3nZNP7u2ipw2533Q9VVgEu2Lu9F2B', amount=210000 - 100000 - 10000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType(address_n=[3], # 1CmzyJp9w3NafXMSEFH4SLYUPAVCSUrrJ5 amount=100000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, inp2], [out1, out2], None, True) # Accepted by network: tx c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb self.assertEqual(binascii.hexlify(serialized_tx), '01000000021c032e5715d1da8115a2fe4f57699e15742fe113b0d2d1ca3b594649d322bec6010000006b483045022100f773c403b2f85a5c1d6c9c4ad69c43de66930fff4b1bc818eb257af98305546a0220443bde4be439f276a6ce793664b463580e210ec6c9255d68354449ac0443c76501210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6ffffffff6ea42cd8d9c8e5441c4c5f85bfe50311078730d2881494f11f4d2257777a4958010000006b48304502210090cff1c1911e771605358a8cddd5ae94c7b60cc96e50275908d9bf9d6367c79f02202bfa72e10260a146abd59d0526e1335bacfbb2b4401780e9e3a7441b0480c8da0121038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3ffffffff02a0860100000000001976a9142f4490d5263906e4887ca2996b9e207af3e7824088aca0860100000000001976a914812c13d97f9159e54e326b481b8f88a73df8507a88ac00000000')
def test_send_mixed(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) inp1 = proto_types.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=123456789, prev_hash=unhexlify( '20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337' ), prev_index=0, script_type=proto_types.SPENDP2SHWITNESS, ) inp2 = proto_types.TxInputType( address_n=parse_path("44'/1'/0'/0/0"), # amount=31000000, prev_hash=unhexlify( 'e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd' ), prev_index=0, script_type=proto_types.PAYTOADDRESS, ) inp3 = proto_types.TxInputType( address_n=parse_path("84'/1'/0'/1/0"), amount=7289000, prev_hash=unhexlify( '65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b' ), prev_index=1, script_type=proto_types.SPENDWITNESS) out1 = proto_types.TxOutputType( address_n=parse_path("44'/1'/0'/1/0"), amount=900000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType( address='2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX', script_type=proto_types.PAYTOADDRESS, amount=123456789 + 31000000 + 7289000 - 9000000, ) with self.client: (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1, inp2, inp3], [out1, out2]) self.assertEquals( hexlify(serialized_tx), b'0100000000010337c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffffcd3b93f5b24ae190ce5141235091cd93fbb2908e24e5b9ff6776aec11b0e04e5000000006a47304402200451ce6fb777e9023a9d9e39370384de734562dc081ab75397d934b3be21218f02207882a9b1f1d27694bba71a9f4cf01eead6d4b517c5239cabe9042dc05a4b7dd10121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff02a0bb0d00000000001976a9143d3cca567e00a04819742b21a696a67da796498b88ac3db71a090000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca870247304402200a2e68318041e40d0ff6e87a070be4b80e48a756410d90551c9fdd733dbf2e1202201a853ac548f47fa1727019fc5cbc84c49678be6eed8554357c608ff7d2390db8012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b79000247304402202c14d58e6d0788ffd8165e4a5892dc39d0955a62c471125cc1771a37675dc0e402203e52c774404200bfefbbbe07153bf96efa7787b1607f4b1437c3857380e034c4012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f00000000' )
def test_nonzero_opreturn(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) out1 = proto_types.TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=390000 - 10000 - 10000, script_type=proto_types.PAYTOADDRESS, ) out1 = proto_types.TxOutputType(op_return_data=b'test of the op_return data', amount=10000, script_type=proto_types.PAYTOOPRETURN, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.Failure() ]) self.assertRaises(CallException, self.client.sign_tx, 'Bitcoin', [inp1, ], [out1, ])
def test_sign_btc_eth_swap(self): self.requires_firmware("7.0.2") self.setup_mnemonic_nopin_nopassphrase() inp1 = proto_types.TxInputType( address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=unhexlify( 'd5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882' ), prev_index=0, ) out1 = proto_types.TxOutputType( op_return_data= b'SWAP:ETH.ETH:0x41e5560054824ea6b0732e656e3ad64e20e94e45:420', amount=0, script_type=proto_types.PAYTOOPRETURN, ) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [ inp1, ], [ out1, ]) self.assertEqual( hexlify(serialized_tx), '010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b483045022100c1cf12191f0a50398dae21553d14d5c796ff3e2e1c378bce3d0a7d43fa9bdf4402201245f76291db518dd8b496b4406128ca0e07165c64d2fe927161eee17402f9c40121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0100000000000000003d6a3b535741503a4554482e4554483a3078343165353536303035343832346561366230373332653635366533616436346532306539346534353a34323000000000' )
def test_sign_btc_add_liquidity(self): self.requires_firmware("7.0.2") self.setup_mnemonic_nopin_nopassphrase() inp1 = proto_types.TxInputType( address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=unhexlify( 'd5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882' ), prev_index=0, ) out1 = proto_types.TxOutputType( op_return_data= b'ADD:BTC.BTC:thorpub1addwnpepq2ynqt500fag3wyxsjuv7570qxr8rqtpx93hw3cpqaqxtwxesy76utgtemp:420', amount=0, script_type=proto_types.PAYTOOPRETURN, ) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [ inp1, ], [ out1, ]) self.assertEqual( hexlify(serialized_tx), '010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b483045022100ed9206af5ba7fe82dda17cf20574197924a120be5b415f875f7d9880f4591e4202201081cb688cceadad65dc20e9843d910d895342ce9316f792b748b0e4a0f757870121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0100000000000000005e6a4c5b4144443a4254432e4254433a74686f7270756231616464776e7065707132796e717435303066616733777978736a7576373537307178723872717470783933687733637071617178747778657379373675746774656d703a34323000000000' )
def test_spend_coinbase(self): # 25 TEST generated to m/1 (mfiGQVPcRcaEvQPYDErR34DcCovtxYvUUV) # tx: d6da21677d7cca5f42fbc7631d062c9ae918a0254f7c6c22de8e8cb7fd5b8236 # input 0: 25.0027823 BTC self.setup_mnemonic_nopin_nopassphrase() inp1 = proto_types.TxInputType(address_n=[1], # mfiGQVPcRcaEvQPYDErR34DcCovtxYvUUV # amount=390000, prev_hash=binascii.unhexlify('d6da21677d7cca5f42fbc7631d062c9ae918a0254f7c6c22de8e8cb7fd5b8236'), prev_index=0, ) out1 = proto_types.TxOutputType(address='mm6FM31rM5Vc3sw5D7kztiBg3jHUzyqF1g', amount=2500278230 - 10000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_tx_api(tx_api.TxApiTestnet) self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d6da21677d7cca5f42fbc7631d062c9ae918a0254f7c6c22de8e8cb7fd5b8236"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1, ], [out1, ], None, True) # Accepted by network: tx self.assertEqual(binascii.hexlify(serialized_tx), '010000000136825bfdb78c8ede226c7c4f25a018e99a2c061d63c7fb425fca7c7d6721dad6000000006a473044022047845c366eb24f40be315c7815a154513c444c7989eb80f7ce7ff6aeb703d26a022007c1f5efadf67c5889634fd7ac39a7ce78bffac291673e8772ecd8389c901d9f01210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6ffffffff01c6100795000000001976a9143d2496e67f5f57a924353da42d4725b318e7a8ea88ac00000000')
def prepare_transfer_tx(hw_session: HwSessionInfo, utxos_to_spend: List[dict], dest_addresses: List[Tuple[str, int, str]], tx_fee): """ Creates a signed transaction. :param hw_session: :param utxos_to_spend: list of utxos to send :param dest_address: destination (Dash) address :param tx_fee: transaction fee :return: tuple (serialized tx, total transaction amount in satoshis) """ insight_network = 'insight_dash' if hw_session.app_config.is_testnet(): insight_network += '_testnet' dash_network = hw_session.app_config.dash_network tx_api = MyTxApiInsight(insight_network, '', hw_session.zyrkd_intf, hw_session.app_config.cache_dir) client = hw_session.hw_client client.set_tx_api(tx_api) inputs = [] outputs = [] inputs_amount = 0 for utxo_index, utxo in enumerate(utxos_to_spend): if not utxo.get('bip32_path', None): raise Exception('No BIP32 path for UTXO ' + utxo['txid']) address_n = client.expand_path(clean_bip32_path(utxo['bip32_path'])) it = proto_types.TxInputType(address_n=address_n, prev_hash=binascii.unhexlify(utxo['txid']), prev_index=utxo['outputIndex']) inputs.append(it) inputs_amount += utxo['satoshis'] outputs_amount = 0 for addr, amount, bip32_path in dest_addresses: outputs_amount += amount if addr[0] in dash_utils.get_chain_params(dash_network).B58_PREFIXES_SCRIPT_ADDRESS: stype = proto_types.PAYTOSCRIPTHASH logging.debug('Transaction type: PAYTOSCRIPTHASH' + str(stype)) elif addr[0] in dash_utils.get_chain_params(dash_network).B58_PREFIXES_PUBKEY_ADDRESS: stype = proto_types.PAYTOADDRESS logging.debug('Transaction type: PAYTOADDRESS ' + str(stype)) else: raise Exception('Invalid prefix of the destination address.') if bip32_path: address_n = client.expand_path(bip32_path) else: address_n = None ot = proto_types.TxOutputType( address=addr if address_n is None else None, address_n=address_n, amount=amount, script_type=stype ) outputs.append(ot) if outputs_amount + tx_fee != inputs_amount: raise Exception('Transaction validation failure: inputs + fee != outputs') signed = client.sign_tx(hw_session.app_config.hw_coin_name, inputs, outputs) logging.info('Signed transaction') return signed[1], inputs_amount
def test_fee_too_high(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) out1 = proto_types.TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=390000 - 250000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_FeeOverThreshold), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, ], None, True) self.assertEqual(binascii.hexlify(serialized_tx), '010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b483045022100a3b17b37de3bfecca47f0d49f7bb0d0f68d45df7defe45713d57e83731f5e3d902205404b14630cea6a88b23a5f7c3a1b88494757a8ca5e1c0b0b93cf3c38231c3bd0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff01e0220200000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000')
def test_two_zero_signature(self): self.setup_mnemonic_nopin_nopassphrase() inp1 = proto_types.TxInputType( address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify( 'd5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882' ), prev_index=0, ) # Following address_n has been mined by 'test_mine_zero_signature' out1 = proto_types.TxOutputType( address_n=[16518], amount=390000 - 10000, script_type=proto_types.PAYTOADDRESS, ) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [ inp1, ], [ out1, ]) siglen = ord(serialized_tx[44]) # KeepKey must strip leading zero from signature self.assertEqual(siglen, 66)
def test_one_one_fee(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) out1 = proto_types.TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=390000 - 10000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, ], None, True) # Accepted by network: tx fd79435246dee76b2f159d2db08032d666c95adc544de64c8c49f474df4a7fee self.assertEqual(binascii.hexlify(serialized_tx), '010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b4830450221009a0b7be0d4ed3146ee262b42202841834698bb3ee39c24e7437df208b8b7077102202b79ab1e7736219387dffe8d615bbdba87e11477104b867ef47afed1a5ede7810121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0160cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000')
def test_estimate_size(self): self.setup_mnemonic_nopin_nopassphrase() inp1 = proto_types.TxInputType( address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify( 'd5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882' ), prev_index=0, ) out1 = proto_types.TxOutputType( address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=390000 - 10000, script_type=proto_types.PAYTOADDRESS, ) est_size = self.client.estimate_tx_size('Bitcoin', [ inp1, ], [ out1, ]) self.assertEqual(est_size, 194) (_, tx) = self.client.sign_tx('Bitcoin', [ inp1, ], [ out1, ]) real_size = len(tx) self.assertGreaterEqual(est_size, real_size)
def prepare_transfer_tx(main_ui, utxos_to_spend, dest_address, tx_fee): """ Creates a signed transaction. :param main_ui: Main window for configuration data :param utxos_to_spend: list of utxos to send :param dest_address: destination (Dash) address :param tx_fee: transaction fee :return: tuple (serialized tx, total transaction amount in satoshis) """ tx_api = MyTxApiInsight('insight_dash', None, main_ui.dashd_intf, main_ui.config.cache_dir) client = main_ui.hw_client client.set_tx_api(tx_api) inputs = [] outputs = [] amt = 0 for utxo in utxos_to_spend: if not utxo.get('bip32_path', None): raise Exception('No BIP32 path for UTXO ' + utxo['txid']) address_n = client.expand_path(utxo['bip32_path']) it = proto_types.TxInputType(address_n=address_n, prev_hash=binascii.unhexlify( utxo['txid']), prev_index=utxo['outputIndex']) inputs.append(it) amt += utxo['satoshis'] amt -= tx_fee amt = int(amt) ot = proto_types.TxOutputType(address=dest_address, amount=amt, script_type=proto_types.PAYTOADDRESS) outputs.append(ot) signed = client.sign_tx('Dash', inputs, outputs) return signed[1], amt
def test_p2sh(self): self.setup_mnemonic_nopin_nopassphrase() inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=400000, prev_hash=binascii.unhexlify('54aa5680dea781f45ebb536e53dffc526d68c0eb5c00547e323b2c32382dfba3'), prev_index=1, ) out1 = proto_types.TxOutputType(address='3DKGE1pvPpBAgZj94MbCinwmksewUNNYVR', # p2sh amount=400000 - 10000, script_type=proto_types.PAYTOSCRIPTHASH, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("54aa5680dea781f45ebb536e53dffc526d68c0eb5c00547e323b2c32382dfba3"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("54aa5680dea781f45ebb536e53dffc526d68c0eb5c00547e323b2c32382dfba3"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("54aa5680dea781f45ebb536e53dffc526d68c0eb5c00547e323b2c32382dfba3"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("54aa5680dea781f45ebb536e53dffc526d68c0eb5c00547e323b2c32382dfba3"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, ]) # Accepted by network: tx 8cc1f4adf7224ce855cf535a5104594a0004cb3b640d6714fdb00b9128832dd5 self.assertEqual(binascii.hexlify(serialized_tx), '0100000001a3fb2d38322c3b327e54005cebc0686d52fcdf536e53bb5ef481a7de8056aa54010000006b4830450221009e020b0390ccad533b73b552f8a99a9d827212c558e4f755503674d07c92ad4502202d606f7316990e0461c51d4add25054f19c697aa3e3c2ced4d568f0b2c57e62f0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0170f305000000000017a9147f844bdb0b8fd54b64e3d16c85dc1170f1ff97c18700000000')
def test_not_enough_funds(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) out1 = proto_types.TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=400000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.Failure(code=proto_types.Failure_NotEnoughFunds) ]) try: self.client.sign_tx('Bitcoin', [inp1, ], [out1, ]) except CallException as e: self.assertEqual(e.args[0], proto_types.Failure_NotEnoughFunds) else: self.assert_(False, "types.Failure_NotEnoughFunds expected")
def test_send_p2sh_change(self): self.setup_mnemonic_allallall() self.client.set_tx_api(TxApiTestnet) inp1 = proto_types.TxInputType( address_n=parse_path("49'/1'/0'/1/0"), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX amount=123456789, prev_hash=unhexlify( '20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337' ), prev_index=0, script_type=proto_types.SPENDP2SHWITNESS, ) out1 = proto_types.TxOutputType( address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC', amount=12300000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType( address_n=parse_path("49'/1'/0'/1/0"), script_type=proto_types.PAYTOP2SHWITNESS, amount=123456789 - 11000 - 12300000, ) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest( request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest( code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest( request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest( request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest( request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest( request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest( request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1, out2]) self.assertEquals( hexlify(serialized_tx), b'0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000' )
def test_one_three_fee(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) # Spend Output address out1 = proto_types.TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=390000 - 80000 - 12000 - 10000, script_type=proto_types.PAYTOADDRESS, address_type=0, ) # Transfer Output address out2 = proto_types.TxOutputType(address_n=[0x8000002c, 0x80000000, 0x80000000, 0, 0 ], amount=10000, script_type=proto_types.PAYTOADDRESS, address_type=1, ) # Change Output address out3 = proto_types.TxOutputType(address_n=[0x8000002c, 0x80000000, 0x80000000, 1, 1 ], amount=80000, script_type=proto_types.PAYTOADDRESS, address_type=2, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmTransferToAccount), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=2)), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=2)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=2)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, out2, out3]) self.assertEqual(binascii.hexlify(serialized_tx), '010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b483045022100c3ceed2bd2365ccdb978d605e9ae6347790b978e2747bbbec623364270be723c022017680d050c2bf0dae4bd249d83b43bc93a33661c1a0b18c7e8a05eb47815f9aa0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0300650400000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac10270000000000001976a9149c9d21f47382762df3ad81391ee0964b28dd951788ac80380100000000001976a914db302d9f1dd36faa220d8dfd7ff18ff5e308a53688ac00000000')
def test_signtx(self): self.setup_mnemonic_pin_passphrase() inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) out1 = proto_types.TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=390000 - 10000, script_type=proto_types.PAYTOADDRESS, ) tx_responses = [ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXFINISHED), ] self.client.clear_session() with self.client: # Pin & Passphrase are needed after device is locked self.client.set_expected_responses([ proto.PinMatrixRequest(), proto.PassphraseRequest(), ] + tx_responses) self.client.sign_tx('Bitcoin', [inp1, ], [out1, ]) with self.client: # Pin & Passphrase not needed, since they're cached, and the device is unlocked self.client.set_expected_responses([ ] + tx_responses) self.client.sign_tx('Bitcoin', [inp1, ], [out1, ]) self.client.clear_session() with self.client: # Pin & Passphrase needed again after session is cleared, and the device is locked self.client.set_expected_responses([ proto.PinMatrixRequest(), proto.PassphraseRequest(), ] + tx_responses) self.client.sign_tx('Bitcoin', [inp1, ], [out1, ])
def test_missing_pubkey(self): self.setup_mnemonic_nopin_nopassphrase() #key1 = self.client.get_public_node([1]) #key2 = self.client.get_public_node([2]) #key3 = self.client.get_public_node([3]) # pubkeys: # 0338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6 # 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3 # 03477b9f0f34ae85434ce795f0c5e1e90c9420e5b5fad084d7cce9a487b94a7902 # multisig address: 3E7GDtuHqnqPmDgwH59pVC7AvySiSkbibz # xpub: # print(ckd_public.serialize(self.client.get_public_node([]).node)) # xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy node = ckd_public.deserialize( 'xpub661MyMwAqRbcF1zGijBb2K6x9YiJPh58xpcCeLvTxMX6spkY3PcpJ4ABcCyWfskq5DDxM3e6Ez5ePCqG5bnPUXR4wL8TZWyoDaUdiWW7bKy' ) multisig = proto_types.MultisigRedeemScriptType( pubkeys=[ proto_types.HDNodePathType(node=node, address_n=[1]), proto_types.HDNodePathType(node=node, address_n=[2]), proto_types.HDNodePathType(node=node, address_n=[3]) ], signatures=['', '', ''], m=2, ) # Let's go to sign with key 10, which is NOT in pubkeys inp1 = proto_types.TxInputType( address_n=[10], prev_hash=binascii.unhexlify( 'c6091adf4c0c23982a35899a6e58ae11e703eacd7954f588ed4b9cdefc4dba52' ), prev_index=1, script_type=proto_types.SPENDMULTISIG, multisig=multisig, ) out1 = proto_types.TxOutputType( address='12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss', amount=100000, script_type=proto_types.PAYTOADDRESS) with self.client: # It should throw Failure 'Pubkey not found in multisig script' self.assertRaises(CallException, self.client.sign_tx, 'Bitcoin', [ inp1, ], [ out1, ])
def test_one_three_fee(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) out1 = proto_types.TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=390000 - 80000 - 12000 - 10000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType(address='13uaUYn6XAooo88QvAqAVsiVvr2mAXutqP', amount=12000, script_type=proto_types.PAYTOADDRESS, ) out3 = proto_types.TxOutputType(address_n=[1], amount=80000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=2)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=2)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=2)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, out2, out3]) self.assertEqual(binascii.hexlify(serialized_tx), '010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b483045022100e695e2c530c7c0fc32e6b79b7cff56a7f70a8c9da787534f46b4204070f914fc02207b0879a81408a11e23b11d4c7965c62b5fc6d5c2d92340f5ee2da7b40e99314a0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0300650400000000001976a914de9b2a8da088824e8fe51debea566617d851537888ace02e0000000000001976a9141fe1d337fb81afca42818051e12fd18245d1b17288ac80380100000000001976a9140223b1a09138753c9cb0baf95a0a62c82711567a88ac00000000')
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_types.MultisigRedeemScriptType( pubkeys=list(map(lambda n: proto_types.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 0]), nodes)), signatures=[b'', b'', b''], m=2, ) inp1 = proto_types.TxInputType( address_n=parse_path("999'/1'/1'/2/0"), prev_hash=unhexlify('9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be'), prev_index=1, script_type=proto_types.SPENDP2SHWITNESS, multisig=multisig, amount=1610436 ) out1 = proto_types.TxOutputType(address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC', amount=1605000, script_type=proto_types.PAYTOADDRESS) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.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_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures2, serialized_tx) = self.client.sign_tx('Testnet', [inp1], [out1]) self.assertEqual(hexlify(serialized_tx), b'01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1ffffffff01887d1800000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac040047304402205b44c20cf2681690edaaf7cd2e30d4704124dd8b7eb1fb7f459d3906c3c374a602205ca359b6544ce2c101c979899c782f7d141c3b0454ea69202b1fb4c09d3b715701473044022052fafa64022554ae436dbf781e550bf0d326fef31eea1438350b3ff1940a180102202851bd19203b7fe8582a9ef52e82aa9f61cd52d4bcedfe6dcc0cf782468e6a8e01695221038e81669c085a5846e68e03875113ddb339ecbb7cb11376d4163bca5dc2e2a0c1210348c5c3be9f0e6cf1954ded1c0475beccc4d26aaa9d0cce2dd902538ff1018a112103931140ebe0fbbb7df0be04ed032a54e9589e30339ba7bbb8b0b71b15df1294da53ae00000000')
def test_xfer_change_fee(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) # Transfer Output address out1 = proto_types.TxOutputType(address_n=[0x8000002c, 0x80000000, 0x80000000, 0, 0 ], amount=390000 - 10000, script_type=proto_types.PAYTOADDRESS, address_type=1, ) # Change Output address out2 = proto_types.TxOutputType(address_n=[0x8000002c, 0x80000000, 0x80000000, 1, 1 ], amount=8000, script_type=proto_types.PAYTOADDRESS, address_type=2, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmTransferToAccount), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, out2]) self.assertEqual(binascii.hexlify(serialized_tx), '010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006a473044022029270ff6991d953cb89135dc43723a64f5be00a69db42efeb845f2918dec50c302201f6589bb44c9c4b6c8152966d5de9b56c2a6ca61172d0f63c6c62e48ad8975130121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0260cc0500000000001976a9149c9d21f47382762df3ad81391ee0964b28dd951788ac401f0000000000001976a914db302d9f1dd36faa220d8dfd7ff18ff5e308a53688ac00000000')
def test_testnet_one_two_fee(self): self.setup_mnemonic_allallall() # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56 # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd # input 0: 0.31 BTC inp1 = proto_types.TxInputType( address_n=parse_path("44'/1'/0'/0/0"), # amount=31000000, prev_hash=TXHASH_e5040e, prev_index=0, ) out1 = proto_types.TxOutputType( address='msj42CCGruhRsFrGATiUuh25dtxYtnpbTx', amount=30090000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType( address_n=parse_path("44'/1'/0'/1/0"), amount=900000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_tx_api(tx_api.TxApiTestnet) self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=TXHASH_e5040e)), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_e5040e)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_e5040e)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_e5040e)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1, ], [out1, out2]) self.assertEqual(binascii.hexlify(serialized_tx), b'0100000001cd3b93f5b24ae190ce5141235091cd93fbb2908e24e5b9ff6776aec11b0e04e5000000006b483045022100eba3bbcbb82ab1ebac88a394e8fb53b0263dadbb3e8072f0a21ee62818c911060220686a9b7f306d028b54a228b5c47cc6c27b1d01a3b0770440bcc64d55d8bace2c0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff021023cb01000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288aca0bb0d00000000001976a9143d3cca567e00a04819742b21a696a67da796498b88ac00000000')
def test_testnet_one_two_fee(self): self.setup_mnemonic_nopin_nopassphrase() # tx: 6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54 # input 1: 10.00000000 BTC inp1 = proto_types.TxInputType(address_n=[0], # mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL # amount=1000000000, prev_hash=binascii.unhexlify('6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54'), prev_index=1, ) out1 = proto_types.TxOutputType(address='mfiGQVPcRcaEvQPYDErR34DcCovtxYvUUV', amount=1000000000 - 500000000 - 10000000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType(address_n=[2], amount=500000000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_tx_api(tx_api.TxApiTestnet) self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_FeeOverThreshold), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1, ], [out1, out2]) self.assertEqual(binascii.hexlify(serialized_tx), '0100000001549d2977998f899a63c0a9da30dedb2841e33fef561097b05822eccbc7f3906f010000006b4830450221009c2d30385519fdb13dce13d5ac038be07d7b2dad0b0f7b2c1c339d7255bcf553022056a2f5bceab3cd0ffed4d388387e631f419d67ff9ce7798e3d7dfe6a6d6ec4bd0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0280ce341d000000001976a9140223b1a09138753c9cb0baf95a0a62c82711567a88ac0065cd1d000000001976a9142db345c36563122e2fd0f5485fb7ea9bbf7cb5a288ac00000000')
def test_testnet_fee_too_high(self): self.setup_mnemonic_nopin_nopassphrase() # tx: 6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54 # input 1: 10.00000000 BTC inp1 = proto_types.TxInputType(address_n=[0], # mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL # amount=1000000000, prev_hash=binascii.unhexlify('6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54'), prev_index=1, ) out1 = proto_types.TxOutputType(address='mfiGQVPcRcaEvQPYDErR34DcCovtxYvUUV', amount=1000000000 - 500000000 - 100000000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType(address_n=[2], amount=500000000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_tx_api(tx_api.TxApiTestnet) self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_FeeOverThreshold), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Testnet', [inp1, ], [out1, out2]) self.assertEqual(binascii.hexlify(serialized_tx), '0100000001549d2977998f899a63c0a9da30dedb2841e33fef561097b05822eccbc7f3906f010000006a47304402205ea68e9d52d4be14420ccecf7f2e11489d49b86bedb79ee99b5e9b7188884150022056219cb3384a5df8048cca286a9533403dbda1571afd84b51379cdaee6a6dea80121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff020084d717000000001976a9140223b1a09138753c9cb0baf95a0a62c82711567a88ac0065cd1d000000001976a9142db345c36563122e2fd0f5485fb7ea9bbf7cb5a288ac00000000')
def test_one_two_fee(self): self.setup_mnemonic_allallall() # tx: c275c333fd1b36bef4af316226c66a8b3693fbfcc081a5e16a2ae5fcb09e92bf inp1 = proto_types.TxInputType( address_n=parse_path("m/44'/0'/0'/0/5"), # 1GA9u9TfCG7SWmKCveBumdA1TZpfom6ZdJ # amount=50000, prev_hash=TXHASH_50f6f1, prev_index=1, ) out1 = proto_types.TxOutputType( address_n=parse_path("m/44'/0'/0'/1/3"), # 1EcL6AyfQTyWKGvXwNSfsWoYnD3whzVFdu amount=30000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType( address='1Up15Msx4sbvUCGm8Xgo2Zp5FQim3wE59', amount=10000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=TXHASH_50f6f1)), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_50f6f1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=TXHASH_50f6f1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=TXHASH_50f6f1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, out2]) self.assertEqual(binascii.hexlify(serialized_tx), b'01000000016d20f69067ad1ffd50ee7c0f377dde2c932ccb03e84b5659732da99c20f1f650010000006a47304402203429bd3ce7b38c5c1e8a15340edd79ced41a2939aae62e259d2e3d18e0c5ee7602201b83b10ebc4d6dcee3f9eb42ba8f1ef8a059a05397e0c1b9223d1565a3e6ec01012102a7a079c1ef9916b289c2ff21a992c808d0de3dfcf8a9f163205c5c9e21f55d5cffffffff0230750000000000001976a914954820f1de627a703596ac0396f986d958e3de4c88ac10270000000000001976a91405427736705cfbfaff76b1cff48283707fb1037088ac00000000')
def test_opreturn(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) out1 = proto_types.TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=390000 - 10000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType(op_return_data=b'test of the op_return data', amount=0, script_type=proto_types.PAYTOOPRETURN, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, out2]) self.assertEqual(binascii.hexlify(serialized_tx), '010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006a4730440220187b7b9c340a32fc8445418ad11fb3827d2e8bac7d730e1c9ad800353e7ba62f02206c0c5820ba8882c82923a39aee8d36d6d32e13daed73f7a3d6199de5f8e7ddfd0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0260cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000000000001c6a1a74657374206f6620746865206f705f72657475726e206461746100000000')
def test_opreturn_big(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) out1 = proto_types.TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=390000 - 10000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType(op_return_data=b'FOXY' * 20, amount=0, script_type=proto_types.PAYTOOPRETURN, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, out2]) self.assertEqual(binascii.hexlify(serialized_tx), '010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b483045022100a67a06774d3cdeda9201cec30a98994bf27dea55c2a684e9a2a7a3cf61b182d5022074671fa54005877d046dbc830dea43cdee666883fdb950470df65bea05a9978e0121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff0260cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac0000000000000000536a4c50464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f5859464f585900000000')
def test_one_two_fee(self): self.setup_mnemonic_nopin_nopassphrase() # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = proto_types.TxInputType(address_n=[0], # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e # amount=390000, prev_hash=binascii.unhexlify('d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882'), prev_index=0, ) out1 = proto_types.TxOutputType(address='1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1', amount=390000 - 80000 - 10000, script_type=proto_types.PAYTOADDRESS, ) out2 = proto_types.TxOutputType(address_n=[1], amount=80000, script_type=proto_types.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXMETA, details=proto_types.TxRequestDetailsType(tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=1, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0, tx_hash=binascii.unhexlify("d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882"))), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.ButtonRequest(code=proto_types.ButtonRequest_ConfirmOutput), proto.ButtonRequest(code=proto_types.ButtonRequest_SignTx), proto.TxRequest(request_type=proto_types.TXINPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=0)), proto.TxRequest(request_type=proto_types.TXOUTPUT, details=proto_types.TxRequestDetailsType(request_index=1)), proto.TxRequest(request_type=proto_types.TXFINISHED), ]) (signatures, serialized_tx) = self.client.sign_tx('Bitcoin', [inp1, ], [out1, out2]) self.assertEqual(binascii.hexlify(serialized_tx), '010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b483045022100c1400d8485d3bdcae7413e123148f35ece84806fc387ab88c66b469df89aef1702201d481d04216b319dc549ffe2333143629ba18828a4e2d1783ab719a6aa263eb70121023230848585885f63803a0a8aecdd6538792d5c539215c91698e315bf0253b43dffffffff02e0930400000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac80380100000000001976a9140223b1a09138753c9cb0baf95a0a62c82711567a88ac00000000')