def test_lots_of_inputs(self, client): # Tests if device implements serialization of len(inputs) correctly # tx 4a7b7e0403ae5607e473949cfa03f09f2cd8b0f404bf99ce10b7303d86280bf7 : 100 UTXO for spending for unit tests inputs = [] for i in range(100): inputs.append( messages.TxInputType( address_n=parse_path(f"44h/0h/0h/0/{i}"), prev_hash=TXHASH_4a7b7e, prev_index=i, )) out = messages.TxOutputType( address="19dvDdyxxptP9dGvozYe8BP6tgFV9L4jg5", amount=100 * 26000 - 15 * 10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) _, serialized_tx = btc.sign_tx(client, "Bitcoin", inputs, [out], prev_txes=TX_CACHE_MAINNET) assert ( tx_hash(serialized_tx).hex() == "f90cdc2224366312be28166e2afe198ece7a60e86e25f5a50f5b14d811713da8")
def test_spend_coinbase(self, client): inp1 = messages.TxInputType( address_n=parse_path("44h/1h/0h/0/0"), amount=2500278230, prev_hash=TXHASH_d6da21, prev_index=0, ) out1 = messages.TxOutputType( address="mm6FM31rM5Vc3sw5D7kztiBg3jHUzyqF1g", amount=2500278230 - 10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses([ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_d6da21), request_input(0, TXHASH_d6da21), request_output(0, TXHASH_d6da21), request_input(0), request_output(0), request_output(0), request_finished(), ]) _, serialized_tx = btc.sign_tx(client, "Testnet", [inp1], [out1], prev_txes=TX_CACHE_TESTNET) # Accepted by network: tx assert ( tx_hash(serialized_tx).hex() == "cf5a8ad5a4f0211953e0d40d9145d6651f0d90203e52913e780065bd00840da3")
def test_p2sh(self, client): inp1 = messages.TxInputType( address_n=parse_path("44h/0h/0h/0/0"), amount=400000, prev_hash=TXHASH_54aa56, prev_index=1, ) out1 = messages.TxOutputType( address="3DKGE1pvPpBAgZj94MbCinwmksewUNNYVR", # p2sh amount=400000 - 10000, script_type=messages.OutputScriptType.PAYTOSCRIPTHASH, ) with client: client.set_expected_responses([ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(TXHASH_54aa56), request_input(0, TXHASH_54aa56), request_output(0, TXHASH_54aa56), request_output(1, TXHASH_54aa56), request_input(0), request_output(0), request_output(0), request_finished(), ]) _, serialized_tx = btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET) assert ( tx_hash(serialized_tx).hex() == "5042aed319b9f018d693dbf8f3db926ee4ab4dae670a2911625b440a1366f79d")
def test_15_of_15(self, client): node = btc.get_public_node( client, parse_path("48h/0h/1h/0"), coin_name="Bitcoin" ).node pubs = [proto.HDNodePathType(node=node, address_n=[x]) for x in range(15)] signatures = [b""] * 15 out1 = proto.TxOutputType( address="17kTB7qSk3MupQxWdiv5ZU3zcrZc2Azes1", amount=10000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) for x in range(15): multisig = proto.MultisigRedeemScriptType( pubkeys=pubs, signatures=signatures, m=15 ) inp1 = proto.TxInputType( address_n=parse_path(f"48h/0h/1h/0/{x}"), prev_hash=TXHASH_6189e3, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) with client: sig, serialized_tx = btc.sign_tx( client, "Bitcoin", [inp1], [out1], prev_txes=TX_API ) signatures[x] = sig[0] assert ( tx_hash(serialized_tx).hex() == "3bffdb495711c57b0e2cd4e0dbd0ddbccf28052aa67466eafa2d4f666e797e5f" )
def test_attack_change_outputs(self, client): inp1 = messages.TxInputType( address_n=parse_path("44h/0h/0h/0/0"), # amount=100000, prev_hash=TXHASH_c6be22, prev_index=1, ) inp2 = messages.TxInputType( address_n=parse_path("44h/0h/0h/0/1"), # amount=110000, prev_hash=TXHASH_58497a, prev_index=1, ) out1 = messages.TxOutputType( address="15Jvu3nZNP7u2ipw2533Q9VVgEu2Lu9F2B", amount=210000 - 100000 - 10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address_n=parse_path("44h/0h/0h/1/0"), amount=100000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) # Test if the transaction can be signed normally _, serialized_tx = btc.sign_tx(client, "Bitcoin", [inp1, inp2], [out1, out2], prev_txes=TX_CACHE_MAINNET) assert ( tx_hash(serialized_tx).hex() == "4601b738e1b0f8a7ff9ca5adf0c896fa39dfe8b8ead7ad0d716c98167e8a5d11") run_attack = False def attack_processor(msg): nonlocal run_attack if msg.tx.outputs and msg.tx.outputs[0] == out2: if not run_attack: run_attack = True else: # Sign output with another amount msg.tx.outputs[0].amount = 9999999 return msg # Set up attack processors client.set_filter(messages.TxAck, attack_processor) with pytest.raises(TrezorFailure, match="Transaction has changed during signing"): btc.sign_tx( client, "Bitcoin", [inp1, inp2], [out1, out2], prev_txes=TX_CACHE_MAINNET, )
def test_lots_of_change(self, client): # Tests if device implements prompting for multiple change addresses correctly # tx: c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb # index 1: 0.0010 BTC # tx: 39a29e954977662ab3879c66fb251ef753e0912223a83d1dcb009111d28265e5 # index 1: 0.0254 BTC inp1 = messages.TxInputType( address_n=parse_path("44h/0h/1h/0/0"), # amount=100000, prev_hash=TXHASH_c63e24, prev_index=1, ) inp2 = messages.TxInputType( address_n=parse_path("44h/0h/1h/0/1"), # amount=2540000, prev_hash=TXHASH_39a29e, prev_index=1, ) outputs = [ messages.TxOutputType( address="1NwN6UduuVkJi6sw3gSiKZaCY5rHgVXC2h", amount=500000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) ] cnt = 20 for i in range(cnt): out = messages.TxOutputType( address_n=parse_path(f"44h/0h/1h/1/{i}"), amount=(100000 + 2540000 - 500000 - 39000) // cnt, script_type=messages.OutputScriptType.PAYTOADDRESS, ) outputs.append(out) request_change_outputs = [request_output(i + 1) for i in range(cnt)] with client: client.set_expected_responses( [ request_input(0), request_meta(TXHASH_c63e24), request_input(0, TXHASH_c63e24), request_input(1, TXHASH_c63e24), request_output(0, TXHASH_c63e24), request_output(1, TXHASH_c63e24), request_input(1), request_meta(TXHASH_39a29e), request_input(0, TXHASH_39a29e), request_output(0, TXHASH_39a29e), request_output(1, TXHASH_39a29e), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), ] + request_change_outputs + [ messages.ButtonRequest(code=B.SignTx), messages.ButtonRequest(code=B.SignTx), request_input(0), request_input(1), request_output(0), ] + request_change_outputs + [request_input(0), request_input(1), request_output(0)] + request_change_outputs + [request_output(0)] + request_change_outputs + [request_finished()]) _, serialized_tx = btc.sign_tx(client, "Bitcoin", [inp1, inp2], outputs, prev_txes=TX_CACHE_MAINNET) assert ( tx_hash(serialized_tx).hex() == "fae68e4a3a4b0540eb200e2218a6d8465eac469788ccb236e0d5822d105ddde9")
def test_two_two(self, client): # tx: c6be22d34946593bcad1d2b013e12f74159e69574ffea21581dad115572e031c # input 1: 0.0010 BTC # tx: 58497a7757224d1ff1941488d23087071103e5bf855f4c1c44e5c8d9d82ca46e # input 1: 0.0011 BTC inp1 = messages.TxInputType( address_n=parse_path("44h/0h/0h/0/0"), # amount=100000, prev_hash=TXHASH_c6be22, prev_index=1, ) inp2 = messages.TxInputType( address_n=parse_path("44h/0h/0h/0/1"), # amount=110000, prev_hash=TXHASH_58497a, prev_index=1, ) out1 = messages.TxOutputType( address="15Jvu3nZNP7u2ipw2533Q9VVgEu2Lu9F2B", amount=210000 - 100000 - 10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address_n=parse_path("44h/0h/0h/1/0"), amount=100000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses([ request_input(0), request_meta(TXHASH_c6be22), request_input(0, TXHASH_c6be22), request_output(0, TXHASH_c6be22), request_output(1, TXHASH_c6be22), request_input(1), request_meta(TXHASH_58497a), request_input(0, TXHASH_58497a), request_output(0, TXHASH_58497a), request_output(1, TXHASH_58497a), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), messages.ButtonRequest(code=B.SignTx), request_input(0), request_input(1), request_output(0), request_output(1), request_input(0), request_input(1), request_output(0), request_output(1), request_output(0), request_output(1), request_finished(), ]) _, serialized_tx = btc.sign_tx( client, "Bitcoin", [inp1, inp2], [out1, out2], prev_txes=TX_CACHE_MAINNET, ) # Accepted by network: tx c63e24ed820c5851b60c54613fbc4bcb37df6cd49b4c96143e99580a472f79fb # The transaction was produced before Trezor implemented BIP-66, so the signature # is now different and txhash doesn't match what is on the blockchain. assert ( tx_hash(serialized_tx).hex() == "6f9775545830731a316a4c2a39515b1890e9c8ab0f9e21e7c6a6ca2c1499116d")
def test_one_three_fee(self, client): # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 # input 0: 0.0039 BTC inp1 = messages.TxInputType( address_n=parse_path("44'/0'/0'/0/0"), # amount=390000, prev_hash=TXHASH_d5f65e, prev_index=0, ) out1 = messages.TxOutputType( address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", amount=390000 - 80000 - 12000 - 10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address="13uaUYn6XAooo88QvAqAVsiVvr2mAXutqP", amount=12000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out3 = messages.TxOutputType( address_n=parse_path("44'/0'/0'/1/0"), amount=80000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses([ request_input(0), request_meta(TXHASH_d5f65e), request_input(0, TXHASH_d5f65e), request_input(1, TXHASH_d5f65e), request_output(0, TXHASH_d5f65e), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), messages.ButtonRequest(code=B.ConfirmOutput), request_output(2), messages.ButtonRequest(code=B.SignTx), request_input(0), request_output(0), request_output(1), request_output(2), request_output(0), request_output(1), request_output(2), request_finished(), ]) _, serialized_tx = btc.sign_tx( client, "Bitcoin", [inp1], [out1, out2, out3], prev_txes=TX_CACHE_MAINNET, ) assert ( tx_hash(serialized_tx).hex() == "fedbba83b115725a713c2b1a13db09fd33de582132d520a3f6ff72503ca5da61")
def test_send_multisig_1(client: Client): # NOTE: fake input tx used nodes = [ btc.get_public_node(client, parse_path(f"m/49h/156h/{i}h"), coin_name="Bgold").node for i in range(1, 4) ] multisig = messages.MultisigRedeemScriptType(nodes=nodes, address_n=[1, 0], signatures=[b"", b"", b""], m=2) inp1 = messages.TxInputType( address_n=parse_path("m/49h/156h/1h/1/0"), prev_hash=FAKE_TXHASH_7f1f6b, prev_index=0, script_type=messages.InputScriptType.SPENDP2SHWITNESS, multisig=multisig, amount=1_252_382_934, ) out1 = messages.TxOutputType( address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", amount=1_252_382_934 - 1_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses([ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(FAKE_TXHASH_7f1f6b), request_input(0, FAKE_TXHASH_7f1f6b), request_output(0, FAKE_TXHASH_7f1f6b), request_output(1, FAKE_TXHASH_7f1f6b), request_input(0), request_output(0), request_input(0), request_finished(), ]) 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([ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(FAKE_TXHASH_7f1f6b), request_input(0, FAKE_TXHASH_7f1f6b), request_output(0, FAKE_TXHASH_7f1f6b), request_output(1, FAKE_TXHASH_7f1f6b), request_input(0), request_output(0), request_input(0), request_finished(), ]) _, serialized_tx = btc.sign_tx(client, "Bgold", [inp1], [out1], prev_txes=TX_API) assert (tx_hash(serialized_tx).hex() == "98e87ee2b5254e9346f2768993950dbfc3a3a4bd084983d0fb78337f1deeca3c")
def test_send_btg_multisig_change(client: Client): # NOTE: fake input tx used nodes = [ btc.get_public_node(client, parse_path(f"m/48h/156h/{i}h/0h"), coin_name="Bgold").node for i in range(1, 4) ] EMPTY_SIGS = [b"", b"", b""] def getmultisig(chain, nr, signatures): return messages.MultisigRedeemScriptType(nodes=nodes, address_n=[chain, nr], signatures=signatures, m=2) inp1 = messages.TxInputType( address_n=parse_path("m/48h/156h/3h/0h/0/0"), multisig=getmultisig(0, 0, EMPTY_SIGS), # 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R amount=1_252_382_934, prev_hash=FAKE_TXHASH_a63dbe, prev_index=0, script_type=messages.InputScriptType.SPENDMULTISIG, ) out1 = messages.TxOutputType( address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", amount=24_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address_n=parse_path("m/48h/156h/3h/0h/1/0"), multisig=getmultisig(1, 0, EMPTY_SIGS), script_type=messages.OutputScriptType.PAYTOMULTISIG, amount=1_252_382_934 - 24_000 - 1_000, ) with client: client.set_expected_responses([ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(FAKE_TXHASH_a63dbe), request_input(0, FAKE_TXHASH_a63dbe), request_output(0, FAKE_TXHASH_a63dbe), request_output(1, FAKE_TXHASH_a63dbe), request_input(0), request_output(0), request_output(1), request_finished(), ]) signatures, serialized_tx = btc.sign_tx(client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API) assert ( signatures[0].hex() == "3045022100bb9b465d2bd7a22b17adc4d8c4600282cfaced0469969f32a2d85e152a528074022030a3698f460c7c935c284f4ffa97d6e44afc200b0c38319d259d15d3deb7c5ac" ) inp1 = messages.TxInputType( address_n=parse_path("m/48h/156h/1h/0h/0/0"), multisig=getmultisig(0, 0, [b"", b"", signatures[0]]), amount=1_252_382_934, prev_hash=FAKE_TXHASH_a63dbe, prev_index=0, script_type=messages.InputScriptType.SPENDMULTISIG, ) out2.address_n[2] = H_(1) with client: client.set_expected_responses([ request_input(0), request_output(0), messages.ButtonRequest(code=B.ConfirmOutput), request_output(1), messages.ButtonRequest(code=B.SignTx), request_input(0), request_meta(FAKE_TXHASH_a63dbe), request_input(0, FAKE_TXHASH_a63dbe), request_output(0, FAKE_TXHASH_a63dbe), request_output(1, FAKE_TXHASH_a63dbe), request_input(0), request_output(0), request_output(1), request_finished(), ]) signatures, serialized_tx = btc.sign_tx(client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API) assert ( signatures[0].hex() == "30440220093c9b193883cd50e81668eb80efe6f82faf01ea707c16c4c33ce1eb40419ccf02200c81b328991389b53a04fcc091365bcc71c2a5c17f62982240b39f1bdefb91f7" ) assert (tx_hash(serialized_tx).hex() == "e5f0bea13c61bf0d02972bbe66f4ca107abd13803015aa785f013114ecec55b7")