diff --git a/tests/device_tests/eos/test_get_public_key.py b/tests/device_tests/eos/test_get_public_key.py index 6a204c2e9b..d83b877a70 100644 --- a/tests/device_tests/eos/test_get_public_key.py +++ b/tests/device_tests/eos/test_get_public_key.py @@ -25,35 +25,34 @@ from ...common import MNEMONIC12 @pytest.mark.altcoin @pytest.mark.eos @pytest.mark.skip_t1 -class TestMsgEosGetpublickey: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_eos_get_public_key(self, client): - public_key = get_public_key( - client, parse_path("m/44'/194'/0'/0/0"), show_display=True - ) - assert ( - public_key.wif_public_key - == "EOS4u6Sfnzj4Sh2pEQnkXyZQJqH3PkKjGByDCbsqqmyq6PttM9KyB" - ) - assert ( - public_key.raw_public_key.hex() - == "02015fabe197c955036bab25f4e7c16558f9f672f9f625314ab1ec8f64f7b1198e" - ) - public_key = get_public_key(client, parse_path("m/44'/194'/0'/0/1")) - assert ( - public_key.wif_public_key - == "EOS5d1VP15RKxT4dSakWu2TFuEgnmaGC2ckfSvQwND7pZC1tXkfLP" - ) - assert ( - public_key.raw_public_key.hex() - == "02608bc2c431521dee0b9d5f2fe34053e15fc3b20d2895e0abda857b9ed8e77a78" - ) - public_key = get_public_key(client, parse_path("m/44'/194'/1'/0/0")) - assert ( - public_key.wif_public_key - == "EOS7UuNeTf13nfcG85rDB7AHGugZi4C4wJ4ft12QRotqNfxdV2NvP" - ) - assert ( - public_key.raw_public_key.hex() - == "035588a197bd5a7356e8a702361b2d535c6372f843874bed6617cd1afe1dfcb502" - ) +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_eos_get_public_key(client): + public_key = get_public_key( + client, parse_path("m/44'/194'/0'/0/0"), show_display=True + ) + assert ( + public_key.wif_public_key + == "EOS4u6Sfnzj4Sh2pEQnkXyZQJqH3PkKjGByDCbsqqmyq6PttM9KyB" + ) + assert ( + public_key.raw_public_key.hex() + == "02015fabe197c955036bab25f4e7c16558f9f672f9f625314ab1ec8f64f7b1198e" + ) + public_key = get_public_key(client, parse_path("m/44'/194'/0'/0/1")) + assert ( + public_key.wif_public_key + == "EOS5d1VP15RKxT4dSakWu2TFuEgnmaGC2ckfSvQwND7pZC1tXkfLP" + ) + assert ( + public_key.raw_public_key.hex() + == "02608bc2c431521dee0b9d5f2fe34053e15fc3b20d2895e0abda857b9ed8e77a78" + ) + public_key = get_public_key(client, parse_path("m/44'/194'/1'/0/0")) + assert ( + public_key.wif_public_key + == "EOS7UuNeTf13nfcG85rDB7AHGugZi4C4wJ4ft12QRotqNfxdV2NvP" + ) + assert ( + public_key.raw_public_key.hex() + == "035588a197bd5a7356e8a702361b2d535c6372f843874bed6617cd1afe1dfcb502" + ) diff --git a/tests/device_tests/eos/test_signtx.py b/tests/device_tests/eos/test_signtx.py index e0d9c1f94e..cd326b8416 100644 --- a/tests/device_tests/eos/test_signtx.py +++ b/tests/device_tests/eos/test_signtx.py @@ -25,642 +25,621 @@ from ...common import MNEMONIC12 CHAIN_ID = "cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f" ADDRESS_N = parse_path("m/44'/194'/0'/0/0") +pytestmark = [ + pytest.mark.altcoin, + pytest.mark.eos, + pytest.mark.skip_t1, + pytest.mark.setup_client(mnemonic=MNEMONIC12), +] -@pytest.mark.altcoin -@pytest.mark.eos -@pytest.mark.skip_t1 -@pytest.mark.setup_client(mnemonic=MNEMONIC12) -class TestMsgEosSignTx: - def test_eos_signtx_transfer_token(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio.token", - "name": "transfer", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "from": "miniminimini", - "to": "maximaximaxi", - "quantity": "1.0000 EOS", - "memo": "testtest", - }, - } - ], - "transaction_extensions": [], - } - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_JveDuew7oyKjgLmApra3NmKArx3QH6HVmatgkLYeUYWv7aGaoQPFyjBwAdcxuo2Skq9wRgsizos92h9iq9i5JbeHh7zNuo" - ) +def test_eos_signtx_transfer_token(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio.token", + "name": "transfer", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "from": "miniminimini", + "to": "maximaximaxi", + "quantity": "1.0000 EOS", + "memo": "testtest", + }, + } + ], + "transaction_extensions": [], + } - def test_eos_signtx_buyram(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "buyram", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "payer": "miniminimini", - "receiver": "miniminimini", - "quant": "1000000000.0000 EOS", - }, - } - ], - "transaction_extensions": [], - } + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_JveDuew7oyKjgLmApra3NmKArx3QH6HVmatgkLYeUYWv7aGaoQPFyjBwAdcxuo2Skq9wRgsizos92h9iq9i5JbeHh7zNuo" + ) - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_K4gU5S9g7rS6MojaPwWppEBCBbPrJm1pyJtVR9mts1sBq5xyN7nJv3FGnrBR7ByjanboCtK4ogY35sNPFX1F5qoZW7BkF9" - ) - def test_eos_signtx_buyrambytes(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "buyrambytes", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "payer": "miniminimini", - "receiver": "miniminimini", - "bytes": 1023, - }, - } - ], - "transaction_extensions": [], - } +def test_eos_signtx_buyram(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "buyram", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "payer": "miniminimini", + "receiver": "miniminimini", + "quant": "1000000000.0000 EOS", + }, + } + ], + "transaction_extensions": [], + } - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_K618wK9f27YxHoPG9hoUCsazZXzxumBj3V9MqcTUh9yCocvP1uFZQAmGmZLhsAtuC2TRR4gtqbeQj57FniYd5i4faQCb6t" - ) + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_K4gU5S9g7rS6MojaPwWppEBCBbPrJm1pyJtVR9mts1sBq5xyN7nJv3FGnrBR7ByjanboCtK4ogY35sNPFX1F5qoZW7BkF9" + ) - def test_eos_signtx_sellram(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "sellram", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": {"account": "miniminimini", "bytes": 1024}, - } - ], - "transaction_extensions": [], - } - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_JusrCS7H5DR53qke7edoWvJuLiQS2VQ84CsN5NWmWYVa7wmJVjh3Hcg5hH42zF8KjAmmvHtaJZ3wkortTW9eds1eoiKsrj" - ) +def test_eos_signtx_buyrambytes(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "buyrambytes", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "payer": "miniminimini", + "receiver": "miniminimini", + "bytes": 1023, + }, + } + ], + "transaction_extensions": [], + } - def test_eos_signtx_delegate(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "delegatebw", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "from": "miniminimini", - "receiver": "maximaximaxi", - "stake_net_quantity": "1.0000 EOS", - "stake_cpu_quantity": "1.0000 EOS", - "transfer": True, - }, - } - ], - "transaction_extensions": [], - } + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_K618wK9f27YxHoPG9hoUCsazZXzxumBj3V9MqcTUh9yCocvP1uFZQAmGmZLhsAtuC2TRR4gtqbeQj57FniYd5i4faQCb6t" + ) - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_Juju8Wjzyn38nuvgS1KT3koKQLHxMMfqVHrp5jMjv4QLU2pUG6EbiJD7D1EHE6xP8DRuwFLVUNR38nTyUKC1Eiz33WocUE" - ) - def test_eos_signtx_undelegate(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "undelegatebw", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "from": "miniminimini", - "receiver": "maximaximaxi", - "unstake_net_quantity": "1.0000 EOS", - "unstake_cpu_quantity": "1.0000 EOS", - }, - } - ], - "transaction_extensions": [], - } +def test_eos_signtx_sellram(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "sellram", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": {"account": "miniminimini", "bytes": 1024}, + } + ], + "transaction_extensions": [], + } - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_K3XXUzCUkT2HEdrJTz1CdDDKZbLMShmyEjknQozGhy4F21yUetr1nEe2vUgmGebk2nyYe49R5nkA155J5yFBBaLsTcSdBL" - ) + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_JusrCS7H5DR53qke7edoWvJuLiQS2VQ84CsN5NWmWYVa7wmJVjh3Hcg5hH42zF8KjAmmvHtaJZ3wkortTW9eds1eoiKsrj" + ) - def test_eos_signtx_refund(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "refund", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": {"owner": "miniminimini"}, - } - ], - "transaction_extensions": [], - } - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_JwWZSSKQZL1hCdMmwEAKjs3r15kau5gaBrQczKy65QANANzovV6U4XbVUZQkZzaQrNGYAtgxrU1WJ1smWgXZNqtKVQUZqc" - ) +def test_eos_signtx_delegate(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "delegatebw", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "from": "miniminimini", + "receiver": "maximaximaxi", + "stake_net_quantity": "1.0000 EOS", + "stake_cpu_quantity": "1.0000 EOS", + "transfer": True, + }, + } + ], + "transaction_extensions": [], + } - def test_eos_signtx_linkauth(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "linkauth", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "account": "maximaximaxi", - "code": "eosbet", - "type": "whatever", - "requirement": "active", - }, - } - ], - "transaction_extensions": [], - } + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_Juju8Wjzyn38nuvgS1KT3koKQLHxMMfqVHrp5jMjv4QLU2pUG6EbiJD7D1EHE6xP8DRuwFLVUNR38nTyUKC1Eiz33WocUE" + ) - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_Kgs3JdLNqTyGz7uyNiuYLK8sy5qhVQWozrBY7bJWKsjrWAxNyDQUKqHsHmTom5rGY21vYdXmCpi4msU6XeMgWvi4bsBxTx" - ) - def test_eos_signtx_unlinkauth(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "unlinkauth", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "account": "miniminimini", - "code": "eosbet", - "type": "whatever", - }, - } - ], - "transaction_extensions": [], - } +def test_eos_signtx_undelegate(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "undelegatebw", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "from": "miniminimini", + "receiver": "maximaximaxi", + "unstake_net_quantity": "1.0000 EOS", + "unstake_cpu_quantity": "1.0000 EOS", + }, + } + ], + "transaction_extensions": [], + } - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_K1ioB5KMRC2mmTwYsGwsFU51ENp1XdSBUrb4bxUCLYhoq7Y733WaLZ4Soq9fdrkaJS8uJ3R7Z1ZjyEKRHU8HU4s4MA86zB" - ) + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_K3XXUzCUkT2HEdrJTz1CdDDKZbLMShmyEjknQozGhy4F21yUetr1nEe2vUgmGebk2nyYe49R5nkA155J5yFBBaLsTcSdBL" + ) - def test_eos_signtx_updateauth(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "updateauth", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "account": "miniminimini", - "permission": "active", - "parent": "owner", - "auth": { - "threshold": 1, - "keys": [ - { - "key": "EOS8Dkj827FpinZBGmhTM28B85H9eXiFH5XzvLoeukCJV5sKfLc6K", - "weight": 1, - }, - { - "key": "EOS8Dkj827FpinZBGmhTM28B85H9eXiFH5XzvLoeukCJV5sKfLc6K", - "weight": 2, - }, - ], - "accounts": [ - { - "permission": { - "actor": "miniminimini", - "permission": "active", - }, - "weight": 3, - } - ], - "waits": [{"wait_sec": 55, "weight": 4}], - }, - }, - } - ], - "transaction_extensions": [], - } - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_JuNuwmJm7nLfpxbCqXZMxZoU56TzBh8F5PH7ZyPvQMti6QxJbErDGbKCAaHhoRxwWKzv5kj6kX3WyWys6jAzVe9pDhXB1k" - ) +def test_eos_signtx_refund(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "refund", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": {"owner": "miniminimini"}, + } + ], + "transaction_extensions": [], + } - def test_eos_signtx_deleteauth(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "deleteauth", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": {"account": "maximaximaxi", "permission": "active"}, - } - ], - "transaction_extensions": [], - } + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_JwWZSSKQZL1hCdMmwEAKjs3r15kau5gaBrQczKy65QANANzovV6U4XbVUZQkZzaQrNGYAtgxrU1WJ1smWgXZNqtKVQUZqc" + ) - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_KjPTp8jCtgBKQWqsndhrH4pdCGiks76Q1qBt9e8MtexW6FQg3FzfVFKDU4SvyVDyFs3worn6RyW6WYavw76ACNqcqkCYjf" - ) - def test_eos_signtx_vote(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "voteproducer", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "account": "miniminimini", - "proxy": "", - "producers": [ - "argentinaeos", - "bitfinexeos1", - "cryptolions1", - "eos42freedom", - "eosamsterdam", - "eosasia11111", - "eosauthority", - "eosbeijingbp", - "eosbixinboot", - "eoscafeblock", - "eoscanadacom", - "eoscannonchn", - "eoscleanerbp", - "eosdacserver", - "eosfishrocks", - "eosflytomars", - "eoshuobipool", - "eosisgravity", - "eoslaomaocom", - "eosliquideos", - "eosnewyorkio", - "eosriobrazil", - "eosswedenorg", - "eostribeprod", - "helloeoscnbp", - "jedaaaaaaaaa", - "libertyblock", - "starteosiobp", - "teamgreymass", +def test_eos_signtx_linkauth(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "linkauth", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "account": "maximaximaxi", + "code": "eosbet", + "type": "whatever", + "requirement": "active", + }, + } + ], + "transaction_extensions": [], + } + + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_Kgs3JdLNqTyGz7uyNiuYLK8sy5qhVQWozrBY7bJWKsjrWAxNyDQUKqHsHmTom5rGY21vYdXmCpi4msU6XeMgWvi4bsBxTx" + ) + + +def test_eos_signtx_unlinkauth(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "unlinkauth", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "account": "miniminimini", + "code": "eosbet", + "type": "whatever", + }, + } + ], + "transaction_extensions": [], + } + + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_K1ioB5KMRC2mmTwYsGwsFU51ENp1XdSBUrb4bxUCLYhoq7Y733WaLZ4Soq9fdrkaJS8uJ3R7Z1ZjyEKRHU8HU4s4MA86zB" + ) + + +def test_eos_signtx_updateauth(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "updateauth", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "account": "miniminimini", + "permission": "active", + "parent": "owner", + "auth": { + "threshold": 1, + "keys": [ + { + "key": "EOS8Dkj827FpinZBGmhTM28B85H9eXiFH5XzvLoeukCJV5sKfLc6K", + "weight": 1, + }, + { + "key": "EOS8Dkj827FpinZBGmhTM28B85H9eXiFH5XzvLoeukCJV5sKfLc6K", + "weight": 2, + }, ], - }, - } - ], - "transaction_extensions": [], - } - - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_JxgVhc6ExoTHee3Djrciwmmf2Xck7NLgvAtC2gfgV4Wj2AqMXEb6aKMhpUcTV59VTR1DdnPF1XbiCcJViJiU3zsk1kQz89" - ) - - def test_eos_signtx_vote_proxy(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "voteproducer", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": {"account": "miniminimini", "proxy": "", "producers": []}, - } - ], - "transaction_extensions": [], - } - - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_KjJzcDg9MT8XbLeP1fgQjdmdE6oNQQisMwbXikqrEZYmJe6GCYg89Wr2donYV6zRfg9h7dJKQDCHugdtsxjtmEdqLtPv25" - ) - - def test_eos_signtx_unknown(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "foocontract", - "name": "baraction", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": "deadbeef", - } - ], - "transaction_extensions": [], - } - - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_JvoJtrHpQJjHAZzEBhiQm75iimYabcAVNDvz8mkempLh6avSJgnXm5JzCCUEBjDtW3syByfXknmgr93Sw3P9RNLnwySmv6" - ) - - def test_eos_signtx_newaccount(self, client): - transaction = { - "expiration": "2018-07-14T10:43:28", - "ref_block_num": 6439, - "ref_block_prefix": 2995713264, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio", - "name": "newaccount", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "creator": "miniminimini", - "name": "maximaximaxi", - "owner": { - "threshold": 1, - "keys": [ - { - "key": "EOS8Dkj827FpinZBGmhTM28B85H9eXiFH5XzvLoeukCJV5sKfLc6K", - "weight": 1, - } - ], - "accounts": [], - "waits": [], - }, - "active": { - "threshold": 1, - "keys": [ - { - "key": "EOS8Dkj827FpinZBGmhTM28B85H9eXiFH5XzvLoeukCJV5sKfLc6K", - "weight": 1, - } - ], - "accounts": [], - "waits": [], - }, + "accounts": [ + { + "permission": { + "actor": "miniminimini", + "permission": "active", + }, + "weight": 3, + } + ], + "waits": [{"wait_sec": 55, "weight": 4}], }, }, - { - "account": "eosio", - "name": "buyrambytes", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} + } + ], + "transaction_extensions": [], + } + + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_JuNuwmJm7nLfpxbCqXZMxZoU56TzBh8F5PH7ZyPvQMti6QxJbErDGbKCAaHhoRxwWKzv5kj6kX3WyWys6jAzVe9pDhXB1k" + ) + + +def test_eos_signtx_deleteauth(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "deleteauth", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": {"account": "maximaximaxi", "permission": "active"}, + } + ], + "transaction_extensions": [], + } + + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_KjPTp8jCtgBKQWqsndhrH4pdCGiks76Q1qBt9e8MtexW6FQg3FzfVFKDU4SvyVDyFs3worn6RyW6WYavw76ACNqcqkCYjf" + ) + + +def test_eos_signtx_vote(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "voteproducer", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "account": "miniminimini", + "proxy": "", + "producers": [ + "argentinaeos", + "bitfinexeos1", + "cryptolions1", + "eos42freedom", + "eosamsterdam", + "eosasia11111", + "eosauthority", + "eosbeijingbp", + "eosbixinboot", + "eoscafeblock", + "eoscanadacom", + "eoscannonchn", + "eoscleanerbp", + "eosdacserver", + "eosfishrocks", + "eosflytomars", + "eoshuobipool", + "eosisgravity", + "eoslaomaocom", + "eosliquideos", + "eosnewyorkio", + "eosriobrazil", + "eosswedenorg", + "eostribeprod", + "helloeoscnbp", + "jedaaaaaaaaa", + "libertyblock", + "starteosiobp", + "teamgreymass", ], - "data": { - "payer": "miniminimini", - "receiver": "maximaximaxi", - "bytes": 4096, + }, + } + ], + "transaction_extensions": [], + } + + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_JxgVhc6ExoTHee3Djrciwmmf2Xck7NLgvAtC2gfgV4Wj2AqMXEb6aKMhpUcTV59VTR1DdnPF1XbiCcJViJiU3zsk1kQz89" + ) + + +def test_eos_signtx_vote_proxy(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "voteproducer", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": {"account": "miniminimini", "proxy": "", "producers": []}, + } + ], + "transaction_extensions": [], + } + + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_KjJzcDg9MT8XbLeP1fgQjdmdE6oNQQisMwbXikqrEZYmJe6GCYg89Wr2donYV6zRfg9h7dJKQDCHugdtsxjtmEdqLtPv25" + ) + + +def test_eos_signtx_unknown(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "foocontract", + "name": "baraction", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": "deadbeef", + } + ], + "transaction_extensions": [], + } + + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_JvoJtrHpQJjHAZzEBhiQm75iimYabcAVNDvz8mkempLh6avSJgnXm5JzCCUEBjDtW3syByfXknmgr93Sw3P9RNLnwySmv6" + ) + + +def test_eos_signtx_newaccount(client): + transaction = { + "expiration": "2018-07-14T10:43:28", + "ref_block_num": 6439, + "ref_block_prefix": 2995713264, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio", + "name": "newaccount", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "creator": "miniminimini", + "name": "maximaximaxi", + "owner": { + "threshold": 1, + "keys": [ + { + "key": "EOS8Dkj827FpinZBGmhTM28B85H9eXiFH5XzvLoeukCJV5sKfLc6K", + "weight": 1, + } + ], + "accounts": [], + "waits": [], + }, + "active": { + "threshold": 1, + "keys": [ + { + "key": "EOS8Dkj827FpinZBGmhTM28B85H9eXiFH5XzvLoeukCJV5sKfLc6K", + "weight": 1, + } + ], + "accounts": [], + "waits": [], }, }, - { - "account": "eosio", - "name": "delegatebw", - "authorization": [ - {"actor": "miniminimini", "permission": "active"} - ], - "data": { - "from": "miniminimini", - "receiver": "maximaximaxi", - "stake_net_quantity": "1.0000 EOS", - "stake_cpu_quantity": "1.0000 EOS", - "transfer": True, - }, + }, + { + "account": "eosio", + "name": "buyrambytes", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "payer": "miniminimini", + "receiver": "maximaximaxi", + "bytes": 4096, }, - ], - "transaction_extensions": [], - } - - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_KhjdS1gKUHR4jKbN3YSdNbPbEqnUVM1Nt6ybdzEAwsUtfbCRJDwpQwPRuEau48CyvhYC5fKo5BiWMPQJbQPrg5ErHThieU" - ) - - def test_eos_signtx_setcontract(self, client): - transaction = { - "expiration": "2018-06-19T13:29:53", - "ref_block_num": 30587, - "ref_block_prefix": 338239089, - "max_net_usage_words": 0, - "max_cpu_usage_ms": 0, - "delay_sec": 0, - "context_free_actions": [], - "actions": [ - { - "account": "eosio1", - "name": "setcode", - "authorization": [ - {"actor": "ednazztokens", "permission": "active"} - ], - "data": "00" * 1024, + }, + { + "account": "eosio", + "name": "delegatebw", + "authorization": [{"actor": "miniminimini", "permission": "active"}], + "data": { + "from": "miniminimini", + "receiver": "maximaximaxi", + "stake_net_quantity": "1.0000 EOS", + "stake_cpu_quantity": "1.0000 EOS", + "transfer": True, }, - { - "account": "eosio1", - "name": "setabi", - "authorization": [ - {"actor": "ednazztokens", "permission": "active"} - ], - "data": "00" * 1024, - }, - ], - "transaction_extensions": [], - "context_free_data": [], - } + }, + ], + "transaction_extensions": [], + } - with client: - resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) - assert isinstance(resp, EosSignedTx) - assert ( - resp.signature - == "SIG_K1_KiG8c8t2SQkSfrEbD9BwJoYT133BPFLx3gu8sAzJadXyFk1EXKYAsgx4tkjt79G6ofuaQzJPAfDqy1FSpgLRbhbeFH9omd" - ) + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_KhjdS1gKUHR4jKbN3YSdNbPbEqnUVM1Nt6ybdzEAwsUtfbCRJDwpQwPRuEau48CyvhYC5fKo5BiWMPQJbQPrg5ErHThieU" + ) + + +def test_eos_signtx_setcontract(client): + transaction = { + "expiration": "2018-06-19T13:29:53", + "ref_block_num": 30587, + "ref_block_prefix": 338239089, + "max_net_usage_words": 0, + "max_cpu_usage_ms": 0, + "delay_sec": 0, + "context_free_actions": [], + "actions": [ + { + "account": "eosio1", + "name": "setcode", + "authorization": [{"actor": "ednazztokens", "permission": "active"}], + "data": "00" * 1024, + }, + { + "account": "eosio1", + "name": "setabi", + "authorization": [{"actor": "ednazztokens", "permission": "active"}], + "data": "00" * 1024, + }, + ], + "transaction_extensions": [], + "context_free_data": [], + } + + with client: + resp = eos.sign_tx(client, ADDRESS_N, transaction, CHAIN_ID) + assert isinstance(resp, EosSignedTx) + assert ( + resp.signature + == "SIG_K1_KiG8c8t2SQkSfrEbD9BwJoYT133BPFLx3gu8sAzJadXyFk1EXKYAsgx4tkjt79G6ofuaQzJPAfDqy1FSpgLRbhbeFH9omd" + ) diff --git a/tests/device_tests/monero/test_getaddress.py b/tests/device_tests/monero/test_getaddress.py index 119a6b7871..ab79f4b2f2 100644 --- a/tests/device_tests/monero/test_getaddress.py +++ b/tests/device_tests/monero/test_getaddress.py @@ -25,18 +25,17 @@ from ...common import MNEMONIC12 @pytest.mark.altcoin @pytest.mark.monero @pytest.mark.skip_t1 -class TestMsgMoneroGetaddress: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_monero_getaddress(self, client): - assert ( - monero.get_address(client, parse_path("m/44h/128h/0h"), show_display=True) - == b"4Ahp23WfMrMFK3wYL2hLWQFGt87ZTeRkufS6JoQZu6MEFDokAQeGWmu9MA3GFq1yVLSJQbKJqVAn9F9DLYGpRzRAEXqAXKM" - ) - assert ( - monero.get_address(client, parse_path("m/44h/128h/1h"), show_display=True) - == b"44iAazhoAkv5a5RqLNVyh82a1n3ceNggmN4Ho7bUBJ14WkEVR8uFTe9f7v5rNnJ2kEbVXxfXiRzsD5Jtc6NvBi4D6WNHPie" - ) - assert ( - monero.get_address(client, parse_path("m/44h/128h/2h"), show_display=True) - == b"47ejhmbZ4wHUhXaqA4b7PN667oPMkokf4ZkNdWrMSPy9TNaLVr7vLqVUQHh2MnmaAEiyrvLsX8xUf99q3j1iAeMV8YvSFcH" - ) +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_monero_getaddress(client): + assert ( + monero.get_address(client, parse_path("m/44h/128h/0h"), show_display=True) + == b"4Ahp23WfMrMFK3wYL2hLWQFGt87ZTeRkufS6JoQZu6MEFDokAQeGWmu9MA3GFq1yVLSJQbKJqVAn9F9DLYGpRzRAEXqAXKM" + ) + assert ( + monero.get_address(client, parse_path("m/44h/128h/1h"), show_display=True) + == b"44iAazhoAkv5a5RqLNVyh82a1n3ceNggmN4Ho7bUBJ14WkEVR8uFTe9f7v5rNnJ2kEbVXxfXiRzsD5Jtc6NvBi4D6WNHPie" + ) + assert ( + monero.get_address(client, parse_path("m/44h/128h/2h"), show_display=True) + == b"47ejhmbZ4wHUhXaqA4b7PN667oPMkokf4ZkNdWrMSPy9TNaLVr7vLqVUQHh2MnmaAEiyrvLsX8xUf99q3j1iAeMV8YvSFcH" + ) diff --git a/tests/device_tests/monero/test_getwatchkey.py b/tests/device_tests/monero/test_getwatchkey.py index fc252cbf46..6d28992339 100644 --- a/tests/device_tests/monero/test_getwatchkey.py +++ b/tests/device_tests/monero/test_getwatchkey.py @@ -25,33 +25,32 @@ from ...common import MNEMONIC12 @pytest.mark.altcoin @pytest.mark.monero @pytest.mark.skip_t1 -class TestMsgMoneroGetwatchkey: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_monero_getwatchkey(self, client): - res = monero.get_watch_key(client, parse_path("m/44h/128h/0h")) - assert ( - res.address - == b"4Ahp23WfMrMFK3wYL2hLWQFGt87ZTeRkufS6JoQZu6MEFDokAQeGWmu9MA3GFq1yVLSJQbKJqVAn9F9DLYGpRzRAEXqAXKM" - ) - assert ( - res.watch_key.hex() - == "8722520a581e2a50cc1adab4a1692401effd37b0d63b9d9b60fd7f34ea2b950e" - ) - res = monero.get_watch_key(client, parse_path("m/44h/128h/1h")) - assert ( - res.address - == b"44iAazhoAkv5a5RqLNVyh82a1n3ceNggmN4Ho7bUBJ14WkEVR8uFTe9f7v5rNnJ2kEbVXxfXiRzsD5Jtc6NvBi4D6WNHPie" - ) - assert ( - res.watch_key.hex() - == "1f70b7d9e86c11b7a5bee883b75c43d6be189c8f812726ea1ecd94b06bb7db04" - ) - res = monero.get_watch_key(client, parse_path("m/44h/128h/2h")) - assert ( - res.address - == b"47ejhmbZ4wHUhXaqA4b7PN667oPMkokf4ZkNdWrMSPy9TNaLVr7vLqVUQHh2MnmaAEiyrvLsX8xUf99q3j1iAeMV8YvSFcH" - ) - assert ( - res.watch_key.hex() - == "e0671fbed2c9231fe4f286962862813a4a4d153c793bf5d0e3742119723f3000" - ) +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_monero_getwatchkey(client): + res = monero.get_watch_key(client, parse_path("m/44h/128h/0h")) + assert ( + res.address + == b"4Ahp23WfMrMFK3wYL2hLWQFGt87ZTeRkufS6JoQZu6MEFDokAQeGWmu9MA3GFq1yVLSJQbKJqVAn9F9DLYGpRzRAEXqAXKM" + ) + assert ( + res.watch_key.hex() + == "8722520a581e2a50cc1adab4a1692401effd37b0d63b9d9b60fd7f34ea2b950e" + ) + res = monero.get_watch_key(client, parse_path("m/44h/128h/1h")) + assert ( + res.address + == b"44iAazhoAkv5a5RqLNVyh82a1n3ceNggmN4Ho7bUBJ14WkEVR8uFTe9f7v5rNnJ2kEbVXxfXiRzsD5Jtc6NvBi4D6WNHPie" + ) + assert ( + res.watch_key.hex() + == "1f70b7d9e86c11b7a5bee883b75c43d6be189c8f812726ea1ecd94b06bb7db04" + ) + res = monero.get_watch_key(client, parse_path("m/44h/128h/2h")) + assert ( + res.address + == b"47ejhmbZ4wHUhXaqA4b7PN667oPMkokf4ZkNdWrMSPy9TNaLVr7vLqVUQHh2MnmaAEiyrvLsX8xUf99q3j1iAeMV8YvSFcH" + ) + assert ( + res.watch_key.hex() + == "e0671fbed2c9231fe4f286962862813a4a4d153c793bf5d0e3742119723f3000" + ) diff --git a/tests/device_tests/nem/test_getaddress.py b/tests/device_tests/nem/test_getaddress.py index 8a3dbef84a..7cde0eea9d 100644 --- a/tests/device_tests/nem/test_getaddress.py +++ b/tests/device_tests/nem/test_getaddress.py @@ -24,18 +24,17 @@ from ...common import MNEMONIC12 @pytest.mark.altcoin @pytest.mark.nem -class TestMsgNEMGetaddress: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_getaddress(self, client): - assert ( - nem.get_address( - client, parse_path("m/44'/1'/0'/0'/0'"), 0x68, show_display=True - ) - == "NB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQGHUBWQN" +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_nem_getaddress(client): + assert ( + nem.get_address( + client, parse_path("m/44'/1'/0'/0'/0'"), 0x68, show_display=True ) - assert ( - nem.get_address( - client, parse_path("m/44'/1'/0'/0'/0'"), 0x98, show_display=True - ) - == "TB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQHSBNBMF" + == "NB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQGHUBWQN" + ) + assert ( + nem.get_address( + client, parse_path("m/44'/1'/0'/0'/0'"), 0x98, show_display=True ) + == "TB3JCHVARQNGDS3UVGAJPTFE22UQFGMCQHSBNBMF" + ) diff --git a/tests/device_tests/nem/test_signtx_mosaics.py b/tests/device_tests/nem/test_signtx_mosaics.py index 566d85860a..6bf0b81dce 100644 --- a/tests/device_tests/nem/test_signtx_mosaics.py +++ b/tests/device_tests/nem/test_signtx_mosaics.py @@ -21,148 +21,149 @@ from trezorlib.tools import parse_path from ...common import MNEMONIC12 +pytestmark = [ + pytest.mark.altcoin, + pytest.mark.nem, + pytest.mark.skip_t2, + pytest.mark.setup_client(mnemonic=MNEMONIC12), +] -# assertion data from T1 -@pytest.mark.altcoin -@pytest.mark.nem -@pytest.mark.skip_t2 -class TestMsgNEMSignTxMosaics: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_mosaic_supply_change(self, client): - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 74649215, - "fee": 2000000, - "type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, - "deadline": 74735615, - "message": {}, - "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"}, - "supplyType": 1, - "delta": 1, - "version": (0x98 << 24), - "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "creationFee": 1500, + +def test_nem_signtx_mosaic_supply_change(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 74649215, + "fee": 2000000, + "type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, + "deadline": 74735615, + "message": {}, + "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"}, + "supplyType": 1, + "delta": 1, + "version": (0x98 << 24), + "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "creationFee": 1500, + }, + ) + + assert ( + tx.data.hex() + == "02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000" + ) + assert ( + tx.signature.hex() + == "928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a" + ) + + +def test_nem_signtx_mosaic_creation(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 74649215, + "fee": 2000000, + "type": nem.TYPE_MOSAIC_CREATION, + "deadline": 74735615, + "message": {}, + "mosaicDefinition": { + "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, + "levy": {}, + "properties": {}, + "description": "lorem", }, - ) + "version": (0x98 << 24), + "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "creationFee": 1500, + }, + ) - assert ( - tx.data.hex() - == "02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000" - ) - assert ( - tx.signature.hex() - == "928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a" - ) + assert ( + tx.data.hex() + == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" + ) + assert ( + tx.signature.hex() + == "537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e" + ) - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_mosaic_creation(self, client): - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 74649215, - "fee": 2000000, - "type": nem.TYPE_MOSAIC_CREATION, - "deadline": 74735615, - "message": {}, - "mosaicDefinition": { - "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, - "levy": {}, - "properties": {}, - "description": "lorem", + +def test_nem_signtx_mosaic_creation_properties(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 74649215, + "fee": 2000000, + "type": nem.TYPE_MOSAIC_CREATION, + "deadline": 74735615, + "message": {}, + "mosaicDefinition": { + "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, + "levy": {}, + "properties": [ + {"name": "divisibility", "value": "4"}, + {"name": "initialSupply", "value": "200"}, + {"name": "supplyMutable", "value": "false"}, + {"name": "transferable", "value": "true"}, + ], + "description": "lorem", + }, + "version": (0x98 << 24), + "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "creationFee": 1500, + }, + ) + + assert ( + tx.data.hex() + == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" + ) + assert ( + tx.signature.hex() + == "f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e" + ) + + +def test_nem_signtx_mosaic_creation_levy(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 74649215, + "fee": 2000000, + "type": nem.TYPE_MOSAIC_CREATION, + "deadline": 74735615, + "message": {}, + "mosaicDefinition": { + "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, + "properties": [ + {"name": "divisibility", "value": "4"}, + {"name": "initialSupply", "value": "200"}, + {"name": "supplyMutable", "value": "false"}, + {"name": "transferable", "value": "true"}, + ], + "levy": { + "type": 1, + "fee": 2, + "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"}, }, - "version": (0x98 << 24), - "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "creationFee": 1500, + "description": "lorem", }, - ) + "version": (0x98 << 24), + "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "creationFee": 1500, + }, + ) - assert ( - tx.data.hex() - == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" - ) - assert ( - tx.signature.hex() - == "537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e" - ) - - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_mosaic_creation_properties(self, client): - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 74649215, - "fee": 2000000, - "type": nem.TYPE_MOSAIC_CREATION, - "deadline": 74735615, - "message": {}, - "mosaicDefinition": { - "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, - "levy": {}, - "properties": [ - {"name": "divisibility", "value": "4"}, - {"name": "initialSupply", "value": "200"}, - {"name": "supplyMutable", "value": "false"}, - {"name": "transferable", "value": "true"}, - ], - "description": "lorem", - }, - "version": (0x98 << 24), - "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "creationFee": 1500, - }, - ) - - assert ( - tx.data.hex() - == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" - ) - assert ( - tx.signature.hex() - == "f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e" - ) - - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_mosaic_creation_levy(self, client): - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 74649215, - "fee": 2000000, - "type": nem.TYPE_MOSAIC_CREATION, - "deadline": 74735615, - "message": {}, - "mosaicDefinition": { - "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, - "properties": [ - {"name": "divisibility", "value": "4"}, - {"name": "initialSupply", "value": "200"}, - {"name": "supplyMutable", "value": "false"}, - {"name": "transferable", "value": "true"}, - ], - "levy": { - "type": 1, - "fee": 2, - "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"}, - }, - "description": "lorem", - }, - "version": (0x98 << 24), - "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "creationFee": 1500, - }, - ) - - assert ( - tx.data.hex() - == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" - ) - assert ( - tx.signature.hex() - == "b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a" - ) + assert ( + tx.data.hex() + == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" + ) + assert ( + tx.signature.hex() + == "b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a" + ) diff --git a/tests/device_tests/nem/test_signtx_mosaics_t2.py b/tests/device_tests/nem/test_signtx_mosaics_t2.py index 32abf364b0..cbe0be5a9c 100644 --- a/tests/device_tests/nem/test_signtx_mosaics_t2.py +++ b/tests/device_tests/nem/test_signtx_mosaics_t2.py @@ -23,142 +23,146 @@ from ...common import MNEMONIC12 ADDRESS_N = parse_path("m/44'/1'/0'/0'/0'") +pytestmark = [ + pytest.mark.altcoin, + pytest.mark.nem, + pytest.mark.skip_t1, + pytest.mark.setup_client(mnemonic=MNEMONIC12), +] + # assertion data from T1 -@pytest.mark.altcoin -@pytest.mark.nem -@pytest.mark.skip_t1 -class TestMsgNEMSignTxMosaics: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_mosaic_supply_change(self, client): - with client: - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 74649215, - "fee": 2000000, - "type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, - "deadline": 74735615, - "message": {}, - "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"}, - "supplyType": 1, - "delta": 1, - "version": (0x98 << 24), - "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "creationFee": 1500, - }, - ) - assert ( - tx.data.hex() - == "02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000" - ) - assert ( - tx.signature.hex() - == "928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a" - ) - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_mosaic_creation(self, client): - test_suite = { - "timeStamp": 74649215, - "fee": 2000000, - "type": nem.TYPE_MOSAIC_CREATION, - "deadline": 74735615, - "message": {}, - "mosaicDefinition": { - "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, - "levy": {}, - "properties": {}, - "description": "lorem", +def test_nem_signtx_mosaic_supply_change(client): + with client: + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 74649215, + "fee": 2000000, + "type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, + "deadline": 74735615, + "message": {}, + "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"}, + "supplyType": 1, + "delta": 1, + "version": (0x98 << 24), + "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "creationFee": 1500, }, - "version": (0x98 << 24), - "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "creationFee": 1500, - } + ) - # not using client.nem_sign_tx() because of swiping - tx = nem.sign_tx(client, ADDRESS_N, test_suite) assert ( tx.data.hex() - == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" + == "02400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963010000000100000000000000" ) assert ( tx.signature.hex() - == "537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e" + == "928b03c4a69fff35ecf0912066ea705895b3028fad141197d7ea2b56f1eef2a2516455e6f35d318f6fa39e2bb40492ac4ae603260790f7ebc7ea69feb4ca4c0a" ) - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_mosaic_creation_properties(self, client): - test_suite = { - "timeStamp": 74649215, - "fee": 2000000, - "type": nem.TYPE_MOSAIC_CREATION, - "deadline": 74735615, - "message": {}, - "mosaicDefinition": { - "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, - "levy": {}, - "properties": [ - {"name": "divisibility", "value": "4"}, - {"name": "initialSupply", "value": "200"}, - {"name": "supplyMutable", "value": "false"}, - {"name": "transferable", "value": "true"}, - ], - "description": "lorem", + +def test_nem_signtx_mosaic_creation(client): + test_suite = { + "timeStamp": 74649215, + "fee": 2000000, + "type": nem.TYPE_MOSAIC_CREATION, + "deadline": 74735615, + "message": {}, + "mosaicDefinition": { + "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, + "levy": {}, + "properties": {}, + "description": "lorem", + }, + "version": (0x98 << 24), + "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "creationFee": 1500, + } + + # not using client.nem_sign_tx() because of swiping + tx = nem.sign_tx(client, ADDRESS_N, test_suite) + assert ( + tx.data.hex() + == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000030160000000d000000696e697469616c537570706c7901000000301a0000000d000000737570706c794d757461626c650500000066616c7365190000000c0000007472616e7366657261626c650500000066616c7365000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" + ) + assert ( + tx.signature.hex() + == "537adf4fd9bd5b46e204b2db0a435257a951ed26008305e0aa9e1201dafa4c306d7601a8dbacabf36b5137724386124958d53202015ab31fb3d0849dfed2df0e" + ) + + +def test_nem_signtx_mosaic_creation_properties(client): + test_suite = { + "timeStamp": 74649215, + "fee": 2000000, + "type": nem.TYPE_MOSAIC_CREATION, + "deadline": 74735615, + "message": {}, + "mosaicDefinition": { + "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, + "levy": {}, + "properties": [ + {"name": "divisibility", "value": "4"}, + {"name": "initialSupply", "value": "200"}, + {"name": "supplyMutable", "value": "false"}, + {"name": "transferable", "value": "true"}, + ], + "description": "lorem", + }, + "version": (0x98 << 24), + "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "creationFee": 1500, + } + + # not using client.nem_sign_tx() because of swiping + tx = nem.sign_tx(client, ADDRESS_N, test_suite) + assert ( + tx.data.hex() + == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" + ) + assert ( + tx.signature.hex() + == "f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e" + ) + + +def test_nem_signtx_mosaic_creation_levy(client): + test_suite = { + "timeStamp": 74649215, + "fee": 2000000, + "type": nem.TYPE_MOSAIC_CREATION, + "deadline": 74735615, + "message": {}, + "mosaicDefinition": { + "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, + "properties": [ + {"name": "divisibility", "value": "4"}, + {"name": "initialSupply", "value": "200"}, + {"name": "supplyMutable", "value": "false"}, + {"name": "transferable", "value": "true"}, + ], + "levy": { + "type": 1, + "fee": 2, + "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"}, }, - "version": (0x98 << 24), - "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "creationFee": 1500, - } + "description": "lorem", + }, + "version": (0x98 << 24), + "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "creationFee": 1500, + } - # not using client.nem_sign_tx() because of swiping - tx = nem.sign_tx(client, ADDRESS_N, test_suite) - assert ( - tx.data.hex() - == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f7404c200000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c650400000074727565000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" - ) - assert ( - tx.signature.hex() - == "f17c859710060f2ea9a0ab740ef427431cf36bdc7d263570ca282bd66032e9f5737a921be9839429732e663be2bb74ccc16f34f5157ff2ef00a65796b54e800e" - ) - - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_mosaic_creation_levy(self, client): - test_suite = { - "timeStamp": 74649215, - "fee": 2000000, - "type": nem.TYPE_MOSAIC_CREATION, - "deadline": 74735615, - "message": {}, - "mosaicDefinition": { - "id": {"namespaceId": "hellom", "name": "Hello mosaic"}, - "properties": [ - {"name": "divisibility", "value": "4"}, - {"name": "initialSupply", "value": "200"}, - {"name": "supplyMutable", "value": "false"}, - {"name": "transferable", "value": "true"}, - ], - "levy": { - "type": 1, - "fee": 2, - "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"}, - }, - "description": "lorem", - }, - "version": (0x98 << 24), - "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "creationFee": 1500, - } - - tx = nem.sign_tx(client, ADDRESS_N, test_suite) - assert ( - tx.data.hex() - == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" - ) - assert ( - tx.signature.hex() - == "b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a" - ) + tx = nem.sign_tx(client, ADDRESS_N, test_suite) + assert ( + tx.data.hex() + == "01400000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74041801000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f73616963050000006c6f72656d04000000150000000c00000064697669736962696c6974790100000034180000000d000000696e697469616c537570706c79030000003230301a0000000d000000737570706c794d757461626c650500000066616c7365180000000c0000007472616e7366657261626c65040000007472756556000000010000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a1a0000000600000068656c6c6f6d0c00000048656c6c6f206d6f7361696302000000000000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000" + ) + assert ( + tx.signature.hex() + == "b87aac1ddf146d35e6a7f3451f57e2fe504ac559031e010a51261257c37bd50fcfa7b2939dd7a3203b54c4807d458475182f5d3dc135ec0d1d4a9cd42159fd0a" + ) diff --git a/tests/device_tests/nem/test_signtx_multisig.py b/tests/device_tests/nem/test_signtx_multisig.py index aca5aae8b8..67e3ea1794 100644 --- a/tests/device_tests/nem/test_signtx_multisig.py +++ b/tests/device_tests/nem/test_signtx_multisig.py @@ -21,180 +21,182 @@ from trezorlib.tools import parse_path from ...common import MNEMONIC12 +pytestmark = [ + pytest.mark.altcoin, + pytest.mark.nem, + pytest.mark.setup_client(mnemonic=MNEMONIC12), +] + # assertion data from T1 -@pytest.mark.altcoin -@pytest.mark.nem -class TestMsgNEMSignTxMultisig: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_aggregate_modification(self, client): - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 74649215, - "fee": 2000000, - "type": nem.TYPE_AGGREGATE_MODIFICATION, - "deadline": 74735615, - "message": {}, - "modifications": [ - { - "modificationType": 1, # Add - "cosignatoryAccount": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", - } - ], - "minCosignatories": {"relativeChange": 3}, - "version": (0x98 << 24), - }, - ) - assert ( - tx.data.hex() - == "01100000020000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f740401000000280000000100000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f878440400000003000000" - ) - assert ( - tx.signature.hex() - == "1200e552d8732ce3eae96719731194abfc5a09d98f61bb35684f4eeaeff15b1bdf326ee7b1bbbe89d3f68c8e07ad3daf72e4c7f031094ad2236b97918ad98601" - ) +def test_nem_signtx_aggregate_modification(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 74649215, + "fee": 2000000, + "type": nem.TYPE_AGGREGATE_MODIFICATION, + "deadline": 74735615, + "message": {}, + "modifications": [ + { + "modificationType": 1, # Add + "cosignatoryAccount": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", + } + ], + "minCosignatories": {"relativeChange": 3}, + "version": (0x98 << 24), + }, + ) + assert ( + tx.data.hex() + == "01100000020000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f740401000000280000000100000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f878440400000003000000" + ) + assert ( + tx.signature.hex() + == "1200e552d8732ce3eae96719731194abfc5a09d98f61bb35684f4eeaeff15b1bdf326ee7b1bbbe89d3f68c8e07ad3daf72e4c7f031094ad2236b97918ad98601" + ) - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_multisig(self, client): - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 1, - "fee": 10000, - "type": nem.TYPE_MULTISIG, - "deadline": 74735615, - "otherTrans": { # simple transaction transfer - "timeStamp": 2, - "amount": 2000000, - "fee": 15000, - "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "type": nem.TYPE_TRANSACTION_TRANSFER, - "deadline": 67890, - "message": { - "payload": b"test_nem_transaction_transfer".hex(), - "type": 1, - }, - "version": (0x98 << 24), - "signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", + +def test_nem_signtx_multisig(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 1, + "fee": 10000, + "type": nem.TYPE_MULTISIG, + "deadline": 74735615, + "otherTrans": { # simple transaction transfer + "timeStamp": 2, + "amount": 2000000, + "fee": 15000, + "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "type": nem.TYPE_TRANSACTION_TRANSFER, + "deadline": 67890, + "message": { + "payload": b"test_nem_transaction_transfer".hex(), + "type": 1, }, "version": (0x98 << 24), + "signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", }, - ) + "version": (0x98 << 24), + }, + ) - assert ( - tx.data.hex() - == "04100000010000980100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841027000000000000ff5f74049900000001010000010000980200000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844983a000000000000320901002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572" - ) - assert ( - tx.signature.hex() - == "0cab2fddf2f02b5d7201675b9a71869292fe25ed33a366c7d2cbea7676fed491faaa03310079b7e17884b6ba2e3ea21c4f728d1cca8f190b8288207f6514820a" - ) + assert ( + tx.data.hex() + == "04100000010000980100000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620841027000000000000ff5f74049900000001010000010000980200000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844983a000000000000320901002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572" + ) + assert ( + tx.signature.hex() + == "0cab2fddf2f02b5d7201675b9a71869292fe25ed33a366c7d2cbea7676fed491faaa03310079b7e17884b6ba2e3ea21c4f728d1cca8f190b8288207f6514820a" + ) - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 74649215, - "fee": 150, - "type": nem.TYPE_MULTISIG, - "deadline": 789, - "otherTrans": { - "timeStamp": 123456, - "fee": 2000, - "type": nem.TYPE_PROVISION_NAMESPACE, - "deadline": 100, - "message": {}, - "newPart": "ABCDE", - "rentalFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "rentalFee": 1500, - "parent": None, - "version": (0x98 << 24), - "signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", - }, - "version": (0x98 << 24), - }, - ) - - assert ( - tx.data.hex() - == "04100000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620849600000000000000150300007d000000012000000100009840e2010020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844d007000000000000640000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000050000004142434445ffffffff" - ) - assert ( - tx.signature.hex() - == "c915ca3332380925f4050301cdc62269cf29437ac5955321b18da34e570c7fdbb1aec2940a2a553a2a5c90950a4db3c8d3ef899c1a108582e0657f66fbbb0b04" - ) - - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_multisig_signer(self, client): - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 333, - "fee": 200, - "type": nem.TYPE_MULTISIG_SIGNATURE, - "deadline": 444, - "otherTrans": { # simple transaction transfer - "timeStamp": 555, - "amount": 2000000, - "fee": 2000000, - "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "type": nem.TYPE_TRANSACTION_TRANSFER, - "deadline": 666, - "message": { - "payload": b"test_nem_transaction_transfer".hex(), - "type": 1, - }, - "version": (0x98 << 24), - "signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", - }, - "version": (0x98 << 24), - }, - ) - - assert ( - tx.data.hex() - == "02100000010000984d01000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084c800000000000000bc010000240000002000000087923cd4805f3babe6b5af9cbb2b08be4458e39531618aed73c911f160c8e38528000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32" - ) - assert ( - tx.signature.hex() - == "286358a16ae545bff798feab93a713440c7c2f236d52ac0e995669d17a1915b0903667c97fa04418eccb42333cba95b19bccc8ac1faa8224dcfaeb41890ae807" - ) - - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 900000, - "fee": 200000, - "type": nem.TYPE_MULTISIG_SIGNATURE, + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 74649215, + "fee": 150, + "type": nem.TYPE_MULTISIG, + "deadline": 789, + "otherTrans": { + "timeStamp": 123456, + "fee": 2000, + "type": nem.TYPE_PROVISION_NAMESPACE, "deadline": 100, - "otherTrans": { # simple transaction transfer - "timeStamp": 101111, - "fee": 1000, - "type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, - "deadline": 13123, - "message": {}, - "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"}, - "supplyType": 1, - "delta": 1, - "version": (0x98 << 24), - "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "creationFee": 1500, - "signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", + "message": {}, + "newPart": "ABCDE", + "rentalFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "rentalFee": 1500, + "parent": None, + "version": (0x98 << 24), + "signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", + }, + "version": (0x98 << 24), + }, + ) + + assert ( + tx.data.hex() + == "04100000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b40620849600000000000000150300007d000000012000000100009840e2010020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844d007000000000000640000002800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000050000004142434445ffffffff" + ) + assert ( + tx.signature.hex() + == "c915ca3332380925f4050301cdc62269cf29437ac5955321b18da34e570c7fdbb1aec2940a2a553a2a5c90950a4db3c8d3ef899c1a108582e0657f66fbbb0b04" + ) + + +def test_nem_signtx_multisig_signer(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 333, + "fee": 200, + "type": nem.TYPE_MULTISIG_SIGNATURE, + "deadline": 444, + "otherTrans": { # simple transaction transfer + "timeStamp": 555, + "amount": 2000000, + "fee": 2000000, + "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "type": nem.TYPE_TRANSACTION_TRANSFER, + "deadline": 666, + "message": { + "payload": b"test_nem_transaction_transfer".hex(), + "type": 1, }, "version": (0x98 << 24), + "signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", }, - ) + "version": (0x98 << 24), + }, + ) - assert ( - tx.data.hex() - == "0210000001000098a0bb0d0020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084400d030000000000640000002400000020000000c51395626a89a71c1ed785fb5974307a049b3b9e2165d56ed0302fe6b4f02a0128000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32" - ) - assert ( - tx.signature.hex() - == "32b1fdf788c4a90c01eedf5972b7709745831d620c13e1e97b0de6481837e162ee551573f2409822754ae940731909ec4b79cf836487e898df476adb10467506" - ) + assert ( + tx.data.hex() + == "02100000010000984d01000020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084c800000000000000bc010000240000002000000087923cd4805f3babe6b5af9cbb2b08be4458e39531618aed73c911f160c8e38528000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32" + ) + assert ( + tx.signature.hex() + == "286358a16ae545bff798feab93a713440c7c2f236d52ac0e995669d17a1915b0903667c97fa04418eccb42333cba95b19bccc8ac1faa8224dcfaeb41890ae807" + ) + + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 900000, + "fee": 200000, + "type": nem.TYPE_MULTISIG_SIGNATURE, + "deadline": 100, + "otherTrans": { # simple transaction transfer + "timeStamp": 101111, + "fee": 1000, + "type": nem.TYPE_MOSAIC_SUPPLY_CHANGE, + "deadline": 13123, + "message": {}, + "mosaicId": {"namespaceId": "hellom", "name": "Hello mosaic"}, + "supplyType": 1, + "delta": 1, + "version": (0x98 << 24), + "creationFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "creationFee": 1500, + "signer": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", + }, + "version": (0x98 << 24), + }, + ) + + assert ( + tx.data.hex() + == "0210000001000098a0bb0d0020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084400d030000000000640000002400000020000000c51395626a89a71c1ed785fb5974307a049b3b9e2165d56ed0302fe6b4f02a0128000000544444324354364c514c49595135364b49584933454e544d36454b3344343450354b5a50464d4b32" + ) + assert ( + tx.signature.hex() + == "32b1fdf788c4a90c01eedf5972b7709745831d620c13e1e97b0de6481837e162ee551573f2409822754ae940731909ec4b79cf836487e898df476adb10467506" + ) diff --git a/tests/device_tests/nem/test_signtx_others.py b/tests/device_tests/nem/test_signtx_others.py index 63616fc0da..dd4b38a9d4 100644 --- a/tests/device_tests/nem/test_signtx_others.py +++ b/tests/device_tests/nem/test_signtx_others.py @@ -21,64 +21,66 @@ from trezorlib.tools import parse_path from ...common import MNEMONIC12 +pytestmark = [ + pytest.mark.altcoin, + pytest.mark.nem, + pytest.mark.setup_client(mnemonic=MNEMONIC12), +] + # assertion data from T1 -@pytest.mark.altcoin -@pytest.mark.nem -class TestMsgNEMSignTxOther: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_importance_transfer(self, client): - with client: - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 12349215, - "fee": 9900, - "type": nem.TYPE_IMPORTANCE_TRANSFER, - "deadline": 99, - "message": {}, - "importanceTransfer": { - "mode": 1, # activate - "publicKey": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", - }, - "version": (0x98 << 24), - }, - ) - - assert ( - tx.data.hex() - == "01080000010000981f6fbc0020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084ac26000000000000630000000100000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844" - ) - assert ( - tx.signature.hex() - == "b6d9434ec5df80e65e6e45d7f0f3c579b4adfe8567c42d981b06e8ac368b1aad2b24eebecd5efd41f4497051fca8ea8a5e77636a79afc46ee1a8e0fe9e3ba90b" - ) - - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_provision_namespace(self, client): +def test_nem_signtx_importance_transfer(client): + with client: tx = nem.sign_tx( client, parse_path("m/44'/1'/0'/0'/0'"), { - "timeStamp": 74649215, - "fee": 2000000, - "type": nem.TYPE_PROVISION_NAMESPACE, - "deadline": 74735615, + "timeStamp": 12349215, + "fee": 9900, + "type": nem.TYPE_IMPORTANCE_TRANSFER, + "deadline": 99, "message": {}, - "newPart": "ABCDE", - "rentalFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "rentalFee": 1500, - "parent": None, + "importanceTransfer": { + "mode": 1, # activate + "publicKey": "c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844", + }, "version": (0x98 << 24), }, ) assert ( tx.data.hex() - == "01200000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000050000004142434445ffffffff" + == "01080000010000981f6fbc0020000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b4062084ac26000000000000630000000100000020000000c5f54ba980fcbb657dbaaa42700539b207873e134d2375efeab5f1ab52f87844" ) assert ( tx.signature.hex() - == "f047ae7987cd3a60c0d5ad123aba211185cb6266a7469dfb0491a0df6b5cd9c92b2e2b9f396cc2a3146ee185ba02df4f9e7fb238fe479917b3d274d97336640d" + == "b6d9434ec5df80e65e6e45d7f0f3c579b4adfe8567c42d981b06e8ac368b1aad2b24eebecd5efd41f4497051fca8ea8a5e77636a79afc46ee1a8e0fe9e3ba90b" ) + + +def test_nem_signtx_provision_namespace(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 74649215, + "fee": 2000000, + "type": nem.TYPE_PROVISION_NAMESPACE, + "deadline": 74735615, + "message": {}, + "newPart": "ABCDE", + "rentalFeeSink": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "rentalFee": 1500, + "parent": None, + "version": (0x98 << 24), + }, + ) + + assert ( + tx.data.hex() + == "01200000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324adc05000000000000050000004142434445ffffffff" + ) + assert ( + tx.signature.hex() + == "f047ae7987cd3a60c0d5ad123aba211185cb6266a7469dfb0491a0df6b5cd9c92b2e2b9f396cc2a3146ee185ba02df4f9e7fb238fe479917b3d274d97336640d" + ) diff --git a/tests/device_tests/nem/test_signtx_transfers.py b/tests/device_tests/nem/test_signtx_transfers.py index b712e8ae2b..2ec6b7a5a7 100644 --- a/tests/device_tests/nem/test_signtx_transfers.py +++ b/tests/device_tests/nem/test_signtx_transfers.py @@ -21,276 +21,284 @@ from trezorlib.tools import parse_path from ...common import MNEMONIC12 +pytestmark = [ + pytest.mark.altcoin, + pytest.mark.nem, + pytest.mark.setup_client(mnemonic=MNEMONIC12), +] + # assertion data from T1 -@pytest.mark.altcoin -@pytest.mark.nem -class TestMsgNEMSignTx: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_simple(self, client): - with client: - client.set_expected_responses( - [ - # Confirm transfer and network fee - proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), - # Unencrypted message - proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), - # Confirm recipient - proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), - proto.NEMSignedTx, - ] - ) +def test_nem_signtx_simple(client): + with client: + client.set_expected_responses( + [ + # Confirm transfer and network fee + proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), + # Unencrypted message + proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), + # Confirm recipient + proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), + proto.NEMSignedTx, + ] + ) - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 74649215, - "amount": 2000000, - "fee": 2000000, - "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "type": nem.TYPE_TRANSACTION_TRANSFER, - "deadline": 74735615, - "message": { - "payload": b"test_nem_transaction_transfer".hex(), - "type": 1, - }, - "version": (0x98 << 24), - }, - ) - - assert ( - tx.data.hex() - == "01010000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572" - ) - assert ( - tx.signature.hex() - == "9cda2045324d05c791a4fc312ecceb62954e7740482f8df8928560d63cf273dea595023640179f112de755c79717757ef76962175378d6d87360ddb3f3e5f70f" - ) - - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_encrypted_payload(self, client): - with client: - client.set_expected_responses( - [ - # Confirm transfer and network fee - proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), - # Ask for encryption - proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), - # Confirm recipient - proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), - proto.NEMSignedTx, - ] - ) - - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 74649215, - "amount": 2000000, - "fee": 2000000, - "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", - "type": nem.TYPE_TRANSACTION_TRANSFER, - "deadline": 74735615, - "message": { - # plain text is 32B long => cipher text is 48B - # as per PKCS#7 another block containing padding is added - "payload": b"this message should be encrypted".hex(), - "publicKey": "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", - "type": 2, - }, - "version": (0x98 << 24), - }, - ) - - assert ( - tx.data[:124].hex() - == "01010000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e0000000000680000000200000060000000" - ) - # after 124th byte comes iv (16B) salt (32B) and encrypted payload (48B) - assert len(tx.data[124:]) == 16 + 32 + 48 - # because IV and salt are random (therefore the encrypted payload as well) those data can't be asserted - assert len(tx.signature) == 64 - - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_xem_as_mosaic(self, client): tx = nem.sign_tx( client, parse_path("m/44'/1'/0'/0'/0'"), { - "timeStamp": 76809215, - "amount": 5000000, - "fee": 1000000, + "timeStamp": 74649215, + "amount": 2000000, + "fee": 2000000, "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "type": nem.TYPE_TRANSACTION_TRANSFER, - "deadline": 76895615, + "deadline": 74735615, + "message": { + "payload": b"test_nem_transaction_transfer".hex(), + "type": 1, + }, "version": (0x98 << 24), - "message": {}, - "mosaics": [ - { - "mosaicId": {"namespaceId": "nem", "name": "xem"}, - "quantity": 9000000, - } - ], }, ) - # trezor should display 45 XEM (multiplied by amount) assert ( tx.data.hex() - == "0101000002000098ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f5595042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a404b4c000000000000000000010000001a0000000e000000030000006e656d0300000078656d4054890000000000" + == "01010000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e000000000025000000010000001d000000746573745f6e656d5f7472616e73616374696f6e5f7472616e73666572" ) assert ( tx.signature.hex() - == "7b25a84b65adb489ea55739f1ca2d83a0ae069c3c58d0ea075fc30bfe8f649519199ad2324ca229c6c3214191469f95326e99712124592cae7cd3a092c93ac0c" + == "9cda2045324d05c791a4fc312ecceb62954e7740482f8df8928560d63cf273dea595023640179f112de755c79717757ef76962175378d6d87360ddb3f3e5f70f" + ) + + +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_nem_signtx_encrypted_payload(client): + with client: + client.set_expected_responses( + [ + # Confirm transfer and network fee + proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), + # Ask for encryption + proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), + # Confirm recipient + proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), + proto.NEMSignedTx, + ] ) - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_unknown_mosaic(self, client): tx = nem.sign_tx( client, parse_path("m/44'/1'/0'/0'/0'"), { - "timeStamp": 76809215, + "timeStamp": 74649215, "amount": 2000000, - "fee": 1000000, + "fee": 2000000, "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", "type": nem.TYPE_TRANSACTION_TRANSFER, - "deadline": 76895615, + "deadline": 74735615, + "message": { + # plain text is 32B long => cipher text is 48B + # as per PKCS#7 another block containing padding is added + "payload": b"this message should be encrypted".hex(), + "publicKey": "5a5e14c633d7d269302849d739d80344ff14db51d7bcda86045723f05c4e4541", + "type": 2, + }, "version": (0x98 << 24), - "message": {}, - "mosaics": [ - { - "mosaicId": {"namespaceId": "xxx", "name": "aa"}, - "quantity": 3500000, - } - ], }, ) - # trezor should display warning about unknown mosaic and then dialog for 7000000 raw units of xxx.aa and 0 XEM assert ( - tx.data.hex() - == "0101000002000098ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f5595042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e00000000000000000001000000190000000d00000003000000787878020000006161e067350000000000" - ) - assert ( - tx.signature.hex() - == "2f0280420eceb41ef9e5d94fa44ddda9cdc70b8f423ae18af577f6d85df64bb4aaf40cf24fc6eef47c63b0963611f8682348cecdc49a9b64eafcbe7afcb49102" + tx.data[:124].hex() + == "01010000010000987f0e730420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208480841e0000000000ff5f74042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e0000000000680000000200000060000000" ) + # after 124th byte comes iv (16B) salt (32B) and encrypted payload (48B) + assert len(tx.data[124:]) == 16 + 32 + 48 + # because IV and salt are random (therefore the encrypted payload as well) those data can't be asserted + assert len(tx.signature) == 64 - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_known_mosaic(self, client): - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 76809215, - "amount": 3000000, - "fee": 1000000, - "recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT", - "type": nem.TYPE_TRANSACTION_TRANSFER, - "deadline": 76895615, - "version": (0x68 << 24), - "message": {}, - "mosaics": [ - { - "mosaicId": {"namespaceId": "dim", "name": "token"}, - "quantity": 111000, - } - ], - }, - ) - # trezor should display 0 XEM and 0.333 DIMTOK - assert ( - tx.data.hex() - == "0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c54c0c62d000000000000000000010000001c000000100000000300000064696d05000000746f6b656e98b1010000000000" - ) - assert ( - tx.signature.hex() - == "e7f14ef8c39727bfd257e109cd5acac31542f2e41f2e5deb258fc1db602b690eb1cabca41a627fe2adc51f3193db85c76b41c80bb60161eb8738ebf20b507104" - ) +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_nem_signtx_xem_as_mosaic(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 76809215, + "amount": 5000000, + "fee": 1000000, + "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "type": nem.TYPE_TRANSACTION_TRANSFER, + "deadline": 76895615, + "version": (0x98 << 24), + "message": {}, + "mosaics": [ + { + "mosaicId": {"namespaceId": "nem", "name": "xem"}, + "quantity": 9000000, + } + ], + }, + ) - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_known_mosaic_with_levy(self, client): - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 76809215, - "amount": 2000000, - "fee": 1000000, - "recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT", - "type": nem.TYPE_TRANSACTION_TRANSFER, - "deadline": 76895615, - "version": (0x68 << 24), - "message": {}, - "mosaics": [ - { - "mosaicId": {"namespaceId": "dim", "name": "coin"}, - "quantity": 222000, - } - ], - }, - ) + # trezor should display 45 XEM (multiplied by amount) + assert ( + tx.data.hex() + == "0101000002000098ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f5595042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a404b4c000000000000000000010000001a0000000e000000030000006e656d0300000078656d4054890000000000" + ) + assert ( + tx.signature.hex() + == "7b25a84b65adb489ea55739f1ca2d83a0ae069c3c58d0ea075fc30bfe8f649519199ad2324ca229c6c3214191469f95326e99712124592cae7cd3a092c93ac0c" + ) - # trezor should display 0 XEM and 0.444 DIM and levy of 0.000444 DIM - assert ( - tx.data.hex() - == "0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c5480841e000000000000000000010000001b0000000f0000000300000064696d04000000636f696e3063030000000000" - ) - assert ( - tx.signature.hex() - == "d3222dd7b83d66bda0539827ac6f909d06e40350b5e5e893d6fa762f954e9bf7da61022ef04950e7b6dfa88a2278f2f8a1b21df2bc3af22b388cb3a90bf76f07" - ) - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_nem_signtx_multiple_mosaics(self, client): - tx = nem.sign_tx( - client, - parse_path("m/44'/1'/0'/0'/0'"), - { - "timeStamp": 76809215, - "amount": 2000000, - "fee": 1000000, - "recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT", - "type": nem.TYPE_TRANSACTION_TRANSFER, - "deadline": 76895615, - "version": (0x68 << 24), - "message": {}, - "mosaics": [ - { - "mosaicId": {"namespaceId": "nem", "name": "xem"}, - "quantity": 3000000, - }, - { - "mosaicId": {"namespaceId": "abc", "name": "mosaic"}, - "quantity": 200, - }, - { - "mosaicId": {"namespaceId": "nem", "name": "xem"}, - "quantity": 30000, - }, - { - "mosaicId": {"namespaceId": "abc", "name": "mosaic"}, - "quantity": 2000000, - }, - { - "mosaicId": {"namespaceId": "breeze", "name": "breeze-token"}, - "quantity": 111000, - }, - ], - }, - ) +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_nem_signtx_unknown_mosaic(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 76809215, + "amount": 2000000, + "fee": 1000000, + "recipient": "TALICE2GMA34CXHD7XLJQ536NM5UNKQHTORNNT2J", + "type": nem.TYPE_TRANSACTION_TRANSFER, + "deadline": 76895615, + "version": (0x98 << 24), + "message": {}, + "mosaics": [ + { + "mosaicId": {"namespaceId": "xxx", "name": "aa"}, + "quantity": 3500000, + } + ], + }, + ) - # trezor should display warning, 6.06 XEM, 4000400 raw units of abc.mosaic (mosaics are merged) - # and 222000 BREEZE - assert ( - tx.data.hex() - == "0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c5480841e000000000000000000030000001d0000001100000003000000616263060000006d6f7361696348851e0000000000260000001a00000006000000627265657a650c000000627265657a652d746f6b656e98b10100000000001a0000000e000000030000006e656d0300000078656df03b2e0000000000" - ) - assert ( - tx.signature.hex() - == "b2b9319fca87a05bee17108edd9a8f78aeffef74bf6b4badc6da5d46e8ff4fe82e24bf69d8e6c4097d072adf39d0c753e7580f8afb21e3288ebfb7c4d84e470d" - ) + # trezor should display warning about unknown mosaic and then dialog for 7000000 raw units of xxx.aa and 0 XEM + assert ( + tx.data.hex() + == "0101000002000098ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f5595042800000054414c49434532474d4133344358484437584c4a513533364e4d35554e4b5148544f524e4e54324a80841e00000000000000000001000000190000000d00000003000000787878020000006161e067350000000000" + ) + assert ( + tx.signature.hex() + == "2f0280420eceb41ef9e5d94fa44ddda9cdc70b8f423ae18af577f6d85df64bb4aaf40cf24fc6eef47c63b0963611f8682348cecdc49a9b64eafcbe7afcb49102" + ) + + +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_nem_signtx_known_mosaic(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 76809215, + "amount": 3000000, + "fee": 1000000, + "recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT", + "type": nem.TYPE_TRANSACTION_TRANSFER, + "deadline": 76895615, + "version": (0x68 << 24), + "message": {}, + "mosaics": [ + { + "mosaicId": {"namespaceId": "dim", "name": "token"}, + "quantity": 111000, + } + ], + }, + ) + + # trezor should display 0 XEM and 0.333 DIMTOK + assert ( + tx.data.hex() + == "0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c54c0c62d000000000000000000010000001c000000100000000300000064696d05000000746f6b656e98b1010000000000" + ) + assert ( + tx.signature.hex() + == "e7f14ef8c39727bfd257e109cd5acac31542f2e41f2e5deb258fc1db602b690eb1cabca41a627fe2adc51f3193db85c76b41c80bb60161eb8738ebf20b507104" + ) + + +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_nem_signtx_known_mosaic_with_levy(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 76809215, + "amount": 2000000, + "fee": 1000000, + "recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT", + "type": nem.TYPE_TRANSACTION_TRANSFER, + "deadline": 76895615, + "version": (0x68 << 24), + "message": {}, + "mosaics": [ + { + "mosaicId": {"namespaceId": "dim", "name": "coin"}, + "quantity": 222000, + } + ], + }, + ) + + # trezor should display 0 XEM and 0.444 DIM and levy of 0.000444 DIM + assert ( + tx.data.hex() + == "0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c5480841e000000000000000000010000001b0000000f0000000300000064696d04000000636f696e3063030000000000" + ) + assert ( + tx.signature.hex() + == "d3222dd7b83d66bda0539827ac6f909d06e40350b5e5e893d6fa762f954e9bf7da61022ef04950e7b6dfa88a2278f2f8a1b21df2bc3af22b388cb3a90bf76f07" + ) + + +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_nem_signtx_multiple_mosaics(client): + tx = nem.sign_tx( + client, + parse_path("m/44'/1'/0'/0'/0'"), + { + "timeStamp": 76809215, + "amount": 2000000, + "fee": 1000000, + "recipient": "NDMYSLXI4L3FYUQWO4MJOVL6BSTJJXKDSZRMT4LT", + "type": nem.TYPE_TRANSACTION_TRANSFER, + "deadline": 76895615, + "version": (0x68 << 24), + "message": {}, + "mosaics": [ + { + "mosaicId": {"namespaceId": "nem", "name": "xem"}, + "quantity": 3000000, + }, + { + "mosaicId": {"namespaceId": "abc", "name": "mosaic"}, + "quantity": 200, + }, + { + "mosaicId": {"namespaceId": "nem", "name": "xem"}, + "quantity": 30000, + }, + { + "mosaicId": {"namespaceId": "abc", "name": "mosaic"}, + "quantity": 2000000, + }, + { + "mosaicId": {"namespaceId": "breeze", "name": "breeze-token"}, + "quantity": 111000, + }, + ], + }, + ) + + # trezor should display warning, 6.06 XEM, 4000400 raw units of abc.mosaic (mosaics are merged) + # and 222000 BREEZE + assert ( + tx.data.hex() + == "0101000002000068ff03940420000000edfd32f6e760648c032f9acb4b30d514265f6a5b5f8a7154f2618922b406208440420f00000000007f559504280000004e444d59534c5849344c3346595551574f344d4a4f564c364253544a4a584b44535a524d54344c5480841e000000000000000000030000001d0000001100000003000000616263060000006d6f7361696348851e0000000000260000001a00000006000000627265657a650c000000627265657a652d746f6b656e98b10100000000001a0000000e000000030000006e656d0300000078656df03b2e0000000000" + ) + assert ( + tx.signature.hex() + == "b2b9319fca87a05bee17108edd9a8f78aeffef74bf6b4badc6da5d46e8ff4fe82e24bf69d8e6c4097d072adf39d0c753e7580f8afb21e3288ebfb7c4d84e470d" + ) diff --git a/tests/device_tests/recovery/test_bip39.py b/tests/device_tests/recovery/test_bip39.py index ead5c3f892..1142e80c42 100644 --- a/tests/device_tests/recovery/test_bip39.py +++ b/tests/device_tests/recovery/test_bip39.py @@ -23,189 +23,193 @@ from ...common import MNEMONIC12 PIN4 = "1234" PIN6 = "789456" +pytestmark = [pytest.mark.skip_t2] -@pytest.mark.skip_t2 -class TestMsgRecoverydevice: - @pytest.mark.setup_client(uninitialized=True) - def test_pin_passphrase(self, client): - mnemonic = MNEMONIC12.split(" ") - ret = client.call_raw( - proto.RecoveryDevice( - word_count=12, - passphrase_protection=True, - pin_protection=True, - label="label", - language="en-US", - enforce_wordlist=True, - ) + +@pytest.mark.setup_client(uninitialized=True) +def test_pin_passphrase(client): + mnemonic = MNEMONIC12.split(" ") + ret = client.call_raw( + proto.RecoveryDevice( + word_count=12, + passphrase_protection=True, + pin_protection=True, + label="label", + language="en-US", + enforce_wordlist=True, ) + ) - # click through confirmation - assert isinstance(ret, proto.ButtonRequest) - client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) + # click through confirmation + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) - assert isinstance(ret, proto.PinMatrixRequest) + assert isinstance(ret, proto.PinMatrixRequest) - # Enter PIN for first time - pin_encoded = client.debug.encode_pin(PIN6) - ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) - assert isinstance(ret, proto.PinMatrixRequest) + # Enter PIN for first time + pin_encoded = client.debug.encode_pin(PIN6) + ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) + assert isinstance(ret, proto.PinMatrixRequest) - # Enter PIN for second time - pin_encoded = client.debug.encode_pin(PIN6) - ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) - - fakes = 0 - for _ in range(int(12 * 2)): - assert isinstance(ret, proto.WordRequest) - (word, pos) = client.debug.read_recovery_word() - - if pos != 0: - ret = client.call_raw(proto.WordAck(word=mnemonic[pos - 1])) - mnemonic[pos - 1] = None - else: - ret = client.call_raw(proto.WordAck(word=word)) - fakes += 1 - - # Workflow succesfully ended - assert isinstance(ret, proto.Success) - - # 12 expected fake words and all words of mnemonic are used - assert fakes == 12 - assert mnemonic == [None] * 12 - - # Mnemonic is the same - client.init_device() - assert client.debug.state().mnemonic_secret == MNEMONIC12.encode() - - assert client.features.pin_protection is True - assert client.features.passphrase_protection is True - - # Do passphrase-protected action, PassphraseRequest should be raised - resp = client.call_raw(proto.GetAddress()) - assert isinstance(resp, proto.PassphraseRequest) - client.call_raw(proto.Cancel()) - - @pytest.mark.setup_client(uninitialized=True) - def test_nopin_nopassphrase(self, client): - mnemonic = MNEMONIC12.split(" ") - ret = client.call_raw( - proto.RecoveryDevice( - word_count=12, - passphrase_protection=False, - pin_protection=False, - label="label", - language="en-US", - enforce_wordlist=True, - ) - ) - - # click through confirmation - assert isinstance(ret, proto.ButtonRequest) - client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) - - fakes = 0 - for _ in range(int(12 * 2)): - assert isinstance(ret, proto.WordRequest) - (word, pos) = client.debug.read_recovery_word() - - if pos != 0: - ret = client.call_raw(proto.WordAck(word=mnemonic[pos - 1])) - mnemonic[pos - 1] = None - else: - ret = client.call_raw(proto.WordAck(word=word)) - fakes += 1 - - # Workflow succesfully ended - assert isinstance(ret, proto.Success) - - # 12 expected fake words and all words of mnemonic are used - assert fakes == 12 - assert mnemonic == [None] * 12 - - # Mnemonic is the same - client.init_device() - assert client.debug.state().mnemonic_secret == MNEMONIC12.encode() - - assert client.features.pin_protection is False - assert client.features.passphrase_protection is False - - # Do pin & passphrase-protected action, PassphraseRequest should NOT be raised - resp = client.call_raw(proto.GetAddress()) - assert isinstance(resp, proto.Address) - - @pytest.mark.setup_client(uninitialized=True) - def test_word_fail(self, client): - ret = client.call_raw( - proto.RecoveryDevice( - word_count=12, - passphrase_protection=False, - pin_protection=False, - label="label", - language="en-US", - enforce_wordlist=True, - ) - ) - - # click through confirmation - assert isinstance(ret, proto.ButtonRequest) - client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) + # Enter PIN for second time + pin_encoded = client.debug.encode_pin(PIN6) + ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) + fakes = 0 + for _ in range(int(12 * 2)): assert isinstance(ret, proto.WordRequest) - for _ in range(int(12 * 2)): - (word, pos) = client.debug.read_recovery_word() - if pos != 0: - ret = client.call_raw(proto.WordAck(word="kwyjibo")) - assert isinstance(ret, proto.Failure) - break - else: - client.call_raw(proto.WordAck(word=word)) + (word, pos) = client.debug.read_recovery_word() - @pytest.mark.setup_client(uninitialized=True) - def test_pin_fail(self, client): - ret = client.call_raw( - proto.RecoveryDevice( - word_count=12, - passphrase_protection=True, - pin_protection=True, - label="label", - language="en-US", - enforce_wordlist=True, - ) + if pos != 0: + ret = client.call_raw(proto.WordAck(word=mnemonic[pos - 1])) + mnemonic[pos - 1] = None + else: + ret = client.call_raw(proto.WordAck(word=word)) + fakes += 1 + + # Workflow succesfully ended + assert isinstance(ret, proto.Success) + + # 12 expected fake words and all words of mnemonic are used + assert fakes == 12 + assert mnemonic == [None] * 12 + + # Mnemonic is the same + client.init_device() + assert client.debug.state().mnemonic_secret == MNEMONIC12.encode() + + assert client.features.pin_protection is True + assert client.features.passphrase_protection is True + + # Do passphrase-protected action, PassphraseRequest should be raised + resp = client.call_raw(proto.GetAddress()) + assert isinstance(resp, proto.PassphraseRequest) + client.call_raw(proto.Cancel()) + + +@pytest.mark.setup_client(uninitialized=True) +def test_nopin_nopassphrase(client): + mnemonic = MNEMONIC12.split(" ") + ret = client.call_raw( + proto.RecoveryDevice( + word_count=12, + passphrase_protection=False, + pin_protection=False, + label="label", + language="en-US", + enforce_wordlist=True, + ) + ) + + # click through confirmation + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) + + fakes = 0 + for _ in range(int(12 * 2)): + assert isinstance(ret, proto.WordRequest) + (word, pos) = client.debug.read_recovery_word() + + if pos != 0: + ret = client.call_raw(proto.WordAck(word=mnemonic[pos - 1])) + mnemonic[pos - 1] = None + else: + ret = client.call_raw(proto.WordAck(word=word)) + fakes += 1 + + # Workflow succesfully ended + assert isinstance(ret, proto.Success) + + # 12 expected fake words and all words of mnemonic are used + assert fakes == 12 + assert mnemonic == [None] * 12 + + # Mnemonic is the same + client.init_device() + assert client.debug.state().mnemonic_secret == MNEMONIC12.encode() + + assert client.features.pin_protection is False + assert client.features.passphrase_protection is False + + # Do pin & passphrase-protected action, PassphraseRequest should NOT be raised + resp = client.call_raw(proto.GetAddress()) + assert isinstance(resp, proto.Address) + + +@pytest.mark.setup_client(uninitialized=True) +def test_word_fail(client): + ret = client.call_raw( + proto.RecoveryDevice( + word_count=12, + passphrase_protection=False, + pin_protection=False, + label="label", + language="en-US", + enforce_wordlist=True, + ) + ) + + # click through confirmation + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) + + assert isinstance(ret, proto.WordRequest) + for _ in range(int(12 * 2)): + (word, pos) = client.debug.read_recovery_word() + if pos != 0: + ret = client.call_raw(proto.WordAck(word="kwyjibo")) + assert isinstance(ret, proto.Failure) + break + else: + client.call_raw(proto.WordAck(word=word)) + + +@pytest.mark.setup_client(uninitialized=True) +def test_pin_fail(client): + ret = client.call_raw( + proto.RecoveryDevice( + word_count=12, + passphrase_protection=True, + pin_protection=True, + label="label", + language="en-US", + enforce_wordlist=True, + ) + ) + + # click through confirmation + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) + + assert isinstance(ret, proto.PinMatrixRequest) + + # Enter PIN for first time + pin_encoded = client.debug.encode_pin(PIN4) + ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) + assert isinstance(ret, proto.PinMatrixRequest) + + # Enter PIN for second time, but different one + pin_encoded = client.debug.encode_pin(PIN6) + ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) + + # Failure should be raised + assert isinstance(ret, proto.Failure) + + +def test_already_initialized(client): + with pytest.raises(RuntimeError): + device.recover( + client, 12, False, False, "label", "en-US", client.mnemonic_callback ) - # click through confirmation - assert isinstance(ret, proto.ButtonRequest) - client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) - - assert isinstance(ret, proto.PinMatrixRequest) - - # Enter PIN for first time - pin_encoded = client.debug.encode_pin(PIN4) - ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) - assert isinstance(ret, proto.PinMatrixRequest) - - # Enter PIN for second time, but different one - pin_encoded = client.debug.encode_pin(PIN6) - ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) - - # Failure should be raised - assert isinstance(ret, proto.Failure) - - def test_already_initialized(self, client): - with pytest.raises(RuntimeError): - device.recover( - client, 12, False, False, "label", "en-US", client.mnemonic_callback - ) - - ret = client.call_raw( - proto.RecoveryDevice( - word_count=12, type=proto.RecoveryDeviceType.ScrambledWords - ) + ret = client.call_raw( + proto.RecoveryDevice( + word_count=12, type=proto.RecoveryDeviceType.ScrambledWords ) - assert isinstance(ret, proto.Failure) - assert "Device is already initialized" in ret.message + ) + assert isinstance(ret, proto.Failure) + assert "Device is already initialized" in ret.message diff --git a/tests/device_tests/reset/test_bip39.py b/tests/device_tests/reset/test_bip39.py index b9046e90d6..061cc3c758 100644 --- a/tests/device_tests/reset/test_bip39.py +++ b/tests/device_tests/reset/test_bip39.py @@ -21,6 +21,8 @@ from trezorlib import device, messages as proto from ...common import generate_entropy +pytestmark = [pytest.mark.skip_t1] + def reset_device(client, strength): # No PIN, no passphrase @@ -88,149 +90,151 @@ def reset_device(client, strength): assert isinstance(resp, proto.Address) -@pytest.mark.skip_t2 -class TestMsgResetDevice: - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_128(self, client): - reset_device(client, 128) +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_128(client): + reset_device(client, 128) - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_192(self, client): - reset_device(client, 192) - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_256_pin(self, client): - external_entropy = b"zlutoucky kun upel divoke ody" * 2 - strength = 256 +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_192(client): + reset_device(client, 192) - ret = client.call_raw( - proto.ResetDevice( - display_random=True, - strength=strength, - passphrase_protection=True, - pin_protection=True, - language="en-US", - label="test", - ) + +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_256_pin(client): + external_entropy = b"zlutoucky kun upel divoke ody" * 2 + strength = 256 + + ret = client.call_raw( + proto.ResetDevice( + display_random=True, + strength=strength, + passphrase_protection=True, + pin_protection=True, + language="en-US", + label="test", ) + ) - # Do you want ... ? + # Do you want ... ? + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) + + # Entropy screen #1 + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) + + # Entropy screen #2 + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) + + assert isinstance(ret, proto.PinMatrixRequest) + + # Enter PIN for first time + pin_encoded = client.debug.encode_pin("654") + ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) + assert isinstance(ret, proto.PinMatrixRequest) + + # Enter PIN for second time + pin_encoded = client.debug.encode_pin("654") + ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) + + # Provide entropy + assert isinstance(ret, proto.EntropyRequest) + internal_entropy = client.debug.state().reset_entropy + ret = client.call_raw(proto.EntropyAck(entropy=external_entropy)) + + # Generate mnemonic locally + entropy = generate_entropy(strength, internal_entropy, external_entropy) + expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) + + mnemonic = [] + for _ in range(strength // 32 * 3): assert isinstance(ret, proto.ButtonRequest) + mnemonic.append(client.debug.read_reset_word()) client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) + client.call_raw(proto.ButtonAck()) - # Entropy screen #1 + mnemonic = " ".join(mnemonic) + + # Compare that device generated proper mnemonic for given entropies + assert mnemonic == expected_mnemonic + + mnemonic = [] + for _ in range(strength // 32 * 3): assert isinstance(ret, proto.ButtonRequest) + mnemonic.append(client.debug.read_reset_word()) client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) + resp = client.call_raw(proto.ButtonAck()) - # Entropy screen #2 - assert isinstance(ret, proto.ButtonRequest) - client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) + assert isinstance(resp, proto.Success) - assert isinstance(ret, proto.PinMatrixRequest) + mnemonic = " ".join(mnemonic) - # Enter PIN for first time - pin_encoded = client.debug.encode_pin("654") - ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) - assert isinstance(ret, proto.PinMatrixRequest) + # Compare that second pass printed out the same mnemonic once again + assert mnemonic == expected_mnemonic - # Enter PIN for second time - pin_encoded = client.debug.encode_pin("654") - ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) + # Check if device is properly initialized + resp = client.call_raw(proto.Initialize()) + assert resp.initialized is True + assert resp.needs_backup is False + assert resp.pin_protection is True + assert resp.passphrase_protection is True - # Provide entropy - assert isinstance(ret, proto.EntropyRequest) - internal_entropy = client.debug.state().reset_entropy - ret = client.call_raw(proto.EntropyAck(entropy=external_entropy)) + # Do passphrase-protected action, PassphraseRequest should be raised + resp = client.call_raw(proto.GetAddress()) + assert isinstance(resp, proto.PassphraseRequest) + client.call_raw(proto.Cancel()) - # Generate mnemonic locally - entropy = generate_entropy(strength, internal_entropy, external_entropy) - expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) - mnemonic = [] - for _ in range(strength // 32 * 3): - assert isinstance(ret, proto.ButtonRequest) - mnemonic.append(client.debug.read_reset_word()) - client.debug.press_yes() - client.call_raw(proto.ButtonAck()) +@pytest.mark.setup_client(uninitialized=True) +def test_failed_pin(client): + # external_entropy = b'zlutoucky kun upel divoke ody' * 2 + strength = 128 - mnemonic = " ".join(mnemonic) - - # Compare that device generated proper mnemonic for given entropies - assert mnemonic == expected_mnemonic - - mnemonic = [] - for _ in range(strength // 32 * 3): - assert isinstance(ret, proto.ButtonRequest) - mnemonic.append(client.debug.read_reset_word()) - client.debug.press_yes() - resp = client.call_raw(proto.ButtonAck()) - - assert isinstance(resp, proto.Success) - - mnemonic = " ".join(mnemonic) - - # Compare that second pass printed out the same mnemonic once again - assert mnemonic == expected_mnemonic - - # Check if device is properly initialized - resp = client.call_raw(proto.Initialize()) - assert resp.initialized is True - assert resp.needs_backup is False - assert resp.pin_protection is True - assert resp.passphrase_protection is True - - # Do passphrase-protected action, PassphraseRequest should be raised - resp = client.call_raw(proto.GetAddress()) - assert isinstance(resp, proto.PassphraseRequest) - client.call_raw(proto.Cancel()) - - @pytest.mark.setup_client(uninitialized=True) - def test_failed_pin(self, client): - # external_entropy = b'zlutoucky kun upel divoke ody' * 2 - strength = 128 - - ret = client.call_raw( - proto.ResetDevice( - display_random=True, - strength=strength, - passphrase_protection=True, - pin_protection=True, - language="en-US", - label="test", - ) + ret = client.call_raw( + proto.ResetDevice( + display_random=True, + strength=strength, + passphrase_protection=True, + pin_protection=True, + language="en-US", + label="test", ) + ) - # Do you want ... ? - assert isinstance(ret, proto.ButtonRequest) - client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) + # Do you want ... ? + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) - # Entropy screen #1 - assert isinstance(ret, proto.ButtonRequest) - client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) + # Entropy screen #1 + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) - # Entropy screen #2 - assert isinstance(ret, proto.ButtonRequest) - client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) + # Entropy screen #2 + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) - assert isinstance(ret, proto.PinMatrixRequest) + assert isinstance(ret, proto.PinMatrixRequest) - # Enter PIN for first time - pin_encoded = client.debug.encode_pin("1234") - ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) - assert isinstance(ret, proto.PinMatrixRequest) + # Enter PIN for first time + pin_encoded = client.debug.encode_pin("1234") + ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) + assert isinstance(ret, proto.PinMatrixRequest) - # Enter PIN for second time - pin_encoded = client.debug.encode_pin("6789") - ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) + # Enter PIN for second time + pin_encoded = client.debug.encode_pin("6789") + ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded)) - assert isinstance(ret, proto.Failure) + assert isinstance(ret, proto.Failure) - def test_already_initialized(self, client): - with pytest.raises(Exception): - device.reset(client, False, 128, True, True, "label", "en-US") + +def test_already_initialized(client): + with pytest.raises(Exception): + device.reset(client, False, 128, True, True, "label", "en-US") diff --git a/tests/device_tests/reset/test_bip39_skipbackup.py b/tests/device_tests/reset/test_bip39_skipbackup.py index 9bd2d4a75f..0cc05cab96 100644 --- a/tests/device_tests/reset/test_bip39_skipbackup.py +++ b/tests/device_tests/reset/test_bip39_skipbackup.py @@ -21,151 +21,151 @@ from trezorlib import messages as proto from ...common import generate_entropy +pytestmark = [pytest.mark.skip_t2] -@pytest.mark.skip_t2 -class TestMsgResetDeviceSkipbackup: +EXTERNAL_ENTROPY = b"zlutoucky kun upel divoke ody" * 2 +STRENGTH = 128 - external_entropy = b"zlutoucky kun upel divoke ody" * 2 - strength = 128 - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_skip_backup(self, client): - ret = client.call_raw( - proto.ResetDevice( - display_random=False, - strength=self.strength, - passphrase_protection=False, - pin_protection=False, - language="en-US", - label="test", - skip_backup=True, - ) +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_skip_backup(client): + ret = client.call_raw( + proto.ResetDevice( + display_random=False, + strength=STRENGTH, + passphrase_protection=False, + pin_protection=False, + language="en-US", + label="test", + skip_backup=True, ) + ) + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) + + # Provide entropy + assert isinstance(ret, proto.EntropyRequest) + internal_entropy = client.debug.state().reset_entropy + ret = client.call_raw(proto.EntropyAck(entropy=EXTERNAL_ENTROPY)) + assert isinstance(ret, proto.Success) + + # Check if device is properly initialized + ret = client.call_raw(proto.Initialize()) + assert ret.initialized is True + assert ret.needs_backup is True + assert ret.unfinished_backup is False + assert ret.no_backup is False + + # Generate mnemonic locally + entropy = generate_entropy(STRENGTH, internal_entropy, EXTERNAL_ENTROPY) + expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) + + # start Backup workflow + ret = client.call_raw(proto.BackupDevice()) + + mnemonic = [] + for _ in range(STRENGTH // 32 * 3): assert isinstance(ret, proto.ButtonRequest) + mnemonic.append(client.debug.read_reset_word()) + client.debug.press_yes() + client.call_raw(proto.ButtonAck()) + + mnemonic = " ".join(mnemonic) + + # Compare that device generated proper mnemonic for given entropies + assert mnemonic == expected_mnemonic + + mnemonic = [] + for _ in range(STRENGTH // 32 * 3): + assert isinstance(ret, proto.ButtonRequest) + mnemonic.append(client.debug.read_reset_word()) client.debug.press_yes() ret = client.call_raw(proto.ButtonAck()) - # Provide entropy - assert isinstance(ret, proto.EntropyRequest) - internal_entropy = client.debug.state().reset_entropy - ret = client.call_raw(proto.EntropyAck(entropy=self.external_entropy)) - assert isinstance(ret, proto.Success) + assert isinstance(ret, proto.Success) - # Check if device is properly initialized - ret = client.call_raw(proto.Initialize()) - assert ret.initialized is True - assert ret.needs_backup is True - assert ret.unfinished_backup is False - assert ret.no_backup is False + mnemonic = " ".join(mnemonic) - # Generate mnemonic locally - entropy = generate_entropy( - self.strength, internal_entropy, self.external_entropy + # Compare that second pass printed out the same mnemonic once again + assert mnemonic == expected_mnemonic + + # start backup again - should fail + ret = client.call_raw(proto.BackupDevice()) + assert isinstance(ret, proto.Failure) + + +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_skip_backup_break(client): + ret = client.call_raw( + proto.ResetDevice( + display_random=False, + strength=STRENGTH, + passphrase_protection=False, + pin_protection=False, + language="en-US", + label="test", + skip_backup=True, ) - expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) + ) - # start Backup workflow - ret = client.call_raw(proto.BackupDevice()) + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) - mnemonic = [] - for _ in range(self.strength // 32 * 3): - assert isinstance(ret, proto.ButtonRequest) - mnemonic.append(client.debug.read_reset_word()) - client.debug.press_yes() - client.call_raw(proto.ButtonAck()) + # Provide entropy + assert isinstance(ret, proto.EntropyRequest) + ret = client.call_raw(proto.EntropyAck(entropy=EXTERNAL_ENTROPY)) + assert isinstance(ret, proto.Success) - mnemonic = " ".join(mnemonic) + # Check if device is properly initialized + ret = client.call_raw(proto.Initialize()) + assert ret.initialized is True + assert ret.needs_backup is True + assert ret.unfinished_backup is False + assert ret.no_backup is False - # Compare that device generated proper mnemonic for given entropies - assert mnemonic == expected_mnemonic + # start Backup workflow + ret = client.call_raw(proto.BackupDevice()) - mnemonic = [] - for _ in range(self.strength // 32 * 3): - assert isinstance(ret, proto.ButtonRequest) - mnemonic.append(client.debug.read_reset_word()) - client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) + # send Initialize -> break workflow + ret = client.call_raw(proto.Initialize()) + assert isinstance(ret, proto.Features) + assert ret.initialized is True + assert ret.needs_backup is False + assert ret.unfinished_backup is True + assert ret.no_backup is False - assert isinstance(ret, proto.Success) + # start backup again - should fail + ret = client.call_raw(proto.BackupDevice()) + assert isinstance(ret, proto.Failure) - mnemonic = " ".join(mnemonic) + # read Features again + ret = client.call_raw(proto.Initialize()) + assert isinstance(ret, proto.Features) + assert ret.initialized is True + assert ret.needs_backup is False + assert ret.unfinished_backup is True + assert ret.no_backup is False - # Compare that second pass printed out the same mnemonic once again - assert mnemonic == expected_mnemonic - # start backup again - should fail - ret = client.call_raw(proto.BackupDevice()) - assert isinstance(ret, proto.Failure) +def test_initialized_device_backup_fail(client): + ret = client.call_raw(proto.BackupDevice()) + assert isinstance(ret, proto.Failure) - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_skip_backup_break(self, client): - ret = client.call_raw( - proto.ResetDevice( - display_random=False, - strength=self.strength, - passphrase_protection=False, - pin_protection=False, - language="en-US", - label="test", - skip_backup=True, - ) + +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_skip_backup_show_entropy_fail(client): + ret = client.call_raw( + proto.ResetDevice( + display_random=True, + strength=STRENGTH, + passphrase_protection=False, + pin_protection=False, + language="en-US", + label="test", + skip_backup=True, ) - - assert isinstance(ret, proto.ButtonRequest) - client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) - - # Provide entropy - assert isinstance(ret, proto.EntropyRequest) - ret = client.call_raw(proto.EntropyAck(entropy=self.external_entropy)) - assert isinstance(ret, proto.Success) - - # Check if device is properly initialized - ret = client.call_raw(proto.Initialize()) - assert ret.initialized is True - assert ret.needs_backup is True - assert ret.unfinished_backup is False - assert ret.no_backup is False - - # start Backup workflow - ret = client.call_raw(proto.BackupDevice()) - - # send Initialize -> break workflow - ret = client.call_raw(proto.Initialize()) - assert isinstance(ret, proto.Features) - assert ret.initialized is True - assert ret.needs_backup is False - assert ret.unfinished_backup is True - assert ret.no_backup is False - - # start backup again - should fail - ret = client.call_raw(proto.BackupDevice()) - assert isinstance(ret, proto.Failure) - - # read Features again - ret = client.call_raw(proto.Initialize()) - assert isinstance(ret, proto.Features) - assert ret.initialized is True - assert ret.needs_backup is False - assert ret.unfinished_backup is True - assert ret.no_backup is False - - def test_initialized_device_backup_fail(self, client): - ret = client.call_raw(proto.BackupDevice()) - assert isinstance(ret, proto.Failure) - - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_skip_backup_show_entropy_fail(self, client): - ret = client.call_raw( - proto.ResetDevice( - display_random=True, - strength=self.strength, - passphrase_protection=False, - pin_protection=False, - language="en-US", - label="test", - skip_backup=True, - ) - ) - assert isinstance(ret, proto.Failure) + ) + assert isinstance(ret, proto.Failure) diff --git a/tests/device_tests/reset/test_bip39_t2.py b/tests/device_tests/reset/test_bip39_t2.py index a8600070c4..e5a1a5626a 100644 --- a/tests/device_tests/reset/test_bip39_t2.py +++ b/tests/device_tests/reset/test_bip39_t2.py @@ -30,6 +30,8 @@ from ...common import ( read_and_confirm_mnemonic, ) +pytestmark = [pytest.mark.skip_t1] + EXTERNAL_ENTROPY = b"zlutoucky kun upel divoke ody" * 2 @@ -105,218 +107,219 @@ def reset_device(client, strength): device.backup(client) -@pytest.mark.skip_t1 -class TestMsgResetDeviceT2: - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device(self, client): - reset_device(client, 128) # 12 words +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device(client): + reset_device(client, 128) # 12 words - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_192(self, client): - reset_device(client, 192) # 18 words - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_pin(self, client): - mnemonic = None - strength = 256 # 24 words +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_192(client): + reset_device(client, 192) # 18 words - def input_flow(): - nonlocal mnemonic - # Confirm Reset - br = yield - assert br.code == B.ResetDevice - client.debug.press_yes() +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_pin(client): + mnemonic = None + strength = 256 # 24 words - # Enter new PIN - yield - client.debug.input("654") - - # Confirm PIN - yield - client.debug.input("654") - - # Confirm entropy - br = yield - assert br.code == B.ResetDevice - client.debug.press_yes() - - # Backup your seed - br = yield - assert br.code == B.ResetDevice - client.debug.press_yes() - - # Confirm warning - br = yield - assert br.code == B.ResetDevice - client.debug.press_yes() - - # mnemonic phrases - mnemonic = yield from read_and_confirm_mnemonic(client.debug) - - # confirm recovery seed check - br = yield - assert br.code == B.Success - client.debug.press_yes() - - # confirm success - br = yield - assert br.code == B.Success - client.debug.press_yes() - - os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) - with mock.patch("os.urandom", os_urandom), client: - client.set_expected_responses( - [ - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.PinEntry), - proto.ButtonRequest(code=B.PinEntry), - proto.ButtonRequest(code=B.ResetDevice), - proto.EntropyRequest(), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.Success), - proto.ButtonRequest(code=B.Success), - proto.Success, - proto.Features, - ] - ) - client.set_input_flow(input_flow) - - # PIN, passphrase, display random - device.reset( - client, - display_random=True, - strength=strength, - passphrase_protection=True, - pin_protection=True, - label="test", - language="en-US", - ) - - # generate mnemonic locally - internal_entropy = client.debug.state().reset_entropy - entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) - expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) - - # Compare that device generated proper mnemonic for given entropies - assert mnemonic == expected_mnemonic - - # Check if device is properly initialized - resp = client.call_raw(proto.Initialize()) - assert resp.initialized is True - assert resp.needs_backup is False - assert resp.pin_protection is True - assert resp.passphrase_protection is True - - @pytest.mark.setup_client(uninitialized=True) - def test_reset_failed_check(self, client): - mnemonic = None - strength = 256 # 24 words - - def input_flow(): - nonlocal mnemonic - # 1. Confirm Reset - # 2. Backup your seed - # 3. Confirm warning - yield from click_through(client.debug, screens=3, code=B.ResetDevice) - - # mnemonic phrases, wrong answer - mnemonic = yield from read_and_confirm_mnemonic( - client.debug, choose_wrong=True - ) - - # warning screen - br = yield - assert br.code == B.ResetDevice - client.debug.press_yes() - - # mnemonic phrases - mnemonic = yield from read_and_confirm_mnemonic(client.debug) - - # confirm recovery seed check - br = yield - assert br.code == B.Success - client.debug.press_yes() - - # confirm success - br = yield - assert br.code == B.Success - client.debug.press_yes() - - os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) - with mock.patch("os.urandom", os_urandom), client: - client.set_expected_responses( - [ - proto.ButtonRequest(code=B.ResetDevice), - proto.EntropyRequest(), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.Success), - proto.ButtonRequest(code=B.Success), - proto.Success, - proto.Features, - ] - ) - client.set_input_flow(input_flow) - - # PIN, passphrase, display random - device.reset( - client, - display_random=False, - strength=strength, - passphrase_protection=False, - pin_protection=False, - label="test", - language="en-US", - ) - - # generate mnemonic locally - internal_entropy = client.debug.state().reset_entropy - entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) - expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) - - # Compare that device generated proper mnemonic for given entropies - assert mnemonic == expected_mnemonic - - # Check if device is properly initialized - resp = client.call_raw(proto.Initialize()) - assert resp.initialized is True - assert resp.needs_backup is False - assert resp.pin_protection is False - assert resp.passphrase_protection is False - assert resp.backup_type is proto.BackupType.Bip39 - - @pytest.mark.setup_client(uninitialized=True) - def test_failed_pin(self, client): - # external_entropy = b'zlutoucky kun upel divoke ody' * 2 - strength = 128 - ret = client.call_raw( - proto.ResetDevice(strength=strength, pin_protection=True, label="test") - ) + def input_flow(): + nonlocal mnemonic # Confirm Reset - assert isinstance(ret, proto.ButtonRequest) + br = yield + assert br.code == B.ResetDevice client.debug.press_yes() - ret = client.call_raw(proto.ButtonAck()) - # Enter PIN for first time - assert isinstance(ret, proto.ButtonRequest) + # Enter new PIN + yield client.debug.input("654") - ret = client.call_raw(proto.ButtonAck()) - # Enter PIN for second time - assert isinstance(ret, proto.ButtonRequest) - client.debug.input("456") - ret = client.call_raw(proto.ButtonAck()) + # Confirm PIN + yield + client.debug.input("654") - assert isinstance(ret, proto.ButtonRequest) + # Confirm entropy + br = yield + assert br.code == B.ResetDevice + client.debug.press_yes() - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_already_initialized(self, client): - with pytest.raises(Exception): - device.reset(client, False, 128, True, True, "label", "en-US") + # Backup your seed + br = yield + assert br.code == B.ResetDevice + client.debug.press_yes() + + # Confirm warning + br = yield + assert br.code == B.ResetDevice + client.debug.press_yes() + + # mnemonic phrases + mnemonic = yield from read_and_confirm_mnemonic(client.debug) + + # confirm recovery seed check + br = yield + assert br.code == B.Success + client.debug.press_yes() + + # confirm success + br = yield + assert br.code == B.Success + client.debug.press_yes() + + os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) + with mock.patch("os.urandom", os_urandom), client: + client.set_expected_responses( + [ + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.PinEntry), + proto.ButtonRequest(code=B.PinEntry), + proto.ButtonRequest(code=B.ResetDevice), + proto.EntropyRequest(), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.Success), + proto.ButtonRequest(code=B.Success), + proto.Success, + proto.Features, + ] + ) + client.set_input_flow(input_flow) + + # PIN, passphrase, display random + device.reset( + client, + display_random=True, + strength=strength, + passphrase_protection=True, + pin_protection=True, + label="test", + language="en-US", + ) + + # generate mnemonic locally + internal_entropy = client.debug.state().reset_entropy + entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) + expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) + + # Compare that device generated proper mnemonic for given entropies + assert mnemonic == expected_mnemonic + + # Check if device is properly initialized + resp = client.call_raw(proto.Initialize()) + assert resp.initialized is True + assert resp.needs_backup is False + assert resp.pin_protection is True + assert resp.passphrase_protection is True + + +@pytest.mark.setup_client(uninitialized=True) +def test_reset_failed_check(client): + mnemonic = None + strength = 256 # 24 words + + def input_flow(): + nonlocal mnemonic + # 1. Confirm Reset + # 2. Backup your seed + # 3. Confirm warning + yield from click_through(client.debug, screens=3, code=B.ResetDevice) + + # mnemonic phrases, wrong answer + mnemonic = yield from read_and_confirm_mnemonic(client.debug, choose_wrong=True) + + # warning screen + br = yield + assert br.code == B.ResetDevice + client.debug.press_yes() + + # mnemonic phrases + mnemonic = yield from read_and_confirm_mnemonic(client.debug) + + # confirm recovery seed check + br = yield + assert br.code == B.Success + client.debug.press_yes() + + # confirm success + br = yield + assert br.code == B.Success + client.debug.press_yes() + + os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) + with mock.patch("os.urandom", os_urandom), client: + client.set_expected_responses( + [ + proto.ButtonRequest(code=B.ResetDevice), + proto.EntropyRequest(), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.Success), + proto.ButtonRequest(code=B.Success), + proto.Success, + proto.Features, + ] + ) + client.set_input_flow(input_flow) + + # PIN, passphrase, display random + device.reset( + client, + display_random=False, + strength=strength, + passphrase_protection=False, + pin_protection=False, + label="test", + language="en-US", + ) + + # generate mnemonic locally + internal_entropy = client.debug.state().reset_entropy + entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) + expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) + + # Compare that device generated proper mnemonic for given entropies + assert mnemonic == expected_mnemonic + + # Check if device is properly initialized + resp = client.call_raw(proto.Initialize()) + assert resp.initialized is True + assert resp.needs_backup is False + assert resp.pin_protection is False + assert resp.passphrase_protection is False + assert resp.backup_type is proto.BackupType.Bip39 + + +@pytest.mark.setup_client(uninitialized=True) +def test_failed_pin(client): + # external_entropy = b'zlutoucky kun upel divoke ody' * 2 + strength = 128 + ret = client.call_raw( + proto.ResetDevice(strength=strength, pin_protection=True, label="test") + ) + + # Confirm Reset + assert isinstance(ret, proto.ButtonRequest) + client.debug.press_yes() + ret = client.call_raw(proto.ButtonAck()) + + # Enter PIN for first time + assert isinstance(ret, proto.ButtonRequest) + client.debug.input("654") + ret = client.call_raw(proto.ButtonAck()) + + # Enter PIN for second time + assert isinstance(ret, proto.ButtonRequest) + client.debug.input("456") + ret = client.call_raw(proto.ButtonAck()) + + assert isinstance(ret, proto.ButtonRequest) + + +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_already_initialized(client): + with pytest.raises(Exception): + device.reset(client, False, 128, True, True, "label", "en-US") diff --git a/tests/device_tests/reset/test_slip39_advanced.py b/tests/device_tests/reset/test_slip39_advanced.py index e87e37be59..a25cf616bc 100644 --- a/tests/device_tests/reset/test_slip39_advanced.py +++ b/tests/device_tests/reset/test_slip39_advanced.py @@ -25,116 +25,116 @@ from trezorlib.messages import BackupType, ButtonRequestType as B from ...common import click_through, generate_entropy, read_and_confirm_mnemonic +pytestmark = [pytest.mark.skip_t1] + EXTERNAL_ENTROPY = b"zlutoucky kun upel divoke ody" * 2 -@pytest.mark.skip_t1 -class TestMsgResetDeviceT2: - # TODO: test with different options - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_slip39_advanced(self, client): - strength = 128 - member_threshold = 3 - all_mnemonics = [] +# TODO: test with different options +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_slip39_advanced(client): + strength = 128 + member_threshold = 3 + all_mnemonics = [] - def input_flow(): - # 1. Confirm Reset - # 2. Backup your seed - # 3. Confirm warning - # 4. shares info - # 5. Set & Confirm number of groups - # 6. threshold info - # 7. Set & confirm group threshold value - # 8-17: for each of 5 groups: - # 1. Set & Confirm number of shares - # 2. Set & confirm share threshold value - # 18. Confirm show seeds - yield from click_through(client.debug, screens=18, code=B.ResetDevice) + def input_flow(): + # 1. Confirm Reset + # 2. Backup your seed + # 3. Confirm warning + # 4. shares info + # 5. Set & Confirm number of groups + # 6. threshold info + # 7. Set & confirm group threshold value + # 8-17: for each of 5 groups: + # 1. Set & Confirm number of shares + # 2. Set & confirm share threshold value + # 18. Confirm show seeds + yield from click_through(client.debug, screens=18, code=B.ResetDevice) - # show & confirm shares for all groups - for _g in range(5): - for _h in range(5): - # mnemonic phrases - mnemonic = yield from read_and_confirm_mnemonic(client.debug) - all_mnemonics.append(mnemonic) + # show & confirm shares for all groups + for _g in range(5): + for _h in range(5): + # mnemonic phrases + mnemonic = yield from read_and_confirm_mnemonic(client.debug) + all_mnemonics.append(mnemonic) - # Confirm continue to next share - br = yield - assert br.code == B.Success - client.debug.press_yes() + # Confirm continue to next share + br = yield + assert br.code == B.Success + client.debug.press_yes() - # safety warning - br = yield - assert br.code == B.Success - client.debug.press_yes() + # safety warning + br = yield + assert br.code == B.Success + client.debug.press_yes() - os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) - with mock.patch("os.urandom", os_urandom), client: - client.set_expected_responses( - [ - proto.ButtonRequest(code=B.ResetDevice), - proto.EntropyRequest(), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), # group #1 counts - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), # group #2 counts - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), # group #3 counts - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), # group #4 counts - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.ResetDevice), # group #5 counts - proto.ButtonRequest(code=B.ResetDevice), - ] - + [ - # individual mnemonic - proto.ButtonRequest(code=B.ResetDevice), - proto.ButtonRequest(code=B.Success), - ] - * (5 * 5) # groups * shares - + [ - proto.ButtonRequest(code=B.Success), - proto.Success, - proto.Features, - ] - ) - client.set_input_flow(input_flow) + os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) + with mock.patch("os.urandom", os_urandom), client: + client.set_expected_responses( + [ + proto.ButtonRequest(code=B.ResetDevice), + proto.EntropyRequest(), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), # group #1 counts + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), # group #2 counts + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), # group #3 counts + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), # group #4 counts + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.ResetDevice), # group #5 counts + proto.ButtonRequest(code=B.ResetDevice), + ] + + [ + # individual mnemonic + proto.ButtonRequest(code=B.ResetDevice), + proto.ButtonRequest(code=B.Success), + ] + * (5 * 5) # groups * shares + + [ + proto.ButtonRequest(code=B.Success), + proto.Success, + proto.Features, + ] + ) + client.set_input_flow(input_flow) - # No PIN, no passphrase, don't display random - device.reset( - client, - display_random=False, - strength=strength, - passphrase_protection=False, - pin_protection=False, - label="test", - language="en-US", - backup_type=BackupType.Slip39_Advanced, - ) + # No PIN, no passphrase, don't display random + device.reset( + client, + display_random=False, + strength=strength, + passphrase_protection=False, + pin_protection=False, + label="test", + language="en-US", + backup_type=BackupType.Slip39_Advanced, + ) - # generate secret locally - internal_entropy = client.debug.state().reset_entropy - secret = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) + # generate secret locally + internal_entropy = client.debug.state().reset_entropy + secret = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) - # validate that all combinations will result in the correct master secret - validate_mnemonics(all_mnemonics, member_threshold, secret) + # validate that all combinations will result in the correct master secret + validate_mnemonics(all_mnemonics, member_threshold, secret) - # Check if device is properly initialized - assert client.features.initialized is True - assert client.features.needs_backup is False - assert client.features.pin_protection is False - assert client.features.passphrase_protection is False - assert client.features.backup_type is BackupType.Slip39_Advanced + # Check if device is properly initialized + assert client.features.initialized is True + assert client.features.needs_backup is False + assert client.features.pin_protection is False + assert client.features.passphrase_protection is False + assert client.features.backup_type is BackupType.Slip39_Advanced - # backup attempt fails because backup was done in reset - with pytest.raises(TrezorFailure, match="ProcessError: Seed already backed up"): - device.backup(client) + # backup attempt fails because backup was done in reset + with pytest.raises(TrezorFailure, match="ProcessError: Seed already backed up"): + device.backup(client) def validate_mnemonics(mnemonics, threshold, expected_ems): diff --git a/tests/device_tests/reset/test_slip39_basic.py b/tests/device_tests/reset/test_slip39_basic.py index 1db46e1bb8..c3e6a90200 100644 --- a/tests/device_tests/reset/test_slip39_basic.py +++ b/tests/device_tests/reset/test_slip39_basic.py @@ -31,6 +31,8 @@ from ...common import ( read_and_confirm_mnemonic, ) +pytestmark = [pytest.mark.skip_t1] + def reset_device(client, strength): member_threshold = 3 @@ -122,15 +124,14 @@ def reset_device(client, strength): device.backup(client) -@pytest.mark.skip_t1 -class TestMsgResetDeviceT2: - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_slip39_basic(self, client): - reset_device(client, 128) +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_slip39_basic(client): + reset_device(client, 128) - @pytest.mark.setup_client(uninitialized=True) - def test_reset_device_slip39_basic_256(self, client): - reset_device(client, 256) + +@pytest.mark.setup_client(uninitialized=True) +def test_reset_device_slip39_basic_256(client): + reset_device(client, 256) def validate_mnemonics(mnemonics, threshold, expected_ems): diff --git a/tests/device_tests/ripple/test_get_address.py b/tests/device_tests/ripple/test_get_address.py index dd5f970772..3a2244f321 100644 --- a/tests/device_tests/ripple/test_get_address.py +++ b/tests/device_tests/ripple/test_get_address.py @@ -25,24 +25,27 @@ CUSTOM_MNEMONIC = ( "whip snack decide blur unfold fiction pumpkin athlete" ) +pytestmark = [ + pytest.mark.altcoin, + pytest.mark.ripple, + pytest.mark.skip_t1, # T1 support is not planned +] -@pytest.mark.altcoin -@pytest.mark.ripple -@pytest.mark.skip_t1 # T1 support is not planned -class TestMsgRippleGetAddress: - def test_ripple_get_address(self, client): - # data from https://iancoleman.io/bip39/ - address = get_address(client, parse_path("m/44'/144'/0'/0/0")) - assert address == "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H" - address = get_address(client, parse_path("m/44'/144'/0'/0/1")) - assert address == "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws" - address = get_address(client, parse_path("m/44'/144'/1'/0/0")) - assert address == "rJX2KwzaLJDyFhhtXKi3htaLfaUH2tptEX" - @pytest.mark.setup_client(mnemonic=CUSTOM_MNEMONIC) - def test_ripple_get_address_other(self, client): - # data from https://github.com/you21979/node-ripple-bip32/blob/master/test/test.js - address = get_address(client, parse_path("m/44'/144'/0'/0/0")) - assert address == "r4ocGE47gm4G4LkA9mriVHQqzpMLBTgnTY" - address = get_address(client, parse_path("m/44'/144'/0'/0/1")) - assert address == "rUt9ULSrUvfCmke8HTFU1szbmFpWzVbBXW" +def test_ripple_get_address(client): + # data from https://iancoleman.io/bip39/ + address = get_address(client, parse_path("m/44'/144'/0'/0/0")) + assert address == "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H" + address = get_address(client, parse_path("m/44'/144'/0'/0/1")) + assert address == "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws" + address = get_address(client, parse_path("m/44'/144'/1'/0/0")) + assert address == "rJX2KwzaLJDyFhhtXKi3htaLfaUH2tptEX" + + +@pytest.mark.setup_client(mnemonic=CUSTOM_MNEMONIC) +def test_ripple_get_address_other(client): + # data from https://github.com/you21979/node-ripple-bip32/blob/master/test/test.js + address = get_address(client, parse_path("m/44'/144'/0'/0/0")) + assert address == "r4ocGE47gm4G4LkA9mriVHQqzpMLBTgnTY" + address = get_address(client, parse_path("m/44'/144'/0'/0/1")) + assert address == "rUt9ULSrUvfCmke8HTFU1szbmFpWzVbBXW" diff --git a/tests/device_tests/ripple/test_sign_tx.py b/tests/device_tests/ripple/test_sign_tx.py index c14c3fb844..fbc20bce1e 100644 --- a/tests/device_tests/ripple/test_sign_tx.py +++ b/tests/device_tests/ripple/test_sign_tx.py @@ -20,94 +20,97 @@ from trezorlib import ripple from trezorlib.exceptions import TrezorFailure from trezorlib.tools import parse_path +pytestmark = [ + pytest.mark.altcoin, + pytest.mark.ripple, + pytest.mark.skip_t1, # T1 support is not planned +] -@pytest.mark.altcoin -@pytest.mark.ripple -@pytest.mark.skip_t1 # T1 support is not planned -class TestMsgRippleSignTx: - def test_ripple_sign_simple_tx(self, client): - msg = ripple.create_sign_tx_msg( - { - "TransactionType": "Payment", - "Payment": { - "Amount": 100000000, - "Destination": "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws", - }, - "Flags": 0x80000000, - "Fee": 100000, - "Sequence": 25, - } - ) - resp = ripple.sign_tx(client, parse_path("m/44'/144'/0'/0/0"), msg) - assert ( - resp.signature.hex() - == "3045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c0" - ) - assert ( - resp.serialized_tx.hex() - == "12000022800000002400000019614000000005f5e1006840000000000186a0732102131facd1eab748d6cddc492f54b04e8c35658894f4add2232ebc5afe7521dbe474473045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c081148fb40e1ffa5d557ce9851a535af94965e0dd098883147148ebebf7304ccdf1676fefcf9734cf1e780826" - ) - msg = ripple.create_sign_tx_msg( - { - "TransactionType": "Payment", - "Payment": { - "Amount": 1, - "Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H", - }, - "Fee": 10, - "Sequence": 1, - } - ) - resp = ripple.sign_tx(client, parse_path("m/44'/144'/0'/0/2"), msg) - assert ( - resp.signature.hex() - == "3044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f" - ) - assert ( - resp.serialized_tx.hex() - == "1200002280000000240000000161400000000000000168400000000000000a732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed274463044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f8114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988" - ) +def test_ripple_sign_simple_tx(client): + msg = ripple.create_sign_tx_msg( + { + "TransactionType": "Payment", + "Payment": { + "Amount": 100000000, + "Destination": "rBKz5MC2iXdoS3XgnNSYmF69K1Yo4NS3Ws", + }, + "Flags": 0x80000000, + "Fee": 100000, + "Sequence": 25, + } + ) + resp = ripple.sign_tx(client, parse_path("m/44'/144'/0'/0/0"), msg) + assert ( + resp.signature.hex() + == "3045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c0" + ) + assert ( + resp.serialized_tx.hex() + == "12000022800000002400000019614000000005f5e1006840000000000186a0732102131facd1eab748d6cddc492f54b04e8c35658894f4add2232ebc5afe7521dbe474473045022100e243ef623675eeeb95965c35c3e06d63a9fc68bb37e17dc87af9c0af83ec057e02206ca8aa5eaab8396397aef6d38d25710441faf7c79d292ee1d627df15ad9346c081148fb40e1ffa5d557ce9851a535af94965e0dd098883147148ebebf7304ccdf1676fefcf9734cf1e780826" + ) - msg = ripple.create_sign_tx_msg( - { - "TransactionType": "Payment", - "Payment": { - "Amount": 100000009, - "Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H", - "DestinationTag": 123456, - }, - "Flags": 0, - "Fee": 100, - "Sequence": 100, - "LastLedgerSequence": 333111, - } - ) - resp = ripple.sign_tx(client, parse_path("m/44'/144'/0'/0/2"), msg) - assert ( - resp.signature.hex() - == "30450221008770743a472bb2d1c746a53ef131cc17cc118d538ec910ca928d221db4494cf702201e4ef242d6c3bff110c3cc3897a471fed0f5ac10987ea57da63f98dfa01e94df" - ) - assert ( - resp.serialized_tx.hex() - == "120000228000000024000000642e0001e240201b00051537614000000005f5e109684000000000000064732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed2744730450221008770743a472bb2d1c746a53ef131cc17cc118d538ec910ca928d221db4494cf702201e4ef242d6c3bff110c3cc3897a471fed0f5ac10987ea57da63f98dfa01e94df8114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988" - ) + msg = ripple.create_sign_tx_msg( + { + "TransactionType": "Payment", + "Payment": { + "Amount": 1, + "Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H", + }, + "Fee": 10, + "Sequence": 1, + } + ) + resp = ripple.sign_tx(client, parse_path("m/44'/144'/0'/0/2"), msg) + assert ( + resp.signature.hex() + == "3044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f" + ) + assert ( + resp.serialized_tx.hex() + == "1200002280000000240000000161400000000000000168400000000000000a732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed274463044022069900e6e578997fad5189981b74b16badc7ba8b9f1052694033fa2779113ddc002206c8006ada310edf099fb22c0c12073550c8fc73247b236a974c5f1144831dd5f8114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988" + ) - def test_ripple_sign_invalid_fee(self, client): - msg = ripple.create_sign_tx_msg( - { - "TransactionType": "Payment", - "Payment": { - "Amount": 1, - "Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H", - }, - "Flags": 1, - "Fee": 1, - "Sequence": 1, - } - ) - with pytest.raises( - TrezorFailure, - match="ProcessError: Fee must be in the range of 10 to 10,000 drops", - ): - ripple.sign_tx(client, parse_path("m/44'/144'/0'/0/2"), msg) + msg = ripple.create_sign_tx_msg( + { + "TransactionType": "Payment", + "Payment": { + "Amount": 100000009, + "Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H", + "DestinationTag": 123456, + }, + "Flags": 0, + "Fee": 100, + "Sequence": 100, + "LastLedgerSequence": 333111, + } + ) + resp = ripple.sign_tx(client, parse_path("m/44'/144'/0'/0/2"), msg) + assert ( + resp.signature.hex() + == "30450221008770743a472bb2d1c746a53ef131cc17cc118d538ec910ca928d221db4494cf702201e4ef242d6c3bff110c3cc3897a471fed0f5ac10987ea57da63f98dfa01e94df" + ) + assert ( + resp.serialized_tx.hex() + == "120000228000000024000000642e0001e240201b00051537614000000005f5e109684000000000000064732103dbed1e77cb91a005e2ec71afbccce5444c9be58276665a3859040f692de8fed2744730450221008770743a472bb2d1c746a53ef131cc17cc118d538ec910ca928d221db4494cf702201e4ef242d6c3bff110c3cc3897a471fed0f5ac10987ea57da63f98dfa01e94df8114bdf86f3ae715ba346b7772ea0e133f48828b766483148fb40e1ffa5d557ce9851a535af94965e0dd0988" + ) + + +def test_ripple_sign_invalid_fee(client): + msg = ripple.create_sign_tx_msg( + { + "TransactionType": "Payment", + "Payment": { + "Amount": 1, + "Destination": "rNaqKtKrMSwpwZSzRckPf7S96DkimjkF4H", + }, + "Flags": 1, + "Fee": 1, + "Sequence": 1, + } + ) + with pytest.raises( + TrezorFailure, + match="ProcessError: Fee must be in the range of 10 to 10,000 drops", + ): + ripple.sign_tx(client, parse_path("m/44'/144'/0'/0/2"), msg) diff --git a/tests/device_tests/test_basic.py b/tests/device_tests/test_basic.py index 4ae83aee37..f1b2b9a28d 100644 --- a/tests/device_tests/test_basic.py +++ b/tests/device_tests/test_basic.py @@ -17,33 +17,35 @@ from trezorlib import device, messages -class TestBasic: - def test_features(self, client): - f0 = client.features - # client erases session_id from its features - f0.session_id = client.session_id - f1 = client.call(messages.Initialize(session_id=f0.session_id)) - assert f0 == f1 +def test_features(client): + f0 = client.features + # client erases session_id from its features + f0.session_id = client.session_id + f1 = client.call(messages.Initialize(session_id=f0.session_id)) + assert f0 == f1 - def test_ping(self, client): - ping = client.call(messages.Ping(message="ahoj!")) - assert ping == messages.Success(message="ahoj!") - def test_device_id_same(self, client): - id1 = client.get_device_id() - client.init_device() - id2 = client.get_device_id() +def test_ping(client): + ping = client.call(messages.Ping(message="ahoj!")) + assert ping == messages.Success(message="ahoj!") - # ID must be at least 12 characters - assert len(id1) >= 12 - # Every resulf of UUID must be the same - assert id1 == id2 +def test_device_id_same(client): + id1 = client.get_device_id() + client.init_device() + id2 = client.get_device_id() - def test_device_id_different(self, client): - id1 = client.get_device_id() - device.wipe(client) - id2 = client.get_device_id() + # ID must be at least 12 characters + assert len(id1) >= 12 - # Device ID must be fresh after every reset - assert id1 != id2 + # Every resulf of UUID must be the same + assert id1 == id2 + + +def test_device_id_different(client): + id1 = client.get_device_id() + device.wipe(client) + id2 = client.get_device_id() + + # Device ID must be fresh after every reset + assert id1 != id2 diff --git a/tests/device_tests/test_bip32_speed.py b/tests/device_tests/test_bip32_speed.py index 46c01c088e..0de66920bd 100644 --- a/tests/device_tests/test_bip32_speed.py +++ b/tests/device_tests/test_bip32_speed.py @@ -21,48 +21,50 @@ import pytest from trezorlib import btc from trezorlib.tools import H_ +pytestmark = [ + pytest.mark.skip_t2, + pytest.mark.flaky(max_runs=5), +] -@pytest.mark.flaky(max_runs=5) -class TestBip32Speed: - @pytest.mark.skip_t2 - def test_public_ckd(self, client): - btc.get_address(client, "Bitcoin", []) # to compute root node via BIP39 - for depth in range(8): - start = time.time() - btc.get_address(client, "Bitcoin", range(depth)) - delay = time.time() - start - expected = (depth + 1) * 0.26 - print("DEPTH", depth, "EXPECTED DELAY", expected, "REAL DELAY", delay) - assert delay <= expected +def test_public_ckd(client): + btc.get_address(client, "Bitcoin", []) # to compute root node via BIP39 - @pytest.mark.skip_t2 - def test_private_ckd(self, client): - btc.get_address(client, "Bitcoin", []) # to compute root node via BIP39 - - for depth in range(8): - start = time.time() - address_n = [H_(-i) for i in range(-depth, 0)] - btc.get_address(client, "Bitcoin", address_n) - delay = time.time() - start - expected = (depth + 1) * 0.26 - print("DEPTH", depth, "EXPECTED DELAY", expected, "REAL DELAY", delay) - assert delay <= expected - - @pytest.mark.skip_t2 - def test_cache(self, client): + for depth in range(8): start = time.time() - for x in range(10): - btc.get_address(client, "Bitcoin", [x, 2, 3, 4, 5, 6, 7, 8]) - nocache_time = time.time() - start + btc.get_address(client, "Bitcoin", range(depth)) + delay = time.time() - start + expected = (depth + 1) * 0.26 + print("DEPTH", depth, "EXPECTED DELAY", expected, "REAL DELAY", delay) + assert delay <= expected + +def test_private_ckd(client): + btc.get_address(client, "Bitcoin", []) # to compute root node via BIP39 + + for depth in range(8): start = time.time() - for x in range(10): - btc.get_address(client, "Bitcoin", [1, 2, 3, 4, 5, 6, 7, x]) - cache_time = time.time() - start + address_n = [H_(-i) for i in range(-depth, 0)] + btc.get_address(client, "Bitcoin", address_n) + delay = time.time() - start + expected = (depth + 1) * 0.26 + print("DEPTH", depth, "EXPECTED DELAY", expected, "REAL DELAY", delay) + assert delay <= expected - print("NOCACHE TIME", nocache_time) - print("CACHED TIME", cache_time) - # Cached time expected to be at least 2x faster - assert cache_time <= nocache_time / 2.0 +def test_cache(client): + start = time.time() + for x in range(10): + btc.get_address(client, "Bitcoin", [x, 2, 3, 4, 5, 6, 7, 8]) + nocache_time = time.time() - start + + start = time.time() + for x in range(10): + btc.get_address(client, "Bitcoin", [1, 2, 3, 4, 5, 6, 7, x]) + cache_time = time.time() - start + + print("NOCACHE TIME", nocache_time) + print("CACHED TIME", cache_time) + + # Cached time expected to be at least 2x faster + assert cache_time <= nocache_time / 2.0 diff --git a/tests/device_tests/test_cosi.py b/tests/device_tests/test_cosi.py index 1f562bb589..b30dd06bd1 100644 --- a/tests/device_tests/test_cosi.py +++ b/tests/device_tests/test_cosi.py @@ -21,77 +21,75 @@ import pytest from trezorlib import cosi from trezorlib.tools import parse_path +pytestmark = pytest.mark.skip_t2 -@pytest.mark.skip_t2 -class TestCosi: - def test_cosi_commit(self, client): - digest = sha256(b"this is a message").digest() - c0 = cosi.commit(client, parse_path("10018'/0'"), digest) - c1 = cosi.commit(client, parse_path("10018'/1'"), digest) - c2 = cosi.commit(client, parse_path("10018'/2'"), digest) +def test_cosi_commit(client): + digest = sha256(b"this is a message").digest() - assert c0.pubkey != c1.pubkey - assert c0.pubkey != c2.pubkey - assert c1.pubkey != c2.pubkey + c0 = cosi.commit(client, parse_path("10018'/0'"), digest) + c1 = cosi.commit(client, parse_path("10018'/1'"), digest) + c2 = cosi.commit(client, parse_path("10018'/2'"), digest) - assert c0.commitment != c1.commitment - assert c0.commitment != c2.commitment - assert c1.commitment != c2.commitment + assert c0.pubkey != c1.pubkey + assert c0.pubkey != c2.pubkey + assert c1.pubkey != c2.pubkey - digestb = sha256(b"this is a different message").digest() + assert c0.commitment != c1.commitment + assert c0.commitment != c2.commitment + assert c1.commitment != c2.commitment - c0b = cosi.commit(client, parse_path("10018'/0'"), digestb) - c1b = cosi.commit(client, parse_path("10018'/1'"), digestb) - c2b = cosi.commit(client, parse_path("10018'/2'"), digestb) + digestb = sha256(b"this is a different message").digest() - assert c0.pubkey == c0b.pubkey - assert c1.pubkey == c1b.pubkey - assert c2.pubkey == c2b.pubkey + c0b = cosi.commit(client, parse_path("10018'/0'"), digestb) + c1b = cosi.commit(client, parse_path("10018'/1'"), digestb) + c2b = cosi.commit(client, parse_path("10018'/2'"), digestb) - assert c0.commitment != c0b.commitment - assert c1.commitment != c1b.commitment - assert c2.commitment != c2b.commitment + assert c0.pubkey == c0b.pubkey + assert c1.pubkey == c1b.pubkey + assert c2.pubkey == c2b.pubkey - def test_cosi_sign(self, client): - digest = sha256(b"this is a message").digest() + assert c0.commitment != c0b.commitment + assert c1.commitment != c1b.commitment + assert c2.commitment != c2b.commitment - c0 = cosi.commit(client, parse_path("10018'/0'"), digest) - c1 = cosi.commit(client, parse_path("10018'/1'"), digest) - c2 = cosi.commit(client, parse_path("10018'/2'"), digest) - global_pk = cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey]) - global_R = cosi.combine_keys([c0.commitment, c1.commitment, c2.commitment]) +def test_cosi_sign(client): + digest = sha256(b"this is a message").digest() - # fmt: off - sig0 = cosi.sign(client, parse_path("10018'/0'"), digest, global_R, global_pk) - sig1 = cosi.sign(client, parse_path("10018'/1'"), digest, global_R, global_pk) - sig2 = cosi.sign(client, parse_path("10018'/2'"), digest, global_R, global_pk) - # fmt: on + c0 = cosi.commit(client, parse_path("10018'/0'"), digest) + c1 = cosi.commit(client, parse_path("10018'/1'"), digest) + c2 = cosi.commit(client, parse_path("10018'/2'"), digest) - sig = cosi.combine_sig( - global_R, [sig0.signature, sig1.signature, sig2.signature] - ) + global_pk = cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey]) + global_R = cosi.combine_keys([c0.commitment, c1.commitment, c2.commitment]) - cosi.verify_combined(sig, digest, global_pk) + # fmt: off + sig0 = cosi.sign(client, parse_path("10018'/0'"), digest, global_R, global_pk) + sig1 = cosi.sign(client, parse_path("10018'/1'"), digest, global_R, global_pk) + sig2 = cosi.sign(client, parse_path("10018'/2'"), digest, global_R, global_pk) + # fmt: on - def test_cosi_compat(self, client): - digest = sha256(b"this is not a pipe").digest() - remote_commit = cosi.commit(client, parse_path("10018'/0'"), digest) + sig = cosi.combine_sig(global_R, [sig0.signature, sig1.signature, sig2.signature]) - local_privkey = sha256(b"private key").digest()[:32] - local_pubkey = cosi.pubkey_from_privkey(local_privkey) - local_nonce, local_commitment = cosi.get_nonce(local_privkey, digest, 42) + cosi.verify_combined(sig, digest, global_pk) - global_pk = cosi.combine_keys([remote_commit.pubkey, local_pubkey]) - global_R = cosi.combine_keys([remote_commit.commitment, local_commitment]) - remote_sig = cosi.sign( - client, parse_path("10018'/0'"), digest, global_R, global_pk - ) - local_sig = cosi.sign_with_privkey( - digest, local_privkey, global_pk, local_nonce, global_R - ) - sig = cosi.combine_sig(global_R, [remote_sig.signature, local_sig]) +def test_cosi_compat(client): + digest = sha256(b"this is not a pipe").digest() + remote_commit = cosi.commit(client, parse_path("10018'/0'"), digest) - cosi.verify_combined(sig, digest, global_pk) + local_privkey = sha256(b"private key").digest()[:32] + local_pubkey = cosi.pubkey_from_privkey(local_privkey) + local_nonce, local_commitment = cosi.get_nonce(local_privkey, digest, 42) + + global_pk = cosi.combine_keys([remote_commit.pubkey, local_pubkey]) + global_R = cosi.combine_keys([remote_commit.commitment, local_commitment]) + + remote_sig = cosi.sign(client, parse_path("10018'/0'"), digest, global_R, global_pk) + local_sig = cosi.sign_with_privkey( + digest, local_privkey, global_pk, local_nonce, global_R + ) + sig = cosi.combine_sig(global_R, [remote_sig.signature, local_sig]) + + cosi.verify_combined(sig, digest, global_pk) diff --git a/tests/device_tests/test_debuglink.py b/tests/device_tests/test_debuglink.py index bf093bff5d..88c958b13a 100644 --- a/tests/device_tests/test_debuglink.py +++ b/tests/device_tests/test_debuglink.py @@ -23,32 +23,35 @@ from ..common import MNEMONIC12 @pytest.mark.skip_t2 -class TestDebuglink: - def test_layout(self, client): - layout = client.debug.state().layout - assert len(layout) == 1024 +def test_layout(client): + layout = client.debug.state().layout + assert len(layout) == 1024 - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_mnemonic(self, client): - client.ensure_unlocked() - mnemonic = client.debug.state().mnemonic_secret - assert mnemonic == MNEMONIC12.encode() - @pytest.mark.setup_client(mnemonic=MNEMONIC12, pin="1234", passphrase="") - def test_pin(self, client): - resp = client.call_raw(messages.GetAddress()) - assert isinstance(resp, messages.PinMatrixRequest) +@pytest.mark.skip_t2 +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_mnemonic(client): + client.ensure_unlocked() + mnemonic = client.debug.state().mnemonic_secret + assert mnemonic == MNEMONIC12.encode() - state = client.debug.state() - assert state.pin == "1234" - assert state.matrix != "" - pin_encoded = client.debug.encode_pin("1234") - resp = client.call_raw(messages.PinMatrixAck(pin=pin_encoded)) - assert isinstance(resp, messages.PassphraseRequest) +@pytest.mark.skip_t2 +@pytest.mark.setup_client(mnemonic=MNEMONIC12, pin="1234", passphrase="") +def test_pin(client): + resp = client.call_raw(messages.GetAddress()) + assert isinstance(resp, messages.PinMatrixRequest) - resp = client.call_raw(messages.PassphraseAck(passphrase="")) - assert isinstance(resp, messages.Address) + state = client.debug.state() + assert state.pin == "1234" + assert state.matrix != "" + + pin_encoded = client.debug.encode_pin("1234") + resp = client.call_raw(messages.PinMatrixAck(pin=pin_encoded)) + assert isinstance(resp, messages.PassphraseRequest) + + resp = client.call_raw(messages.PassphraseAck(passphrase="")) + assert isinstance(resp, messages.Address) @pytest.mark.skip_t1 diff --git a/tests/device_tests/test_msg_applysettings.py b/tests/device_tests/test_msg_applysettings.py index 1246caca13..8e85ff4752 100644 --- a/tests/device_tests/test_msg_applysettings.py +++ b/tests/device_tests/test_msg_applysettings.py @@ -29,6 +29,8 @@ EXPECTED_RESPONSES_PIN_TT = [messages.ButtonRequest()] + EXPECTED_RESPONSES_NOPI PIN4 = "1234" +pytestmark = pytest.mark.setup_client(pin=PIN4) + def _set_expected_responses(client): client.use_pin_sequence([PIN4]) @@ -38,184 +40,156 @@ def _set_expected_responses(client): client.set_expected_responses(EXPECTED_RESPONSES_PIN_TT) -@pytest.mark.setup_client(pin=PIN4) -class TestMsgApplysettings: - def test_apply_settings(self, client): - assert client.features.label == "test" +def test_apply_settings(client): + assert client.features.label == "test" - with client: - _set_expected_responses(client) - device.apply_settings(client, label="new label") + with client: + _set_expected_responses(client) + device.apply_settings(client, label="new label") - assert client.features.label == "new label" + assert client.features.label == "new label" - @pytest.mark.skip_t1 - def test_apply_settings_rotation(self, client): - assert client.features.display_rotation is None - with client: - _set_expected_responses(client) - device.apply_settings(client, display_rotation=270) +@pytest.mark.skip_t1 +def test_apply_settings_rotation(client): + assert client.features.display_rotation is None - assert client.features.display_rotation == 270 + with client: + _set_expected_responses(client) + device.apply_settings(client, display_rotation=270) - @pytest.mark.skip_t2 - def test_invalid_language(self, client): - assert client.features.language == "en-US" + assert client.features.display_rotation == 270 - with client: - _set_expected_responses(client) - device.apply_settings(client, language="nonexistent") - assert client.features.language == "en-US" +@pytest.mark.skip_t2 +def test_invalid_language(client): + assert client.features.language == "en-US" - @pytest.mark.setup_client(pin=PIN4, passphrase=False) - def test_apply_settings_passphrase(self, client): - with client: - _set_expected_responses(client) - device.apply_settings(client, use_passphrase=True) + with client: + _set_expected_responses(client) + device.apply_settings(client, language="nonexistent") - assert client.features.passphrase_protection is True + assert client.features.language == "en-US" - with client: - client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) - device.apply_settings(client, use_passphrase=False) - assert client.features.passphrase_protection is False +@pytest.mark.setup_client(pin=PIN4, passphrase=False) +def test_apply_settings_passphrase(client): + with client: + _set_expected_responses(client) + device.apply_settings(client, use_passphrase=True) - with client: - client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) - device.apply_settings(client, use_passphrase=True) + assert client.features.passphrase_protection is True - assert client.features.passphrase_protection is True + with client: + client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) + device.apply_settings(client, use_passphrase=False) - @pytest.mark.setup_client(passphrase=False) - @pytest.mark.skip_t1 - def test_apply_settings_passphrase_on_device(self, client): - # enable passphrase - with client: - client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) - device.apply_settings(client, use_passphrase=True) + assert client.features.passphrase_protection is False - assert client.features.passphrase_protection is True + with client: + client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) + device.apply_settings(client, use_passphrase=True) - # enable force on device - with client: - client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) - device.apply_settings(client, passphrase_always_on_device=True) + assert client.features.passphrase_protection is True - assert client.features.passphrase_protection is True - assert client.features.passphrase_always_on_device is True - # turning off the passphrase should also clear the always_on_device setting - with client: - client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) - device.apply_settings(client, use_passphrase=False) +@pytest.mark.setup_client(passphrase=False) +@pytest.mark.skip_t1 +def test_apply_settings_passphrase_on_device(client): + # enable passphrase + with client: + client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) + device.apply_settings(client, use_passphrase=True) - assert client.features.passphrase_protection is False - assert client.features.passphrase_always_on_device is False + assert client.features.passphrase_protection is True - # and turning it back on does not modify always_on_device - with client: - client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) - device.apply_settings(client, use_passphrase=True) + # enable force on device + with client: + client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) + device.apply_settings(client, passphrase_always_on_device=True) - assert client.features.passphrase_protection is True - assert client.features.passphrase_always_on_device is False + assert client.features.passphrase_protection is True + assert client.features.passphrase_always_on_device is True - @pytest.mark.skip_t1 - def test_apply_homescreen_toif(self, client): - img = b"TOIf\x90\x00\x90\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0OV" + # turning off the passphrase should also clear the always_on_device setting + with client: + client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) + device.apply_settings(client, use_passphrase=False) - with client: - _set_expected_responses(client) - device.apply_settings(client, homescreen=img) + assert client.features.passphrase_protection is False + assert client.features.passphrase_always_on_device is False - client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) - device.apply_settings(client, homescreen=b"") + # and turning it back on does not modify always_on_device + with client: + client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) + device.apply_settings(client, use_passphrase=True) - @pytest.mark.parametrize( - "toif_data", - [ - # incomplete header - b"TOIf\x90\00\x90\x00~" - # wrong magic - b"XXXf\x90\x00\x90\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0OV" - # wrong datasize in header - b"TOIf\x90\x00\x90\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - # grayscale 144x144 - b"TOIg\x90\x00\x90\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0OV", - # fullcolor 128x128 - b"TOIf\x80\x00\x80\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0OV", - ], - ) - @pytest.mark.skip_t1 - def test_apply_homescreen_toif_fail(self, client, toif_data): - with pytest.raises(exceptions.TrezorFailure), client: - client.use_pin_sequence([PIN4]) - device.apply_settings(client, homescreen=toif_data) + assert client.features.passphrase_protection is True + assert client.features.passphrase_always_on_device is False - @pytest.mark.skip_t2 - def test_apply_homescreen(self, client): - img = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x04\x88\x02\x00\x00\x00\x02\x91\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x90@\x00\x11@\x00\x00\x00\x00\x00\x00\x08\x00\x10\x92\x12\x04\x00\x00\x05\x12D\x00\x00\x00\x00\x00 \x00\x00\x08\x00Q\x00\x00\x02\xc0\x00\x00\x00\x00\x00\x00\x00\x10\x02 \x01\x04J\x00)$\x00\x00\x00\x00\x80\x00\x00\x00\x00\x08\x10\xa1\x00\x00\x02\x81 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\tP\x00\x00\x00\x00\x00\x00 \x00\x00\xa0\x00\xa0R \x12\x84\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x08\x00\tP\x00\x00\x00\x00 \x00\x04 \x00\x80\x02\x00@\x02T\xc2 \x00\x00\x00\x00\x00\x00\x00\x10@\x00)\t@\n\xa0\x80\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x80@\x14\xa9H\x04\x00\x00\x88@\x00\x00\x00\x00\x00\x02\x02$\x00\x15B@\x00\nP\x00\x00\x00\x00\x00\x80\x00\x00\x91\x01UP\x00\x00 \x02\x00\x00\x00\x00\x00\x00\x02\x08@ Z\xa5 \x00\x00\x80\x00\x00\x00\x00\x00\x00\x08\xa1%\x14*\xa0\x00\x00\x02\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xaa\x91 \x00\x05E\x80\x00\x00\x00\x00\x00\x02*T\x05-D\x00\x00\x05 @\x00\x00\x00\x00\x00%@\x80\x11V\xa0\x88\x00\x05@\xb0\x00\x00\x00\x00\x00\x818$\x04\xabD \x00\x06\xa1T\x00\x00\x00\x00\x02\x03\xb8\x01R\xd5\x01\x00\x00\x05AP\x00\x00\x00\x00\x08\xadT\x00\x05j\xa4@\x00\x87ah\x00\x00\x00\x00\x02\x8d\xb8\x08\x00.\x01\x00\x00\x02\xa5\xa8\x10\x00\x00\x00*\xc1\xec \n\xaa\x88 \x02@\xf6\xd0\x02\x00\x00\x00\x0bB\xb6\x14@U"\x80\x00\x01{`\x00\x00\x00\x00M\xa3\xf8 \x15*\x00\x00\x00\x10n\xc0\x04\x00\x00\x02\x06\xc2\xa8)\x00\x96\x84\x80\x00\x00\x1b\x00\x00\x80@\x10\x87\xa7\xf0\x84\x10\xaa\x10\x00\x00D\x00\x00\x02 \x00\x8a\x06\xfa\xe0P\n-\x02@\x00\x12\x00\x00\x00\x00\x10@\x83\xdf\xa0\x00\x08\xaa@\x00\x00\x01H\x00\x05H\x04\x12\x01\xf7\x81P\x02T\t\x00\x00\x00 \x00\x00\x84\x10\x00\x00z\x00@)* \x00\x00\x01\n\xa0\x02 \x05\n\x00\x00\x05\x10\x84\xa8\x84\x80\x00\x00@\x14\x00\x92\x10\x80\x00\x04\x11@\tT\x00\x00\x00\x00\n@\x00\x08\x84@$\x00H\x00\x12Q\x02\x00\x00\x00\x00\x90\x02A\x12\xa8\n\xaa\x92\x10\x04\xa8\x10@\x00\x00\x04\x04\x00\x04I\x00\x04\x14H\x80"R\x01\x00\x00\x00!@\x00\x00$\xa0EB\x80\x08\x95hH\x00\x00\x00\x84\x10 \x05Z\x00\x00(\x00\x02\x00\xa1\x01\x00\x00\x04\x00@\x82\x00\xadH*\x92P\x00\xaaP\x00\x00\x00\x00\x11\x02\x01*\xad\x01\x00\x01\x01"\x11D\x08\x00\x00\x10\x80 \x00\x81W\x80J\x94\x04\x08\xa5 !\x00\x00\x00\x02\x00B*\xae\xa1\x00\x80\x10\x01\x08\xa4\x00\x00\x00\x00\x00\x84\x00\t[@"HA\x04E\x00\x84\x00\x00\x00\x10\x00\x01J\xd5\x82\x90\x02\x00!\x02\xa2\x00\x00\x00\x00\x00\x00\x00\x05~\xa0\x00 \x10\n)\x00\x11\x00\x00\x00\x00\x00\x00!U\x80\xa8\x88\x82\x80\x01\x00\x00\x00\x00\x00\x00H@\x11\xaa\xc0\x82\x00 *\n\x00\x00\x00\x00\x00\x00\x00\x00\n\xabb@ \x04\x00! \x84\x00\x00\x00\x00\x02@\xa5\x15A$\x04\x81(\n\x00\x00\x00\x00\x00\x00 \x01\x10\x02\xe0\x91\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x01 \xa9\tQH@\x91 P\x00\x00\x00\x00\x00\x00\x08\x00\x00\xa0T\xa5\x00@\x80\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\xa2\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00 T\xa0\t\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00@\x02\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x10\x00\x00\x10\x02\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00@\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x08@\x10\x00\x00\x00\x00' - with client: - _set_expected_responses(client) - device.apply_settings(client, homescreen=img) +@pytest.mark.skip_t1 +def test_apply_homescreen_toif(client): + img = b"TOIf\x90\x00\x90\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0OV" - @pytest.mark.setup_client(pin=None) - def test_safety_checks(self, client): - def get_bad_address(): - btc.get_address(client, "Bitcoin", parse_path("m/44'"), show_display=True) + with client: + _set_expected_responses(client) + device.apply_settings(client, homescreen=img) - assert client.features.safety_checks == messages.SafetyCheckLevel.Strict + client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) + device.apply_settings(client, homescreen=b"") - with pytest.raises( - exceptions.TrezorFailure, match="Forbidden key path" - ), client: - client.set_expected_responses([messages.Failure]) - get_bad_address() - if client.features.model != "1": - with client: - client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) - device.apply_settings( - client, safety_checks=messages.SafetyCheckLevel.PromptAlways - ) +@pytest.mark.parametrize( + "toif_data", + [ + # incomplete header + b"TOIf\x90\00\x90\x00~" + # wrong magic + b"XXXf\x90\x00\x90\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0OV" + # wrong datasize in header + b"TOIf\x90\x00\x90\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + # grayscale 144x144 + b"TOIg\x90\x00\x90\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0OV", + # fullcolor 128x128 + b"TOIf\x80\x00\x80\x00~\x00\x00\x00\xed\xd2\xcb\r\x83@\x10D\xc1^.\xde#!\xac31\x99\x10\x8aC%\x14~\x16\x92Y9\x02WI3\x01<\xf5cI2d\x1es(\xe1[\xdbn\xba\xca\xe8s7\xa4\xd5\xd4\xb3\x13\xbdw\xf6:\xf3\xd1\xe7%\xc7]\xdd_\xb3\x9e\x9f\x9e\x9fN\xed\xaaE\xef\xdc\xcf$D\xa7\xa4X\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0OV", + ], +) +@pytest.mark.skip_t1 +def test_apply_homescreen_toif_fail(client, toif_data): + with pytest.raises(exceptions.TrezorFailure), client: + client.use_pin_sequence([PIN4]) + device.apply_settings(client, homescreen=toif_data) - assert ( - client.features.safety_checks == messages.SafetyCheckLevel.PromptAlways - ) - with client: - client.set_expected_responses( - [messages.ButtonRequest, messages.ButtonRequest, messages.Address] - ) - get_bad_address() +@pytest.mark.skip_t2 +def test_apply_homescreen(client): + img = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x04\x88\x02\x00\x00\x00\x02\x91\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x90@\x00\x11@\x00\x00\x00\x00\x00\x00\x08\x00\x10\x92\x12\x04\x00\x00\x05\x12D\x00\x00\x00\x00\x00 \x00\x00\x08\x00Q\x00\x00\x02\xc0\x00\x00\x00\x00\x00\x00\x00\x10\x02 \x01\x04J\x00)$\x00\x00\x00\x00\x80\x00\x00\x00\x00\x08\x10\xa1\x00\x00\x02\x81 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\tP\x00\x00\x00\x00\x00\x00 \x00\x00\xa0\x00\xa0R \x12\x84\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x08\x00\tP\x00\x00\x00\x00 \x00\x04 \x00\x80\x02\x00@\x02T\xc2 \x00\x00\x00\x00\x00\x00\x00\x10@\x00)\t@\n\xa0\x80\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x80@\x14\xa9H\x04\x00\x00\x88@\x00\x00\x00\x00\x00\x02\x02$\x00\x15B@\x00\nP\x00\x00\x00\x00\x00\x80\x00\x00\x91\x01UP\x00\x00 \x02\x00\x00\x00\x00\x00\x00\x02\x08@ Z\xa5 \x00\x00\x80\x00\x00\x00\x00\x00\x00\x08\xa1%\x14*\xa0\x00\x00\x02\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xaa\x91 \x00\x05E\x80\x00\x00\x00\x00\x00\x02*T\x05-D\x00\x00\x05 @\x00\x00\x00\x00\x00%@\x80\x11V\xa0\x88\x00\x05@\xb0\x00\x00\x00\x00\x00\x818$\x04\xabD \x00\x06\xa1T\x00\x00\x00\x00\x02\x03\xb8\x01R\xd5\x01\x00\x00\x05AP\x00\x00\x00\x00\x08\xadT\x00\x05j\xa4@\x00\x87ah\x00\x00\x00\x00\x02\x8d\xb8\x08\x00.\x01\x00\x00\x02\xa5\xa8\x10\x00\x00\x00*\xc1\xec \n\xaa\x88 \x02@\xf6\xd0\x02\x00\x00\x00\x0bB\xb6\x14@U"\x80\x00\x01{`\x00\x00\x00\x00M\xa3\xf8 \x15*\x00\x00\x00\x10n\xc0\x04\x00\x00\x02\x06\xc2\xa8)\x00\x96\x84\x80\x00\x00\x1b\x00\x00\x80@\x10\x87\xa7\xf0\x84\x10\xaa\x10\x00\x00D\x00\x00\x02 \x00\x8a\x06\xfa\xe0P\n-\x02@\x00\x12\x00\x00\x00\x00\x10@\x83\xdf\xa0\x00\x08\xaa@\x00\x00\x01H\x00\x05H\x04\x12\x01\xf7\x81P\x02T\t\x00\x00\x00 \x00\x00\x84\x10\x00\x00z\x00@)* \x00\x00\x01\n\xa0\x02 \x05\n\x00\x00\x05\x10\x84\xa8\x84\x80\x00\x00@\x14\x00\x92\x10\x80\x00\x04\x11@\tT\x00\x00\x00\x00\n@\x00\x08\x84@$\x00H\x00\x12Q\x02\x00\x00\x00\x00\x90\x02A\x12\xa8\n\xaa\x92\x10\x04\xa8\x10@\x00\x00\x04\x04\x00\x04I\x00\x04\x14H\x80"R\x01\x00\x00\x00!@\x00\x00$\xa0EB\x80\x08\x95hH\x00\x00\x00\x84\x10 \x05Z\x00\x00(\x00\x02\x00\xa1\x01\x00\x00\x04\x00@\x82\x00\xadH*\x92P\x00\xaaP\x00\x00\x00\x00\x11\x02\x01*\xad\x01\x00\x01\x01"\x11D\x08\x00\x00\x10\x80 \x00\x81W\x80J\x94\x04\x08\xa5 !\x00\x00\x00\x02\x00B*\xae\xa1\x00\x80\x10\x01\x08\xa4\x00\x00\x00\x00\x00\x84\x00\t[@"HA\x04E\x00\x84\x00\x00\x00\x10\x00\x01J\xd5\x82\x90\x02\x00!\x02\xa2\x00\x00\x00\x00\x00\x00\x00\x05~\xa0\x00 \x10\n)\x00\x11\x00\x00\x00\x00\x00\x00!U\x80\xa8\x88\x82\x80\x01\x00\x00\x00\x00\x00\x00H@\x11\xaa\xc0\x82\x00 *\n\x00\x00\x00\x00\x00\x00\x00\x00\n\xabb@ \x04\x00! \x84\x00\x00\x00\x00\x02@\xa5\x15A$\x04\x81(\n\x00\x00\x00\x00\x00\x00 \x01\x10\x02\xe0\x91\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x01 \xa9\tQH@\x91 P\x00\x00\x00\x00\x00\x00\x08\x00\x00\xa0T\xa5\x00@\x80\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\xa2\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00 T\xa0\t\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00@\x02\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x10\x00\x00\x10\x02\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00@\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x08@\x10\x00\x00\x00\x00' + with client: + _set_expected_responses(client) + device.apply_settings(client, homescreen=img) + + +@pytest.mark.setup_client(pin=None) +def test_safety_checks(client): + def get_bad_address(): + btc.get_address(client, "Bitcoin", parse_path("m/44'"), show_display=True) + + assert client.features.safety_checks == messages.SafetyCheckLevel.Strict + + with pytest.raises(exceptions.TrezorFailure, match="Forbidden key path"), client: + client.set_expected_responses([messages.Failure]) + get_bad_address() + + if client.features.model != "1": with client: client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) device.apply_settings( - client, safety_checks=messages.SafetyCheckLevel.Strict + client, safety_checks=messages.SafetyCheckLevel.PromptAlways ) - assert client.features.safety_checks == messages.SafetyCheckLevel.Strict - - with pytest.raises( - exceptions.TrezorFailure, match="Forbidden key path" - ), client: - client.set_expected_responses([messages.Failure]) - get_bad_address() - - with client: - client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) - device.apply_settings( - client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily - ) - - assert ( - client.features.safety_checks == messages.SafetyCheckLevel.PromptTemporarily - ) + assert client.features.safety_checks == messages.SafetyCheckLevel.PromptAlways with client: client.set_expected_responses( @@ -223,61 +197,87 @@ class TestMsgApplysettings: ) get_bad_address() - @pytest.mark.skip_t1 - def test_experimental_features(self, client): - def experimental_call(): - btc.authorize_coinjoin( - client, - coordinator="www.example.com", - max_total_fee=10010, - fee_per_anonymity=5000000, # 0.005 % - n=parse_path("m/84'/1'/0'"), - coin_name="Testnet", - script_type=messages.InputScriptType.SPENDWITNESS, - ) + with client: + client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) + device.apply_settings(client, safety_checks=messages.SafetyCheckLevel.Strict) - assert client.features.experimental_features is None + assert client.features.safety_checks == messages.SafetyCheckLevel.Strict - # unlock - with client: - _set_expected_responses(client) - device.apply_settings(client, label="new label") + with pytest.raises(exceptions.TrezorFailure, match="Forbidden key path"), client: + client.set_expected_responses([messages.Failure]) + get_bad_address() - assert client.features.experimental_features + with client: + client.set_expected_responses(EXPECTED_RESPONSES_NOPIN) + device.apply_settings( + client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily + ) - with client: - client.set_expected_responses( - [messages.ButtonRequest, messages.ButtonRequest, messages.Success] - ) - experimental_call() + assert client.features.safety_checks == messages.SafetyCheckLevel.PromptTemporarily - # relock and try again - client.lock() - with client: - client.use_pin_sequence([PIN4]) - client.set_expected_responses( - [ - messages.ButtonRequest, - messages.ButtonRequest, - messages.ButtonRequest, - messages.Success, - ] - ) - experimental_call() + with client: + client.set_expected_responses( + [messages.ButtonRequest, messages.ButtonRequest, messages.Address] + ) + get_bad_address() - # unset experimental features - with client: - client.set_expected_responses([messages.Success, messages.Features]) - device.apply_settings(client, experimental_features=False) - assert not client.features.experimental_features +@pytest.mark.skip_t1 +def test_experimental_features(client): + def experimental_call(): + btc.authorize_coinjoin( + client, + coordinator="www.example.com", + max_total_fee=10010, + fee_per_anonymity=5000000, # 0.005 % + n=parse_path("m/84'/1'/0'"), + coin_name="Testnet", + script_type=messages.InputScriptType.SPENDWITNESS, + ) - with pytest.raises(exceptions.TrezorFailure, match="DataError"), client: - client.set_expected_responses([messages.Failure]) - experimental_call() + assert client.features.experimental_features is None - @pytest.mark.setup_client(pin=None) - def test_label_too_long(self, client): - with pytest.raises(exceptions.TrezorFailure), client: - client.set_expected_responses([messages.Failure]) - device.apply_settings(client, label="A" * 33) + # unlock + with client: + _set_expected_responses(client) + device.apply_settings(client, label="new label") + + assert client.features.experimental_features + + with client: + client.set_expected_responses( + [messages.ButtonRequest, messages.ButtonRequest, messages.Success] + ) + experimental_call() + + # relock and try again + client.lock() + with client: + client.use_pin_sequence([PIN4]) + client.set_expected_responses( + [ + messages.ButtonRequest, + messages.ButtonRequest, + messages.ButtonRequest, + messages.Success, + ] + ) + experimental_call() + + # unset experimental features + with client: + client.set_expected_responses([messages.Success, messages.Features]) + device.apply_settings(client, experimental_features=False) + + assert not client.features.experimental_features + + with pytest.raises(exceptions.TrezorFailure, match="DataError"), client: + client.set_expected_responses([messages.Failure]) + experimental_call() + + +@pytest.mark.setup_client(pin=None) +def test_label_too_long(client): + with pytest.raises(exceptions.TrezorFailure), client: + client.set_expected_responses([messages.Failure]) + device.apply_settings(client, label="A" * 33) diff --git a/tests/device_tests/test_msg_cipherkeyvalue.py b/tests/device_tests/test_msg_cipherkeyvalue.py index 18cb321acf..88723e92f5 100644 --- a/tests/device_tests/test_msg_cipherkeyvalue.py +++ b/tests/device_tests/test_msg_cipherkeyvalue.py @@ -21,166 +21,167 @@ from trezorlib import misc from ..common import MNEMONIC12 -class TestMsgCipherkeyvalue: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_encrypt(self, client): - res = misc.encrypt_keyvalue( - client, - [0, 1, 2], - "test", - b"testing message!", - ask_on_encrypt=True, - ask_on_decrypt=True, - ) - assert res.hex() == "676faf8f13272af601776bc31bc14e8f" +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_encrypt(client): + res = misc.encrypt_keyvalue( + client, + [0, 1, 2], + "test", + b"testing message!", + ask_on_encrypt=True, + ask_on_decrypt=True, + ) + assert res.hex() == "676faf8f13272af601776bc31bc14e8f" - res = misc.encrypt_keyvalue( - client, - [0, 1, 2], - "test", - b"testing message!", - ask_on_encrypt=True, - ask_on_decrypt=False, - ) - assert res.hex() == "5aa0fbcb9d7fa669880745479d80c622" + res = misc.encrypt_keyvalue( + client, + [0, 1, 2], + "test", + b"testing message!", + ask_on_encrypt=True, + ask_on_decrypt=False, + ) + assert res.hex() == "5aa0fbcb9d7fa669880745479d80c622" - res = misc.encrypt_keyvalue( - client, - [0, 1, 2], - "test", - b"testing message!", - ask_on_encrypt=False, - ask_on_decrypt=True, - ) - assert res.hex() == "958d4f63269b61044aaedc900c8d6208" + res = misc.encrypt_keyvalue( + client, + [0, 1, 2], + "test", + b"testing message!", + ask_on_encrypt=False, + ask_on_decrypt=True, + ) + assert res.hex() == "958d4f63269b61044aaedc900c8d6208" - res = misc.encrypt_keyvalue( - client, - [0, 1, 2], - "test", - b"testing message!", - ask_on_encrypt=False, - ask_on_decrypt=False, - ) - assert res.hex() == "e0cf0eb0425947000eb546cc3994bc6c" + res = misc.encrypt_keyvalue( + client, + [0, 1, 2], + "test", + b"testing message!", + ask_on_encrypt=False, + ask_on_decrypt=False, + ) + assert res.hex() == "e0cf0eb0425947000eb546cc3994bc6c" - # different key - res = misc.encrypt_keyvalue( - client, - [0, 1, 2], - "test2", - b"testing message!", - ask_on_encrypt=True, - ask_on_decrypt=True, - ) - assert res.hex() == "de247a6aa6be77a134bb3f3f925f13af" + # different key + res = misc.encrypt_keyvalue( + client, + [0, 1, 2], + "test2", + b"testing message!", + ask_on_encrypt=True, + ask_on_decrypt=True, + ) + assert res.hex() == "de247a6aa6be77a134bb3f3f925f13af" - # different message - res = misc.encrypt_keyvalue( - client, - [0, 1, 2], - "test", - b"testing message! it is different", - ask_on_encrypt=True, - ask_on_decrypt=True, - ) - assert ( - res.hex() - == "676faf8f13272af601776bc31bc14e8f3ae1c88536bf18f1b44f1e4c2c4a613d" - ) + # different message + res = misc.encrypt_keyvalue( + client, + [0, 1, 2], + "test", + b"testing message! it is different", + ask_on_encrypt=True, + ask_on_decrypt=True, + ) + assert ( + res.hex() == "676faf8f13272af601776bc31bc14e8f3ae1c88536bf18f1b44f1e4c2c4a613d" + ) - # different path - res = misc.encrypt_keyvalue( - client, - [0, 1, 3], - "test", - b"testing message!", - ask_on_encrypt=True, - ask_on_decrypt=True, - ) - assert res.hex() == "b4811a9d492f5355a5186ddbfccaae7b" + # different path + res = misc.encrypt_keyvalue( + client, + [0, 1, 3], + "test", + b"testing message!", + ask_on_encrypt=True, + ask_on_decrypt=True, + ) + assert res.hex() == "b4811a9d492f5355a5186ddbfccaae7b" - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_decrypt(self, client): - res = misc.decrypt_keyvalue( - client, - [0, 1, 2], - "test", - bytes.fromhex("676faf8f13272af601776bc31bc14e8f"), - ask_on_encrypt=True, - ask_on_decrypt=True, - ) - assert res == b"testing message!" - res = misc.decrypt_keyvalue( - client, - [0, 1, 2], - "test", - bytes.fromhex("5aa0fbcb9d7fa669880745479d80c622"), - ask_on_encrypt=True, - ask_on_decrypt=False, - ) - assert res == b"testing message!" +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_decrypt(client): + res = misc.decrypt_keyvalue( + client, + [0, 1, 2], + "test", + bytes.fromhex("676faf8f13272af601776bc31bc14e8f"), + ask_on_encrypt=True, + ask_on_decrypt=True, + ) + assert res == b"testing message!" - res = misc.decrypt_keyvalue( - client, - [0, 1, 2], - "test", - bytes.fromhex("958d4f63269b61044aaedc900c8d6208"), - ask_on_encrypt=False, - ask_on_decrypt=True, - ) - assert res == b"testing message!" + res = misc.decrypt_keyvalue( + client, + [0, 1, 2], + "test", + bytes.fromhex("5aa0fbcb9d7fa669880745479d80c622"), + ask_on_encrypt=True, + ask_on_decrypt=False, + ) + assert res == b"testing message!" - res = misc.decrypt_keyvalue( - client, - [0, 1, 2], - "test", - bytes.fromhex("e0cf0eb0425947000eb546cc3994bc6c"), - ask_on_encrypt=False, - ask_on_decrypt=False, - ) - assert res == b"testing message!" + res = misc.decrypt_keyvalue( + client, + [0, 1, 2], + "test", + bytes.fromhex("958d4f63269b61044aaedc900c8d6208"), + ask_on_encrypt=False, + ask_on_decrypt=True, + ) + assert res == b"testing message!" - # different key - res = misc.decrypt_keyvalue( - client, - [0, 1, 2], - "test2", - bytes.fromhex("de247a6aa6be77a134bb3f3f925f13af"), - ask_on_encrypt=True, - ask_on_decrypt=True, - ) - assert res == b"testing message!" + res = misc.decrypt_keyvalue( + client, + [0, 1, 2], + "test", + bytes.fromhex("e0cf0eb0425947000eb546cc3994bc6c"), + ask_on_encrypt=False, + ask_on_decrypt=False, + ) + assert res == b"testing message!" - # different message - res = misc.decrypt_keyvalue( - client, - [0, 1, 2], - "test", - bytes.fromhex( - "676faf8f13272af601776bc31bc14e8f3ae1c88536bf18f1b44f1e4c2c4a613d" - ), - ask_on_encrypt=True, - ask_on_decrypt=True, - ) - assert res == b"testing message! it is different" + # different key + res = misc.decrypt_keyvalue( + client, + [0, 1, 2], + "test2", + bytes.fromhex("de247a6aa6be77a134bb3f3f925f13af"), + ask_on_encrypt=True, + ask_on_decrypt=True, + ) + assert res == b"testing message!" - # different path - res = misc.decrypt_keyvalue( - client, - [0, 1, 3], - "test", - bytes.fromhex("b4811a9d492f5355a5186ddbfccaae7b"), - ask_on_encrypt=True, - ask_on_decrypt=True, - ) - assert res == b"testing message!" + # different message + res = misc.decrypt_keyvalue( + client, + [0, 1, 2], + "test", + bytes.fromhex( + "676faf8f13272af601776bc31bc14e8f3ae1c88536bf18f1b44f1e4c2c4a613d" + ), + ask_on_encrypt=True, + ask_on_decrypt=True, + ) + assert res == b"testing message! it is different" - def test_encrypt_badlen(self, client): - with pytest.raises(Exception): - misc.encrypt_keyvalue(client, [0, 1, 2], "test", b"testing") + # different path + res = misc.decrypt_keyvalue( + client, + [0, 1, 3], + "test", + bytes.fromhex("b4811a9d492f5355a5186ddbfccaae7b"), + ask_on_encrypt=True, + ask_on_decrypt=True, + ) + assert res == b"testing message!" - def test_decrypt_badlen(self, client): - with pytest.raises(Exception): - misc.decrypt_keyvalue(client, [0, 1, 2], "test", b"testing") + +def test_encrypt_badlen(client): + with pytest.raises(Exception): + misc.encrypt_keyvalue(client, [0, 1, 2], "test", b"testing") + + +def test_decrypt_badlen(client): + with pytest.raises(Exception): + misc.decrypt_keyvalue(client, [0, 1, 2], "test", b"testing") diff --git a/tests/device_tests/test_msg_getaddress.py b/tests/device_tests/test_msg_getaddress.py index da6409142e..b86a768407 100644 --- a/tests/device_tests/test_msg_getaddress.py +++ b/tests/device_tests/test_msg_getaddress.py @@ -33,200 +33,208 @@ def getmultisig(chain, nr, xpubs): ) -class TestMsgGetaddress: - def test_btc(self, client): - assert ( - btc.get_address(client, "Bitcoin", parse_path("m/44'/0'/0'/0/0")) - == "1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL" - ) - assert ( - btc.get_address(client, "Bitcoin", parse_path("m/44'/0'/0'/0/1")) - == "1GWFxtwWmNVqotUPXLcKVL2mUKpshuJYo" - ) - assert ( - btc.get_address(client, "Bitcoin", parse_path("m/44'/0'/0'/1/0")) - == "1DyHzbQUoQEsLxJn6M7fMD8Xdt1XvNiwNE" - ) +def test_btc(client): + assert ( + btc.get_address(client, "Bitcoin", parse_path("m/44'/0'/0'/0/0")) + == "1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL" + ) + assert ( + btc.get_address(client, "Bitcoin", parse_path("m/44'/0'/0'/0/1")) + == "1GWFxtwWmNVqotUPXLcKVL2mUKpshuJYo" + ) + assert ( + btc.get_address(client, "Bitcoin", parse_path("m/44'/0'/0'/1/0")) + == "1DyHzbQUoQEsLxJn6M7fMD8Xdt1XvNiwNE" + ) - @pytest.mark.altcoin - def test_ltc(self, client): - assert ( - btc.get_address(client, "Litecoin", parse_path("m/44'/2'/0'/0/0")) - == "LcubERmHD31PWup1fbozpKuiqjHZ4anxcL" - ) - assert ( - btc.get_address(client, "Litecoin", parse_path("m/44'/2'/0'/0/1")) - == "LVWBmHBkCGNjSPHucvL2PmnuRAJnucmRE6" - ) - assert ( - btc.get_address(client, "Litecoin", parse_path("m/44'/2'/0'/1/0")) - == "LWj6ApswZxay4cJEJES2sGe7fLMLRvvv8h" - ) - def test_tbtc(self, client): - assert ( - btc.get_address(client, "Testnet", parse_path("m/44'/1'/0'/0/0")) - == "mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q" - ) - assert ( - btc.get_address(client, "Testnet", parse_path("m/44'/1'/0'/0/1")) - == "mopZWqZZyQc3F2Sy33cvDtJchSAMsnLi7b" - ) - assert ( - btc.get_address(client, "Testnet", parse_path("m/44'/1'/0'/1/0")) - == "mm6kLYbGEL1tGe4ZA8xacfgRPdW1NLjCbZ" - ) +@pytest.mark.altcoin +def test_ltc(client): + assert ( + btc.get_address(client, "Litecoin", parse_path("m/44'/2'/0'/0/0")) + == "LcubERmHD31PWup1fbozpKuiqjHZ4anxcL" + ) + assert ( + btc.get_address(client, "Litecoin", parse_path("m/44'/2'/0'/0/1")) + == "LVWBmHBkCGNjSPHucvL2PmnuRAJnucmRE6" + ) + assert ( + btc.get_address(client, "Litecoin", parse_path("m/44'/2'/0'/1/0")) + == "LWj6ApswZxay4cJEJES2sGe7fLMLRvvv8h" + ) - @pytest.mark.altcoin - def test_bch(self, client): - assert ( - btc.get_address(client, "Bcash", parse_path("44'/145'/0'/0/0")) - == "bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv" - ) - assert ( - btc.get_address(client, "Bcash", parse_path("44'/145'/0'/0/1")) - == "bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4" - ) - assert ( - btc.get_address(client, "Bcash", parse_path("44'/145'/0'/1/0")) - == "bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw" - ) - @pytest.mark.altcoin - def test_grs(self, client): - assert ( - btc.get_address(client, "Groestlcoin", parse_path("44'/17'/0'/0/0")) - == "Fj62rBJi8LvbmWu2jzkaUX1NFXLEqDLoZM" - ) - assert ( - btc.get_address(client, "Groestlcoin", parse_path("44'/17'/0'/1/0")) - == "FmRaqvVBRrAp2Umfqx9V1ectZy8gw54QDN" - ) - assert ( - btc.get_address(client, "Groestlcoin", parse_path("44'/17'/0'/1/1")) - == "Fmhtxeh7YdCBkyQF7AQG4QnY8y3rJg89di" - ) +def test_tbtc(client): + assert ( + btc.get_address(client, "Testnet", parse_path("m/44'/1'/0'/0/0")) + == "mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q" + ) + assert ( + btc.get_address(client, "Testnet", parse_path("m/44'/1'/0'/0/1")) + == "mopZWqZZyQc3F2Sy33cvDtJchSAMsnLi7b" + ) + assert ( + btc.get_address(client, "Testnet", parse_path("m/44'/1'/0'/1/0")) + == "mm6kLYbGEL1tGe4ZA8xacfgRPdW1NLjCbZ" + ) - @pytest.mark.altcoin - def test_elements(self, client): + +@pytest.mark.altcoin +def test_bch(client): + assert ( + btc.get_address(client, "Bcash", parse_path("44'/145'/0'/0/0")) + == "bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv" + ) + assert ( + btc.get_address(client, "Bcash", parse_path("44'/145'/0'/0/1")) + == "bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4" + ) + assert ( + btc.get_address(client, "Bcash", parse_path("44'/145'/0'/1/0")) + == "bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw" + ) + + +@pytest.mark.altcoin +def test_grs(client): + assert ( + btc.get_address(client, "Groestlcoin", parse_path("44'/17'/0'/0/0")) + == "Fj62rBJi8LvbmWu2jzkaUX1NFXLEqDLoZM" + ) + assert ( + btc.get_address(client, "Groestlcoin", parse_path("44'/17'/0'/1/0")) + == "FmRaqvVBRrAp2Umfqx9V1ectZy8gw54QDN" + ) + assert ( + btc.get_address(client, "Groestlcoin", parse_path("44'/17'/0'/1/1")) + == "Fmhtxeh7YdCBkyQF7AQG4QnY8y3rJg89di" + ) + + +@pytest.mark.altcoin +def test_elements(client): + assert ( + btc.get_address(client, "Elements", parse_path("m/44'/1'/0'/0/0")) + == "2dpWh6jbhAowNsQ5agtFzi7j6nKscj6UnEr" + ) + + +@pytest.mark.multisig +def test_multisig(client): + xpubs = [] + for n in range(1, 4): + node = btc.get_public_node(client, parse_path(f"44'/0'/{n}'")) + xpubs.append(node.xpub) + + for nr in range(1, 4): assert ( - btc.get_address(client, "Elements", parse_path("m/44'/1'/0'/0/0")) - == "2dpWh6jbhAowNsQ5agtFzi7j6nKscj6UnEr" - ) - - @pytest.mark.multisig - def test_multisig(self, client): - xpubs = [] - for n in range(1, 4): - node = btc.get_public_node(client, parse_path(f"44'/0'/{n}'")) - xpubs.append(node.xpub) - - for nr in range(1, 4): - assert ( - btc.get_address( - client, - "Bitcoin", - parse_path(f"44'/0'/{nr}'/0/0"), - show_display=(nr == 1), - multisig=getmultisig(0, 0, xpubs=xpubs), - ) - == "3Pdz86KtfJBuHLcSv4DysJo4aQfanTqCzG" + btc.get_address( + client, + "Bitcoin", + parse_path(f"44'/0'/{nr}'/0/0"), + show_display=(nr == 1), + multisig=getmultisig(0, 0, xpubs=xpubs), ) - assert ( - btc.get_address( - client, - "Bitcoin", - parse_path(f"44'/0'/{nr}'/1/0"), - show_display=(nr == 1), - multisig=getmultisig(1, 0, xpubs=xpubs), - ) - == "36gP3KVx1ooStZ9quZDXbAF3GCr42b2zzd" + == "3Pdz86KtfJBuHLcSv4DysJo4aQfanTqCzG" + ) + assert ( + btc.get_address( + client, + "Bitcoin", + parse_path(f"44'/0'/{nr}'/1/0"), + show_display=(nr == 1), + multisig=getmultisig(1, 0, xpubs=xpubs), + ) + == "36gP3KVx1ooStZ9quZDXbAF3GCr42b2zzd" + ) + + +@pytest.mark.multisig +@pytest.mark.parametrize("show_display", (True, False)) +def test_multisig_missing(client, show_display): + # Multisig with global suffix specification. + # Use account numbers 1, 2 and 3 to create a valid multisig, + # but not containing the keys from account 0 used below. + nodes = [ + btc.get_public_node(client, parse_path(f"44'/0'/{i}'")).node + for i in range(1, 4) + ] + multisig1 = messages.MultisigRedeemScriptType( + nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2 + ) + + # Multisig with per-node suffix specification. + node = btc.get_public_node( + client, parse_path("44h/0h/0h/0"), coin_name="Bitcoin" + ).node + + multisig2 = messages.MultisigRedeemScriptType( + pubkeys=[ + messages.HDNodePathType(node=node, address_n=[1]), + messages.HDNodePathType(node=node, address_n=[2]), + messages.HDNodePathType(node=node, address_n=[3]), + ], + signatures=[b"", b"", b""], + m=2, + ) + + for multisig in (multisig1, multisig2): + with pytest.raises(TrezorFailure): + btc.get_address( + client, + "Bitcoin", + parse_path("44'/0'/0'/0/0"), + show_display=show_display, + multisig=multisig, ) - @pytest.mark.multisig - @pytest.mark.parametrize("show_display", (True, False)) - def test_multisig_missing(self, client, show_display): - # Multisig with global suffix specification. - # Use account numbers 1, 2 and 3 to create a valid multisig, - # but not containing the keys from account 0 used below. - nodes = [ - btc.get_public_node(client, parse_path(f"44'/0'/{i}'")).node - for i in range(1, 4) - ] - multisig1 = messages.MultisigRedeemScriptType( - nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2 - ) - # Multisig with per-node suffix specification. +@pytest.mark.altcoin +@pytest.mark.multisig +def test_bch_multisig(client): + xpubs = [] + for n in range(1, 4): node = btc.get_public_node( - client, parse_path("44h/0h/0h/0"), coin_name="Bitcoin" - ).node + client, parse_path(f"44'/145'/{n}'"), coin_name="Bcash" + ) + xpubs.append(node.xpub) - multisig2 = messages.MultisigRedeemScriptType( - pubkeys=[ - messages.HDNodePathType(node=node, address_n=[1]), - messages.HDNodePathType(node=node, address_n=[2]), - messages.HDNodePathType(node=node, address_n=[3]), - ], - signatures=[b"", b"", b""], - m=2, + for nr in range(1, 4): + assert ( + btc.get_address( + client, + "Bcash", + parse_path(f"44'/145'/{nr}'/0/0"), + show_display=(nr == 1), + multisig=getmultisig(0, 0, xpubs=xpubs), + ) + == "bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw" + ) + assert ( + btc.get_address( + client, + "Bcash", + parse_path(f"44'/145'/{nr}'/1/0"), + show_display=(nr == 1), + multisig=getmultisig(1, 0, xpubs=xpubs), + ) + == "bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a" ) - for multisig in (multisig1, multisig2): - with pytest.raises(TrezorFailure): - btc.get_address( - client, - "Bitcoin", - parse_path("44'/0'/0'/0/0"), - show_display=show_display, - multisig=multisig, - ) - @pytest.mark.altcoin - @pytest.mark.multisig - def test_bch_multisig(self, client): - xpubs = [] - for n in range(1, 4): - node = btc.get_public_node( - client, parse_path(f"44'/145'/{n}'"), coin_name="Bcash" - ) - xpubs.append(node.xpub) +def test_public_ckd(client): + node = btc.get_public_node(client, parse_path("m/44'/0'/0'")).node + node_sub1 = btc.get_public_node(client, parse_path("m/44'/0'/0'/1/0")).node + node_sub2 = bip32.public_ckd(node, [1, 0]) - for nr in range(1, 4): - assert ( - btc.get_address( - client, - "Bcash", - parse_path(f"44'/145'/{nr}'/0/0"), - show_display=(nr == 1), - multisig=getmultisig(0, 0, xpubs=xpubs), - ) - == "bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw" - ) - assert ( - btc.get_address( - client, - "Bcash", - parse_path(f"44'/145'/{nr}'/1/0"), - show_display=(nr == 1), - multisig=getmultisig(1, 0, xpubs=xpubs), - ) - == "bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a" - ) + assert node_sub1.chain_code == node_sub2.chain_code + assert node_sub1.public_key == node_sub2.public_key - def test_public_ckd(self, client): - node = btc.get_public_node(client, parse_path("m/44'/0'/0'")).node - node_sub1 = btc.get_public_node(client, parse_path("m/44'/0'/0'/1/0")).node - node_sub2 = bip32.public_ckd(node, [1, 0]) + address1 = btc.get_address(client, "Bitcoin", parse_path("m/44'/0'/0'/1/0")) + address2 = bip32.get_address(node_sub2, 0) - assert node_sub1.chain_code == node_sub2.chain_code - assert node_sub1.public_key == node_sub2.public_key - - address1 = btc.get_address(client, "Bitcoin", parse_path("m/44'/0'/0'/1/0")) - address2 = bip32.get_address(node_sub2, 0) - - assert address2 == "1DyHzbQUoQEsLxJn6M7fMD8Xdt1XvNiwNE" - assert address1 == address2 + assert address2 == "1DyHzbQUoQEsLxJn6M7fMD8Xdt1XvNiwNE" + assert address1 == address2 def test_invalid_path(client): diff --git a/tests/device_tests/test_msg_getaddress_segwit.py b/tests/device_tests/test_msg_getaddress_segwit.py index 74d8f38d7f..46049cf5f4 100644 --- a/tests/device_tests/test_msg_getaddress_segwit.py +++ b/tests/device_tests/test_msg_getaddress_segwit.py @@ -21,143 +21,145 @@ from trezorlib.exceptions import TrezorFailure from trezorlib.tools import parse_path -class TestMsgGetaddressSegwit: - def test_show_segwit(self, client): - assert ( - btc.get_address( - client, - "Testnet", - parse_path("49'/1'/0'/1/0"), - True, - None, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - ) - == "2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX" +def test_show_segwit(client): + assert ( + btc.get_address( + client, + "Testnet", + parse_path("49'/1'/0'/1/0"), + True, + None, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) - assert ( - btc.get_address( - client, - "Testnet", - parse_path("49'/1'/0'/0/0"), - False, - None, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - ) - == "2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp" + == "2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX" + ) + assert ( + btc.get_address( + client, + "Testnet", + parse_path("49'/1'/0'/0/0"), + False, + None, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) - assert ( - btc.get_address( - client, - "Testnet", - parse_path("44'/1'/0'/0/0"), - False, - None, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - ) - == "2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc" + == "2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp" + ) + assert ( + btc.get_address( + client, + "Testnet", + parse_path("44'/1'/0'/0/0"), + False, + None, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) - assert ( - btc.get_address( - client, - "Testnet", - parse_path("44'/1'/0'/0/0"), - False, - None, - script_type=proto.InputScriptType.SPENDADDRESS, - ) - == "mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q" + == "2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc" + ) + assert ( + btc.get_address( + client, + "Testnet", + parse_path("44'/1'/0'/0/0"), + False, + None, + script_type=proto.InputScriptType.SPENDADDRESS, ) + == "mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q" + ) - @pytest.mark.altcoin - def test_show_segwit_altcoin(self, client): - assert ( - btc.get_address( - client, - "Groestlcoin Testnet", - parse_path("49'/1'/0'/0/0"), - False, - None, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - ) - == "2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e" - ) - assert ( - btc.get_address( - client, - "Elements", - parse_path("m/49'/1'/0'/0/0"), - False, - None, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - ) - == "XNW67ZQA9K3AuXPBWvJH4zN2y5QBDTwy2Z" - ) - @pytest.mark.multisig - def test_show_multisig_3(self, client): - nodes = [ - btc.get_public_node( - client, parse_path(f"49'/1'/{i}'"), coin_name="Testnet" - ).node - for i in range(1, 4) - ] - - multisig1 = proto.MultisigRedeemScriptType( - nodes=nodes, address_n=[0, 7], signatures=[b"", b"", b""], m=2 +@pytest.mark.altcoin +def test_show_segwit_altcoin(client): + assert ( + btc.get_address( + client, + "Groestlcoin Testnet", + parse_path("49'/1'/0'/0/0"), + False, + None, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) - # multisig2 = proto.MultisigRedeemScriptType( - # pubkeys=map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 1]), nodes), - # signatures=[b'', b'', b''], - # m=2, - # ) - for i in [1, 2, 3]: - assert ( - btc.get_address( - client, - "Testnet", - parse_path(f"49'/1'/{i}'/0/7"), - False, - multisig1, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - ) - == "2MwuUwUzPG17wiKQpfXmzfxJEoe7RXZDRad" - ) - - @pytest.mark.multisig - @pytest.mark.parametrize("show_display", (True, False)) - def test_multisig_missing(self, client, show_display): - # Multisig with global suffix specification. - # Use account numbers 1, 2 and 3 to create a valid multisig, - # but not containing the keys from account 0 used below. - nodes = [ - btc.get_public_node(client, parse_path(f"49'/0'/{i}'")).node - for i in range(1, 4) - ] - multisig1 = proto.MultisigRedeemScriptType( - nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2 + == "2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e" + ) + assert ( + btc.get_address( + client, + "Elements", + parse_path("m/49'/1'/0'/0/0"), + False, + None, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, ) + == "XNW67ZQA9K3AuXPBWvJH4zN2y5QBDTwy2Z" + ) - # Multisig with per-node suffix specification. - node = btc.get_public_node( - client, parse_path("49h/0h/0h/0"), coin_name="Bitcoin" + +@pytest.mark.multisig +def test_show_multisig_3(client): + nodes = [ + btc.get_public_node( + client, parse_path(f"49'/1'/{i}'"), coin_name="Testnet" ).node - multisig2 = proto.MultisigRedeemScriptType( - pubkeys=[ - proto.HDNodePathType(node=node, address_n=[1]), - proto.HDNodePathType(node=node, address_n=[2]), - proto.HDNodePathType(node=node, address_n=[3]), - ], - signatures=[b"", b"", b""], - m=2, + for i in range(1, 4) + ] + + multisig1 = proto.MultisigRedeemScriptType( + nodes=nodes, address_n=[0, 7], signatures=[b"", b"", b""], m=2 + ) + # multisig2 = proto.MultisigRedeemScriptType( + # pubkeys=map(lambda n: proto.HDNodePathType(node=bip32.deserialize(n.xpub), address_n=[2, 1]), nodes), + # signatures=[b'', b'', b''], + # m=2, + # ) + for i in [1, 2, 3]: + assert ( + btc.get_address( + client, + "Testnet", + parse_path(f"49'/1'/{i}'/0/7"), + False, + multisig1, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + ) + == "2MwuUwUzPG17wiKQpfXmzfxJEoe7RXZDRad" ) - for multisig in (multisig1, multisig2): - with pytest.raises(TrezorFailure): - btc.get_address( - client, - "Bitcoin", - parse_path("49'/0'/0'/0/0"), - show_display=show_display, - multisig=multisig, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - ) + +@pytest.mark.multisig +@pytest.mark.parametrize("show_display", (True, False)) +def test_multisig_missing(client, show_display): + # Multisig with global suffix specification. + # Use account numbers 1, 2 and 3 to create a valid multisig, + # but not containing the keys from account 0 used below. + nodes = [ + btc.get_public_node(client, parse_path(f"49'/0'/{i}'")).node + for i in range(1, 4) + ] + multisig1 = proto.MultisigRedeemScriptType( + nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2 + ) + + # Multisig with per-node suffix specification. + node = btc.get_public_node( + client, parse_path("49h/0h/0h/0"), coin_name="Bitcoin" + ).node + multisig2 = proto.MultisigRedeemScriptType( + pubkeys=[ + proto.HDNodePathType(node=node, address_n=[1]), + proto.HDNodePathType(node=node, address_n=[2]), + proto.HDNodePathType(node=node, address_n=[3]), + ], + signatures=[b"", b"", b""], + m=2, + ) + + for multisig in (multisig1, multisig2): + with pytest.raises(TrezorFailure): + btc.get_address( + client, + "Bitcoin", + parse_path("49'/0'/0'/0/0"), + show_display=show_display, + multisig=multisig, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + ) diff --git a/tests/device_tests/test_msg_getecdhsessionkey.py b/tests/device_tests/test_msg_getecdhsessionkey.py index 2d8049d4d5..89def5deca 100644 --- a/tests/device_tests/test_msg_getecdhsessionkey.py +++ b/tests/device_tests/test_msg_getecdhsessionkey.py @@ -21,68 +21,67 @@ from trezorlib import messages as proto, misc from ..common import MNEMONIC12 -class TestMsgGetECDHSessionKey: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_ecdh(self, client): - identity = proto.IdentityType( - proto="gpg", - user="", - host="Satoshi Nakamoto ", - port="", - path="", - index=0, - ) +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_ecdh(client): + identity = proto.IdentityType( + proto="gpg", + user="", + host="Satoshi Nakamoto ", + port="", + path="", + index=0, + ) - peer_public_key = bytes.fromhex( - "0407f2c6e5becf3213c1d07df0cfbe8e39f70a8c643df7575e5c56859ec52c45ca950499c019719dae0fda04248d851e52cf9d66eeb211d89a77be40de22b6c89d" - ) - result = misc.get_ecdh_session_key( - client, - identity=identity, - peer_public_key=peer_public_key, - ecdsa_curve_name="secp256k1", - ) - assert ( - result.session_key.hex() - == "0495e5d8c9e5cc09e7cf4908774f52decb381ce97f2fc9ba56e959c13f03f9f47a03dd151cbc908bc1db84d46e2c33e7bbb9daddc800f985244c924fd64adf6647" - ) - assert ( - result.public_key.hex() - == "02a3b34db999f994aa91accb7b73ecafe0ce8ce228e17a45525ccbf73feeb7c809" - ) + peer_public_key = bytes.fromhex( + "0407f2c6e5becf3213c1d07df0cfbe8e39f70a8c643df7575e5c56859ec52c45ca950499c019719dae0fda04248d851e52cf9d66eeb211d89a77be40de22b6c89d" + ) + result = misc.get_ecdh_session_key( + client, + identity=identity, + peer_public_key=peer_public_key, + ecdsa_curve_name="secp256k1", + ) + assert ( + result.session_key.hex() + == "0495e5d8c9e5cc09e7cf4908774f52decb381ce97f2fc9ba56e959c13f03f9f47a03dd151cbc908bc1db84d46e2c33e7bbb9daddc800f985244c924fd64adf6647" + ) + assert ( + result.public_key.hex() + == "02a3b34db999f994aa91accb7b73ecafe0ce8ce228e17a45525ccbf73feeb7c809" + ) - peer_public_key = bytes.fromhex( - "04811a6c2bd2a547d0dd84747297fec47719e7c3f9b0024f027c2b237be99aac39a9230acbd163d0cb1524a0f5ea4bfed6058cec6f18368f72a12aa0c4d083ff64" - ) - result = misc.get_ecdh_session_key( - client, - identity=identity, - peer_public_key=peer_public_key, - ecdsa_curve_name="nist256p1", - ) - assert ( - result.session_key.hex() - == "046d1f5c48af2cf2c57076ac2c9d7808db2086f614cb7b8107119ff2c6270cd209749809efe0196f01a0cc633788cef1f4a2bd650c99570d06962f923fca6d8fdf" - ) - assert ( - result.public_key.hex() - == "03fda61bc6e6be9b1dd99f7f9d04836d1bf2a6ea2426095210c8ce65091b09000a" - ) + peer_public_key = bytes.fromhex( + "04811a6c2bd2a547d0dd84747297fec47719e7c3f9b0024f027c2b237be99aac39a9230acbd163d0cb1524a0f5ea4bfed6058cec6f18368f72a12aa0c4d083ff64" + ) + result = misc.get_ecdh_session_key( + client, + identity=identity, + peer_public_key=peer_public_key, + ecdsa_curve_name="nist256p1", + ) + assert ( + result.session_key.hex() + == "046d1f5c48af2cf2c57076ac2c9d7808db2086f614cb7b8107119ff2c6270cd209749809efe0196f01a0cc633788cef1f4a2bd650c99570d06962f923fca6d8fdf" + ) + assert ( + result.public_key.hex() + == "03fda61bc6e6be9b1dd99f7f9d04836d1bf2a6ea2426095210c8ce65091b09000a" + ) - peer_public_key = bytes.fromhex( - "40a8cf4b6a64c4314e80f15a8ea55812bd735fbb365936a48b2d78807b575fa17a" - ) - result = misc.get_ecdh_session_key( - client, - identity=identity, - peer_public_key=peer_public_key, - ecdsa_curve_name="curve25519", - ) - assert ( - result.session_key.hex() - == "04e24516669e0b7d3d72e5129fddd07b6644c30915f5c8b7f1f62324afb3624311" - ) - assert ( - result.public_key.hex() - == "019753a0738c55c7ba7c17dd4a9a975ce9b0d2b62e8a1ecef4a76767fad99d3c71" - ) + peer_public_key = bytes.fromhex( + "40a8cf4b6a64c4314e80f15a8ea55812bd735fbb365936a48b2d78807b575fa17a" + ) + result = misc.get_ecdh_session_key( + client, + identity=identity, + peer_public_key=peer_public_key, + ecdsa_curve_name="curve25519", + ) + assert ( + result.session_key.hex() + == "04e24516669e0b7d3d72e5129fddd07b6644c30915f5c8b7f1f62324afb3624311" + ) + assert ( + result.public_key.hex() + == "019753a0738c55c7ba7c17dd4a9a975ce9b0d2b62e8a1ecef4a76767fad99d3c71" + ) diff --git a/tests/device_tests/test_msg_loaddevice.py b/tests/device_tests/test_msg_loaddevice.py index b8fa842f24..bbb64221c9 100644 --- a/tests/device_tests/test_msg_loaddevice.py +++ b/tests/device_tests/test_msg_loaddevice.py @@ -26,137 +26,137 @@ from ..common import ( get_test_address, ) +pytestmark = pytest.mark.setup_client(uninitialized=True) -@pytest.mark.setup_client(uninitialized=True) -class TestDeviceLoad: - def test_load_device_1(self, client): - debuglink.load_device( - client, - mnemonic=MNEMONIC12, - pin="", - passphrase_protection=False, - label="test", - ) - state = client.debug.state() - assert state.mnemonic_secret == MNEMONIC12.encode() - assert state.pin is None - assert state.passphrase_protection is False - address = get_test_address(client) - assert address == "mkqRFzxmkCGX9jxgpqqFHcxRUmLJcLDBer" +def test_load_device_1(client): + debuglink.load_device( + client, + mnemonic=MNEMONIC12, + pin="", + passphrase_protection=False, + label="test", + ) + state = client.debug.state() + assert state.mnemonic_secret == MNEMONIC12.encode() + assert state.pin is None + assert state.passphrase_protection is False - def test_load_device_2(self, client): - debuglink.load_device( - client, - mnemonic=MNEMONIC12, - pin="1234", - passphrase_protection=True, - label="test", - ) - client.use_passphrase("passphrase") - state = client.debug.state() - assert state.mnemonic_secret == MNEMONIC12.encode() + address = get_test_address(client) + assert address == "mkqRFzxmkCGX9jxgpqqFHcxRUmLJcLDBer" - if client.features.model == "1": - # we do not send PIN in DebugLinkState in Core - assert state.pin == "1234" - assert state.passphrase_protection is True - address = get_test_address(client) - assert address == "mx77VZjTVixVsU7nCtAKHnGFdsyNCnsWWw" +def test_load_device_2(client): + debuglink.load_device( + client, + mnemonic=MNEMONIC12, + pin="1234", + passphrase_protection=True, + label="test", + ) + client.use_passphrase("passphrase") + state = client.debug.state() + assert state.mnemonic_secret == MNEMONIC12.encode() - @pytest.mark.skip_t1 - def test_load_device_slip39_basic(self, client): - debuglink.load_device( - client, - mnemonic=MNEMONIC_SLIP39_BASIC_20_3of6, - pin="", - passphrase_protection=False, - label="test", - ) - assert client.features.backup_type == BackupType.Slip39_Basic + if client.features.model == "1": + # we do not send PIN in DebugLinkState in Core + assert state.pin == "1234" + assert state.passphrase_protection is True - @pytest.mark.skip_t1 - def test_load_device_slip39_advanced(self, client): - debuglink.load_device( - client, - mnemonic=MNEMONIC_SLIP39_ADVANCED_20, - pin="", - passphrase_protection=False, - label="test", - ) - assert client.features.backup_type == BackupType.Slip39_Advanced + address = get_test_address(client) + assert address == "mx77VZjTVixVsU7nCtAKHnGFdsyNCnsWWw" - def test_load_device_utf(self, client): - words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" - words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" - words_nfkc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" - words_nfd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" - passphrase_nfkd = ( - u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko" - ) - passphrase_nfc = ( - u"Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko" - ) - passphrase_nfkc = ( - u"Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko" - ) - passphrase_nfd = ( - u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko" - ) +@pytest.mark.skip_t1 +def test_load_device_slip39_basic(client): + debuglink.load_device( + client, + mnemonic=MNEMONIC_SLIP39_BASIC_20_3of6, + pin="", + passphrase_protection=False, + label="test", + ) + assert client.features.backup_type == BackupType.Slip39_Basic - debuglink.load_device( - client, - mnemonic=words_nfkd, - pin="", - passphrase_protection=True, - label="test", - language="en-US", - skip_checksum=True, - ) - client.use_passphrase(passphrase_nfkd) - address_nfkd = get_test_address(client) - device.wipe(client) - debuglink.load_device( - client, - mnemonic=words_nfc, - pin="", - passphrase_protection=True, - label="test", - language="en-US", - skip_checksum=True, - ) - client.use_passphrase(passphrase_nfc) - address_nfc = get_test_address(client) +@pytest.mark.skip_t1 +def test_load_device_slip39_advanced(client): + debuglink.load_device( + client, + mnemonic=MNEMONIC_SLIP39_ADVANCED_20, + pin="", + passphrase_protection=False, + label="test", + ) + assert client.features.backup_type == BackupType.Slip39_Advanced - device.wipe(client) - debuglink.load_device( - client, - mnemonic=words_nfkc, - pin="", - passphrase_protection=True, - label="test", - language="en-US", - skip_checksum=True, - ) - client.use_passphrase(passphrase_nfkc) - address_nfkc = get_test_address(client) - device.wipe(client) - debuglink.load_device( - client, - mnemonic=words_nfd, - pin="", - passphrase_protection=True, - label="test", - language="en-US", - skip_checksum=True, - ) - client.use_passphrase(passphrase_nfd) - address_nfd = get_test_address(client) +def test_load_device_utf(client): + words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" + words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" + words_nfkc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" + words_nfd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" - assert address_nfkd == address_nfc - assert address_nfkd == address_nfkc - assert address_nfkd == address_nfd + passphrase_nfkd = ( + u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko" + ) + passphrase_nfc = u"Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko" + passphrase_nfkc = u"Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko" + passphrase_nfd = ( + u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko" + ) + + debuglink.load_device( + client, + mnemonic=words_nfkd, + pin="", + passphrase_protection=True, + label="test", + language="en-US", + skip_checksum=True, + ) + client.use_passphrase(passphrase_nfkd) + address_nfkd = get_test_address(client) + + device.wipe(client) + debuglink.load_device( + client, + mnemonic=words_nfc, + pin="", + passphrase_protection=True, + label="test", + language="en-US", + skip_checksum=True, + ) + client.use_passphrase(passphrase_nfc) + address_nfc = get_test_address(client) + + device.wipe(client) + debuglink.load_device( + client, + mnemonic=words_nfkc, + pin="", + passphrase_protection=True, + label="test", + language="en-US", + skip_checksum=True, + ) + client.use_passphrase(passphrase_nfkc) + address_nfkc = get_test_address(client) + + device.wipe(client) + debuglink.load_device( + client, + mnemonic=words_nfd, + pin="", + passphrase_protection=True, + label="test", + language="en-US", + skip_checksum=True, + ) + client.use_passphrase(passphrase_nfd) + address_nfd = get_test_address(client) + + assert address_nfkd == address_nfc + assert address_nfkd == address_nfkc + assert address_nfkd == address_nfd diff --git a/tests/device_tests/test_msg_signidentity.py b/tests/device_tests/test_msg_signidentity.py index bb99f2aa93..093c95f02a 100644 --- a/tests/device_tests/test_msg_signidentity.py +++ b/tests/device_tests/test_msg_signidentity.py @@ -21,126 +21,125 @@ from trezorlib import messages as proto, misc from ..common import MNEMONIC12 -class TestMsgSignidentity: - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_sign(self, client): - hidden = bytes.fromhex( - "cd8552569d6e4509266ef137584d1e62c7579b5b8ed69bbafa4b864c6521e7c2" - ) - visual = "2015-03-23 17:39:22" +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_sign(client): + hidden = bytes.fromhex( + "cd8552569d6e4509266ef137584d1e62c7579b5b8ed69bbafa4b864c6521e7c2" + ) + visual = "2015-03-23 17:39:22" - # URI : https://satoshi@bitcoin.org/login - # hash : d0e2389d4c8394a9f3e32de01104bf6e8db2d9e2bb0905d60fffa5a18fd696db - # path : m/2147483661/2637750992/2845082444/3761103859/4005495825 - identity = proto.IdentityType( - proto="https", - user="satoshi", - host="bitcoin.org", - port="", - path="/login", - index=0, - ) - sig = misc.sign_identity(client, identity, hidden, visual) - assert sig.address == "17F17smBTX9VTZA9Mj8LM5QGYNZnmziCjL" - assert ( - sig.public_key.hex() - == "023a472219ad3327b07c18273717bb3a40b39b743756bf287fbd5fa9d263237f45" - ) - assert ( - sig.signature.hex() - == "20f2d1a42d08c3a362be49275c3ffeeaa415fc040971985548b9f910812237bb41770bf2c8d488428799fbb7e52c11f1a3404011375e4080e077e0e42ab7a5ba02" - ) + # URI : https://satoshi@bitcoin.org/login + # hash : d0e2389d4c8394a9f3e32de01104bf6e8db2d9e2bb0905d60fffa5a18fd696db + # path : m/2147483661/2637750992/2845082444/3761103859/4005495825 + identity = proto.IdentityType( + proto="https", + user="satoshi", + host="bitcoin.org", + port="", + path="/login", + index=0, + ) + sig = misc.sign_identity(client, identity, hidden, visual) + assert sig.address == "17F17smBTX9VTZA9Mj8LM5QGYNZnmziCjL" + assert ( + sig.public_key.hex() + == "023a472219ad3327b07c18273717bb3a40b39b743756bf287fbd5fa9d263237f45" + ) + assert ( + sig.signature.hex() + == "20f2d1a42d08c3a362be49275c3ffeeaa415fc040971985548b9f910812237bb41770bf2c8d488428799fbb7e52c11f1a3404011375e4080e077e0e42ab7a5ba02" + ) - # URI : ftp://satoshi@bitcoin.org:2323/pub - # hash : 79a6b53831c6ff224fb283587adc4ebae8fb0d734734a46c876838f52dff53f3 - # path : m/2147483661/3098912377/2734671409/3632509519/3125730426 - identity = proto.IdentityType( - proto="ftp", - user="satoshi", - host="bitcoin.org", - port="2323", - path="/pub", - index=3, - ) - sig = misc.sign_identity(client, identity, hidden, visual) - assert sig.address == "1KAr6r5qF2kADL8bAaRQBjGKYEGxn9WrbS" - assert ( - sig.public_key.hex() - == "0266cf12d2ba381c5fd797da0d64f59c07a6f1b034ad276cca6bf2729e92b20d9c" - ) - assert ( - sig.signature.hex() - == "20bbd12dc657d534fc0f7e40186e22c447e0866a016f654f380adffa9a84e9faf412a1bb0ae908296537838cf91145e77da08681c63d07b7dca40728b9e6cb17cf" - ) + # URI : ftp://satoshi@bitcoin.org:2323/pub + # hash : 79a6b53831c6ff224fb283587adc4ebae8fb0d734734a46c876838f52dff53f3 + # path : m/2147483661/3098912377/2734671409/3632509519/3125730426 + identity = proto.IdentityType( + proto="ftp", + user="satoshi", + host="bitcoin.org", + port="2323", + path="/pub", + index=3, + ) + sig = misc.sign_identity(client, identity, hidden, visual) + assert sig.address == "1KAr6r5qF2kADL8bAaRQBjGKYEGxn9WrbS" + assert ( + sig.public_key.hex() + == "0266cf12d2ba381c5fd797da0d64f59c07a6f1b034ad276cca6bf2729e92b20d9c" + ) + assert ( + sig.signature.hex() + == "20bbd12dc657d534fc0f7e40186e22c447e0866a016f654f380adffa9a84e9faf412a1bb0ae908296537838cf91145e77da08681c63d07b7dca40728b9e6cb17cf" + ) - # URI : ssh://satoshi@bitcoin.org - # hash : 5fa612f558a1a3b1fb7f010b2ea0a25cb02520a0ffa202ce74a92fc6145da5f3 - # path : m/2147483661/4111640159/2980290904/2332131323/3701645358 - identity = proto.IdentityType( - proto="ssh", user="satoshi", host="bitcoin.org", port="", path="", index=47 - ) - sig = misc.sign_identity( - client, identity, hidden, visual, ecdsa_curve_name="nist256p1" - ) - assert sig.address is None - assert ( - sig.public_key.hex() - == "0373f21a3da3d0e96fc2189f81dd826658c3d76b2d55bd1da349bc6c3573b13ae4" - ) - assert ( - sig.signature.hex() - == "005122cebabb852cdd32103b602662afa88e54c0c0c1b38d7099c64dcd49efe908288114e66ed2d8c82f23a70b769a4db723173ec53840c08aafb840d3f09a18d3" - ) + # URI : ssh://satoshi@bitcoin.org + # hash : 5fa612f558a1a3b1fb7f010b2ea0a25cb02520a0ffa202ce74a92fc6145da5f3 + # path : m/2147483661/4111640159/2980290904/2332131323/3701645358 + identity = proto.IdentityType( + proto="ssh", user="satoshi", host="bitcoin.org", port="", path="", index=47 + ) + sig = misc.sign_identity( + client, identity, hidden, visual, ecdsa_curve_name="nist256p1" + ) + assert sig.address is None + assert ( + sig.public_key.hex() + == "0373f21a3da3d0e96fc2189f81dd826658c3d76b2d55bd1da349bc6c3573b13ae4" + ) + assert ( + sig.signature.hex() + == "005122cebabb852cdd32103b602662afa88e54c0c0c1b38d7099c64dcd49efe908288114e66ed2d8c82f23a70b769a4db723173ec53840c08aafb840d3f09a18d3" + ) - # URI : ssh://satoshi@bitcoin.org - # hash : 5fa612f558a1a3b1fb7f010b2ea0a25cb02520a0ffa202ce74a92fc6145da5f3 - # path : m/2147483661/4111640159/2980290904/2332131323/3701645358 - identity = proto.IdentityType( - proto="ssh", user="satoshi", host="bitcoin.org", port="", path="", index=47 - ) - sig = misc.sign_identity( - client, identity, hidden, visual, ecdsa_curve_name="ed25519" - ) - assert sig.address is None - assert ( - sig.public_key.hex() - == "000fac2a491e0f5b871dc48288a4cae551bac5cb0ed19df0764d6e721ec5fade18" - ) - assert ( - sig.signature.hex() - == "00f05e5085e666429de397c70a081932654369619c0bd2a6579ea6c1ef2af112ef79998d6c862a16b932d44b1ac1b83c8cbcd0fbda228274fde9e0d0ca6e9cb709" - ) + # URI : ssh://satoshi@bitcoin.org + # hash : 5fa612f558a1a3b1fb7f010b2ea0a25cb02520a0ffa202ce74a92fc6145da5f3 + # path : m/2147483661/4111640159/2980290904/2332131323/3701645358 + identity = proto.IdentityType( + proto="ssh", user="satoshi", host="bitcoin.org", port="", path="", index=47 + ) + sig = misc.sign_identity( + client, identity, hidden, visual, ecdsa_curve_name="ed25519" + ) + assert sig.address is None + assert ( + sig.public_key.hex() + == "000fac2a491e0f5b871dc48288a4cae551bac5cb0ed19df0764d6e721ec5fade18" + ) + assert ( + sig.signature.hex() + == "00f05e5085e666429de397c70a081932654369619c0bd2a6579ea6c1ef2af112ef79998d6c862a16b932d44b1ac1b83c8cbcd0fbda228274fde9e0d0ca6e9cb709" + ) - # URI : gpg://satoshi@bitcoin.org - identity = proto.IdentityType( - proto="gpg", user="satoshi", host="bitcoin.org", port="", path="" - ) - sig = misc.sign_identity( - client, identity, hidden, visual, ecdsa_curve_name="ed25519" - ) - assert sig.address is None - assert ( - sig.public_key.hex() - == "00d18cdf4dbdbb50ef1fdba1ae0539451f3354a366d6a35313712ab82f16d4cd9e" - ) - assert ( - sig.signature.hex() - == "00f47f1a09a2875b971811ebbece19c3004c3ecbe84e65666dc8c36cc2fc002544af8a3f545375ebe53d73b41c700df2f9020256c31bb774a7eb03ed9819226407" - ) + # URI : gpg://satoshi@bitcoin.org + identity = proto.IdentityType( + proto="gpg", user="satoshi", host="bitcoin.org", port="", path="" + ) + sig = misc.sign_identity( + client, identity, hidden, visual, ecdsa_curve_name="ed25519" + ) + assert sig.address is None + assert ( + sig.public_key.hex() + == "00d18cdf4dbdbb50ef1fdba1ae0539451f3354a366d6a35313712ab82f16d4cd9e" + ) + assert ( + sig.signature.hex() + == "00f47f1a09a2875b971811ebbece19c3004c3ecbe84e65666dc8c36cc2fc002544af8a3f545375ebe53d73b41c700df2f9020256c31bb774a7eb03ed9819226407" + ) - # URI : signify://satoshi@bitcoin.org - identity = proto.IdentityType( - proto="signify", user="satoshi", host="bitcoin.org", port="", path="" - ) - sig = misc.sign_identity( - client, identity, hidden, visual, ecdsa_curve_name="ed25519" - ) - assert sig.address is None - assert ( - sig.public_key.hex() - == "0038c0f42c0e47b233e837763098f029fd01009b74fdf4b0d60db114fb0f4f8b17" - ) - assert ( - sig.signature.hex() - == "009bb30a7a894e6cdd86e2b75803745e93bd5294b979f9e00ce9dc870642c7f6ad7322af4c54d401ea793494e8a5fdf2bf8b88c6e875094512bd67b94f9188000d" - ) + # URI : signify://satoshi@bitcoin.org + identity = proto.IdentityType( + proto="signify", user="satoshi", host="bitcoin.org", port="", path="" + ) + sig = misc.sign_identity( + client, identity, hidden, visual, ecdsa_curve_name="ed25519" + ) + assert sig.address is None + assert ( + sig.public_key.hex() + == "0038c0f42c0e47b233e837763098f029fd01009b74fdf4b0d60db114fb0f4f8b17" + ) + assert ( + sig.signature.hex() + == "009bb30a7a894e6cdd86e2b75803745e93bd5294b979f9e00ce9dc870642c7f6ad7322af4c54d401ea793494e8a5fdf2bf8b88c6e875094512bd67b94f9188000d" + ) diff --git a/tests/device_tests/test_msg_signtx.py b/tests/device_tests/test_msg_signtx.py index ec6de1b16a..721e4349f2 100644 --- a/tests/device_tests/test_msg_signtx.py +++ b/tests/device_tests/test_msg_signtx.py @@ -75,1413 +75,1423 @@ TXHASH_2bac7a = bytes.fromhex( ) -class TestMsgSigntx: - def test_one_one_fee(self, client): - # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 - # input 0: 0.0039 BTC +def test_one_one_fee(client): + # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 + # input 0: 0.0039 BTC - inp1 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - amount=390000, - prev_hash=TXHASH_d5f65e, - prev_index=0, + inp1 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + amount=390000, + prev_hash=TXHASH_d5f65e, + prev_index=0, + ) + + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=390000 - 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_d5f65e), + request_input(0, TXHASH_d5f65e), + request_input(1, TXHASH_d5f65e), + request_output(0, TXHASH_d5f65e), + request_input(0), + request_output(0), + request_output(0), + request_finished(), + ] ) - out1 = messages.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=390000 - 10000, - script_type=messages.OutputScriptType.PAYTOADDRESS, + _, serialized_tx = btc.sign_tx( + client, "Bitcoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET ) - 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_d5f65e), - request_input(0, TXHASH_d5f65e), - request_input(1, TXHASH_d5f65e), - request_output(0, TXHASH_d5f65e), - request_input(0), - request_output(0), - request_output(0), - request_finished(), - ] - ) + assert ( + tx_hash(serialized_tx).hex() + == "f6b22f324894c708e32d340a60af670c8accb3b62d05906d31e60ae49696c0c3" + ) - _, serialized_tx = btc.sign_tx( - client, "Bitcoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET - ) - assert ( - tx_hash(serialized_tx).hex() - == "f6b22f324894c708e32d340a60af670c8accb3b62d05906d31e60ae49696c0c3" - ) +def test_testnet_one_two_fee(client): + # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56 - def test_testnet_one_two_fee(self, client): - # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56 + # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd + # input 0: 0.31 BTC + inp1 = messages.TxInputType( + address_n=parse_path("44'/1'/0'/0/0"), + amount=31000000, + prev_hash=TXHASH_e5040e, + prev_index=0, + ) - # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd - # input 0: 0.31 BTC - inp1 = messages.TxInputType( - address_n=parse_path("44'/1'/0'/0/0"), - amount=31000000, - prev_hash=TXHASH_e5040e, - prev_index=0, - ) + out1 = messages.TxOutputType( + address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx", + amount=30090000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) - out1 = messages.TxOutputType( - address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx", - amount=30090000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) + out2 = messages.TxOutputType( + address_n=parse_path("44'/1'/0'/1/0"), + amount=900000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) - out2 = messages.TxOutputType( - address_n=parse_path("44'/1'/0'/1/0"), - amount=900000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - 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(TXHASH_e5040e), - request_input(0, TXHASH_e5040e), - request_output(0, TXHASH_e5040e), - request_output(1, TXHASH_e5040e), - request_input(0), - request_output(0), - request_output(1), - request_output(0), - request_output(1), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET - ) - - assert ( - serialized_tx.hex() - == "0100000001cd3b93f5b24ae190ce5141235091cd93fbb2908e24e5b9ff6776aec11b0e04e5000000006b483045022100eba3bbcbb82ab1ebac88a394e8fb53b0263dadbb3e8072f0a21ee62818c911060220686a9b7f306d028b54a228b5c47cc6c27b1d01a3b0770440bcc64d55d8bace2c0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff021023cb01000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288aca0bb0d00000000001976a9143d3cca567e00a04819742b21a696a67da796498b88ac00000000" - ) - - def test_testnet_fee_high_warning(self, client): - # tx: 6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54 - # input 1: 10.00000000 BTC - inp1 = messages.TxInputType( - address_n=parse_path("44'/1'/0'/0/0"), - amount=1000000000, - prev_hash=TXHASH_6f90f3, - prev_index=1, - ) - - out1 = messages.TxOutputType( - address="mfiGQVPcRcaEvQPYDErR34DcCovtxYvUUV", - amount=1000000000 - 500000000 - 8000000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - out2 = messages.TxOutputType( - address_n=parse_path("44'/1'/0'/1/0"), - amount=500000000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - messages.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - messages.ButtonRequest(code=B.FeeOverThreshold), - messages.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_6f90f3), - request_input(0, TXHASH_6f90f3), - request_input(1, TXHASH_6f90f3), - request_output(0, TXHASH_6f90f3), - request_output(1, TXHASH_6f90f3), - request_input(0), - request_output(0), - request_output(1), - request_output(0), - request_output(1), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET - ) - - assert ( - tx_hash(serialized_tx).hex() - == "54fd5e9b65b8acc10144c1e78ea9720df7606d7d4a543e4c547ecd45b2ae226b" - ) - - def test_one_two_fee(self, client): - # tx: c275c333fd1b36bef4af316226c66a8b3693fbfcc081a5e16a2ae5fcb09e92bf - - inp1 = messages.TxInputType( - address_n=parse_path( - "m/44'/0'/0'/0/5" - ), # 1GA9u9TfCG7SWmKCveBumdA1TZpfom6ZdJ - amount=50000, - prev_hash=TXHASH_50f6f1, - prev_index=1, - ) - - out1 = messages.TxOutputType( - address_n=parse_path( - "m/44'/0'/0'/1/3" - ), # 1EcL6AyfQTyWKGvXwNSfsWoYnD3whzVFdu - amount=30000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - out2 = messages.TxOutputType( - address="1Up15Msx4sbvUCGm8Xgo2Zp5FQim3wE59", - amount=10000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - request_output(1), - messages.ButtonRequest(code=B.ConfirmOutput), - messages.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_50f6f1), - request_input(0, TXHASH_50f6f1), - request_output(0, TXHASH_50f6f1), - request_output(1, TXHASH_50f6f1), - request_input(0), - request_output(0), - request_output(1), - request_output(0), - request_output(1), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bitcoin", [inp1], [out1, out2], prev_txes=TX_CACHE_MAINNET - ) - - assert ( - serialized_tx.hex() - == "01000000016d20f69067ad1ffd50ee7c0f377dde2c932ccb03e84b5659732da99c20f1f650010000006a47304402203429bd3ce7b38c5c1e8a15340edd79ced41a2939aae62e259d2e3d18e0c5ee7602201b83b10ebc4d6dcee3f9eb42ba8f1ef8a059a05397e0c1b9223d1565a3e6ec01012102a7a079c1ef9916b289c2ff21a992c808d0de3dfcf8a9f163205c5c9e21f55d5cffffffff0230750000000000001976a914954820f1de627a703596ac0396f986d958e3de4c88ac10270000000000001976a91405427736705cfbfaff76b1cff48283707fb1037088ac00000000" - ) - - 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_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_meta(TXHASH_d5f65e), - request_input(0, TXHASH_d5f65e), - request_input(1, TXHASH_d5f65e), - request_output(0, TXHASH_d5f65e), - 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_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_input(1), - request_output(0), - messages.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - messages.ButtonRequest(code=B.SignTx), - 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_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" - ) - - @pytest.mark.slow - 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}"), - amount=26000, - prev_hash=TXHASH_4a7b7e, - prev_index=i, - ) - ) - out = messages.TxOutputType( - address="19dvDdyxxptP9dGvozYe8BP6tgFV9L4jg5", - amount=100 * 26000 - 15 * 10000, - script_type=messages.OutputScriptType.PAYTOADDRESS, + 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(TXHASH_e5040e), + request_input(0, TXHASH_e5040e), + request_output(0, TXHASH_e5040e), + request_output(1, TXHASH_e5040e), + request_input(0), + request_output(0), + request_output(1), + request_output(0), + request_output(1), + request_finished(), + ] ) _, serialized_tx = btc.sign_tx( - client, "Bitcoin", inputs, [out], prev_txes=TX_CACHE_MAINNET - ) - assert ( - tx_hash(serialized_tx).hex() - == "f90cdc2224366312be28166e2afe198ece7a60e86e25f5a50f5b14d811713da8" + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET ) - @pytest.mark.slow - def test_lots_of_outputs(self, client): - # Tests if device implements serialization of len(outputs) correctly + assert ( + serialized_tx.hex() + == "0100000001cd3b93f5b24ae190ce5141235091cd93fbb2908e24e5b9ff6776aec11b0e04e5000000006b483045022100eba3bbcbb82ab1ebac88a394e8fb53b0263dadbb3e8072f0a21ee62818c911060220686a9b7f306d028b54a228b5c47cc6c27b1d01a3b0770440bcc64d55d8bace2c0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff021023cb01000000001976a91485eb47fe98f349065d6f044e27a4ac541af79ee288aca0bb0d00000000001976a9143d3cca567e00a04819742b21a696a67da796498b88ac00000000" + ) - # 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, +def test_testnet_fee_high_warning(client): + # tx: 6f90f3c7cbec2258b0971056ef3fe34128dbde30daa9c0639a898f9977299d54 + # input 1: 10.00000000 BTC + inp1 = messages.TxInputType( + address_n=parse_path("44'/1'/0'/0/0"), + amount=1000000000, + prev_hash=TXHASH_6f90f3, + prev_index=1, + ) + + out1 = messages.TxOutputType( + address="mfiGQVPcRcaEvQPYDErR34DcCovtxYvUUV", + amount=1000000000 - 500000000 - 8000000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + out2 = messages.TxOutputType( + address_n=parse_path("44'/1'/0'/1/0"), + amount=500000000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + messages.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + messages.ButtonRequest(code=B.FeeOverThreshold), + messages.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_6f90f3), + request_input(0, TXHASH_6f90f3), + request_input(1, TXHASH_6f90f3), + request_output(0, TXHASH_6f90f3), + request_output(1, TXHASH_6f90f3), + request_input(0), + request_output(0), + request_output(1), + request_output(0), + request_output(1), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET ) - inp2 = messages.TxInputType( - address_n=parse_path("44h/0h/1h/0/1"), - amount=2540000, - prev_hash=TXHASH_39a29e, - prev_index=1, + assert ( + tx_hash(serialized_tx).hex() + == "54fd5e9b65b8acc10144c1e78ea9720df7606d7d4a543e4c547ecd45b2ae226b" + ) + + +def test_one_two_fee(client): + # tx: c275c333fd1b36bef4af316226c66a8b3693fbfcc081a5e16a2ae5fcb09e92bf + + inp1 = messages.TxInputType( + address_n=parse_path("m/44'/0'/0'/0/5"), # 1GA9u9TfCG7SWmKCveBumdA1TZpfom6ZdJ + amount=50000, + prev_hash=TXHASH_50f6f1, + prev_index=1, + ) + + out1 = messages.TxOutputType( + address_n=parse_path("m/44'/0'/0'/1/3"), # 1EcL6AyfQTyWKGvXwNSfsWoYnD3whzVFdu + amount=30000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + out2 = messages.TxOutputType( + address="1Up15Msx4sbvUCGm8Xgo2Zp5FQim3wE59", + amount=10000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + request_output(1), + messages.ButtonRequest(code=B.ConfirmOutput), + messages.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_50f6f1), + request_input(0, TXHASH_50f6f1), + request_output(0, TXHASH_50f6f1), + request_output(1, TXHASH_50f6f1), + request_input(0), + request_output(0), + request_output(1), + request_output(0), + request_output(1), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Bitcoin", [inp1], [out1, out2], prev_txes=TX_CACHE_MAINNET ) - outputs = [] - cnt = 255 - for _ in range(cnt): - out = messages.TxOutputType( - address="1NwN6UduuVkJi6sw3gSiKZaCY5rHgVXC2h", - amount=(100000 + 2540000 - 39000) // cnt, - script_type=messages.OutputScriptType.PAYTOADDRESS, + assert ( + serialized_tx.hex() + == "01000000016d20f69067ad1ffd50ee7c0f377dde2c932ccb03e84b5659732da99c20f1f650010000006a47304402203429bd3ce7b38c5c1e8a15340edd79ced41a2939aae62e259d2e3d18e0c5ee7602201b83b10ebc4d6dcee3f9eb42ba8f1ef8a059a05397e0c1b9223d1565a3e6ec01012102a7a079c1ef9916b289c2ff21a992c808d0de3dfcf8a9f163205c5c9e21f55d5cffffffff0230750000000000001976a914954820f1de627a703596ac0396f986d958e3de4c88ac10270000000000001976a91405427736705cfbfaff76b1cff48283707fb1037088ac00000000" + ) + + +def test_one_three_fee(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_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_meta(TXHASH_d5f65e), + request_input(0, TXHASH_d5f65e), + request_input(1, TXHASH_d5f65e), + request_output(0, TXHASH_d5f65e), + 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_two_two(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_input(1), + request_output(0), + messages.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + messages.ButtonRequest(code=B.SignTx), + 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_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" + ) + + +@pytest.mark.slow +def test_lots_of_inputs(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}"), + amount=26000, + prev_hash=TXHASH_4a7b7e, + prev_index=i, ) - outputs.append(out) + ) + 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" + ) + + +@pytest.mark.slow +def test_lots_of_outputs(client): + # Tests if device implements serialization of len(outputs) 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 = [] + cnt = 255 + for _ in range(cnt): + out = messages.TxOutputType( + address="1NwN6UduuVkJi6sw3gSiKZaCY5rHgVXC2h", + amount=(100000 + 2540000 - 39000) // cnt, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + outputs.append(out) + + _, serialized_tx = btc.sign_tx( + client, "Bitcoin", [inp1, inp2], outputs, prev_txes=TX_CACHE_MAINNET + ) + + assert ( + tx_hash(serialized_tx).hex() + == "aa0cfe57938b71db47a3992b25d4bee39f258a5de513c907727b982478648a7d" + ) + + +@pytest.mark.slow +def test_lots_of_change(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_input(1), + 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_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_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() - == "aa0cfe57938b71db47a3992b25d4bee39f258a5de513c907727b982478648a7d" + assert ( + tx_hash(serialized_tx).hex() + == "fae68e4a3a4b0540eb200e2218a6d8465eac469788ccb236e0d5822d105ddde9" + ) + + +def test_fee_high_warning(client): + # tx: 1570416eb4302cf52979afd5e6909e37d8fdd874301f7cc87e547e509cb1caa6 + # input 0: 1.0 BTC + + inp1 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + amount=100000000, + prev_hash=TXHASH_157041, + prev_index=0, + ) + + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=100000000 - 510000, + 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.FeeOverThreshold), + messages.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_157041), + request_input(0, TXHASH_157041), + request_output(0, TXHASH_157041), + request_output(1, TXHASH_157041), + 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 ) - @pytest.mark.slow - def test_lots_of_change(self, client): - # Tests if device implements prompting for multiple change addresses correctly + assert ( + tx_hash(serialized_tx).hex() + == "c36928aca6452d50cb63e2592200bbcc3722ce6b631b1dfd185ccdf9a954af28" + ) - # 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, +@pytest.mark.skip_t1 +def test_fee_high_hardfail(client): + # tx: 1570416eb4302cf52979afd5e6909e37d8fdd874301f7cc87e547e509cb1caa6 + # input 0: 1.0 BTC + + inp1 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + amount=100000000, + prev_hash=TXHASH_157041, + prev_index=0, + ) + + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=100000000 - 5100000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + with pytest.raises(TrezorFailure, match="fee is unexpectedly large"): + btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET) + + # set SafetyCheckLevel to PromptTemporarily and try again + device.apply_settings( + client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily + ) + with client: + finished = False + + def input_flow(): + nonlocal finished + for expected in (B.ConfirmOutput, B.FeeOverThreshold, B.SignTx): + br = yield + assert br.code == expected + client.debug.press_yes() + finished = True + + client.set_input_flow(input_flow) + + _, serialized_tx = btc.sign_tx( + client, "Bitcoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET ) + assert finished - inp2 = messages.TxInputType( - address_n=parse_path("44h/0h/1h/0/1"), - amount=2540000, - prev_hash=TXHASH_39a29e, - prev_index=1, + assert ( + tx_hash(serialized_tx).hex() + == "0fadc325662e84fd1a5efcb20c5369cf9134a24b6d29bce99f61e69680397a79" + ) + + +def test_not_enough_funds(client): + # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 + # input 0: 0.0039 BTC + + inp1 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + amount=390000, + prev_hash=TXHASH_d5f65e, + prev_index=0, + ) + + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=400000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + messages.ButtonRequest(code=B.ConfirmOutput), + messages.Failure(code=messages.FailureType.NotEnoughFunds), + ] ) - - 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_input(1), - 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_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_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_fee_high_warning(self, client): - # tx: 1570416eb4302cf52979afd5e6909e37d8fdd874301f7cc87e547e509cb1caa6 - # input 0: 1.0 BTC - - inp1 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - amount=100000000, - prev_hash=TXHASH_157041, - prev_index=0, - ) - - out1 = messages.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=100000000 - 510000, - 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.FeeOverThreshold), - messages.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_157041), - request_input(0, TXHASH_157041), - request_output(0, TXHASH_157041), - request_output(1, TXHASH_157041), - 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() - == "c36928aca6452d50cb63e2592200bbcc3722ce6b631b1dfd185ccdf9a954af28" - ) - - @pytest.mark.skip_t1 - def test_fee_high_hardfail(self, client): - # tx: 1570416eb4302cf52979afd5e6909e37d8fdd874301f7cc87e547e509cb1caa6 - # input 0: 1.0 BTC - - inp1 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - amount=100000000, - prev_hash=TXHASH_157041, - prev_index=0, - ) - - out1 = messages.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=100000000 - 5100000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - with pytest.raises(TrezorFailure, match="fee is unexpectedly large"): + with pytest.raises(TrezorFailure, match="NotEnoughFunds"): btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET) - # set SafetyCheckLevel to PromptTemporarily and try again - device.apply_settings( - client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily + +def test_p2sh(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(), + ] ) - with client: - finished = False - - def input_flow(): - nonlocal finished - for expected in (B.ConfirmOutput, B.FeeOverThreshold, B.SignTx): - br = yield - assert br.code == expected - client.debug.press_yes() - finished = True - - client.set_input_flow(input_flow) - - _, serialized_tx = btc.sign_tx( - client, "Bitcoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET - ) - assert finished - - assert ( - tx_hash(serialized_tx).hex() - == "0fadc325662e84fd1a5efcb20c5369cf9134a24b6d29bce99f61e69680397a79" + _, serialized_tx = btc.sign_tx( + client, "Bitcoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET ) - def test_not_enough_funds(self, client): - # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 - # input 0: 0.0039 BTC + assert ( + tx_hash(serialized_tx).hex() + == "5042aed319b9f018d693dbf8f3db926ee4ab4dae670a2911625b440a1366f79d" + ) - inp1 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - amount=390000, - prev_hash=TXHASH_d5f65e, - prev_index=0, + +def test_testnet_big_amount(client): + # This test is testing transaction with amount bigger than fits to uint32 + + # tx: 2bac7ad1dec654579a71ea9555463f63ac7b7df9d8ba67b4682bba4e514d0f0c:1 + # input 1: 411102528330 Satoshi + + inp1 = messages.TxInputType( + address_n=parse_path("m/44'/1'/0'/0/0"), + amount=411102528330, + prev_hash=TXHASH_2bac7a, + prev_index=1, + ) + out1 = messages.TxOutputType( + address="mopZWqZZyQc3F2Sy33cvDtJchSAMsnLi7b", # seed allallall, bip32: m/44'/1'/0'/0/1 + amount=411102528330, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1], prev_txes=TX_CACHE_TESTNET + ) + assert ( + serialized_tx.hex() + == "01000000010c0f4d514eba2b68b467bad8f97d7bac633f465595ea719a5754c6ded17aac2b010000006b4830450221008e3b926f04d8830bd5b67698af25c9e00c9db1b1ef3e5d69af794446753da94a02202d4a7509f26bba29ff643a7ac0d43fb128c1a632cc502b8f44eada8930fb9c9b0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff014ac39eb75f0000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000" + ) + + +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_attack_change_outputs(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 + + with client, pytest.raises( + TrezorFailure, match="Transaction has changed during signing" + ): + # Set up attack processors + client.set_filter(messages.TxAck, attack_processor) + + btc.sign_tx( + client, + "Bitcoin", + [inp1, inp2], + [out1, out2], + prev_txes=TX_CACHE_MAINNET, ) - out1 = messages.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=400000, - script_type=messages.OutputScriptType.PAYTOADDRESS, + +# Ensure that if the change output is modified after the user confirms the +# transaction, then signing fails. +def test_attack_modify_change_address(client): + # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56 + + # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd + # input 0: 0.31 BTC + inp1 = messages.TxInputType( + address_n=parse_path("44'/1'/0'/0/0"), + amount=31000000, + prev_hash=TXHASH_e5040e, + prev_index=0, + ) + + out1 = messages.TxOutputType( + address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx", + amount=30090000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + out2 = messages.TxOutputType( + address_n=parse_path("44'/1'/0'/1/0"), + amount=900000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + 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: + msg.tx.outputs[0].address_n = [] + msg.tx.outputs[0].address = "mwue7mokpBRAsJtHqEMcRPanYBmsSmYKvY" + + return msg + + with client, pytest.raises( + TrezorFailure, match="Transaction has changed during signing" + ): + # Set up attack processors + client.set_filter(messages.TxAck, attack_processor) + + btc.sign_tx(client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET) + + +def test_attack_change_input_address(client): + inp1 = messages.TxInputType( + address_n=parse_path("44'/1'/4'/0/0"), + # moUJnmge8SRXuediK7bW6t4YfrPqbE6hD7 + prev_hash=TXHASH_d2dcda, + amount=123400000, + prev_index=1, + script_type=messages.InputScriptType.SPENDADDRESS, + ) + + out1 = messages.TxOutputType( + address="mwue7mokpBRAsJtHqEMcRPanYBmsSmYKvY", + amount=100000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + out2 = messages.TxOutputType( + address_n=parse_path("44'/1'/4'/1/0"), + amount=123400000 - 5000 - 100000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + # Test if the transaction can be signed normally + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET + ) + + assert ( + serialized_tx.hex() + == "0100000001243e15b53cc553d93ec4e27e16984adc3d885ef107c613a7577fea47f5dadcd2010000006b483045022100eedaadde3a771967beee39f1daa9e9450f72fccdec63488a96d71eeae4224b4002203a22be3c1677d3451c93a49550b69e8f8fc06328823c7e0f633dde13d67ef96b01210364430c9122948e525e2f1c6d88f00f47679274f0810fd8c63754954f310995c1ffffffff02a0860100000000001976a914b3cc67f3349974d0f1b50e9bb5dfdf226f888fa088ac18555907000000001976a914f80fb232a1e54b1fa732bc120cae72eabd7fcf6888ac00000000" + ) + + attack_count = 2 + + def attack_processor(msg): + nonlocal attack_count + if msg.tx.inputs and msg.tx.inputs[0] == inp1: + if attack_count > 0: + attack_count -= 1 + else: + msg.tx.inputs[0].address_n[2] = H_(12) + + return msg + + # Now run the attack, must trigger the exception + with client: + client.set_filter(messages.TxAck, attack_processor) + 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(TXHASH_d2dcda), + request_input(0, TXHASH_d2dcda), + request_output(0, TXHASH_d2dcda), + request_output(1, TXHASH_d2dcda), + request_input(0), + messages.Failure(code=messages.FailureType.ProcessError), + ] ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - messages.ButtonRequest(code=B.ConfirmOutput), - messages.Failure(code=messages.FailureType.NotEnoughFunds), - ] - ) - with pytest.raises(TrezorFailure, match="NotEnoughFunds"): - btc.sign_tx( - client, "Bitcoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET - ) - - 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 + # Now run the attack, must trigger the exception + with pytest.raises(TrezorFailure) as exc: + btc.sign_tx( + client, + "Testnet", + [inp1], + [out1, out2], + prev_txes=TX_CACHE_TESTNET, ) - assert ( - tx_hash(serialized_tx).hex() - == "5042aed319b9f018d693dbf8f3db926ee4ab4dae670a2911625b440a1366f79d" - ) + assert exc.value.code == messages.FailureType.ProcessError + assert exc.value.message.endswith("Transaction has changed during signing") - def test_testnet_big_amount(self, client): - # This test is testing transaction with amount bigger than fits to uint32 - # tx: 2bac7ad1dec654579a71ea9555463f63ac7b7df9d8ba67b4682bba4e514d0f0c:1 - # input 1: 411102528330 Satoshi +def test_spend_coinbase(client): + inp1 = messages.TxInputType( + address_n=parse_path("44h/1h/0h/0/0"), + amount=2500278230, + prev_hash=TXHASH_d6da21, + prev_index=0, + ) - inp1 = messages.TxInputType( - address_n=parse_path("m/44'/1'/0'/0/0"), - amount=411102528330, - prev_hash=TXHASH_2bac7a, - prev_index=1, - ) - out1 = messages.TxOutputType( - address="mopZWqZZyQc3F2Sy33cvDtJchSAMsnLi7b", # seed allallall, bip32: m/44'/1'/0'/0/1 - amount=411102528330, - script_type=messages.OutputScriptType.PAYTOADDRESS, + 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 ) - assert ( - serialized_tx.hex() - == "01000000010c0f4d514eba2b68b467bad8f97d7bac633f465595ea719a5754c6ded17aac2b010000006b4830450221008e3b926f04d8830bd5b67698af25c9e00c9db1b1ef3e5d69af794446753da94a02202d4a7509f26bba29ff643a7ac0d43fb128c1a632cc502b8f44eada8930fb9c9b0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff014ac39eb75f0000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000" - ) - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - 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 - - with client, pytest.raises( - TrezorFailure, match="Transaction has changed during signing" - ): - # Set up attack processors - client.set_filter(messages.TxAck, attack_processor) - - btc.sign_tx( - client, - "Bitcoin", - [inp1, inp2], - [out1, out2], - prev_txes=TX_CACHE_MAINNET, - ) - - # Ensure that if the change output is modified after the user confirms the - # transaction, then signing fails. - def test_attack_modify_change_address(self, client): - # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56 - - # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd - # input 0: 0.31 BTC - inp1 = messages.TxInputType( - address_n=parse_path("44'/1'/0'/0/0"), - amount=31000000, - prev_hash=TXHASH_e5040e, - prev_index=0, - ) - - out1 = messages.TxOutputType( - address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx", - amount=30090000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - out2 = messages.TxOutputType( - address_n=parse_path("44'/1'/0'/1/0"), - amount=900000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - 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: - msg.tx.outputs[0].address_n = [] - msg.tx.outputs[0].address = "mwue7mokpBRAsJtHqEMcRPanYBmsSmYKvY" - - return msg - - with client, pytest.raises( - TrezorFailure, match="Transaction has changed during signing" - ): - # Set up attack processors - client.set_filter(messages.TxAck, attack_processor) - - btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET - ) - - def test_attack_change_input_address(self, client): - inp1 = messages.TxInputType( - address_n=parse_path("44'/1'/4'/0/0"), - # moUJnmge8SRXuediK7bW6t4YfrPqbE6hD7 - prev_hash=TXHASH_d2dcda, - amount=123400000, - prev_index=1, - script_type=messages.InputScriptType.SPENDADDRESS, - ) - - out1 = messages.TxOutputType( - address="mwue7mokpBRAsJtHqEMcRPanYBmsSmYKvY", - amount=100000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - out2 = messages.TxOutputType( - address_n=parse_path("44'/1'/4'/1/0"), - amount=123400000 - 5000 - 100000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - # Test if the transaction can be signed normally - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET - ) - - assert ( - serialized_tx.hex() - == "0100000001243e15b53cc553d93ec4e27e16984adc3d885ef107c613a7577fea47f5dadcd2010000006b483045022100eedaadde3a771967beee39f1daa9e9450f72fccdec63488a96d71eeae4224b4002203a22be3c1677d3451c93a49550b69e8f8fc06328823c7e0f633dde13d67ef96b01210364430c9122948e525e2f1c6d88f00f47679274f0810fd8c63754954f310995c1ffffffff02a0860100000000001976a914b3cc67f3349974d0f1b50e9bb5dfdf226f888fa088ac18555907000000001976a914f80fb232a1e54b1fa732bc120cae72eabd7fcf6888ac00000000" - ) - - attack_count = 2 - - def attack_processor(msg): - nonlocal attack_count - if msg.tx.inputs and msg.tx.inputs[0] == inp1: - if attack_count > 0: - attack_count -= 1 - else: - msg.tx.inputs[0].address_n[2] = H_(12) - - return msg - - # Now run the attack, must trigger the exception - with client: - client.set_filter(messages.TxAck, attack_processor) - 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(TXHASH_d2dcda), - request_input(0, TXHASH_d2dcda), - request_output(0, TXHASH_d2dcda), - request_output(1, TXHASH_d2dcda), - request_input(0), - messages.Failure(code=messages.FailureType.ProcessError), - ] - ) - # Now run the attack, must trigger the exception - with pytest.raises(TrezorFailure) as exc: - btc.sign_tx( - client, - "Testnet", - [inp1], - [out1, out2], - prev_txes=TX_CACHE_TESTNET, - ) - - assert exc.value.code == messages.FailureType.ProcessError - assert exc.value.message.endswith("Transaction has changed during signing") - - 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_two_changes(self, client): - # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56 - - # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd - # input 0: 0.31 BTC - inp1 = messages.TxInputType( - address_n=parse_path("44'/1'/0'/0/0"), - amount=31000000, - prev_hash=TXHASH_e5040e, - prev_index=0, - ) - - out1 = messages.TxOutputType( - address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx", - amount=30090000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - out_change1 = messages.TxOutputType( - address_n=parse_path("44'/1'/0'/1/0"), - amount=900000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - out_change2 = messages.TxOutputType( - address_n=parse_path("44'/1'/0'/1/1"), - amount=10000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - messages.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - request_output(2), - messages.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_e5040e), - request_input(0, TXHASH_e5040e), - request_output(0, TXHASH_e5040e), - request_output(1, TXHASH_e5040e), - request_input(0), - request_output(0), - request_output(1), - request_output(2), - request_output(0), - request_output(1), - request_output(2), - request_finished(), - ] - ) - - btc.sign_tx( - client, - "Testnet", - [inp1], - [out1, out_change1, out_change2], - prev_txes=TX_CACHE_TESTNET, - ) - - def test_change_on_main_chain_allowed(self, client): - # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56 - - # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd - # input 0: 0.31 BTC - inp1 = messages.TxInputType( - address_n=parse_path("44'/1'/0'/0/0"), - amount=31000000, - prev_hash=TXHASH_e5040e, - prev_index=0, - ) - - out1 = messages.TxOutputType( - address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx", - amount=30090000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - # change on main chain is allowed => treated as a change - out_change = messages.TxOutputType( - address_n=parse_path("44'/1'/0'/0/0"), - amount=900000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - 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(TXHASH_e5040e), - request_input(0, TXHASH_e5040e), - request_output(0, TXHASH_e5040e), - request_output(1, TXHASH_e5040e), - request_input(0), - request_output(0), - request_output(1), - request_output(0), - request_output(1), - request_finished(), - ] - ) - - btc.sign_tx( - client, - "Testnet", - [inp1], - [out1, out_change], - prev_txes=TX_CACHE_TESTNET, - ) - - def test_not_enough_vouts(self, client): - prev_tx = TX_CACHE_MAINNET[TXHASH_157041] - - # tx has two vouts - assert len(prev_tx.bin_outputs) == 2 - - # vout[0] and vout[1] exist - inp0 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - prev_hash=TXHASH_157041, - amount=100000000, - prev_index=0, - ) - inp1 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/1"), - prev_hash=TXHASH_157041, - amount=120160000, - prev_index=1, - ) - # vout[2] does not exist - inp2 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/1/0"), - prev_hash=TXHASH_157041, - amount=100000000, - prev_index=2, - ) - - # try to spend the sum of existing vouts - out1 = messages.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=100000000 + 120160000 + 100000000 - 10000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - with pytest.raises( - TrezorFailure, match="Not enough outputs in previous transaction." - ): - btc.sign_tx( - client, - "Bitcoin", - [inp0, inp1, inp2], - [out1], - prev_txes=TX_CACHE_MAINNET, - ) - - @pytest.mark.parametrize( - "field, value", - ( - ("extra_data", b"hello world"), - ("expiry", 9), - ("timestamp", 42), - ("version_group_id", 69), - ("branch_id", 13), - ), + # Accepted by network: tx + assert ( + tx_hash(serialized_tx).hex() + == "cf5a8ad5a4f0211953e0d40d9145d6651f0d90203e52913e780065bd00840da3" ) - def test_prevtx_forbidden_fields(self, client, field, value): - inp0 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - prev_hash=TXHASH_157041, - amount=100000000, - prev_index=0, - ) - out1 = messages.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=100000000 - 1000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - prev_tx = TX_CACHE_MAINNET[TXHASH_157041] - setattr(prev_tx, field, value) - name = field.replace("_", " ") - with pytest.raises( - TrezorFailure, match=rf"(?i){name} not enabled on this coin" - ): - btc.sign_tx( - client, "Bitcoin", [inp0], [out1], prev_txes={TXHASH_157041: prev_tx} - ) - @pytest.mark.parametrize( - "field, value", - (("expiry", 9), ("timestamp", 42), ("version_group_id", 69), ("branch_id", 13)), +def test_two_changes(client): + # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56 + + # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd + # input 0: 0.31 BTC + inp1 = messages.TxInputType( + address_n=parse_path("44'/1'/0'/0/0"), + amount=31000000, + prev_hash=TXHASH_e5040e, + prev_index=0, ) - def test_signtx_forbidden_fields(self, client, field, value): - inp0 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - prev_hash=TXHASH_157041, - amount=100000000, - prev_index=0, - ) - out1 = messages.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=1000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - kwargs = {field: value} - name = field.replace("_", " ") - with pytest.raises( - TrezorFailure, match=rf"(?i){name} not enabled on this coin" - ): - btc.sign_tx( - client, "Bitcoin", [inp0], [out1], prev_txes=TX_CACHE_MAINNET, **kwargs - ) - - @pytest.mark.parametrize( - "script_type", - (messages.InputScriptType.SPENDADDRESS, messages.InputScriptType.EXTERNAL), + out1 = messages.TxOutputType( + address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx", + amount=30090000, + script_type=messages.OutputScriptType.PAYTOADDRESS, ) - def test_incorrect_input_script_type(self, client, script_type): - address_n = parse_path("44'/1'/0'/0/0") - attacker_multisig_public_key = bytes.fromhex( - "030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" - ) - multisig = messages.MultisigRedeemScriptType( - m=1, - nodes=[ - btc.get_public_node(client, address_n, coin_name="Testnet").node, - messages.HDNodeType( - depth=0, - fingerprint=0, - child_num=0, - chain_code=bytes(32), - public_key=attacker_multisig_public_key, - ), - ], - address_n=[], - ) - inp1 = messages.TxInputType( - address_n=address_n, - amount=142920000, - prev_index=1, - sequence=0xFFFFFFFF, - script_type=script_type, # incorrect script type - multisig=multisig, - prev_hash=TXHASH_e5040e, - ) - out1 = messages.TxOutputType( - address_n=address_n, - amount=1000000 - 50000 - 10000, - script_type=messages.OutputScriptType.PAYTOMULTISIG, - multisig=multisig, - ) - out2 = messages.TxOutputType( - address="mtkyndbpgv1G7nwggwKDVagRpxEJrwwyh6", - amount=50000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - with pytest.raises( - TrezorFailure, match="Multisig field provided but not expected." - ): - btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET - ) - - @pytest.mark.parametrize( - "script_type", - ( - messages.OutputScriptType.PAYTOADDRESS, - messages.OutputScriptType.PAYTOSCRIPTHASH, - ), + out_change1 = messages.TxOutputType( + address_n=parse_path("44'/1'/0'/1/0"), + amount=900000, + script_type=messages.OutputScriptType.PAYTOADDRESS, ) - def test_incorrect_output_script_type(self, client, script_type): - address_n = parse_path("44'/1'/0'/0/0") - attacker_multisig_public_key = bytes.fromhex( - "030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" - ) - multisig = messages.MultisigRedeemScriptType( - m=1, - nodes=[ - btc.get_public_node(client, address_n, coin_name="Testnet").node, - messages.HDNodeType( - depth=0, - fingerprint=0, - child_num=0, - chain_code=bytes(32), - public_key=attacker_multisig_public_key, - ), - ], - address_n=[], - ) - inp1 = messages.TxInputType( - address_n=address_n, - amount=142920000, - prev_index=1, - sequence=0xFFFFFFFF, - script_type=messages.InputScriptType.SPENDADDRESS, - prev_hash=TXHASH_e5040e, - ) - out1 = messages.TxOutputType( - address_n=address_n, - amount=1000000 - 50000 - 10000, - script_type=script_type, # incorrect script type - multisig=multisig, - ) - out2 = messages.TxOutputType( - address="mtkyndbpgv1G7nwggwKDVagRpxEJrwwyh6", - amount=50000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - with pytest.raises( - TrezorFailure, match="Multisig field provided but not expected." - ): - btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET - ) - - @pytest.mark.parametrize( - "lock_time, sequence", - ((499999999, 0xFFFFFFFE), (500000000, 0xFFFFFFFE), (1, 0xFFFFFFFF)), + out_change2 = messages.TxOutputType( + address_n=parse_path("44'/1'/0'/1/1"), + amount=10000, + script_type=messages.OutputScriptType.PAYTOADDRESS, ) - def test_lock_time(self, client, lock_time, sequence): - # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 - # input 0: 0.0039 BTC - inp1 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - amount=390000, - prev_hash=TXHASH_d5f65e, - prev_index=0, - sequence=sequence, + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + messages.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + request_output(2), + messages.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_e5040e), + request_input(0, TXHASH_e5040e), + request_output(0, TXHASH_e5040e), + request_output(1, TXHASH_e5040e), + request_input(0), + request_output(0), + request_output(1), + request_output(2), + request_output(0), + request_output(1), + request_output(2), + request_finished(), + ] ) - out1 = messages.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=390000 - 10000, - script_type=messages.OutputScriptType.PAYTOADDRESS, + btc.sign_tx( + client, + "Testnet", + [inp1], + [out1, out_change1, out_change2], + prev_txes=TX_CACHE_TESTNET, ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - messages.ButtonRequest(code=B.ConfirmOutput), - messages.ButtonRequest(code=B.SignTx), - messages.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_d5f65e), - request_input(0, TXHASH_d5f65e), - request_input(1, TXHASH_d5f65e), - request_output(0, TXHASH_d5f65e), - request_input(0), - request_output(0), - request_output(0), - request_finished(), - ] - ) - btc.sign_tx( - client, - "Bitcoin", - [inp1], - [out1], - lock_time=lock_time, - prev_txes=TX_CACHE_MAINNET, - ) +def test_change_on_main_chain_allowed(client): + # see 87be0736f202f7c2bff0781b42bad3e0cdcb54761939da69ea793a3735552c56 - @pytest.mark.skip_t1(reason="Cannot test layouts on T1") - def test_lock_time_blockheight(self, client): - # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 - # input 0: 0.0039 BTC - - inp1 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - amount=390000, - prev_hash=TXHASH_d5f65e, - prev_index=0, - sequence=0xFFFF_FFFE, - ) - - out1 = messages.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=390000 - 10000, - script_type=messages.OutputScriptType.PAYTOADDRESS, - ) - - def input_flow(): - yield # confirm output - client.debug.wait_layout() - client.debug.press_yes() - - yield # confirm locktime - layout = client.debug.wait_layout() - assert "blockheight" in layout.text - assert "499999999" in layout.text - client.debug.press_yes() - - yield # confirm transaction - client.debug.press_yes() - - with client: - client.set_input_flow(input_flow) - client.watch_layout(True) - - btc.sign_tx( - client, - "Bitcoin", - [inp1], - [out1], - lock_time=499999999, - prev_txes=TX_CACHE_MAINNET, - ) - - @pytest.mark.skip_t1(reason="Cannot test layouts on T1") - @pytest.mark.parametrize( - "lock_time_str", ("1985-11-05 00:53:20", "2048-08-16 22:14:00") + # tx: e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd + # input 0: 0.31 BTC + inp1 = messages.TxInputType( + address_n=parse_path("44'/1'/0'/0/0"), + amount=31000000, + prev_hash=TXHASH_e5040e, + prev_index=0, ) - def test_lock_time_datetime(self, client, lock_time_str): - # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 - # input 0: 0.0039 BTC - inp1 = messages.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - amount=390000, - prev_hash=TXHASH_d5f65e, - prev_index=0, - sequence=0xFFFF_FFFE, + out1 = messages.TxOutputType( + address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx", + amount=30090000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + # change on main chain is allowed => treated as a change + out_change = messages.TxOutputType( + address_n=parse_path("44'/1'/0'/0/0"), + amount=900000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + 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(TXHASH_e5040e), + request_input(0, TXHASH_e5040e), + request_output(0, TXHASH_e5040e), + request_output(1, TXHASH_e5040e), + request_input(0), + request_output(0), + request_output(1), + request_output(0), + request_output(1), + request_finished(), + ] ) - out1 = messages.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=390000 - 10000, - script_type=messages.OutputScriptType.PAYTOADDRESS, + btc.sign_tx( + client, + "Testnet", + [inp1], + [out1, out_change], + prev_txes=TX_CACHE_TESTNET, ) - def input_flow(): - yield # confirm output - client.debug.wait_layout() - client.debug.press_yes() - yield # confirm locktime - layout = client.debug.wait_layout() - assert lock_time_str in layout.text +def test_not_enough_vouts(client): + prev_tx = TX_CACHE_MAINNET[TXHASH_157041] - client.debug.press_yes() + # tx has two vouts + assert len(prev_tx.bin_outputs) == 2 - yield # confirm transaction - client.debug.press_yes() + # vout[0] and vout[1] exist + inp0 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + prev_hash=TXHASH_157041, + amount=100000000, + prev_index=0, + ) + inp1 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/1"), + prev_hash=TXHASH_157041, + amount=120160000, + prev_index=1, + ) + # vout[2] does not exist + inp2 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/1/0"), + prev_hash=TXHASH_157041, + amount=100000000, + prev_index=2, + ) - lock_time_naive = datetime.strptime(lock_time_str, "%Y-%m-%d %H:%M:%S") - lock_time_utc = lock_time_naive.replace(tzinfo=timezone.utc) - lock_time_timestamp = int(lock_time_utc.timestamp()) + # try to spend the sum of existing vouts + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=100000000 + 120160000 + 100000000 - 10000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) - with client: - client.set_input_flow(input_flow) - client.watch_layout(True) + with pytest.raises( + TrezorFailure, match="Not enough outputs in previous transaction." + ): + btc.sign_tx( + client, + "Bitcoin", + [inp0, inp1, inp2], + [out1], + prev_txes=TX_CACHE_MAINNET, + ) - btc.sign_tx( - client, - "Bitcoin", - [inp1], - [out1], - lock_time=lock_time_timestamp, - prev_txes=TX_CACHE_MAINNET, - ) + +@pytest.mark.parametrize( + "field, value", + ( + ("extra_data", b"hello world"), + ("expiry", 9), + ("timestamp", 42), + ("version_group_id", 69), + ("branch_id", 13), + ), +) +def test_prevtx_forbidden_fields(client, field, value): + inp0 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + prev_hash=TXHASH_157041, + amount=100000000, + prev_index=0, + ) + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=100000000 - 1000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + prev_tx = TX_CACHE_MAINNET[TXHASH_157041] + setattr(prev_tx, field, value) + name = field.replace("_", " ") + with pytest.raises(TrezorFailure, match=rf"(?i){name} not enabled on this coin"): + btc.sign_tx( + client, "Bitcoin", [inp0], [out1], prev_txes={TXHASH_157041: prev_tx} + ) + + +@pytest.mark.parametrize( + "field, value", + (("expiry", 9), ("timestamp", 42), ("version_group_id", 69), ("branch_id", 13)), +) +def test_signtx_forbidden_fields(client, field, value): + inp0 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + prev_hash=TXHASH_157041, + amount=100000000, + prev_index=0, + ) + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=1000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + kwargs = {field: value} + name = field.replace("_", " ") + with pytest.raises(TrezorFailure, match=rf"(?i){name} not enabled on this coin"): + btc.sign_tx( + client, "Bitcoin", [inp0], [out1], prev_txes=TX_CACHE_MAINNET, **kwargs + ) + + +@pytest.mark.parametrize( + "script_type", + (messages.InputScriptType.SPENDADDRESS, messages.InputScriptType.EXTERNAL), +) +def test_incorrect_input_script_type(client, script_type): + address_n = parse_path("44'/1'/0'/0/0") + attacker_multisig_public_key = bytes.fromhex( + "030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" + ) + + multisig = messages.MultisigRedeemScriptType( + m=1, + nodes=[ + btc.get_public_node(client, address_n, coin_name="Testnet").node, + messages.HDNodeType( + depth=0, + fingerprint=0, + child_num=0, + chain_code=bytes(32), + public_key=attacker_multisig_public_key, + ), + ], + address_n=[], + ) + inp1 = messages.TxInputType( + address_n=address_n, + amount=142920000, + prev_index=1, + sequence=0xFFFFFFFF, + script_type=script_type, # incorrect script type + multisig=multisig, + prev_hash=TXHASH_e5040e, + ) + out1 = messages.TxOutputType( + address_n=address_n, + amount=1000000 - 50000 - 10000, + script_type=messages.OutputScriptType.PAYTOMULTISIG, + multisig=multisig, + ) + out2 = messages.TxOutputType( + address="mtkyndbpgv1G7nwggwKDVagRpxEJrwwyh6", + amount=50000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + with pytest.raises( + TrezorFailure, match="Multisig field provided but not expected." + ): + btc.sign_tx(client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET) + + +@pytest.mark.parametrize( + "script_type", + ( + messages.OutputScriptType.PAYTOADDRESS, + messages.OutputScriptType.PAYTOSCRIPTHASH, + ), +) +def test_incorrect_output_script_type(client, script_type): + address_n = parse_path("44'/1'/0'/0/0") + attacker_multisig_public_key = bytes.fromhex( + "030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" + ) + + multisig = messages.MultisigRedeemScriptType( + m=1, + nodes=[ + btc.get_public_node(client, address_n, coin_name="Testnet").node, + messages.HDNodeType( + depth=0, + fingerprint=0, + child_num=0, + chain_code=bytes(32), + public_key=attacker_multisig_public_key, + ), + ], + address_n=[], + ) + inp1 = messages.TxInputType( + address_n=address_n, + amount=142920000, + prev_index=1, + sequence=0xFFFFFFFF, + script_type=messages.InputScriptType.SPENDADDRESS, + prev_hash=TXHASH_e5040e, + ) + out1 = messages.TxOutputType( + address_n=address_n, + amount=1000000 - 50000 - 10000, + script_type=script_type, # incorrect script type + multisig=multisig, + ) + out2 = messages.TxOutputType( + address="mtkyndbpgv1G7nwggwKDVagRpxEJrwwyh6", + amount=50000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + with pytest.raises( + TrezorFailure, match="Multisig field provided but not expected." + ): + btc.sign_tx(client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET) + + +@pytest.mark.parametrize( + "lock_time, sequence", + ((499999999, 0xFFFFFFFE), (500000000, 0xFFFFFFFE), (1, 0xFFFFFFFF)), +) +def test_lock_time(client, lock_time, sequence): + # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 + # input 0: 0.0039 BTC + + inp1 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + amount=390000, + prev_hash=TXHASH_d5f65e, + prev_index=0, + sequence=sequence, + ) + + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=390000 - 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), + messages.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_d5f65e), + request_input(0, TXHASH_d5f65e), + request_input(1, TXHASH_d5f65e), + request_output(0, TXHASH_d5f65e), + request_input(0), + request_output(0), + request_output(0), + request_finished(), + ] + ) + + btc.sign_tx( + client, + "Bitcoin", + [inp1], + [out1], + lock_time=lock_time, + prev_txes=TX_CACHE_MAINNET, + ) + + +@pytest.mark.skip_t1(reason="Cannot test layouts on T1") +def test_lock_time_blockheight(client): + # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 + # input 0: 0.0039 BTC + + inp1 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + amount=390000, + prev_hash=TXHASH_d5f65e, + prev_index=0, + sequence=0xFFFF_FFFE, + ) + + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=390000 - 10000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + def input_flow(): + yield # confirm output + client.debug.wait_layout() + client.debug.press_yes() + + yield # confirm locktime + layout = client.debug.wait_layout() + assert "blockheight" in layout.text + assert "499999999" in layout.text + client.debug.press_yes() + + yield # confirm transaction + client.debug.press_yes() + + with client: + client.set_input_flow(input_flow) + client.watch_layout(True) + + btc.sign_tx( + client, + "Bitcoin", + [inp1], + [out1], + lock_time=499999999, + prev_txes=TX_CACHE_MAINNET, + ) + + +@pytest.mark.skip_t1(reason="Cannot test layouts on T1") +@pytest.mark.parametrize( + "lock_time_str", ("1985-11-05 00:53:20", "2048-08-16 22:14:00") +) +def test_lock_time_datetime(client, lock_time_str): + # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 + # input 0: 0.0039 BTC + + inp1 = messages.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + amount=390000, + prev_hash=TXHASH_d5f65e, + prev_index=0, + sequence=0xFFFF_FFFE, + ) + + out1 = messages.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=390000 - 10000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + def input_flow(): + yield # confirm output + client.debug.wait_layout() + client.debug.press_yes() + + yield # confirm locktime + layout = client.debug.wait_layout() + assert lock_time_str in layout.text + + client.debug.press_yes() + + yield # confirm transaction + client.debug.press_yes() + + lock_time_naive = datetime.strptime(lock_time_str, "%Y-%m-%d %H:%M:%S") + lock_time_utc = lock_time_naive.replace(tzinfo=timezone.utc) + lock_time_timestamp = int(lock_time_utc.timestamp()) + + with client: + client.set_input_flow(input_flow) + client.watch_layout(True) + + btc.sign_tx( + client, + "Bitcoin", + [inp1], + [out1], + lock_time=lock_time_timestamp, + prev_txes=TX_CACHE_MAINNET, + ) diff --git a/tests/device_tests/test_msg_signtx_bcash.py b/tests/device_tests/test_msg_signtx_bcash.py index 6a90d50154..a3554cb0c4 100644 --- a/tests/device_tests/test_msg_signtx_bcash.py +++ b/tests/device_tests/test_msg_signtx_bcash.py @@ -39,459 +39,465 @@ TXHASH_8b6db9 = bytes.fromhex( "8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0" ) +pytestmark = pytest.mark.altcoin -@pytest.mark.altcoin -class TestMsgSigntxBch: - def test_send_bch_change(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/145'/0'/0/0"), - # bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv - amount=1995344, - prev_hash=TXHASH_bc37c2, - 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 client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_bc37c2), - request_input(0, TXHASH_bc37c2), - request_output(0, TXHASH_bc37c2), - request_input(0), - request_output(0), - request_output(1), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API - ) - assert ( - serialized_tx.hex() - == "0100000001781a716b1e15b41b07157933e5d777392a75bf87132650cb2e7d46fb8dc237bc000000006a473044022061aee4f17abe044d5df8c52c9ffd3b84e5a29743517e488b20ecf1ae0b3e4d3a02206bb84c55e407f3b684ff8d9bea0a3409cfd865795a19d10b3d3c31f12795c34a412103a020b36130021a0f037c1d1a02042e325c0cb666d6478c1afdcd9d913b9ef080ffffffff0272ee1c00000000001976a914b1401fce7e8bf123c88a0467e0ed11e3b9fbef5488acec1e0100000000001976a914d51eca49695cdf47e7f4b55507893e3ad53fe9d888ac00000000" +def test_send_bch_change(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/145'/0'/0/0"), + # bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv + amount=1995344, + prev_hash=TXHASH_bc37c2, + 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 client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_bc37c2), + request_input(0, TXHASH_bc37c2), + request_output(0, TXHASH_bc37c2), + request_input(0), + request_output(0), + request_output(1), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_bch_nochange(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/145'/0'/1/0"), - # bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw - amount=1896050, - prev_hash=TXHASH_502e85, - 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=TXHASH_502e85, - prev_index=1, - script_type=proto.InputScriptType.SPENDADDRESS, - ) - out1 = proto.TxOutputType( - address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4", - amount=1934960, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_input(1), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_502e85), - request_input(0, TXHASH_502e85), - request_output(0, TXHASH_502e85), - request_output(1, TXHASH_502e85), - request_input(1), - request_meta(TXHASH_502e85), - request_input(0, TXHASH_502e85), - request_output(0, TXHASH_502e85), - request_output(1, TXHASH_502e85), - request_input(0), - request_input(1), - request_output(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API - ) + assert ( + serialized_tx.hex() + == "0100000001781a716b1e15b41b07157933e5d777392a75bf87132650cb2e7d46fb8dc237bc000000006a473044022061aee4f17abe044d5df8c52c9ffd3b84e5a29743517e488b20ecf1ae0b3e4d3a02206bb84c55e407f3b684ff8d9bea0a3409cfd865795a19d10b3d3c31f12795c34a412103a020b36130021a0f037c1d1a02042e325c0cb666d6478c1afdcd9d913b9ef080ffffffff0272ee1c00000000001976a914b1401fce7e8bf123c88a0467e0ed11e3b9fbef5488acec1e0100000000001976a914d51eca49695cdf47e7f4b55507893e3ad53fe9d888ac00000000" + ) - assert ( - serialized_tx.hex() - == "01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000" + +def test_send_bch_nochange(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/145'/0'/1/0"), + # bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw + amount=1896050, + prev_hash=TXHASH_502e85, + 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=TXHASH_502e85, + prev_index=1, + script_type=proto.InputScriptType.SPENDADDRESS, + ) + out1 = proto.TxOutputType( + address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4", + amount=1934960, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_input(1), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_502e85), + request_input(0, TXHASH_502e85), + request_output(0, TXHASH_502e85), + request_output(1, TXHASH_502e85), + request_input(1), + request_meta(TXHASH_502e85), + request_input(0, TXHASH_502e85), + request_output(0, TXHASH_502e85), + request_output(1, TXHASH_502e85), + request_input(0), + request_input(1), + request_output(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API ) - def test_send_bch_oldaddr(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/145'/0'/1/0"), - # bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw - amount=1896050, - prev_hash=TXHASH_502e85, - 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=TXHASH_502e85, - prev_index=1, - script_type=proto.InputScriptType.SPENDADDRESS, - ) - out1 = proto.TxOutputType( - address="15pnEDZJo3ycPUamqP3tEDnEju1oW5fBCz", - amount=1934960, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_input(1), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_502e85), - request_input(0, TXHASH_502e85), - request_output(0, TXHASH_502e85), - request_output(1, TXHASH_502e85), - request_input(1), - request_meta(TXHASH_502e85), - request_input(0, TXHASH_502e85), - request_output(0, TXHASH_502e85), - request_output(1, TXHASH_502e85), - request_input(0), - request_input(1), - request_output(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API - ) + assert ( + serialized_tx.hex() + == "01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000" + ) - assert ( - serialized_tx.hex() - == "01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000" + +def test_send_bch_oldaddr(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/145'/0'/1/0"), + # bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw + amount=1896050, + prev_hash=TXHASH_502e85, + 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=TXHASH_502e85, + prev_index=1, + script_type=proto.InputScriptType.SPENDADDRESS, + ) + out1 = proto.TxOutputType( + address="15pnEDZJo3ycPUamqP3tEDnEju1oW5fBCz", + amount=1934960, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_input(1), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_502e85), + request_input(0, TXHASH_502e85), + request_output(0, TXHASH_502e85), + request_output(1, TXHASH_502e85), + request_input(1), + request_meta(TXHASH_502e85), + request_input(0, TXHASH_502e85), + request_output(0, TXHASH_502e85), + request_output(1, TXHASH_502e85), + request_input(0), + request_input(1), + request_output(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API ) - def test_attack_change_input(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/145'/10'/0/0"), - amount=1995344, - prev_hash=TXHASH_bc37c2, - prev_index=0, - script_type=proto.InputScriptType.SPENDADDRESS, + assert ( + serialized_tx.hex() + == "01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000" + ) + + +def test_attack_change_input(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/145'/10'/0/0"), + amount=1995344, + prev_hash=TXHASH_bc37c2, + 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, + ) + + attack_count = 2 + + def attack_processor(msg): + nonlocal attack_count + + if msg.tx.inputs and msg.tx.inputs[0] == inp1: + if attack_count > 0: + attack_count -= 1 + else: + msg.tx.inputs[0].address_n[2] = H_(1) + + return msg + + with client: + client.set_filter(proto.TxAck, attack_processor) + client.set_expected_responses( + [ + request_input(0), + request_output(0), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_bc37c2), + request_input(0, TXHASH_bc37c2), + request_output(0, TXHASH_bc37c2), + request_input(0), + proto.Failure(code=proto.FailureType.ProcessError), + ] ) - 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, + with pytest.raises(TrezorFailure): + btc.sign_tx(client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API) + + +@pytest.mark.multisig +def test_send_bch_multisig_wrongchange(client): + nodes = [ + btc.get_public_node( + client, parse_path(f"48'/145'/{i}'/0'"), coin_name="Bcash" + ).node + for i in range(1, 4) + ] + + def getmultisig(chain, nr, signatures): + return proto.MultisigRedeemScriptType( + nodes=nodes, address_n=[chain, nr], signatures=signatures, m=2 ) - attack_count = 2 - - def attack_processor(msg): - nonlocal attack_count - - if msg.tx.inputs and msg.tx.inputs[0] == inp1: - if attack_count > 0: - attack_count -= 1 - else: - msg.tx.inputs[0].address_n[2] = H_(1) - - return msg - - with client: - client.set_filter(proto.TxAck, attack_processor) - client.set_expected_responses( - [ - request_input(0), - request_output(0), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_bc37c2), - request_input(0, TXHASH_bc37c2), - request_output(0, TXHASH_bc37c2), - request_input(0), - proto.Failure(code=proto.FailureType.ProcessError), - ] - ) - with pytest.raises(TrezorFailure): - btc.sign_tx(client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API) - - @pytest.mark.multisig - def test_send_bch_multisig_wrongchange(self, client): - nodes = [ - btc.get_public_node( - client, parse_path(f"48'/145'/{i}'/0'"), coin_name="Bcash" - ).node - for i in range(1, 4) - ] - - def getmultisig(chain, nr, signatures): - 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" - ), + 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'/0'/1/0"), + multisig=getmultisig(1, 0, [b"", sig, b""]), + # bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a + amount=24000, + prev_hash=TXHASH_f68caf, + prev_index=1, + script_type=proto.InputScriptType.SPENDMULTISIG, + ) + out1 = proto.TxOutputType( + address_n=parse_path("48'/145'/1'/0'/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 client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_f68caf), + request_input(0, TXHASH_f68caf), + request_output(0, TXHASH_f68caf), + request_output(1, TXHASH_f68caf), + request_input(0), + request_output(0), + request_finished(), + ] ) - sig = bytes.fromhex( - "304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae" + (signatures1, serialized_tx) = btc.sign_tx( + client, "Bcash", [inp1], [out1], prev_txes=TX_API ) - inp1 = proto.TxInputType( - address_n=parse_path("48'/145'/1'/0'/1/0"), - multisig=getmultisig(1, 0, [b"", sig, b""]), - # bitcoincash:pp6kcpkhua7789g2vyj0qfkcux3yvje7euhyhltn0a - amount=24000, - prev_hash=TXHASH_f68caf, - prev_index=1, - script_type=proto.InputScriptType.SPENDMULTISIG, - ) - out1 = proto.TxOutputType( - address_n=parse_path("48'/145'/1'/0'/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 client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_f68caf), - request_input(0, TXHASH_f68caf), - request_output(0, TXHASH_f68caf), - request_output(1, TXHASH_f68caf), - request_input(0), - request_output(0), - request_finished(), - ] - ) - (signatures1, serialized_tx) = btc.sign_tx( - client, "Bcash", [inp1], [out1], prev_txes=TX_API - ) - assert ( - signatures1[0].hex() - == "304402205ce02f7bf3ef225e4a17e2b5a98dc6ca5536a6b68088f94200390a1d505c4f3e022045657781095e01422736c5541b03b014101d76e54089eda030cb016dfce10e98" - ) - assert ( - serialized_tx.hex() - == "01000000015f3d291cae106548f3be5ed0f4cbedc65668fa881d60347ab0d512df10af8cf601000000fc0047304402205ce02f7bf3ef225e4a17e2b5a98dc6ca5536a6b68088f94200390a1d505c4f3e022045657781095e01422736c5541b03b014101d76e54089eda030cb016dfce10e984147304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae414c69522102962724052105f03332ab700812afc5ca665d264b13339be1fe7f7fdd3a2a685821024364cd1fdc2aa05bc8b09874a57aa1082a47ac9062d35f22ed5f4afefb3f67fc21024d375b44804f3b0c3493ea0806eb25cc85f51e0d616d6bd6e4ef0388e71cd29e53aeffffffff01d85900000000000017a9140d5566bfc721e6c3d5ab583841d387f3939ffed38700000000" + assert ( + signatures1[0].hex() + == "304402205ce02f7bf3ef225e4a17e2b5a98dc6ca5536a6b68088f94200390a1d505c4f3e022045657781095e01422736c5541b03b014101d76e54089eda030cb016dfce10e98" + ) + assert ( + serialized_tx.hex() + == "01000000015f3d291cae106548f3be5ed0f4cbedc65668fa881d60347ab0d512df10af8cf601000000fc0047304402205ce02f7bf3ef225e4a17e2b5a98dc6ca5536a6b68088f94200390a1d505c4f3e022045657781095e01422736c5541b03b014101d76e54089eda030cb016dfce10e984147304402207274b5a4d15e75f3df7319a375557b0efba9b27bc63f9f183a17da95a6125c94022000efac57629f1522e2d3958430e2ef073b0706cfac06cce492651b79858f09ae414c69522102962724052105f03332ab700812afc5ca665d264b13339be1fe7f7fdd3a2a685821024364cd1fdc2aa05bc8b09874a57aa1082a47ac9062d35f22ed5f4afefb3f67fc21024d375b44804f3b0c3493ea0806eb25cc85f51e0d616d6bd6e4ef0388e71cd29e53aeffffffff01d85900000000000017a9140d5566bfc721e6c3d5ab583841d387f3939ffed38700000000" + ) + + +@pytest.mark.multisig +def test_send_bch_multisig_change(client): + nodes = [ + btc.get_public_node( + client, parse_path(f"48'/145'/{i}'/0'"), coin_name="Bcash" + ).node + for i in range(1, 4) + ] + + EMPTY_SIGNATURES = [b"", b"", b""] + + def getmultisig(chain, nr, signatures): + return proto.MultisigRedeemScriptType( + nodes=nodes, address_n=[chain, nr], signatures=signatures, m=2 ) - @pytest.mark.multisig - def test_send_bch_multisig_change(self, client): - nodes = [ - btc.get_public_node( - client, parse_path(f"48'/145'/{i}'/0'"), coin_name="Bcash" - ).node - for i in range(1, 4) - ] - - EMPTY_SIGNATURES = [b"", b"", b""] - - def getmultisig(chain, nr, signatures): - 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/0"), - multisig=getmultisig(0, 0, EMPTY_SIGNATURES), - amount=48490, - prev_hash=TXHASH_8b6db9, - prev_index=0, - script_type=proto.InputScriptType.SPENDMULTISIG, + inp1 = proto.TxInputType( + address_n=parse_path("48'/145'/3'/0'/0/0"), + multisig=getmultisig(0, 0, EMPTY_SIGNATURES), + amount=48490, + prev_hash=TXHASH_8b6db9, + 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'/0'/1/0"), + multisig=getmultisig(1, 0, EMPTY_SIGNATURES), + script_type=proto.OutputScriptType.PAYTOMULTISIG, + amount=24000, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_8b6db9), + request_input(0, TXHASH_8b6db9), + request_output(0, TXHASH_8b6db9), + request_input(0), + request_output(0), + request_output(1), + request_finished(), + ] ) - out1 = proto.TxOutputType( - address="bitcoincash:qqq8gx2j76nw4dfefumxmdwvtf2tpsjznusgsmzex9", - amount=24000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address_n=parse_path("48'/145'/3'/0'/1/0"), - multisig=getmultisig(1, 0, EMPTY_SIGNATURES), - script_type=proto.OutputScriptType.PAYTOMULTISIG, - amount=24000, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_8b6db9), - request_input(0, TXHASH_8b6db9), - request_output(0, TXHASH_8b6db9), - request_input(0), - request_output(0), - request_output(1), - request_finished(), - ] - ) - (signatures1, serialized_tx) = btc.sign_tx( - client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API - ) - - assert ( - signatures1[0].hex() - == "304402202b75dbb307d2556b9a85851d27ab118b3f06344bccb6e21b0a5dfcf74e0e644f02206611c59396d44741d34fd7bb602be06ef91690b22b47c3f3c271e15e20176ac0" + (signatures1, serialized_tx) = btc.sign_tx( + client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API ) - inp1 = proto.TxInputType( - address_n=parse_path("48'/145'/1'/0'/0/0"), - multisig=getmultisig(0, 0, [b"", b"", signatures1[0]]), - # bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw - amount=48490, - prev_hash=TXHASH_8b6db9, - prev_index=0, - script_type=proto.InputScriptType.SPENDMULTISIG, - ) - out2.address_n[2] = H_(1) + assert ( + signatures1[0].hex() + == "304402202b75dbb307d2556b9a85851d27ab118b3f06344bccb6e21b0a5dfcf74e0e644f02206611c59396d44741d34fd7bb602be06ef91690b22b47c3f3c271e15e20176ac0" + ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_8b6db9), - request_input(0, TXHASH_8b6db9), - request_output(0, TXHASH_8b6db9), - request_input(0), - request_output(0), - request_output(1), - request_finished(), - ] - ) - (signatures1, serialized_tx) = btc.sign_tx( - client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API - ) + inp1 = proto.TxInputType( + address_n=parse_path("48'/145'/1'/0'/0/0"), + multisig=getmultisig(0, 0, [b"", b"", signatures1[0]]), + # bitcoincash:pqguz4nqq64jhr5v3kvpq4dsjrkda75hwy86gq0qzw + amount=48490, + prev_hash=TXHASH_8b6db9, + prev_index=0, + script_type=proto.InputScriptType.SPENDMULTISIG, + ) + out2.address_n[2] = H_(1) - assert ( - signatures1[0].hex() - == "3045022100cc12faf18a489d8014e978ef7ca0760aa6487cdb40b49dd991bfe9c66625f5a802206088fef49ecad30679d55eaa870741bbb8b83fac08eb078872ac276c8139015d" + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_8b6db9), + request_input(0, TXHASH_8b6db9), + request_output(0, TXHASH_8b6db9), + request_input(0), + request_output(0), + request_output(1), + request_finished(), + ] ) - assert ( - serialized_tx.hex() - == "0100000001a07660b10df9868df9393c9cf8962bc34f48cb2cea53b0865d2324bab8b96d8b00000000fdfd0000483045022100cc12faf18a489d8014e978ef7ca0760aa6487cdb40b49dd991bfe9c66625f5a802206088fef49ecad30679d55eaa870741bbb8b83fac08eb078872ac276c8139015d4147304402202b75dbb307d2556b9a85851d27ab118b3f06344bccb6e21b0a5dfcf74e0e644f02206611c59396d44741d34fd7bb602be06ef91690b22b47c3f3c271e15e20176ac0414c6952210290cc724ccb90a6c7c1c3b291938449464ea474390183909e51bcd2807ecb779d210222f537684e2933563f737192fbf1947fd9034402e5708d10f6decd8e1f03e172210350df5cb41013d6b06581230556006b0a85ccccd205745cc10c927755193c241b53aeffffffff02c05d0000000000001976a91400741952f6a6eab5394f366db5cc5a54b0c2429f88acc05d00000000000017a914dfc8c2dda26f7151ed7df8aeeca24089e6410fdd8700000000" + (signatures1, serialized_tx) = btc.sign_tx( + client, "Bcash", [inp1], [out1, out2], prev_txes=TX_API ) - @pytest.mark.skip_t1 - def test_send_bch_external_presigned(self, client): - inp1 = proto.TxInputType( - # address_n=parse_path("44'/145'/0'/1/0"), - # bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw - amount=1896050, - prev_hash=TXHASH_502e85, - prev_index=0, - script_type=proto.InputScriptType.EXTERNAL, - script_pubkey=bytes.fromhex( - "76a914b1401fce7e8bf123c88a0467e0ed11e3b9fbef5488ac" - ), - script_sig=bytes.fromhex( - "47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2d" - ), - ) - inp2 = proto.TxInputType( - address_n=parse_path("44'/145'/0'/0/1"), - # bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4 - amount=73452, - prev_hash=TXHASH_502e85, - prev_index=1, - script_type=proto.InputScriptType.SPENDADDRESS, - ) - out1 = proto.TxOutputType( - address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4", - amount=1934960, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_input(1), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_502e85), - request_input(0, TXHASH_502e85), - request_output(0, TXHASH_502e85), - request_output(1, TXHASH_502e85), - request_input(1), - request_meta(TXHASH_502e85), - request_input(0, TXHASH_502e85), - request_output(0, TXHASH_502e85), - request_output(1, TXHASH_502e85), - request_input(0), - request_input(1), - request_output(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API - ) + assert ( + signatures1[0].hex() + == "3045022100cc12faf18a489d8014e978ef7ca0760aa6487cdb40b49dd991bfe9c66625f5a802206088fef49ecad30679d55eaa870741bbb8b83fac08eb078872ac276c8139015d" + ) + assert ( + serialized_tx.hex() + == "0100000001a07660b10df9868df9393c9cf8962bc34f48cb2cea53b0865d2324bab8b96d8b00000000fdfd0000483045022100cc12faf18a489d8014e978ef7ca0760aa6487cdb40b49dd991bfe9c66625f5a802206088fef49ecad30679d55eaa870741bbb8b83fac08eb078872ac276c8139015d4147304402202b75dbb307d2556b9a85851d27ab118b3f06344bccb6e21b0a5dfcf74e0e644f02206611c59396d44741d34fd7bb602be06ef91690b22b47c3f3c271e15e20176ac0414c6952210290cc724ccb90a6c7c1c3b291938449464ea474390183909e51bcd2807ecb779d210222f537684e2933563f737192fbf1947fd9034402e5708d10f6decd8e1f03e172210350df5cb41013d6b06581230556006b0a85ccccd205745cc10c927755193c241b53aeffffffff02c05d0000000000001976a91400741952f6a6eab5394f366db5cc5a54b0c2429f88acc05d00000000000017a914dfc8c2dda26f7151ed7df8aeeca24089e6410fdd8700000000" + ) - assert ( - serialized_tx.hex() - == "01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000" + +@pytest.mark.skip_t1 +def test_send_bch_external_presigned(client): + inp1 = proto.TxInputType( + # address_n=parse_path("44'/145'/0'/1/0"), + # bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw + amount=1896050, + prev_hash=TXHASH_502e85, + prev_index=0, + script_type=proto.InputScriptType.EXTERNAL, + script_pubkey=bytes.fromhex( + "76a914b1401fce7e8bf123c88a0467e0ed11e3b9fbef5488ac" + ), + script_sig=bytes.fromhex( + "47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2d" + ), + ) + inp2 = proto.TxInputType( + address_n=parse_path("44'/145'/0'/0/1"), + # bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4 + amount=73452, + prev_hash=TXHASH_502e85, + prev_index=1, + script_type=proto.InputScriptType.SPENDADDRESS, + ) + out1 = proto.TxOutputType( + address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4", + amount=1934960, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_input(1), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_502e85), + request_input(0, TXHASH_502e85), + request_output(0, TXHASH_502e85), + request_output(1, TXHASH_502e85), + request_input(1), + request_meta(TXHASH_502e85), + request_input(0, TXHASH_502e85), + request_output(0, TXHASH_502e85), + request_output(1, TXHASH_502e85), + request_input(0), + request_input(1), + request_output(0), + request_finished(), + ] ) + _, serialized_tx = btc.sign_tx( + client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API + ) + + assert ( + serialized_tx.hex() + == "01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000" + ) diff --git a/tests/device_tests/test_msg_signtx_bgold.py b/tests/device_tests/test_msg_signtx_bgold.py index 6b87aad4fc..916ed590c5 100644 --- a/tests/device_tests/test_msg_signtx_bgold.py +++ b/tests/device_tests/test_msg_signtx_bgold.py @@ -36,534 +36,538 @@ TXHASH_f55c5b = bytes.fromhex( "f55c5bc925eb2a0bf9de0ac142b24bed81ec46dd2151d5f69728070eaea1aded" ) +pytestmark = pytest.mark.altcoin + # All data taken from T1 -@pytest.mark.altcoin -class TestMsgSigntxBitcoinGold: - def test_send_bitcoin_gold_change(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/156'/0'/0/0"), - amount=1252382934, - prev_hash=TXHASH_25526b, - prev_index=0, - script_type=proto.InputScriptType.SPENDADDRESS, +def test_send_bitcoin_gold_change(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/156'/0'/0/0"), + amount=1252382934, + prev_hash=TXHASH_25526b, + prev_index=0, + script_type=proto.InputScriptType.SPENDADDRESS, + ) + out1 = proto.TxOutputType( + address_n=parse_path("44'/156'/0'/1/0"), + amount=1896050, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", + amount=1252382934 - 1896050 - 1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_25526b), + request_input(0, TXHASH_25526b), + request_output(0, TXHASH_25526b), + request_output(1, TXHASH_25526b), + request_input(0), + request_output(0), + request_output(1), + request_finished(), + ] ) - out1 = proto.TxOutputType( - address_n=parse_path("44'/156'/0'/1/0"), - amount=1896050, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", - amount=1252382934 - 1896050 - 1000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_25526b), - request_input(0, TXHASH_25526b), - request_output(0, TXHASH_25526b), - request_output(1, TXHASH_25526b), - request_input(0), - request_output(0), - request_output(1), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API - ) - - assert ( - btc_hash(serialized_tx)[::-1].hex() - == "39a0716c361610724c7c40916baa20808cbdd7538b6c38689ce80cb73e7f51d1" + _, serialized_tx = btc.sign_tx( + client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_bitcoin_gold_nochange(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/156'/0'/1/0"), - amount=1252382934, - prev_hash=TXHASH_25526b, - prev_index=0, - script_type=proto.InputScriptType.SPENDADDRESS, - ) - inp2 = proto.TxInputType( - address_n=parse_path("44'/156'/0'/0/1"), - # 1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3 - amount=38448607, - prev_hash=TXHASH_db77c2, - prev_index=0, - script_type=proto.InputScriptType.SPENDADDRESS, - ) - out1 = proto.TxOutputType( - address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", - amount=1252382934 + 38448607 - 1000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_input(1), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_25526b), - request_input(0, TXHASH_25526b), - request_output(0, TXHASH_25526b), - request_output(1, TXHASH_25526b), - request_input(1), - request_meta(TXHASH_db77c2), - request_input(0, TXHASH_db77c2), - request_input(1, TXHASH_db77c2), - request_output(0, TXHASH_db77c2), - request_input(0), - request_input(1), - request_output(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bgold", [inp1, inp2], [out1], prev_txes=TX_API - ) + assert ( + btc_hash(serialized_tx)[::-1].hex() + == "39a0716c361610724c7c40916baa20808cbdd7538b6c38689ce80cb73e7f51d1" + ) - assert ( - btc_hash(serialized_tx)[::-1].hex() - == "ac9d452b900eb747d3137e1f3044bb0f46efaeb6e0fc8c27b02d1d08d238a904" + +def test_send_bitcoin_gold_nochange(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/156'/0'/1/0"), + amount=1252382934, + prev_hash=TXHASH_25526b, + prev_index=0, + script_type=proto.InputScriptType.SPENDADDRESS, + ) + inp2 = proto.TxInputType( + address_n=parse_path("44'/156'/0'/0/1"), + # 1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3 + amount=38448607, + prev_hash=TXHASH_db77c2, + prev_index=0, + script_type=proto.InputScriptType.SPENDADDRESS, + ) + out1 = proto.TxOutputType( + address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", + amount=1252382934 + 38448607 - 1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_input(1), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_25526b), + request_input(0, TXHASH_25526b), + request_output(0, TXHASH_25526b), + request_output(1, TXHASH_25526b), + request_input(1), + request_meta(TXHASH_db77c2), + request_input(0, TXHASH_db77c2), + request_input(1, TXHASH_db77c2), + request_output(0, TXHASH_db77c2), + request_input(0), + request_input(1), + request_output(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Bgold", [inp1, inp2], [out1], prev_txes=TX_API ) - def test_attack_change_input(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/156'/11'/0/0"), - amount=1252382934, - prev_hash=TXHASH_25526b, - prev_index=0, - script_type=proto.InputScriptType.SPENDADDRESS, + assert ( + btc_hash(serialized_tx)[::-1].hex() + == "ac9d452b900eb747d3137e1f3044bb0f46efaeb6e0fc8c27b02d1d08d238a904" + ) + + +def test_attack_change_input(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/156'/11'/0/0"), + amount=1252382934, + prev_hash=TXHASH_25526b, + 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=1252382934 - 1896050 - 1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + attack_count = 2 + + def attack_processor(msg): + nonlocal attack_count + + if msg.tx.inputs and msg.tx.inputs[0] == inp1: + if attack_count > 0: + attack_count -= 1 + else: + msg.tx.inputs[0].address_n[2] = H_(1) + + return msg + + with client: + client.set_filter(proto.TxAck, attack_processor) + client.set_expected_responses( + [ + request_input(0), + request_output(0), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_25526b), + request_input(0, TXHASH_25526b), + request_output(0, TXHASH_25526b), + request_output(1, TXHASH_25526b), + request_input(0), + proto.Failure(code=proto.FailureType.ProcessError), + ] ) - 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=1252382934 - 1896050 - 1000, - script_type=proto.OutputScriptType.PAYTOADDRESS, + with pytest.raises(TrezorFailure): + btc.sign_tx(client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API) + + +@pytest.mark.multisig +def test_send_btg_multisig_change(client): + nodes = [ + btc.get_public_node( + client, parse_path(f"48'/156'/{i}'/0'"), coin_name="Bgold" + ).node + for i in range(1, 4) + ] + + EMPTY_SIGS = [b"", b"", b""] + + def getmultisig(chain, nr, signatures): + return proto.MultisigRedeemScriptType( + nodes=nodes, address_n=[chain, nr], signatures=signatures, m=2 ) - attack_count = 2 - - def attack_processor(msg): - nonlocal attack_count - - if msg.tx.inputs and msg.tx.inputs[0] == inp1: - if attack_count > 0: - attack_count -= 1 - else: - msg.tx.inputs[0].address_n[2] = H_(1) - - return msg - - with client: - client.set_filter(proto.TxAck, attack_processor) - client.set_expected_responses( - [ - request_input(0), - request_output(0), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_25526b), - request_input(0, TXHASH_25526b), - request_output(0, TXHASH_25526b), - request_output(1, TXHASH_25526b), - request_input(0), - proto.Failure(code=proto.FailureType.ProcessError), - ] - ) - with pytest.raises(TrezorFailure): - btc.sign_tx(client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API) - - @pytest.mark.multisig - def test_send_btg_multisig_change(self, client): - nodes = [ - btc.get_public_node( - client, parse_path(f"48'/156'/{i}'/0'"), coin_name="Bgold" - ).node - for i in range(1, 4) - ] - - EMPTY_SIGS = [b"", b"", b""] - - def getmultisig(chain, nr, signatures): - 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/0"), - multisig=getmultisig(0, 0, EMPTY_SIGS), - # 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R - amount=1252382934, - prev_hash=TXHASH_25526b, - prev_index=0, - script_type=proto.InputScriptType.SPENDMULTISIG, + inp1 = proto.TxInputType( + address_n=parse_path("48'/156'/3'/0'/0/0"), + multisig=getmultisig(0, 0, EMPTY_SIGS), + # 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R + amount=1252382934, + prev_hash=TXHASH_25526b, + 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'/0'/1/0"), + multisig=getmultisig(1, 0, EMPTY_SIGS), + script_type=proto.OutputScriptType.PAYTOMULTISIG, + amount=1252382934 - 24000 - 1000, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_25526b), + request_input(0, TXHASH_25526b), + request_output(0, TXHASH_25526b), + request_output(1, TXHASH_25526b), + request_input(0), + request_output(0), + request_output(1), + request_finished(), + ] ) - out1 = proto.TxOutputType( - address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", - amount=24000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address_n=parse_path("48'/156'/3'/0'/1/0"), - multisig=getmultisig(1, 0, EMPTY_SIGS), - script_type=proto.OutputScriptType.PAYTOMULTISIG, - amount=1252382934 - 24000 - 1000, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_25526b), - request_input(0, TXHASH_25526b), - request_output(0, TXHASH_25526b), - request_output(1, TXHASH_25526b), - 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() - == "30440220263c427e6e889c161206edee39b9b969350c154ddd8eb76d2ab8ca8e0fc083b702200fb1d0ef430fa2d0293dcbb0b237775d4f9748222a6ed9fc3ff747837b99020a" + signatures, serialized_tx = btc.sign_tx( + client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API ) - inp1 = proto.TxInputType( - address_n=parse_path("48'/156'/1'/0'/0/0"), - multisig=getmultisig(0, 0, [b"", b"", signatures[0]]), - amount=1252382934, - prev_hash=TXHASH_25526b, - prev_index=0, - script_type=proto.InputScriptType.SPENDMULTISIG, - ) - out2.address_n[2] = H_(1) + assert ( + signatures[0].hex() + == "30440220263c427e6e889c161206edee39b9b969350c154ddd8eb76d2ab8ca8e0fc083b702200fb1d0ef430fa2d0293dcbb0b237775d4f9748222a6ed9fc3ff747837b99020a" + ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_25526b), - request_input(0, TXHASH_25526b), - request_output(0, TXHASH_25526b), - request_output(1, TXHASH_25526b), - 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 - ) + inp1 = proto.TxInputType( + address_n=parse_path("48'/156'/1'/0'/0/0"), + multisig=getmultisig(0, 0, [b"", b"", signatures[0]]), + amount=1252382934, + prev_hash=TXHASH_25526b, + prev_index=0, + script_type=proto.InputScriptType.SPENDMULTISIG, + ) + out2.address_n[2] = H_(1) - assert ( - signatures[0].hex() - == "3045022100c9094b060b4b095e78403493912b0e06ca12ffbdc0f2fbeec20b02d7eaa73f8702206813e33e04a2b9c4493ecfa2024f2e9d69b5a2ab5c10433d9ab762add5bdde27" + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_25526b), + request_input(0, TXHASH_25526b), + request_output(0, TXHASH_25526b), + request_output(1, TXHASH_25526b), + request_input(0), + request_output(0), + request_output(1), + request_finished(), + ] ) - assert ( - btc_hash(serialized_tx)[::-1].hex() - == "2677130ec0c5eea2249787fe17b85770cfb35dfce550830a7fb6c6acd9375114" + signatures, serialized_tx = btc.sign_tx( + client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_p2sh(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("49'/156'/0'/1/0"), - amount=1252382934, - prev_hash=TXHASH_25526b, - 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=1252382934 - 11000 - 12300000, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_25526b), - request_input(0, TXHASH_25526b), - request_output(0, TXHASH_25526b), - request_output(1, TXHASH_25526b), - request_input(0), - request_output(0), - request_output(1), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API - ) + assert ( + signatures[0].hex() + == "3045022100c9094b060b4b095e78403493912b0e06ca12ffbdc0f2fbeec20b02d7eaa73f8702206813e33e04a2b9c4493ecfa2024f2e9d69b5a2ab5c10433d9ab762add5bdde27" + ) + assert ( + btc_hash(serialized_tx)[::-1].hex() + == "2677130ec0c5eea2249787fe17b85770cfb35dfce550830a7fb6c6acd9375114" + ) - assert ( - btc_hash(serialized_tx)[::-1].hex() - == "d5732fc8a594ae3b7ba695d7b276b2186f8572b0eb157120e0ba35d3511c6060" + +def test_send_p2sh(client): + inp1 = proto.TxInputType( + address_n=parse_path("49'/156'/0'/1/0"), + amount=1252382934, + prev_hash=TXHASH_25526b, + 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=1252382934 - 11000 - 12300000, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_25526b), + request_input(0, TXHASH_25526b), + request_output(0, TXHASH_25526b), + request_output(1, TXHASH_25526b), + request_input(0), + request_output(0), + request_output(1), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_p2sh_witness_change(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("49'/156'/0'/1/0"), - amount=1252382934, - prev_hash=TXHASH_25526b, - 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=1252382934 - 11000 - 12300000, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_25526b), - request_input(0, TXHASH_25526b), - request_output(0, TXHASH_25526b), - request_output(1, TXHASH_25526b), - request_input(0), - request_output(0), - request_output(1), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API - ) + assert ( + btc_hash(serialized_tx)[::-1].hex() + == "d5732fc8a594ae3b7ba695d7b276b2186f8572b0eb157120e0ba35d3511c6060" + ) - assert ( - btc_hash(serialized_tx)[::-1].hex() - == "eed4ef86a408602e35ae416591f349847db38cdaddef1429a9bb0e39520d100d" + +def test_send_p2sh_witness_change(client): + inp1 = proto.TxInputType( + address_n=parse_path("49'/156'/0'/1/0"), + amount=1252382934, + prev_hash=TXHASH_25526b, + 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=1252382934 - 11000 - 12300000, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_25526b), + request_input(0, TXHASH_25526b), + request_output(0, TXHASH_25526b), + request_output(1, TXHASH_25526b), + request_input(0), + request_output(0), + request_output(1), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API ) - @pytest.mark.multisig - def test_send_multisig_1(self, client): - nodes = [ - btc.get_public_node( - client, parse_path(f"49'/156'/{i}'"), coin_name="Bgold" - ).node - for i in range(1, 4) - ] - multisig = proto.MultisigRedeemScriptType( - nodes=nodes, address_n=[1, 0], signatures=[b"", b"", b""], m=2 + assert ( + btc_hash(serialized_tx)[::-1].hex() + == "eed4ef86a408602e35ae416591f349847db38cdaddef1429a9bb0e39520d100d" + ) + + +@pytest.mark.multisig +def test_send_multisig_1(client): + nodes = [ + btc.get_public_node( + client, parse_path(f"49'/156'/{i}'"), coin_name="Bgold" + ).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=TXHASH_25526b, + prev_index=0, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + multisig=multisig, + amount=1252382934, + ) + + out1 = proto.TxOutputType( + address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", + amount=1252382934 - 1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_25526b), + request_input(0, TXHASH_25526b), + request_output(0, TXHASH_25526b), + request_output(1, TXHASH_25526b), + 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), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_25526b), + request_input(0, TXHASH_25526b), + request_output(0, TXHASH_25526b), + request_output(1, TXHASH_25526b), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Bgold", [inp1], [out1], prev_txes=TX_API ) - inp1 = proto.TxInputType( - address_n=parse_path("49'/156'/1'/1/0"), - prev_hash=TXHASH_25526b, - prev_index=0, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - multisig=multisig, - amount=1252382934, + assert ( + btc_hash(serialized_tx)[::-1].hex() + == "efa5b21916ac7ea5316c38b2d7d5520d80cbe563c58304f956ea6ddb241001d1" + ) + + +def test_send_mixed_inputs(client): + # First is non-segwit, second is segwit. + + inp1 = proto.TxInputType( + address_n=parse_path("44'/156'/11'/0/0"), + amount=38448607, + prev_hash=TXHASH_db77c2, + prev_index=0, + script_type=proto.InputScriptType.SPENDADDRESS, + ) + inp2 = proto.TxInputType( + address_n=parse_path("49'/156'/0'/1/0"), + amount=1252382934, + prev_hash=TXHASH_25526b, + prev_index=0, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + ) + out1 = proto.TxOutputType( + address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", + amount=38448607 + 1252382934 - 1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + _, serialized_tx = btc.sign_tx( + client, "Bgold", [inp1, inp2], [out1], prev_txes=TX_API ) - out1 = proto.TxOutputType( - address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", - amount=1252382934 - 1000, - script_type=proto.OutputScriptType.PAYTOADDRESS, + assert ( + btc_hash(serialized_tx)[::-1].hex() + == "2c64109fba890657e37f0782efda29bbc277dfd521658f185d302ddffcacffd2" + ) + + +@pytest.mark.skip_t1 +def test_send_btg_external_presigned(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/156'/0'/1/0"), + amount=1252382934, + prev_hash=TXHASH_25526b, + prev_index=0, + script_type=proto.InputScriptType.SPENDADDRESS, + ) + inp2 = proto.TxInputType( + # address_n=parse_path("49'/156'/0'/0/0"), + # AXibjT5r96ZaVA8Lu4BQZocdTx7p5Ud8ZP + amount=58456, + prev_hash=TXHASH_f55c5b, + prev_index=0, + script_type=proto.InputScriptType.EXTERNAL, + script_pubkey=bytes.fromhex("a914aee37ad448e17438cabfee1756f2a08e33ed3ce887"), + script_sig=bytes.fromhex("1600147c5edda9b293db2c8894b9d81efd77764910c445"), + witness=bytes.fromhex( + "024730440220091eece828409b3a9aa92dd2f9b032f9fb3a12b21b323a3fdea3cb18d08249af022065412107afcf76b0d28b90188c802f8f17b41790ed81c868d0ee23f1dd2ec53441210386789a34fe1a49bfc3e174adc6706c6222b0d80de76b884a0e3d32f8e9c4dc3e" + ), + ) + out1 = proto.TxOutputType( + address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", + amount=1252382934 + 58456 - 1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_input(1), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_25526b), + request_input(0, TXHASH_25526b), + request_output(0, TXHASH_25526b), + request_output(1, TXHASH_25526b), + request_input(1), + request_meta(TXHASH_f55c5b), + request_input(0, TXHASH_f55c5b), + request_output(0, TXHASH_f55c5b), + request_output(1, TXHASH_f55c5b), + request_input(0), + request_input(1), + request_output(0), + request_input(1), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Bgold", [inp1, inp2], [out1], prev_txes=TX_API ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_25526b), - request_input(0, TXHASH_25526b), - request_output(0, TXHASH_25526b), - request_output(1, TXHASH_25526b), - 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), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_25526b), - request_input(0, TXHASH_25526b), - request_output(0, TXHASH_25526b), - request_output(1, TXHASH_25526b), - 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 ( - btc_hash(serialized_tx)[::-1].hex() - == "efa5b21916ac7ea5316c38b2d7d5520d80cbe563c58304f956ea6ddb241001d1" - ) - - def test_send_mixed_inputs(self, client): - # First is non-segwit, second is segwit. - - inp1 = proto.TxInputType( - address_n=parse_path("44'/156'/11'/0/0"), - amount=38448607, - prev_hash=TXHASH_db77c2, - prev_index=0, - script_type=proto.InputScriptType.SPENDADDRESS, - ) - inp2 = proto.TxInputType( - address_n=parse_path("49'/156'/0'/1/0"), - amount=1252382934, - prev_hash=TXHASH_25526b, - prev_index=0, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - ) - out1 = proto.TxOutputType( - address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", - amount=38448607 + 1252382934 - 1000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - _, serialized_tx = btc.sign_tx( - client, "Bgold", [inp1, inp2], [out1], prev_txes=TX_API - ) - - assert ( - btc_hash(serialized_tx)[::-1].hex() - == "2c64109fba890657e37f0782efda29bbc277dfd521658f185d302ddffcacffd2" - ) - - @pytest.mark.skip_t1 - def test_send_btg_external_presigned(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/156'/0'/1/0"), - amount=1252382934, - prev_hash=TXHASH_25526b, - prev_index=0, - script_type=proto.InputScriptType.SPENDADDRESS, - ) - inp2 = proto.TxInputType( - # address_n=parse_path("49'/156'/0'/0/0"), - # AXibjT5r96ZaVA8Lu4BQZocdTx7p5Ud8ZP - amount=58456, - prev_hash=TXHASH_f55c5b, - prev_index=0, - script_type=proto.InputScriptType.EXTERNAL, - script_pubkey=bytes.fromhex( - "a914aee37ad448e17438cabfee1756f2a08e33ed3ce887" - ), - script_sig=bytes.fromhex("1600147c5edda9b293db2c8894b9d81efd77764910c445"), - witness=bytes.fromhex( - "024730440220091eece828409b3a9aa92dd2f9b032f9fb3a12b21b323a3fdea3cb18d08249af022065412107afcf76b0d28b90188c802f8f17b41790ed81c868d0ee23f1dd2ec53441210386789a34fe1a49bfc3e174adc6706c6222b0d80de76b884a0e3d32f8e9c4dc3e" - ), - ) - out1 = proto.TxOutputType( - address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe", - amount=1252382934 + 58456 - 1000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_input(1), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_25526b), - request_input(0, TXHASH_25526b), - request_output(0, TXHASH_25526b), - request_output(1, TXHASH_25526b), - request_input(1), - request_meta(TXHASH_f55c5b), - request_input(0, TXHASH_f55c5b), - request_output(0, TXHASH_f55c5b), - request_output(1, TXHASH_f55c5b), - request_input(0), - request_input(1), - request_output(0), - request_input(1), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bgold", [inp1, inp2], [out1], prev_txes=TX_API - ) - - assert ( - btc_hash(serialized_tx)[::-1].hex() - == "95ebe5cdfb8dc3c112eb0107fc3bd7701689ac5ec4a74a3d12e203333d0832d3" - ) + assert ( + btc_hash(serialized_tx)[::-1].hex() + == "95ebe5cdfb8dc3c112eb0107fc3bd7701689ac5ec4a74a3d12e203333d0832d3" + ) diff --git a/tests/device_tests/test_msg_signtx_dash.py b/tests/device_tests/test_msg_signtx_dash.py index d45a1e6539..7ba4b0f26b 100644 --- a/tests/device_tests/test_msg_signtx_dash.py +++ b/tests/device_tests/test_msg_signtx_dash.py @@ -38,97 +38,96 @@ TXHASH_15575a = bytes.fromhex( "15575a1c874bd60a819884e116c42e6791c8283ce1fc3b79f0d18531a61bbb8a" ) +pytestmark = pytest.mark.altcoin -@pytest.mark.altcoin -class TestMsgSigntxDash: - def test_send_dash(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/5'/0'/0/0"), - # dash:XdTw4G5AWW4cogGd7ayybyBNDbuB45UpgH - amount=1000000000, - prev_hash=TXHASH_5579ea, - prev_index=1, - script_type=proto.InputScriptType.SPENDADDRESS, - ) - out1 = proto.TxOutputType( - address="XpTc36DPAeWmaueNBA9JqCg2GC8XDLKSYe", - amount=999999000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(inp1.prev_hash), - request_input(0, inp1.prev_hash), - request_input(1, inp1.prev_hash), - request_output(0, inp1.prev_hash), - request_output(1, inp1.prev_hash), - request_input(0), - request_output(0), - request_output(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Dash", [inp1], [out1], prev_txes=TX_API - ) - assert ( - serialized_tx.hex() - == "01000000014fb02af26dca339e7e06c4f148dfce57c9afa5f537d0d8e733022a4ba6ea7955010000006a4730440220387be4d1e4b5e355614091416373e99e1a3532b8cc9a8629368060aff2681bdb02200a0c4a5e9eb2ce6adb6c2e01ec8f954463dcc04f531ed8a89a2b40019d5aeb0b012102936f80cac2ba719ddb238646eb6b78a170a55a52a9b9f08c43523a4a6bd5c896ffffffff0118c69a3b000000001976a9149710d6545407e78c326aa8c8ae386ec7f883b0af88ac00000000" +def test_send_dash(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/5'/0'/0/0"), + # dash:XdTw4G5AWW4cogGd7ayybyBNDbuB45UpgH + amount=1000000000, + prev_hash=TXHASH_5579ea, + prev_index=1, + script_type=proto.InputScriptType.SPENDADDRESS, + ) + out1 = proto.TxOutputType( + address="XpTc36DPAeWmaueNBA9JqCg2GC8XDLKSYe", + amount=999999000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(inp1.prev_hash), + request_input(0, inp1.prev_hash), + request_input(1, inp1.prev_hash), + request_output(0, inp1.prev_hash), + request_output(1, inp1.prev_hash), + request_input(0), + request_output(0), + request_output(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx(client, "Dash", [inp1], [out1], prev_txes=TX_API) + + assert ( + serialized_tx.hex() + == "01000000014fb02af26dca339e7e06c4f148dfce57c9afa5f537d0d8e733022a4ba6ea7955010000006a4730440220387be4d1e4b5e355614091416373e99e1a3532b8cc9a8629368060aff2681bdb02200a0c4a5e9eb2ce6adb6c2e01ec8f954463dcc04f531ed8a89a2b40019d5aeb0b012102936f80cac2ba719ddb238646eb6b78a170a55a52a9b9f08c43523a4a6bd5c896ffffffff0118c69a3b000000001976a9149710d6545407e78c326aa8c8ae386ec7f883b0af88ac00000000" + ) + + +def test_send_dash_dip2_input(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/5'/0'/0/0"), + # dash:XdTw4G5AWW4cogGd7ayybyBNDbuB45UpgH + amount=4095000260, + prev_hash=TXHASH_15575a, + 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 client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(inp1.prev_hash), + request_input(0, inp1.prev_hash), + request_output(0, inp1.prev_hash), + request_output(1, inp1.prev_hash), + request_extra_data(0, 39, inp1.prev_hash), + request_input(0), + request_output(0), + request_output(1), + request_output(0), + request_output(1), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Dash", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_dash_dip2_input(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/5'/0'/0/0"), - # dash:XdTw4G5AWW4cogGd7ayybyBNDbuB45UpgH - amount=4095000260, - prev_hash=TXHASH_15575a, - 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 client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(inp1.prev_hash), - request_input(0, inp1.prev_hash), - request_output(0, inp1.prev_hash), - request_output(1, inp1.prev_hash), - request_extra_data(0, 39, inp1.prev_hash), - request_input(0), - request_output(0), - request_output(1), - request_output(0), - request_output(1), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Dash", [inp1], [out1, out2], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "01000000018abb1ba63185d1f0793bfce13c28c891672ec416e18498810ad64b871c5a5715010000006b483045022100f0442b6d9c7533cd6f74afa993b280ed9475276d69df4dac631bc3b5591ba71b022051daf125372c1c477681bbd804a6445d8ff6840901854fb0b485b1c6c7866c44012102936f80cac2ba719ddb238646eb6b78a170a55a52a9b9f08c43523a4a6bd5c896ffffffff0200286bee000000001976a914fd61dd017dad1f505c0511142cc9ac51ef3a5beb88acc095a905000000001976a914aa7a6a1f43dfc34d17e562ce1845b804b73fc31e88ac00000000" - ) + assert ( + serialized_tx.hex() + == "01000000018abb1ba63185d1f0793bfce13c28c891672ec416e18498810ad64b871c5a5715010000006b483045022100f0442b6d9c7533cd6f74afa993b280ed9475276d69df4dac631bc3b5591ba71b022051daf125372c1c477681bbd804a6445d8ff6840901854fb0b485b1c6c7866c44012102936f80cac2ba719ddb238646eb6b78a170a55a52a9b9f08c43523a4a6bd5c896ffffffff0200286bee000000001976a914fd61dd017dad1f505c0511142cc9ac51ef3a5beb88acc095a905000000001976a914aa7a6a1f43dfc34d17e562ce1845b804b73fc31e88ac00000000" + ) diff --git a/tests/device_tests/test_msg_signtx_decred.py b/tests/device_tests/test_msg_signtx_decred.py index cd3f6aa77f..5659cae710 100644 --- a/tests/device_tests/test_msg_signtx_decred.py +++ b/tests/device_tests/test_msg_signtx_decred.py @@ -51,214 +51,318 @@ TXHASH_1f00fc = bytes.fromhex( "1f00fc54530d7c4877f5032e91b6c507f6a1531861dede2ab134e5c0b5dfe8c8" ) +pytestmark = [pytest.mark.altcoin, pytest.mark.decred] -@pytest.mark.altcoin -@pytest.mark.decred -class TestMsgSigntxDecred: - def test_send_decred(self, client): + +def test_send_decred(client): + inp1 = proto.TxInputType( + # TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz + address_n=parse_path("m/44'/1'/0'/0/0"), + prev_hash=TXHASH_e16248, + prev_index=1, + amount=200000000, + script_type=proto.InputScriptType.SPENDADDRESS, + decred_tree=0, + ) + + out1 = proto.TxOutputType( + address="TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz", + amount=190000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.FeeOverThreshold), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_e16248), + request_input(0, TXHASH_e16248), + request_output(0, TXHASH_e16248), + request_output(1, TXHASH_e16248), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Decred Testnet", [inp1], [out1], prev_txes=TX_API + ) + + assert ( + serialized_tx.hex() + == "0100000001edd579e9462ee0e80127a817e0500d4f942a4cf8f2d6530e0c0a9ab3f04862e10100000000ffffffff01802b530b0000000000001976a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac00000000000000000100c2eb0b0000000000000000ffffffff6a473044022009e394c7dec76ab6988270b467839b1462ad781556bce37383b76e026418ce6302204f7f6ef535d2986b095d7c96232a0990a0b9ce3004894b39c167bb18e5833ac30121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" + ) + + +@pytest.mark.skip_t1 +def test_purchase_ticket_decred(client): + inp1 = proto.TxInputType( + address_n=parse_path("m/44'/1'/0'/0/0"), + prev_hash=TXHASH_e16248, + prev_index=1, + amount=200000000, + decred_tree=0, + script_type=proto.InputScriptType.SPENDADDRESS, + ) + + out1 = proto.TxOutputType( + address="TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz", + script_type=proto.OutputScriptType.PAYTOADDRESS, + amount=199900000, + ) + out2 = proto.TxOutputType( + address_n=parse_path("m/44'/1'/0'/0/0"), + amount=200000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out3 = proto.TxOutputType( + address="TsR28UZRprhgQQhzWns2M6cAwchrNVvbYq2", + amount=0, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + request_output(2), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_e16248), + request_input(0, TXHASH_e16248), + request_output(0, TXHASH_e16248), + request_output(1, TXHASH_e16248), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, + "Decred Testnet", + [inp1], + [out1, out2, out3], + prev_txes=TX_API, + decred_staking_ticket=True, + ) + + assert ( + serialized_tx.hex() + == "0100000001edd579e9462ee0e80127a817e0500d4f942a4cf8f2d6530e0c0a9ab3f04862e10100000000ffffffff03603bea0b0000000000001aba76a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac00000000000000000000206a1edc1a98d791735eb9a8715a2a219c23680edcedad00c2eb0b000000000058000000000000000000001abd76a914000000000000000000000000000000000000000088ac00000000000000000100c2eb0b0000000000000000ffffffff6b4830450221008ced5411a6d92b761bdd8b9f7fbc5bfae3c31f9369050c218977f4540ab1ec9602206e89c821878ebfd959d1c4a63100eec5b1154c8d9508c039bb78e333498a73b40121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" + ) + + +@pytest.mark.skip_t1 +def test_spend_from_stake_generation_and_revocation_decred(client): + inp1 = proto.TxInputType( + address_n=parse_path("m/44'/1'/0'/0/0"), + prev_hash=TXHASH_8b6890, + prev_index=2, + amount=200000000, + script_type=proto.InputScriptType.SPENDADDRESS, + decred_staking_spend=proto.DecredStakingSpendType.SSGen, + decred_tree=1, + ) + + inp2 = proto.TxInputType( + address_n=parse_path("m/44'/1'/0'/0/0"), + prev_hash=TXHASH_1f00fc, + prev_index=0, + amount=200000000, + script_type=proto.InputScriptType.SPENDADDRESS, + decred_staking_spend=proto.DecredStakingSpendType.SSRTX, + decred_tree=1, + ) + + out1 = proto.TxOutputType( + address="TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz", + amount=399900000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_input(1), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_8b6890), + request_input(0, TXHASH_8b6890), + request_input(1, TXHASH_8b6890), + request_output(0, TXHASH_8b6890), + request_output(1, TXHASH_8b6890), + request_output(2, TXHASH_8b6890), + request_input(1), + request_meta(TXHASH_1f00fc), + request_input(0, TXHASH_1f00fc), + request_output(0, TXHASH_1f00fc), + request_input(0), + request_input(1), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Decred Testnet", [inp1, inp2], [out1], prev_txes=TX_API + ) + + assert ( + serialized_tx.hex() + == "010000000254e249113666e84c70de1dbee976f18d1438e4b7c58b376ffe64370ac190688b0200000001ffffffffc8e8dfb5c0e534b12adede611853a1f607c5b6912e03f577487c0d5354fc001f0000000001ffffffff0160fdd5170000000000001976a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac00000000000000000200c2eb0b0000000000000000ffffffff6b483045022100bdcb877c97d72db74eca06fefa21a7f7b00afcd5d916fce2155ed7df1ca5546102201e1f9efd7d652b449474c2c70171bfc4535544927bed62021f7334447d1ea4740121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd000c2eb0b0000000000000000ffffffff6a473044022030c5743c442bd696d19dcf73d54e95526e726de965c2e2b4b9fd70248eaae21d02201305a3bcc2bb0e33122277763990e3b48f317d61264a68d190fb8acfc004cc640121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" + ) + + +def test_send_decred_change(client): + inp1 = proto.TxInputType( + # TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz + address_n=parse_path("m/44'/1'/0'/0/0"), + amount=190000000, + prev_hash=TXHASH_5e6e35, + prev_index=0, + script_type=proto.InputScriptType.SPENDADDRESS, + decred_tree=0, + ) + + inp2 = proto.TxInputType( + # TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz + address_n=parse_path("m/44'/1'/0'/0/0"), + amount=200000000, + prev_hash=TXHASH_ccf95b, + prev_index=1, + script_type=proto.InputScriptType.SPENDADDRESS, + decred_tree=0, + ) + + inp3 = proto.TxInputType( + # Tskt39YEvzoJ5KBDH4f1auNzG3jViVjZ2RV + address_n=parse_path("m/44'/1'/0'/0/1"), + amount=200000000, + prev_hash=TXHASH_f395ef, + prev_index=0, + script_type=proto.InputScriptType.SPENDADDRESS, + decred_tree=0, + ) + + out1 = proto.TxOutputType( + address="TsWjioPrP8E1TuTMmTrVMM2BA4iPrjQXBpR", + amount=489975000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + out2 = proto.TxOutputType( + # TsaSFRwfN9muW5F6ZX36iSksc9hruiC5F97 + address_n=parse_path("m/44'/1'/0'/1/0"), + amount=100000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_input(1), + request_input(2), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_5e6e35), + request_input(0, TXHASH_5e6e35), + request_output(0, TXHASH_5e6e35), + request_input(1), + request_meta(TXHASH_ccf95b), + request_input(0, TXHASH_ccf95b), + request_output(0, TXHASH_ccf95b), + request_output(1, TXHASH_ccf95b), + request_input(2), + request_meta(TXHASH_f395ef), + request_input(0, TXHASH_f395ef), + request_output(0, TXHASH_f395ef), + request_output(1, TXHASH_f395ef), + request_input(0), + request_input(1), + request_input(2), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, + "Decred Testnet", + [inp1, inp2, inp3], + [out1, out2], + prev_txes=TX_API, + ) + + assert ( + serialized_tx.hex() + == "010000000370b95980a47b9bcb4ec2c2b450888a53179b1a5fdb23f5023cc533a300356e5e0000000000ffffffff74bc93bcfce18aff2e522d6822817522e2815a00175b2eae59ef20d20f5bf9cc0100000000ffffffff13317ab453832deabd684d2302eed42580c28ba3e715db66a731a8723eef95f30000000000ffffffff02d86c341d0000000000001976a9143eb656115197956125365348c542e37b6d3d259988ac00e1f5050000000000001976a9143ee6f9d662e7be18373d80e5eb44627014c2bf6688ac000000000000000003802b530b0000000000000000ffffffff6a47304402200e50a6d43c462045917792e7d03b4354900c3baccb7abef66f556a32b12f2ca6022031ae94fdf2a41dd6ed2e081faf0f8f1c64411a1b46eb26f7f35d94402b2bde110121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd000c2eb0b0000000000000000ffffffff6a47304402204894c2f8e76c4645d2df600cdd01443aeb48807b72150c4bc10eebd126529532022054cd37462a3f0ddb85c75b4e874ab0c2aad7eebcff3e6c1ac20e1c16babe36720121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd000c2eb0b0000000000000000ffffffff6b4830450221009f1ba584023da8aafd57374e83be68f1a097b906967ec9e50736f31bfc7989f102204a190fc2885e394572b5c2ced046657b1dd07abdb19144e21e78987968c7f17601210294e3e5e77e22eea0e4c0d30d89beb4db7f69b4bf1ae709e411d6a06618b8f852" + ) + + +@pytest.mark.multisig +def test_decred_multisig_change(client): + paths = [parse_path(f"m/48'/1'/{index}'/0'") for index in range(3)] + nodes = [ + btc.get_public_node(client, address_n, coin_name="Decred Testnet").node + for address_n in paths + ] + + signatures = [[b"", b"", b""], [b"", b"", b""]] + + def create_multisig(index, address, signatures=None): + address_n = parse_path(address) + multisig = proto.MultisigRedeemScriptType( + nodes=nodes, address_n=address_n, signatures=signatures, m=2 + ) + + return (paths[index] + address_n), multisig + + def test_multisig(index): + address_n, multisig = create_multisig(index, "m/0/0", signatures[0]) inp1 = proto.TxInputType( - # TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz - address_n=parse_path("m/44'/1'/0'/0/0"), - prev_hash=TXHASH_e16248, - prev_index=1, + address_n=address_n, + # TchpthUkRys1VQWgnQyLJNaA4MLBjVmRL2c + multisig=multisig, amount=200000000, - script_type=proto.InputScriptType.SPENDADDRESS, + prev_hash=TXHASH_3f7c39, + prev_index=1, + script_type=proto.InputScriptType.SPENDMULTISIG, decred_tree=0, ) - out1 = proto.TxOutputType( - address="TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz", - amount=190000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.FeeOverThreshold), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_e16248), - request_input(0, TXHASH_e16248), - request_output(0, TXHASH_e16248), - request_output(1, TXHASH_e16248), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Decred Testnet", [inp1], [out1], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "0100000001edd579e9462ee0e80127a817e0500d4f942a4cf8f2d6530e0c0a9ab3f04862e10100000000ffffffff01802b530b0000000000001976a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac00000000000000000100c2eb0b0000000000000000ffffffff6a473044022009e394c7dec76ab6988270b467839b1462ad781556bce37383b76e026418ce6302204f7f6ef535d2986b095d7c96232a0990a0b9ce3004894b39c167bb18e5833ac30121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" - ) - - @pytest.mark.skip_t1 - def test_purchase_ticket_decred(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("m/44'/1'/0'/0/0"), - prev_hash=TXHASH_e16248, - prev_index=1, + address_n, multisig = create_multisig(index, "m/0/1", signatures[1]) + inp2 = proto.TxInputType( + address_n=address_n, + # TcnfDEfMhkM3oLWqiq9v9GmYgLK7qfjitKG + multisig=multisig, amount=200000000, + prev_hash=TXHASH_16da18, + prev_index=0, + script_type=proto.InputScriptType.SPENDMULTISIG, decred_tree=0, - script_type=proto.InputScriptType.SPENDADDRESS, ) + address_n, multisig = create_multisig(index, "m/1/0") out1 = proto.TxOutputType( - address="TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz", - script_type=proto.OutputScriptType.PAYTOADDRESS, - amount=199900000, + address_n=address_n, + # TcrrURA3Bzj4isGU48PdSP9SDoU5oCpjEcb + multisig=multisig, + amount=99900000, + script_type=proto.OutputScriptType.PAYTOMULTISIG, ) + out2 = proto.TxOutputType( - address_n=parse_path("m/44'/1'/0'/0/0"), - amount=200000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out3 = proto.TxOutputType( - address="TsR28UZRprhgQQhzWns2M6cAwchrNVvbYq2", - amount=0, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - request_output(2), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_e16248), - request_input(0, TXHASH_e16248), - request_output(0, TXHASH_e16248), - request_output(1, TXHASH_e16248), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, - "Decred Testnet", - [inp1], - [out1, out2, out3], - prev_txes=TX_API, - decred_staking_ticket=True, - ) - - assert ( - serialized_tx.hex() - == "0100000001edd579e9462ee0e80127a817e0500d4f942a4cf8f2d6530e0c0a9ab3f04862e10100000000ffffffff03603bea0b0000000000001aba76a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac00000000000000000000206a1edc1a98d791735eb9a8715a2a219c23680edcedad00c2eb0b000000000058000000000000000000001abd76a914000000000000000000000000000000000000000088ac00000000000000000100c2eb0b0000000000000000ffffffff6b4830450221008ced5411a6d92b761bdd8b9f7fbc5bfae3c31f9369050c218977f4540ab1ec9602206e89c821878ebfd959d1c4a63100eec5b1154c8d9508c039bb78e333498a73b40121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" - ) - - @pytest.mark.skip_t1 - def test_spend_from_stake_generation_and_revocation_decred(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("m/44'/1'/0'/0/0"), - prev_hash=TXHASH_8b6890, - prev_index=2, - amount=200000000, - script_type=proto.InputScriptType.SPENDADDRESS, - decred_staking_spend=proto.DecredStakingSpendType.SSGen, - decred_tree=1, - ) - - inp2 = proto.TxInputType( - address_n=parse_path("m/44'/1'/0'/0/0"), - prev_hash=TXHASH_1f00fc, - prev_index=0, - amount=200000000, - script_type=proto.InputScriptType.SPENDADDRESS, - decred_staking_spend=proto.DecredStakingSpendType.SSRTX, - decred_tree=1, - ) - - out1 = proto.TxOutputType( - address="TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz", - amount=399900000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_input(1), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_8b6890), - request_input(0, TXHASH_8b6890), - request_input(1, TXHASH_8b6890), - request_output(0, TXHASH_8b6890), - request_output(1, TXHASH_8b6890), - request_output(2, TXHASH_8b6890), - request_input(1), - request_meta(TXHASH_1f00fc), - request_input(0, TXHASH_1f00fc), - request_output(0, TXHASH_1f00fc), - request_input(0), - request_input(1), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Decred Testnet", [inp1, inp2], [out1], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "010000000254e249113666e84c70de1dbee976f18d1438e4b7c58b376ffe64370ac190688b0200000001ffffffffc8e8dfb5c0e534b12adede611853a1f607c5b6912e03f577487c0d5354fc001f0000000001ffffffff0160fdd5170000000000001976a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac00000000000000000200c2eb0b0000000000000000ffffffff6b483045022100bdcb877c97d72db74eca06fefa21a7f7b00afcd5d916fce2155ed7df1ca5546102201e1f9efd7d652b449474c2c70171bfc4535544927bed62021f7334447d1ea4740121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd000c2eb0b0000000000000000ffffffff6a473044022030c5743c442bd696d19dcf73d54e95526e726de965c2e2b4b9fd70248eaae21d02201305a3bcc2bb0e33122277763990e3b48f317d61264a68d190fb8acfc004cc640121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" - ) - - def test_send_decred_change(self, client): - inp1 = proto.TxInputType( - # TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz - address_n=parse_path("m/44'/1'/0'/0/0"), - amount=190000000, - prev_hash=TXHASH_5e6e35, - prev_index=0, - script_type=proto.InputScriptType.SPENDADDRESS, - decred_tree=0, - ) - - inp2 = proto.TxInputType( - # TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz - address_n=parse_path("m/44'/1'/0'/0/0"), - amount=200000000, - prev_hash=TXHASH_ccf95b, - prev_index=1, - script_type=proto.InputScriptType.SPENDADDRESS, - decred_tree=0, - ) - - inp3 = proto.TxInputType( - # Tskt39YEvzoJ5KBDH4f1auNzG3jViVjZ2RV - address_n=parse_path("m/44'/1'/0'/0/1"), - amount=200000000, - prev_hash=TXHASH_f395ef, - prev_index=0, - script_type=proto.InputScriptType.SPENDADDRESS, - decred_tree=0, - ) - - out1 = proto.TxOutputType( address="TsWjioPrP8E1TuTMmTrVMM2BA4iPrjQXBpR", - amount=489975000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - out2 = proto.TxOutputType( - # TsaSFRwfN9muW5F6ZX36iSksc9hruiC5F97 - address_n=parse_path("m/44'/1'/0'/1/0"), - amount=100000000, + amount=300000000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) @@ -267,142 +371,41 @@ class TestMsgSigntxDecred: [ request_input(0), request_input(1), - request_input(2), request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), proto.ButtonRequest(code=B.SignTx), request_input(0), - request_meta(TXHASH_5e6e35), - request_input(0, TXHASH_5e6e35), - request_output(0, TXHASH_5e6e35), + request_meta(TXHASH_3f7c39), + request_input(0, TXHASH_3f7c39), + request_output(0, TXHASH_3f7c39), + request_output(1, TXHASH_3f7c39), request_input(1), - request_meta(TXHASH_ccf95b), - request_input(0, TXHASH_ccf95b), - request_output(0, TXHASH_ccf95b), - request_output(1, TXHASH_ccf95b), - request_input(2), - request_meta(TXHASH_f395ef), - request_input(0, TXHASH_f395ef), - request_output(0, TXHASH_f395ef), - request_output(1, TXHASH_f395ef), + request_meta(TXHASH_16da18), + request_input(0, TXHASH_16da18), + request_output(0, TXHASH_16da18), + request_output(1, TXHASH_16da18), request_input(0), request_input(1), - request_input(2), request_finished(), ] ) - _, serialized_tx = btc.sign_tx( + signature, serialized_tx = btc.sign_tx( client, "Decred Testnet", - [inp1, inp2, inp3], + [inp1, inp2], [out1, out2], prev_txes=TX_API, ) - assert ( - serialized_tx.hex() - == "010000000370b95980a47b9bcb4ec2c2b450888a53179b1a5fdb23f5023cc533a300356e5e0000000000ffffffff74bc93bcfce18aff2e522d6822817522e2815a00175b2eae59ef20d20f5bf9cc0100000000ffffffff13317ab453832deabd684d2302eed42580c28ba3e715db66a731a8723eef95f30000000000ffffffff02d86c341d0000000000001976a9143eb656115197956125365348c542e37b6d3d259988ac00e1f5050000000000001976a9143ee6f9d662e7be18373d80e5eb44627014c2bf6688ac000000000000000003802b530b0000000000000000ffffffff6a47304402200e50a6d43c462045917792e7d03b4354900c3baccb7abef66f556a32b12f2ca6022031ae94fdf2a41dd6ed2e081faf0f8f1c64411a1b46eb26f7f35d94402b2bde110121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd000c2eb0b0000000000000000ffffffff6a47304402204894c2f8e76c4645d2df600cdd01443aeb48807b72150c4bc10eebd126529532022054cd37462a3f0ddb85c75b4e874ab0c2aad7eebcff3e6c1ac20e1c16babe36720121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd000c2eb0b0000000000000000ffffffff6b4830450221009f1ba584023da8aafd57374e83be68f1a097b906967ec9e50736f31bfc7989f102204a190fc2885e394572b5c2ced046657b1dd07abdb19144e21e78987968c7f17601210294e3e5e77e22eea0e4c0d30d89beb4db7f69b4bf1ae709e411d6a06618b8f852" - ) + signatures[0][index] = signature[0] + signatures[1][index] = signature[1] + return serialized_tx - @pytest.mark.multisig - def test_decred_multisig_change(self, client): - paths = [parse_path(f"m/48'/1'/{index}'/0'") for index in range(3)] - nodes = [ - btc.get_public_node(client, address_n, coin_name="Decred Testnet").node - for address_n in paths - ] + test_multisig(2) + serialized_tx = test_multisig(0) - signatures = [[b"", b"", b""], [b"", b"", b""]] - - def create_multisig(index, address, signatures=None): - address_n = parse_path(address) - multisig = proto.MultisigRedeemScriptType( - nodes=nodes, address_n=address_n, signatures=signatures, m=2 - ) - - return (paths[index] + address_n), multisig - - def test_multisig(index): - address_n, multisig = create_multisig(index, "m/0/0", signatures[0]) - inp1 = proto.TxInputType( - address_n=address_n, - # TchpthUkRys1VQWgnQyLJNaA4MLBjVmRL2c - multisig=multisig, - amount=200000000, - prev_hash=TXHASH_3f7c39, - prev_index=1, - script_type=proto.InputScriptType.SPENDMULTISIG, - decred_tree=0, - ) - - address_n, multisig = create_multisig(index, "m/0/1", signatures[1]) - inp2 = proto.TxInputType( - address_n=address_n, - # TcnfDEfMhkM3oLWqiq9v9GmYgLK7qfjitKG - multisig=multisig, - amount=200000000, - prev_hash=TXHASH_16da18, - prev_index=0, - script_type=proto.InputScriptType.SPENDMULTISIG, - decred_tree=0, - ) - - address_n, multisig = create_multisig(index, "m/1/0") - out1 = proto.TxOutputType( - address_n=address_n, - # TcrrURA3Bzj4isGU48PdSP9SDoU5oCpjEcb - multisig=multisig, - amount=99900000, - script_type=proto.OutputScriptType.PAYTOMULTISIG, - ) - - out2 = proto.TxOutputType( - address="TsWjioPrP8E1TuTMmTrVMM2BA4iPrjQXBpR", - amount=300000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_input(1), - request_output(0), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_3f7c39), - request_input(0, TXHASH_3f7c39), - request_output(0, TXHASH_3f7c39), - request_output(1, TXHASH_3f7c39), - request_input(1), - request_meta(TXHASH_16da18), - request_input(0, TXHASH_16da18), - request_output(0, TXHASH_16da18), - request_output(1, TXHASH_16da18), - request_input(0), - request_input(1), - request_finished(), - ] - ) - signature, serialized_tx = btc.sign_tx( - client, - "Decred Testnet", - [inp1, inp2], - [out1, out2], - prev_txes=TX_API, - ) - - signatures[0][index] = signature[0] - signatures[1][index] = signature[1] - return serialized_tx - - test_multisig(2) - serialized_tx = test_multisig(0) - - assert ( - serialized_tx.hex() - == "01000000023f4c9e61b1cf469cad3785a03566ef23876217fe657561e78783d32155397c3f0100000000ffffffffa806ca135db5160eb91202506ce2645b215805149ce730a6850d74525018da160000000000ffffffff02605af40500000000000017a914d4ea4e064d969064ca56a4cede56f7bf6cf62f118700a3e1110000000000001976a9143eb656115197956125365348c542e37b6d3d259988ac00000000000000000200c2eb0b0000000000000000fffffffffc483045022100a35fd1ed579362ac65b583ba910a3d814c5e9b87da835993bf4166a6b3a8482b02204b3e167fad7d37dd62aa585c68d3c8e00c3c43bf7a25d74f6407870a4a7499e9014730440220720fd7b6dfd337056c5e6dad76e307b3758e702ccfd39471bf90e0db3a5f5eba02205bd062c78fcdd56057723a0e39d661a790f325e59e643b54c47b7218a5781684014c69522103defea6f243b97354449bb348446a97e38df2fbed33afc3a7185bfdd26757cfdb2103725d6c5253f2040a9a73af24bcc196bf302d6cc94374dd7197b138e10912670121038924e94fff15302a3fb45ad4fc0ed17178800f0f1c2bdacb1017f4db951aa9f153ae00c2eb0b0000000000000000fffffffffc4730440220625357288f0880be21d6a44275033fd84cf04bc23227eef810455ad711507e4402207d303548bb0476f98c52f223fe4430f82a78a73f757b186453948b0908f5af3101483045022100e140f586e370824b13576c77cf9f2855294fd415316f2a130126d8412a7cf08c0220308d1f5c83847458b271c93bfca5eba7fc1691b9c5d6e57955985affd1110e24014c695221021ef4b5d81f21593071b993bd4d8c564c569a6f84de0d4511135cbc66d8bf7bcd2103f1e53b6e0ff99adf7e8fa826a94bdac83163d8abbc1d19a8d6b88a4af91b9a67210390c8ea70e1f2f60e0052be65183c43bb01b2f02dfa4e448f74e359997f74e6ad53ae" - ) + assert ( + serialized_tx.hex() + == "01000000023f4c9e61b1cf469cad3785a03566ef23876217fe657561e78783d32155397c3f0100000000ffffffffa806ca135db5160eb91202506ce2645b215805149ce730a6850d74525018da160000000000ffffffff02605af40500000000000017a914d4ea4e064d969064ca56a4cede56f7bf6cf62f118700a3e1110000000000001976a9143eb656115197956125365348c542e37b6d3d259988ac00000000000000000200c2eb0b0000000000000000fffffffffc483045022100a35fd1ed579362ac65b583ba910a3d814c5e9b87da835993bf4166a6b3a8482b02204b3e167fad7d37dd62aa585c68d3c8e00c3c43bf7a25d74f6407870a4a7499e9014730440220720fd7b6dfd337056c5e6dad76e307b3758e702ccfd39471bf90e0db3a5f5eba02205bd062c78fcdd56057723a0e39d661a790f325e59e643b54c47b7218a5781684014c69522103defea6f243b97354449bb348446a97e38df2fbed33afc3a7185bfdd26757cfdb2103725d6c5253f2040a9a73af24bcc196bf302d6cc94374dd7197b138e10912670121038924e94fff15302a3fb45ad4fc0ed17178800f0f1c2bdacb1017f4db951aa9f153ae00c2eb0b0000000000000000fffffffffc4730440220625357288f0880be21d6a44275033fd84cf04bc23227eef810455ad711507e4402207d303548bb0476f98c52f223fe4430f82a78a73f757b186453948b0908f5af3101483045022100e140f586e370824b13576c77cf9f2855294fd415316f2a130126d8412a7cf08c0220308d1f5c83847458b271c93bfca5eba7fc1691b9c5d6e57955985affd1110e24014c695221021ef4b5d81f21593071b993bd4d8c564c569a6f84de0d4511135cbc66d8bf7bcd2103f1e53b6e0ff99adf7e8fa826a94bdac83163d8abbc1d19a8d6b88a4af91b9a67210390c8ea70e1f2f60e0052be65183c43bb01b2f02dfa4e448f74e359997f74e6ad53ae" + ) diff --git a/tests/device_tests/test_msg_signtx_grs.py b/tests/device_tests/test_msg_signtx_grs.py index fcba39b880..036e71ad6b 100644 --- a/tests/device_tests/test_msg_signtx_grs.py +++ b/tests/device_tests/test_msg_signtx_grs.py @@ -35,179 +35,182 @@ TXHASH_4f2f85 = bytes.fromhex( "4f2f857f39ed1afe05542d058fb0be865a387446e32fc876d086203f483f61d1" ) +pytestmark = pytest.mark.altcoin -@pytest.mark.altcoin -class TestMsgSigntxGRS: - def test_legacy(self, client): - inp1 = proto.TxInputType( - # FXHDsC5ZqWQHkDmShzgRVZ1MatpWhwxTAA - address_n=parse_path("44'/17'/0'/0/2"), - amount=210016, - prev_hash=TXHASH_cb74c8, - prev_index=0, - ) - out1 = proto.TxOutputType( - address="FtM4zAn9aVYgHgxmamWBgWPyZsb6RhvkA9", - amount=210016 - 192, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - _, serialized_tx = btc.sign_tx( - client, "Groestlcoin", [inp1], [out1], prev_txes=TX_API - ) - assert ( - serialized_tx.hex() - == "01000000014a9d1fdba915e0907ab02f04f88898863112a2b4fdcf872c7414588c47c874cb000000006a47304402201fb96d20d0778f54520ab59afe70d5fb20e500ecc9f02281cf57934e8029e8e10220383d5a3e80f2e1eb92765b6da0f23d454aecbd8236f083d483e9a7430236876101210331693756f749180aeed0a65a0fab0625a2250bd9abca502282a4cf0723152e67ffffffff01a0330300000000001976a914fe40329c95c5598ac60752a5310b320cb52d18e688ac00000000" - ) - def test_legacy_change(self, client): - inp1 = proto.TxInputType( - # FXHDsC5ZqWQHkDmShzgRVZ1MatpWhwxTAA - address_n=parse_path("44'/17'/0'/0/2"), - amount=210016, - prev_hash=TXHASH_cb74c8, - prev_index=0, - ) - out1 = proto.TxOutputType( - address_n=parse_path( - "44'/17'/0'/0/3" - ), # FtM4zAn9aVYgHgxmamWBgWPyZsb6RhvkA9 - amount=210016 - 192, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - _, serialized_tx = btc.sign_tx( - client, "Groestlcoin", [inp1], [out1], prev_txes=TX_API - ) - assert ( - serialized_tx.hex() - == "01000000014a9d1fdba915e0907ab02f04f88898863112a2b4fdcf872c7414588c47c874cb000000006a47304402201fb96d20d0778f54520ab59afe70d5fb20e500ecc9f02281cf57934e8029e8e10220383d5a3e80f2e1eb92765b6da0f23d454aecbd8236f083d483e9a7430236876101210331693756f749180aeed0a65a0fab0625a2250bd9abca502282a4cf0723152e67ffffffff01a0330300000000001976a914fe40329c95c5598ac60752a5310b320cb52d18e688ac00000000" - ) +def test_legacy(client): + inp1 = proto.TxInputType( + # FXHDsC5ZqWQHkDmShzgRVZ1MatpWhwxTAA + address_n=parse_path("44'/17'/0'/0/2"), + amount=210016, + prev_hash=TXHASH_cb74c8, + prev_index=0, + ) + out1 = proto.TxOutputType( + address="FtM4zAn9aVYgHgxmamWBgWPyZsb6RhvkA9", + amount=210016 - 192, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + _, serialized_tx = btc.sign_tx( + client, "Groestlcoin", [inp1], [out1], prev_txes=TX_API + ) + assert ( + serialized_tx.hex() + == "01000000014a9d1fdba915e0907ab02f04f88898863112a2b4fdcf872c7414588c47c874cb000000006a47304402201fb96d20d0778f54520ab59afe70d5fb20e500ecc9f02281cf57934e8029e8e10220383d5a3e80f2e1eb92765b6da0f23d454aecbd8236f083d483e9a7430236876101210331693756f749180aeed0a65a0fab0625a2250bd9abca502282a4cf0723152e67ffffffff01a0330300000000001976a914fe40329c95c5598ac60752a5310b320cb52d18e688ac00000000" + ) - def test_send_segwit_p2sh(self, client): - inp1 = proto.TxInputType( - # 2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7 - address_n=parse_path("49'/1'/0'/1/0"), - amount=123456789, - prev_hash=TXHASH_09a48b, - prev_index=0, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - sequence=0xFFFFFFFE, - ) - out1 = proto.TxOutputType( - address="mvbu1Gdy8SUjTenqerxUaZyYjmvedc787y", - amount=12300000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address="2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7", - amount=123456789 - 11000 - 12300000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - _, serialized_tx = btc.sign_tx( - client, - "Groestlcoin Testnet", - [inp1], - [out1, out2], - lock_time=650756, - prev_txes=TX_API_TESTNET, - ) - assert ( - serialized_tx.hex() - == "01000000000101cf60ded29a2bd7ebf93453feace8551889d0321beab90c4f6e5c9d2fce8ba4090000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5feffffff02e0aebb00000000001976a914a579388225827d9f2fe9014add644487808c695d88ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100b7ce2972bcbc3a661fe320ba901e680913b2753fcb47055c9c6ba632fc4acf81022001c3cfd6c2fe92eb60f5176ce0f43707114dd7223da19c56f2df89c13c2fef80012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7904ee0900" - ) - def test_send_segwit_p2sh_change(self, client): - inp1 = proto.TxInputType( - # 2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7 - address_n=parse_path("49'/1'/0'/1/0"), - amount=123456789, - prev_hash=TXHASH_09a48b, - prev_index=0, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - sequence=0xFFFFFFFE, - ) - out1 = proto.TxOutputType( - address="mvbu1Gdy8SUjTenqerxUaZyYjmvedc787y", - 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, - ) - _, serialized_tx = btc.sign_tx( - client, - "Groestlcoin Testnet", - [inp1], - [out1, out2], - lock_time=650756, - prev_txes=TX_API_TESTNET, - ) - assert ( - serialized_tx.hex() - == "01000000000101cf60ded29a2bd7ebf93453feace8551889d0321beab90c4f6e5c9d2fce8ba4090000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5feffffff02e0aebb00000000001976a914a579388225827d9f2fe9014add644487808c695d88ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100b7ce2972bcbc3a661fe320ba901e680913b2753fcb47055c9c6ba632fc4acf81022001c3cfd6c2fe92eb60f5176ce0f43707114dd7223da19c56f2df89c13c2fef80012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7904ee0900" - ) +def test_legacy_change(client): + inp1 = proto.TxInputType( + # FXHDsC5ZqWQHkDmShzgRVZ1MatpWhwxTAA + address_n=parse_path("44'/17'/0'/0/2"), + amount=210016, + prev_hash=TXHASH_cb74c8, + prev_index=0, + ) + out1 = proto.TxOutputType( + address_n=parse_path("44'/17'/0'/0/3"), # FtM4zAn9aVYgHgxmamWBgWPyZsb6RhvkA9 + amount=210016 - 192, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + _, serialized_tx = btc.sign_tx( + client, "Groestlcoin", [inp1], [out1], prev_txes=TX_API + ) + assert ( + serialized_tx.hex() + == "01000000014a9d1fdba915e0907ab02f04f88898863112a2b4fdcf872c7414588c47c874cb000000006a47304402201fb96d20d0778f54520ab59afe70d5fb20e500ecc9f02281cf57934e8029e8e10220383d5a3e80f2e1eb92765b6da0f23d454aecbd8236f083d483e9a7430236876101210331693756f749180aeed0a65a0fab0625a2250bd9abca502282a4cf0723152e67ffffffff01a0330300000000001976a914fe40329c95c5598ac60752a5310b320cb52d18e688ac00000000" + ) - def test_send_segwit_native(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("84'/1'/0'/0/0"), - amount=12300000, - prev_hash=TXHASH_4f2f85, - prev_index=0, - script_type=proto.InputScriptType.SPENDWITNESS, - sequence=0xFFFFFFFE, - ) - out1 = proto.TxOutputType( - address="2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e", - amount=5000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address="tgrs1qejqxwzfld7zr6mf7ygqy5s5se5xq7vmt9lkd57", - script_type=proto.OutputScriptType.PAYTOADDRESS, - amount=12300000 - 11000 - 5000000, - ) - _, serialized_tx = btc.sign_tx( - client, - "Groestlcoin Testnet", - [inp1], - [out1, out2], - lock_time=650713, - prev_txes=TX_API_TESTNET, - ) - assert ( - serialized_tx.hex() - == "01000000000101d1613f483f2086d076c82fe34674385a86beb08f052d5405fe1aed397f852f4f0000000000feffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b02483045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f862d9ed0900" - ) - def test_send_segwit_native_change(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("84'/1'/0'/0/0"), - amount=12300000, - prev_hash=TXHASH_4f2f85, - prev_index=0, - script_type=proto.InputScriptType.SPENDWITNESS, - sequence=0xFFFFFFFE, - ) - out1 = proto.TxOutputType( - address="2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e", - amount=5000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address_n=parse_path("84'/1'/0'/1/0"), - script_type=proto.OutputScriptType.PAYTOWITNESS, - amount=12300000 - 11000 - 5000000, - ) - _, serialized_tx = btc.sign_tx( - client, - "Groestlcoin Testnet", - [inp1], - [out1, out2], - lock_time=650713, - prev_txes=TX_API_TESTNET, - ) - assert ( - serialized_tx.hex() - == "01000000000101d1613f483f2086d076c82fe34674385a86beb08f052d5405fe1aed397f852f4f0000000000feffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b02483045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f862d9ed0900" - ) +def test_send_segwit_p2sh(client): + inp1 = proto.TxInputType( + # 2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7 + address_n=parse_path("49'/1'/0'/1/0"), + amount=123456789, + prev_hash=TXHASH_09a48b, + prev_index=0, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + sequence=0xFFFFFFFE, + ) + out1 = proto.TxOutputType( + address="mvbu1Gdy8SUjTenqerxUaZyYjmvedc787y", + amount=12300000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + address="2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7", + amount=123456789 - 11000 - 12300000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + _, serialized_tx = btc.sign_tx( + client, + "Groestlcoin Testnet", + [inp1], + [out1, out2], + lock_time=650756, + prev_txes=TX_API_TESTNET, + ) + assert ( + serialized_tx.hex() + == "01000000000101cf60ded29a2bd7ebf93453feace8551889d0321beab90c4f6e5c9d2fce8ba4090000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5feffffff02e0aebb00000000001976a914a579388225827d9f2fe9014add644487808c695d88ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100b7ce2972bcbc3a661fe320ba901e680913b2753fcb47055c9c6ba632fc4acf81022001c3cfd6c2fe92eb60f5176ce0f43707114dd7223da19c56f2df89c13c2fef80012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7904ee0900" + ) + + +def test_send_segwit_p2sh_change(client): + inp1 = proto.TxInputType( + # 2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7 + address_n=parse_path("49'/1'/0'/1/0"), + amount=123456789, + prev_hash=TXHASH_09a48b, + prev_index=0, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + sequence=0xFFFFFFFE, + ) + out1 = proto.TxOutputType( + address="mvbu1Gdy8SUjTenqerxUaZyYjmvedc787y", + 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, + ) + _, serialized_tx = btc.sign_tx( + client, + "Groestlcoin Testnet", + [inp1], + [out1, out2], + lock_time=650756, + prev_txes=TX_API_TESTNET, + ) + assert ( + serialized_tx.hex() + == "01000000000101cf60ded29a2bd7ebf93453feace8551889d0321beab90c4f6e5c9d2fce8ba4090000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5feffffff02e0aebb00000000001976a914a579388225827d9f2fe9014add644487808c695d88ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100b7ce2972bcbc3a661fe320ba901e680913b2753fcb47055c9c6ba632fc4acf81022001c3cfd6c2fe92eb60f5176ce0f43707114dd7223da19c56f2df89c13c2fef80012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7904ee0900" + ) + + +def test_send_segwit_native(client): + inp1 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/0/0"), + amount=12300000, + prev_hash=TXHASH_4f2f85, + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + sequence=0xFFFFFFFE, + ) + out1 = proto.TxOutputType( + address="2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e", + amount=5000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + address="tgrs1qejqxwzfld7zr6mf7ygqy5s5se5xq7vmt9lkd57", + script_type=proto.OutputScriptType.PAYTOADDRESS, + amount=12300000 - 11000 - 5000000, + ) + _, serialized_tx = btc.sign_tx( + client, + "Groestlcoin Testnet", + [inp1], + [out1, out2], + lock_time=650713, + prev_txes=TX_API_TESTNET, + ) + assert ( + serialized_tx.hex() + == "01000000000101d1613f483f2086d076c82fe34674385a86beb08f052d5405fe1aed397f852f4f0000000000feffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b02483045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f862d9ed0900" + ) + + +def test_send_segwit_native_change(client): + inp1 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/0/0"), + amount=12300000, + prev_hash=TXHASH_4f2f85, + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + sequence=0xFFFFFFFE, + ) + out1 = proto.TxOutputType( + address="2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e", + amount=5000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + address_n=parse_path("84'/1'/0'/1/0"), + script_type=proto.OutputScriptType.PAYTOWITNESS, + amount=12300000 - 11000 - 5000000, + ) + _, serialized_tx = btc.sign_tx( + client, + "Groestlcoin Testnet", + [inp1], + [out1, out2], + lock_time=650713, + prev_txes=TX_API_TESTNET, + ) + assert ( + serialized_tx.hex() + == "01000000000101d1613f483f2086d076c82fe34674385a86beb08f052d5405fe1aed397f852f4f0000000000feffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b02483045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f862d9ed0900" + ) diff --git a/tests/device_tests/test_msg_signtx_invalid_path.py b/tests/device_tests/test_msg_signtx_invalid_path.py index e393e74f5d..e9569371f0 100644 --- a/tests/device_tests/test_msg_signtx_invalid_path.py +++ b/tests/device_tests/test_msg_signtx_invalid_path.py @@ -32,88 +32,86 @@ TXHASH_d5f65e = bytes.fromhex( "d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882" ) +pytestmark = pytest.mark.altcoin -class TestMsgSigntxInvalidPath: +# Adapted from TestMsgSigntx.test_one_one_fee, +# only changed the coin from Bitcoin to Litecoin. +# Litecoin does not have strong replay protection using SIGHASH_FORKID, +# spending from Bitcoin path should fail. +def test_invalid_path_fail(client): + # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 + # input 0: 0.0039 BTC - # Adapted from TestMsgSigntx.test_one_one_fee, - # only changed the coin from Bitcoin to Litecoin. - # Litecoin does not have strong replay protection using SIGHASH_FORKID, - # spending from Bitcoin path should fail. - @pytest.mark.altcoin - def test_invalid_path_fail(self, client): - # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 - # input 0: 0.0039 BTC + inp1 = proto.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + amount=390000, + prev_hash=TXHASH_d5f65e, + prev_index=0, + ) - inp1 = proto.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - amount=390000, - prev_hash=TXHASH_d5f65e, - prev_index=0, - ) - - # address is converted from 1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1 by changing the version - out1 = proto.TxOutputType( - address="LfWz9wLHmqU9HoDkMg9NqbRosrHvEixeVZ", - amount=390000 - 10000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with pytest.raises(TrezorFailure) as exc: - btc.sign_tx(client, "Litecoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET) - - assert exc.value.code == proto.FailureType.DataError - assert exc.value.message.endswith("Forbidden key path") - - # Adapted from TestMsgSigntx.test_one_one_fee, - # only changed the coin from Bitcoin to Litecoin and set safety checks to prompt. - # Litecoin does not have strong replay protection using SIGHASH_FORKID, but - # spending from Bitcoin path should pass with safety checks set to prompt. - @pytest.mark.altcoin - def test_invalid_path_prompt(self, client): - # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 - # input 0: 0.0039 BTC - - inp1 = proto.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - amount=390000, - prev_hash=TXHASH_d5f65e, - prev_index=0, - ) - - # address is converted from 1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1 by changing the version - out1 = proto.TxOutputType( - address="LfWz9wLHmqU9HoDkMg9NqbRosrHvEixeVZ", - amount=390000 - 10000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - device.apply_settings( - client, safety_checks=proto.SafetyCheckLevel.PromptTemporarily - ) + # address is converted from 1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1 by changing the version + out1 = proto.TxOutputType( + address="LfWz9wLHmqU9HoDkMg9NqbRosrHvEixeVZ", + amount=390000 - 10000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + with pytest.raises(TrezorFailure) as exc: btc.sign_tx(client, "Litecoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET) - # Adapted from TestMsgSigntx.test_one_one_fee, - # only changed the coin from Bitcoin to Bcash. - # Bcash does have strong replay protection using SIGHASH_FORKID, - # spending from Bitcoin path should work. - @pytest.mark.altcoin - def test_invalid_path_pass_forkid(self, client): - # tx: 8cc1f4adf7224ce855cf535a5104594a0004cb3b640d6714fdb00b9128832dd5 - # input 0: 0.0039 BTC + assert exc.value.code == proto.FailureType.DataError + assert exc.value.message.endswith("Forbidden key path") - inp1 = proto.TxInputType( - address_n=parse_path("44h/0h/0h/0/0"), - amount=390000, - prev_hash=TXHASH_8cc1f4, - prev_index=0, - ) - # address is converted from 1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1 to cashaddr format - out1 = proto.TxOutputType( - address="bitcoincash:qr0fk25d5zygyn50u5w7h6jkvctas52n0qxff9ja6r", - amount=390000 - 10000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) +# Adapted from TestMsgSigntx.test_one_one_fee, +# only changed the coin from Bitcoin to Litecoin and set safety checks to prompt. +# Litecoin does not have strong replay protection using SIGHASH_FORKID, but +# spending from Bitcoin path should pass with safety checks set to prompt. +def test_invalid_path_prompt(client): + # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882 + # input 0: 0.0039 BTC - btc.sign_tx(client, "Bcash", [inp1], [out1], prev_txes=TX_CACHE_BCASH) + inp1 = proto.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + amount=390000, + prev_hash=TXHASH_d5f65e, + prev_index=0, + ) + + # address is converted from 1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1 by changing the version + out1 = proto.TxOutputType( + address="LfWz9wLHmqU9HoDkMg9NqbRosrHvEixeVZ", + amount=390000 - 10000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + device.apply_settings( + client, safety_checks=proto.SafetyCheckLevel.PromptTemporarily + ) + + btc.sign_tx(client, "Litecoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET) + + +# Adapted from TestMsgSigntx.test_one_one_fee, +# only changed the coin from Bitcoin to Bcash. +# Bcash does have strong replay protection using SIGHASH_FORKID, +# spending from Bitcoin path should work. +def test_invalid_path_pass_forkid(client): + # tx: 8cc1f4adf7224ce855cf535a5104594a0004cb3b640d6714fdb00b9128832dd5 + # input 0: 0.0039 BTC + + inp1 = proto.TxInputType( + address_n=parse_path("44h/0h/0h/0/0"), + amount=390000, + prev_hash=TXHASH_8cc1f4, + prev_index=0, + ) + + # address is converted from 1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1 to cashaddr format + out1 = proto.TxOutputType( + address="bitcoincash:qr0fk25d5zygyn50u5w7h6jkvctas52n0qxff9ja6r", + amount=390000 - 10000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + btc.sign_tx(client, "Bcash", [inp1], [out1], prev_txes=TX_CACHE_BCASH) diff --git a/tests/device_tests/test_msg_signtx_komodo.py b/tests/device_tests/test_msg_signtx_komodo.py index fd8f8b886a..a60a93b289 100644 --- a/tests/device_tests/test_msg_signtx_komodo.py +++ b/tests/device_tests/test_msg_signtx_komodo.py @@ -38,126 +38,126 @@ TXHASH_7b28bd = bytes.fromhex( "7b28bd91119e9776f0d4ebd80e570165818a829bbf4477cd1afe5149dbcd34b1" ) +pytestmark = [pytest.mark.altcoin, pytest.mark.komodo] -@pytest.mark.altcoin -@pytest.mark.komodo -class TestMsgSigntxKomodo: - def test_one_one_fee_sapling(self, client): - # prevout: 2807c5b126ec8e2b078cab0f12e4c8b4ce1d7724905f8ebef8dca26b0c8e0f1d:0 - # input 1: 10.9998 KMD - inp1 = proto.TxInputType( - # R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi - address_n=parse_path("44'/141'/0'/0/0"), - amount=1099980000, - prev_hash=TXHASH_2807c, - prev_index=0, +def test_one_one_fee_sapling(client): + # prevout: 2807c5b126ec8e2b078cab0f12e4c8b4ce1d7724905f8ebef8dca26b0c8e0f1d:0 + # input 1: 10.9998 KMD + + inp1 = proto.TxInputType( + # R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi + address_n=parse_path("44'/141'/0'/0/0"), + amount=1099980000, + prev_hash=TXHASH_2807c, + prev_index=0, + ) + + out1 = proto.TxOutputType( + address="R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi", + amount=1099980000 - 10000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_2807c), + request_input(0, TXHASH_2807c), + request_output(0, TXHASH_2807c), + request_extra_data(0, 11, TXHASH_2807c), + request_input(0), + request_output(0), + request_finished(), + ] ) - out1 = proto.TxOutputType( - address="R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi", - amount=1099980000 - 10000, - script_type=proto.OutputScriptType.PAYTOADDRESS, + _, serialized_tx = btc.sign_tx( + client, + "Komodo", + [inp1], + [out1], + version=4, + version_group_id=0x892F2085, + branch_id=0x76B809BB, + lock_time=0x5D2A30B8, + prev_txes=TX_API, ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_2807c), - request_input(0, TXHASH_2807c), - request_output(0, TXHASH_2807c), - request_extra_data(0, 11, TXHASH_2807c), - request_input(0), - request_output(0), - request_finished(), - ] - ) + # Accepted by network: tx 7b28bd91119e9776f0d4ebd80e570165818a829bbf4477cd1afe5149dbcd34b1 + assert ( + serialized_tx.hex() + == "0400008085202f89011d0f8e0c6ba2dcf8be8e5f9024771dceb4c8e4120fab8c072b8eec26b1c50728000000006a4730440220158c970ca2fc6bcc33026eb5366f0342f63b35d178f7efb334b1df78fe90b67202207bc4ff69f67cf843b08564a5adc77bf5593e28ab4d5104911824ac13fe885d8f012102a87aef7b1a8f676e452d6240767699719cd58b0261c822472c25df146938bca5ffffffff01d0359041000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acb8302a5d000000000000000000000000000000" + ) - _, serialized_tx = btc.sign_tx( - client, - "Komodo", - [inp1], - [out1], - version=4, - version_group_id=0x892F2085, - branch_id=0x76B809BB, - lock_time=0x5D2A30B8, - prev_txes=TX_API, - ) - # Accepted by network: tx 7b28bd91119e9776f0d4ebd80e570165818a829bbf4477cd1afe5149dbcd34b1 - assert ( - serialized_tx.hex() - == "0400008085202f89011d0f8e0c6ba2dcf8be8e5f9024771dceb4c8e4120fab8c072b8eec26b1c50728000000006a4730440220158c970ca2fc6bcc33026eb5366f0342f63b35d178f7efb334b1df78fe90b67202207bc4ff69f67cf843b08564a5adc77bf5593e28ab4d5104911824ac13fe885d8f012102a87aef7b1a8f676e452d6240767699719cd58b0261c822472c25df146938bca5ffffffff01d0359041000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acb8302a5d000000000000000000000000000000" +def test_one_one_rewards_claim(client): + # prevout: 7b28bd91119e9776f0d4ebd80e570165818a829bbf4477cd1afe5149dbcd34b1:0 + # input 1: 10.9997 KMD + + inp1 = proto.TxInputType( + # R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi + address_n=parse_path("44'/141'/0'/0/0"), + 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: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_7b28bd), + request_input(0, TXHASH_7b28bd), + request_output(0, TXHASH_7b28bd), + request_extra_data(0, 11, TXHASH_7b28bd), + request_input(0), + request_output(0), + request_output(1), + request_finished(), + ] ) - def test_one_one_rewards_claim(self, client): - # prevout: 7b28bd91119e9776f0d4ebd80e570165818a829bbf4477cd1afe5149dbcd34b1:0 - # input 1: 10.9997 KMD - - inp1 = proto.TxInputType( - # R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi - address_n=parse_path("44'/141'/0'/0/0"), - amount=1099970000, - prev_hash=TXHASH_7b28bd, - prev_index=0, + _, serialized_tx = btc.sign_tx( + client, + "Komodo", + [inp1], + [out1, out2], + prev_txes=TX_API, + version=4, + version_group_id=0x892F2085, + branch_id=0x76B809BB, + lock_time=0x5D2AF1F2, ) - 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: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_7b28bd), - request_input(0, TXHASH_7b28bd), - request_output(0, TXHASH_7b28bd), - request_extra_data(0, 11, TXHASH_7b28bd), - request_input(0), - request_output(0), - request_output(1), - request_finished(), - ] - ) - - _, serialized_tx = btc.sign_tx( - client, - "Komodo", - [inp1], - [out1, out2], - prev_txes=TX_API, - version=4, - version_group_id=0x892F2085, - branch_id=0x76B809BB, - lock_time=0x5D2AF1F2, - ) - - # Accepted by network: tx c775678ceb18277729b427c7acf2f8ce63ac02fc2366f47ce08a3f443ff0e059 - assert ( - serialized_tx.hex() - == "0400008085202f8901b134cddb4951fe1acd7744bf9b828a816501570ed8ebd4f076979e1191bd287b000000006a4730440220483a58f5be3a147c773c663008c992a7fcea4d03bdf4c1d4bc0535c0d98ddf0602207b19d69140dd00c7a94f048c712aeaed55dfd27f581c7212d9cc5e476fe1dc9f012102a87aef7b1a8f676e452d6240767699719cd58b0261c822472c25df146938bca5ffffffff02c00e9041000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acf5360100000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acf2f12a5d000000000000000000000000000000" - ) + # Accepted by network: tx c775678ceb18277729b427c7acf2f8ce63ac02fc2366f47ce08a3f443ff0e059 + assert ( + serialized_tx.hex() + == "0400008085202f8901b134cddb4951fe1acd7744bf9b828a816501570ed8ebd4f076979e1191bd287b000000006a4730440220483a58f5be3a147c773c663008c992a7fcea4d03bdf4c1d4bc0535c0d98ddf0602207b19d69140dd00c7a94f048c712aeaed55dfd27f581c7212d9cc5e476fe1dc9f012102a87aef7b1a8f676e452d6240767699719cd58b0261c822472c25df146938bca5ffffffff02c00e9041000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acf5360100000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acf2f12a5d000000000000000000000000000000" + ) diff --git a/tests/device_tests/test_msg_signtx_segwit.py b/tests/device_tests/test_msg_signtx_segwit.py index af143de8d6..317020d95a 100644 --- a/tests/device_tests/test_msg_signtx_segwit.py +++ b/tests/device_tests/test_msg_signtx_segwit.py @@ -40,397 +40,399 @@ TXHASH_e5040e = bytes.fromhex( ) -class TestMsgSigntxSegwit: - def test_send_p2sh(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("49'/1'/0'/1/0"), - # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX - amount=123456789, - prev_hash=TXHASH_20912f, - prev_index=0, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, +def test_send_p2sh(client): + inp1 = proto.TxInputType( + address_n=parse_path("49'/1'/0'/1/0"), + # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX + amount=123456789, + prev_hash=TXHASH_20912f, + prev_index=0, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + ) + out1 = proto.TxOutputType( + address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC", + amount=12300000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + address="2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX", + script_type=proto.OutputScriptType.PAYTOADDRESS, + amount=123456789 - 11000 - 12300000, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_20912f), + request_input(0, TXHASH_20912f), + request_output(0, TXHASH_20912f), + request_output(1, TXHASH_20912f), + request_input(0), + request_output(0), + request_output(1), + request_input(0), + request_finished(), + ] ) - out1 = proto.TxOutputType( - address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC", - amount=12300000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address="2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX", - script_type=proto.OutputScriptType.PAYTOADDRESS, - amount=123456789 - 11000 - 12300000, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_20912f), - request_input(0, TXHASH_20912f), - request_output(0, TXHASH_20912f), - request_output(1, TXHASH_20912f), - request_input(0), - request_output(0), - request_output(1), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_p2sh_change(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("49'/1'/0'/1/0"), - # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX - amount=123456789, - prev_hash=TXHASH_20912f, - 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 client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_20912f), - request_input(0, TXHASH_20912f), - request_output(0, TXHASH_20912f), - request_output(1, TXHASH_20912f), - request_input(0), - request_output(0), - request_output(1), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API - ) + assert ( + serialized_tx.hex() + == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" + ) - assert ( - serialized_tx.hex() - == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" + +def test_send_p2sh_change(client): + inp1 = proto.TxInputType( + address_n=parse_path("49'/1'/0'/1/0"), + # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX + amount=123456789, + prev_hash=TXHASH_20912f, + 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 client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_20912f), + request_input(0, TXHASH_20912f), + request_output(0, TXHASH_20912f), + request_output(1, TXHASH_20912f), + request_input(0), + request_output(0), + request_output(1), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) - def test_testnet_segwit_big_amount(self, client): - # This test is testing transaction with amount bigger than fits to uint32 + assert ( + serialized_tx.hex() + == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100ccd253bfdf8a5593cd7b6701370c531199f0f05a418cd547dfc7da3f21515f0f02203fa08a0753688871c220648f9edadbdb98af42e5d8269364a326572cf703895b012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" + ) - inp1 = proto.TxInputType( - address_n=parse_path("m/49'/1'/0'/0/0"), - amount=2 ** 32 + 1, - prev_hash=TXHASH_dee13c, - prev_index=0, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, + +def test_testnet_segwit_big_amount(client): + # This test is testing transaction with amount bigger than fits to uint32 + + inp1 = proto.TxInputType( + address_n=parse_path("m/49'/1'/0'/0/0"), + amount=2 ** 32 + 1, + prev_hash=TXHASH_dee13c, + prev_index=0, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + ) + out1 = proto.TxOutputType( + address="2Mt7P2BAfE922zmfXrdcYTLyR7GUvbwSEns", # seed allallall, bip32: m/49'/1'/0'/0/1, script type:p2shsegwit + amount=2 ** 32 + 1, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_dee13c), + request_output(0, TXHASH_dee13c), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] ) - out1 = proto.TxOutputType( - address="2Mt7P2BAfE922zmfXrdcYTLyR7GUvbwSEns", # seed allallall, bip32: m/49'/1'/0'/0/1, script type:p2shsegwit - amount=2 ** 32 + 1, - script_type=proto.OutputScriptType.PAYTOADDRESS, + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1], prev_txes=TX_API ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_dee13c), - request_output(0, TXHASH_dee13c), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1], prev_txes=TX_API - ) - assert ( - serialized_tx.hex() - == "01000000000101023a2995a4a60c59df1b9559b49b6d8940cb740d47cea10881b27a9e463ce1de00000000171600140099a7ecbd938ed1839f5f6bf6d50933c6db9d5cffffffff01010000000100000017a914097c569095163e84475d07aa95a1f736df895b7b8702483045022100965aa8897c7cd5f0bff830481ed5259bf662ed0415ab497a6a152a3c335eb0a1022060acbbbada909b6575ac6f19382a6bdf4cab2fa1c5421aa66677806f380ddb870121033add1f0e8e3c3136f7428dd4a4de1057380bd311f5b0856e2269170b4ffa65bf00000000" + assert ( + serialized_tx.hex() + == "01000000000101023a2995a4a60c59df1b9559b49b6d8940cb740d47cea10881b27a9e463ce1de00000000171600140099a7ecbd938ed1839f5f6bf6d50933c6db9d5cffffffff01010000000100000017a914097c569095163e84475d07aa95a1f736df895b7b8702483045022100965aa8897c7cd5f0bff830481ed5259bf662ed0415ab497a6a152a3c335eb0a1022060acbbbada909b6575ac6f19382a6bdf4cab2fa1c5421aa66677806f380ddb870121033add1f0e8e3c3136f7428dd4a4de1057380bd311f5b0856e2269170b4ffa65bf00000000" + ) + + +@pytest.mark.multisig +def test_send_multisig_1(client): + nodes = [ + btc.get_public_node( + client, parse_path(f"49'/1'/{i}'"), coin_name="Testnet" + ).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'/1'/1'/1/0"), + prev_hash=TXHASH_9c3192, + 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 client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_9c3192), + request_input(0, TXHASH_9c3192), + request_output(0, TXHASH_9c3192), + request_output(1, TXHASH_9c3192), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + signatures, _ = btc.sign_tx(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) + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_9c3192), + request_input(0, TXHASH_9c3192), + request_output(0, TXHASH_9c3192), + request_output(1, TXHASH_9c3192), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1], prev_txes=TX_API ) - @pytest.mark.multisig - def test_send_multisig_1(self, client): - nodes = [ - btc.get_public_node( - client, parse_path(f"49'/1'/{i}'"), coin_name="Testnet" - ).node - for i in range(1, 4) - ] + assert ( + serialized_tx.hex() + == "01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c0100000023220020cf28684ff8a6dda1a7a9704dde113ddfcf236558da5ce35ad3f8477474dbdaf7ffffffff01887d1800000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac040047304402203fc3fbe6cd6250d82ace4a585debc07587c07d2efc8bb56558c91e1f810fe65402206025bd9a4e80960f617b6e5bfdd568e34aa085d093471b7976e6b14c2a2402a7014730440220327abf491a57964d75c67fad204eb782fa74aa4abde40e5ad30fb0b7696102b7022049e31f2302417be0a87e2f818b93a862a7e67d4178b7cbeee680264f0882113f0169522103d54ab3c8b81cb7f8f8088df4c62c105e8acaa2fb53b180f6bc6f922faecf3fdc21036aa47994f3f18f0976d6073ca79997003c3fa29c4f93907998fefc1151b4529b2102a092580f2828272517c402da9461425c5032860ab40180e041fbbb88ea2a520453ae00000000" + ) - multisig = proto.MultisigRedeemScriptType( - nodes=nodes, address_n=[1, 0], signatures=[b"", b"", b""], m=2 + +def test_attack_change_input_address(client): + inp1 = proto.TxInputType( + address_n=parse_path("49'/1'/0'/1/0"), + # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX + amount=123456789, + prev_hash=TXHASH_20912f, + 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 client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_20912f), + request_input(0, TXHASH_20912f), + request_output(0, TXHASH_20912f), + request_output(1, TXHASH_20912f), + request_input(0), + request_output(0), + request_output(1), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) - inp1 = proto.TxInputType( - address_n=parse_path("49'/1'/1'/1/0"), - prev_hash=TXHASH_9c3192, - prev_index=1, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - multisig=multisig, - amount=1610436, + assert ( + serialized_tx.hex() + == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a9142f98413cb83ff8b3eaf1926192e68973cbd68a3a8702473044022013cbce7c575337ca05dbe03b5920a0805b510cd8dfd3180bd7c5d01cec6439cd0220050001be4bcefb585caf973caae0ffec682347f2127cc22f26efd93ee54fd852012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" + ) + + attack_count = 2 + + def attack_processor(msg): + nonlocal attack_count + + if attack_count > 0 and msg.tx.inputs and msg.tx.inputs[0] == inp1: + attack_count -= 1 + msg.tx.inputs[0].address_n[2] = H_(12) + + return msg + + # Now run the attack, must trigger the exception + with client: + client.set_filter(proto.TxAck, attack_processor) + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_20912f), + request_input(0, TXHASH_20912f), + request_output(0, TXHASH_20912f), + request_output(1, TXHASH_20912f), + request_input(0), + proto.Failure(code=proto.FailureType.ProcessError), + ] + ) + with pytest.raises(TrezorFailure) as exc: + btc.sign_tx(client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API) + assert exc.value.code == proto.FailureType.ProcessError + assert exc.value.message.endswith("Transaction has changed during signing") + + +def test_attack_mixed_inputs(client): + TRUE_AMOUNT = 123456789 + FAKE_AMOUNT = 120000000 + + inp1 = proto.TxInputType( + address_n=parse_path("44'/1'/0'/0/0"), + amount=31000000, + prev_hash=TXHASH_e5040e, + prev_index=0, + script_type=proto.InputScriptType.SPENDADDRESS, + sequence=0xFFFFFFFD, + ) + inp2 = proto.TxInputType( + address_n=parse_path("49'/1'/0'/1/0"), + amount=TRUE_AMOUNT, + prev_hash=TXHASH_20912f, + prev_index=0, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + sequence=0xFFFFFFFD, + ) + out1 = proto.TxOutputType( + address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC", + amount=31000000 + TRUE_AMOUNT - 3456789, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + expected_responses = [ + request_input(0), + request_input(1), + request_output(0), + proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), + proto.ButtonRequest(code=proto.ButtonRequestType.FeeOverThreshold), + proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), + request_input(0), + request_meta(TXHASH_e5040e), + request_input(0, TXHASH_e5040e), + request_output(0, TXHASH_e5040e), + request_output(1, TXHASH_e5040e), + request_input(1), + request_meta(TXHASH_20912f), + request_input(0, TXHASH_20912f), + request_output(0, TXHASH_20912f), + request_output(1, TXHASH_20912f), + request_input(0), + request_input(1), + request_output(0), + request_input(1), + request_output(0), + request_input(1), + request_finished(), + ] + + if client.features.model == "1": + # T1 asks for first input for witness again + expected_responses.insert(-2, request_input(0)) + + with client: + # Sign unmodified transaction. + # "Fee over threshold" warning is displayed - fee is the whole TRUE_AMOUNT + client.set_expected_responses(expected_responses) + btc.sign_tx( + client, + "Testnet", + [inp1, inp2], + [out1], + prev_txes=TX_API, ) - out1 = proto.TxOutputType( - address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC", - amount=1605000, - script_type=proto.OutputScriptType.PAYTOADDRESS, + # In Phase 1 make the user confirm a lower value of the segwit input. + inp2.amount = FAKE_AMOUNT + + if client.features.model == "1": + # T1 fails as soon as it encounters the fake amount. + expected_responses = ( + expected_responses[:4] + expected_responses[5:15] + [proto.Failure()] + ) + else: + expected_responses = ( + expected_responses[:4] + expected_responses[5:16] + [proto.Failure()] ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_9c3192), - request_input(0, TXHASH_9c3192), - request_output(0, TXHASH_9c3192), - request_output(1, TXHASH_9c3192), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - signatures, _ = btc.sign_tx( - 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) - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_9c3192), - request_input(0, TXHASH_9c3192), - request_output(0, TXHASH_9c3192), - request_output(1, TXHASH_9c3192), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c0100000023220020cf28684ff8a6dda1a7a9704dde113ddfcf236558da5ce35ad3f8477474dbdaf7ffffffff01887d1800000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac040047304402203fc3fbe6cd6250d82ace4a585debc07587c07d2efc8bb56558c91e1f810fe65402206025bd9a4e80960f617b6e5bfdd568e34aa085d093471b7976e6b14c2a2402a7014730440220327abf491a57964d75c67fad204eb782fa74aa4abde40e5ad30fb0b7696102b7022049e31f2302417be0a87e2f818b93a862a7e67d4178b7cbeee680264f0882113f0169522103d54ab3c8b81cb7f8f8088df4c62c105e8acaa2fb53b180f6bc6f922faecf3fdc21036aa47994f3f18f0976d6073ca79997003c3fa29c4f93907998fefc1151b4529b2102a092580f2828272517c402da9461425c5032860ab40180e041fbbb88ea2a520453ae00000000" + with pytest.raises(TrezorFailure) as e, client: + client.set_expected_responses(expected_responses) + btc.sign_tx( + client, + "Testnet", + [inp1, inp2], + [out1], + prev_txes=TX_API, ) - def test_attack_change_input_address(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("49'/1'/0'/1/0"), - # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX - amount=123456789, - prev_hash=TXHASH_20912f, - 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 client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_20912f), - request_input(0, TXHASH_20912f), - request_output(0, TXHASH_20912f), - request_output(1, TXHASH_20912f), - request_input(0), - request_output(0), - request_output(1), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac3df39f060000000017a9142f98413cb83ff8b3eaf1926192e68973cbd68a3a8702473044022013cbce7c575337ca05dbe03b5920a0805b510cd8dfd3180bd7c5d01cec6439cd0220050001be4bcefb585caf973caae0ffec682347f2127cc22f26efd93ee54fd852012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" - ) - - attack_count = 2 - - def attack_processor(msg): - nonlocal attack_count - - if attack_count > 0 and msg.tx.inputs and msg.tx.inputs[0] == inp1: - attack_count -= 1 - msg.tx.inputs[0].address_n[2] = H_(12) - - return msg - - # Now run the attack, must trigger the exception - with client: - client.set_filter(proto.TxAck, attack_processor) - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_20912f), - request_input(0, TXHASH_20912f), - request_output(0, TXHASH_20912f), - request_output(1, TXHASH_20912f), - request_input(0), - proto.Failure(code=proto.FailureType.ProcessError), - ] - ) - with pytest.raises(TrezorFailure) as exc: - btc.sign_tx(client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API) - assert exc.value.code == proto.FailureType.ProcessError - assert exc.value.message.endswith("Transaction has changed during signing") - - def test_attack_mixed_inputs(self, client): - TRUE_AMOUNT = 123456789 - FAKE_AMOUNT = 120000000 - - inp1 = proto.TxInputType( - address_n=parse_path("44'/1'/0'/0/0"), - amount=31000000, - prev_hash=TXHASH_e5040e, - prev_index=0, - script_type=proto.InputScriptType.SPENDADDRESS, - sequence=0xFFFFFFFD, - ) - inp2 = proto.TxInputType( - address_n=parse_path("49'/1'/0'/1/0"), - amount=TRUE_AMOUNT, - prev_hash=TXHASH_20912f, - prev_index=0, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - sequence=0xFFFFFFFD, - ) - out1 = proto.TxOutputType( - address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC", - amount=31000000 + TRUE_AMOUNT - 3456789, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - expected_responses = [ - request_input(0), - request_input(1), - request_output(0), - proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), - proto.ButtonRequest(code=proto.ButtonRequestType.FeeOverThreshold), - proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), - request_input(0), - request_meta(TXHASH_e5040e), - request_input(0, TXHASH_e5040e), - request_output(0, TXHASH_e5040e), - request_output(1, TXHASH_e5040e), - request_input(1), - request_meta(TXHASH_20912f), - request_input(0, TXHASH_20912f), - request_output(0, TXHASH_20912f), - request_output(1, TXHASH_20912f), - request_input(0), - request_input(1), - request_output(0), - request_input(1), - request_output(0), - request_input(1), - request_finished(), - ] - - if client.features.model == "1": - # T1 asks for first input for witness again - expected_responses.insert(-2, request_input(0)) - - with client: - # Sign unmodified transaction. - # "Fee over threshold" warning is displayed - fee is the whole TRUE_AMOUNT - client.set_expected_responses(expected_responses) - btc.sign_tx( - client, - "Testnet", - [inp1, inp2], - [out1], - prev_txes=TX_API, - ) - - # In Phase 1 make the user confirm a lower value of the segwit input. - inp2.amount = FAKE_AMOUNT - - if client.features.model == "1": - # T1 fails as soon as it encounters the fake amount. - expected_responses = ( - expected_responses[:4] + expected_responses[5:15] + [proto.Failure()] - ) - else: - expected_responses = ( - expected_responses[:4] + expected_responses[5:16] + [proto.Failure()] - ) - - with pytest.raises(TrezorFailure) as e, client: - client.set_expected_responses(expected_responses) - btc.sign_tx( - client, - "Testnet", - [inp1, inp2], - [out1], - prev_txes=TX_API, - ) - - assert e.value.failure.message.endswith("Invalid amount specified") + assert e.value.failure.message.endswith("Invalid amount specified") diff --git a/tests/device_tests/test_msg_signtx_segwit_native.py b/tests/device_tests/test_msg_signtx_segwit_native.py index 2e54e392a0..e262fdb16d 100644 --- a/tests/device_tests/test_msg_signtx_segwit_native.py +++ b/tests/device_tests/test_msg_signtx_segwit_native.py @@ -58,719 +58,712 @@ TXHASH_ec16dc = bytes.fromhex( ) -class TestMsgSigntxSegwitNative: - def test_send_p2sh(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("49'/1'/0'/1/0"), - # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX - amount=123456789, - prev_hash=TXHASH_20912f, - prev_index=0, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, +def test_send_p2sh(client): + inp1 = proto.TxInputType( + address_n=parse_path("49'/1'/0'/1/0"), + # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX + amount=123456789, + prev_hash=TXHASH_20912f, + prev_index=0, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + ) + out1 = proto.TxOutputType( + address="tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s", + amount=12300000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + address="2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX", + script_type=proto.OutputScriptType.PAYTOADDRESS, + amount=123456789 - 11000 - 12300000, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_20912f), + request_input(0, TXHASH_20912f), + request_output(0, TXHASH_20912f), + request_output(1, TXHASH_20912f), + request_input(0), + request_output(0), + request_output(1), + request_input(0), + request_finished(), + ] ) - out1 = proto.TxOutputType( - address="tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s", - amount=12300000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address="2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX", - script_type=proto.OutputScriptType.PAYTOADDRESS, - amount=123456789 - 11000 - 12300000, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_20912f), - request_input(0, TXHASH_20912f), - request_output(0, TXHASH_20912f), - request_output(1, TXHASH_20912f), - request_input(0), - request_output(0), - request_output(1), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001600140099a7ecbd938ed1839f5f6bf6d50933c6db9d5c3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100bd3d8b8ad35c094e01f6282277300e575f1021678fc63ec3f9945d6e35670da3022052e26ef0dd5f3741c9d5939d1dec5464c15ab5f2c85245e70a622df250d4eb7c012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_p2sh_change(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("49'/1'/0'/1/0"), - # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX - amount=123456789, - prev_hash=TXHASH_20912f, - prev_index=0, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - ) - out1 = proto.TxOutputType( - address="tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s", - amount=12300000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address_n=parse_path("49'/1'/0'/1/0"), - script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, - amount=123456789 - 11000 - 12300000, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_20912f), - request_input(0, TXHASH_20912f), - request_output(0, TXHASH_20912f), - request_output(1, TXHASH_20912f), - request_input(0), - request_output(0), - request_output(1), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API - ) + assert ( + serialized_tx.hex() + == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001600140099a7ecbd938ed1839f5f6bf6d50933c6db9d5c3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100bd3d8b8ad35c094e01f6282277300e575f1021678fc63ec3f9945d6e35670da3022052e26ef0dd5f3741c9d5939d1dec5464c15ab5f2c85245e70a622df250d4eb7c012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" + ) - assert ( - serialized_tx.hex() - == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001600140099a7ecbd938ed1839f5f6bf6d50933c6db9d5c3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100bd3d8b8ad35c094e01f6282277300e575f1021678fc63ec3f9945d6e35670da3022052e26ef0dd5f3741c9d5939d1dec5464c15ab5f2c85245e70a622df250d4eb7c012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" + +def test_send_p2sh_change(client): + inp1 = proto.TxInputType( + address_n=parse_path("49'/1'/0'/1/0"), + # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX + amount=123456789, + prev_hash=TXHASH_20912f, + prev_index=0, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + ) + out1 = proto.TxOutputType( + address="tb1qqzv60m9ajw8drqulta4ld4gfx0rdh82un5s65s", + amount=12300000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + address_n=parse_path("49'/1'/0'/1/0"), + script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, + amount=123456789 - 11000 - 12300000, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_20912f), + request_input(0, TXHASH_20912f), + request_output(0, TXHASH_20912f), + request_output(1, TXHASH_20912f), + request_input(0), + request_output(0), + request_output(1), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_native(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("84'/1'/0'/0/0"), - amount=12300000, - prev_hash=TXHASH_091446, - prev_index=0, - script_type=proto.InputScriptType.SPENDWITNESS, - ) - out1 = proto.TxOutputType( - address="2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp", - amount=5000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address="tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu", - script_type=proto.OutputScriptType.PAYTOADDRESS, - amount=12300000 - 11000 - 5000000, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_091446), - request_input(0, TXHASH_091446), - request_output(0, TXHASH_091446), - request_output(1, TXHASH_091446), - request_input(0), - request_output(0), - request_output(1), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API - ) + assert ( + serialized_tx.hex() + == "0100000000010137c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02e0aebb00000000001600140099a7ecbd938ed1839f5f6bf6d50933c6db9d5c3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100bd3d8b8ad35c094e01f6282277300e575f1021678fc63ec3f9945d6e35670da3022052e26ef0dd5f3741c9d5939d1dec5464c15ab5f2c85245e70a622df250d4eb7c012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7900000000" + ) - assert ( - serialized_tx.hex() - == "010000000001018a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014d16b8c0680c61fc6ed2e407455715055e41052f502473044022073ce72dcf2f6e42eeb44adbe7d5038cf3763f168d1c04bd8b873a19b53331f51022016b051725731e7f53a567021bcd9c370727f551c81e857ebae7c128472119652012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86200000000" + +def test_send_native(client): + inp1 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/0/0"), + amount=12300000, + prev_hash=TXHASH_091446, + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + ) + out1 = proto.TxOutputType( + address="2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp", + amount=5000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + address="tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu", + script_type=proto.OutputScriptType.PAYTOADDRESS, + amount=12300000 - 11000 - 5000000, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_091446), + request_input(0, TXHASH_091446), + request_output(0, TXHASH_091446), + request_output(1, TXHASH_091446), + request_input(0), + request_output(0), + request_output(1), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_to_taproot(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("84'/1'/0'/0/0"), - amount=10000, - prev_hash=TXHASH_ec16dc, - prev_index=0, - script_type=proto.InputScriptType.SPENDWITNESS, - ) - out1 = proto.TxOutputType( - address="tb1pdvdljpj774356dpk32c2ks0yqv7q7c4f98px2d9e76s73vpudpxs7tl6vp", - amount=7000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address="tb1qcc4ext5rsa8pzqa2m030jk670wmn5f649pu7sr", - script_type=proto.OutputScriptType.PAYTOADDRESS, - amount=10000 - 7000 - 200, - ) - with client: - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API - ) + assert ( + serialized_tx.hex() + == "010000000001018a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014d16b8c0680c61fc6ed2e407455715055e41052f502473044022073ce72dcf2f6e42eeb44adbe7d5038cf3763f168d1c04bd8b873a19b53331f51022016b051725731e7f53a567021bcd9c370727f551c81e857ebae7c128472119652012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86200000000" + ) - assert ( - serialized_tx.hex() - == "0100000000010131223ed7300b8707bdf87dc789c294520bbb7dc371741a00605d9c535adc16ec0000000000ffffffff02581b0000000000002251206b1bf9065ef5634d34368ab0ab41e4033c0f62a929c26534b9f6a1e8b03c684df00a000000000000160014c62b932e83874e1103aadbe2f95b5e7bb73a275502473044022008ce0e893e91935ada9a31fe6b2f6228070dd2a5bdebc413429e658be761901502207086e0d3aa6abbad29c966444d3b791e43c174f88154381d07c92a84fec7c527012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86200000000" + +def test_send_to_taproot(client): + inp1 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/0/0"), + amount=10000, + prev_hash=TXHASH_ec16dc, + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + ) + out1 = proto.TxOutputType( + address="tb1pdvdljpj774356dpk32c2ks0yqv7q7c4f98px2d9e76s73vpudpxs7tl6vp", + amount=7000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + address="tb1qcc4ext5rsa8pzqa2m030jk670wmn5f649pu7sr", + script_type=proto.OutputScriptType.PAYTOADDRESS, + amount=10000 - 7000 - 200, + ) + with client: + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_native_change(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("84'/1'/0'/0/0"), - amount=12300000, - prev_hash=TXHASH_091446, - prev_index=0, - script_type=proto.InputScriptType.SPENDWITNESS, - ) - out1 = proto.TxOutputType( - address="2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp", - amount=5000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - address_n=parse_path("84'/1'/0'/1/0"), - script_type=proto.OutputScriptType.PAYTOWITNESS, - amount=12300000 - 11000 - 5000000, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_091446), - request_input(0, TXHASH_091446), - request_output(0, TXHASH_091446), - request_output(1, TXHASH_091446), - request_input(0), - request_output(0), - request_output(1), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API - ) + assert ( + serialized_tx.hex() + == "0100000000010131223ed7300b8707bdf87dc789c294520bbb7dc371741a00605d9c535adc16ec0000000000ffffffff02581b0000000000002251206b1bf9065ef5634d34368ab0ab41e4033c0f62a929c26534b9f6a1e8b03c684df00a000000000000160014c62b932e83874e1103aadbe2f95b5e7bb73a275502473044022008ce0e893e91935ada9a31fe6b2f6228070dd2a5bdebc413429e658be761901502207086e0d3aa6abbad29c966444d3b791e43c174f88154381d07c92a84fec7c527012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86200000000" + ) - assert ( - serialized_tx.hex() - == "010000000001018a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b024730440220067675423ca6a0be3ddd5e13da00a9433775041e5cebc838873d2686f1d2840102201a5819e0312e6451d6b6180689101bce995685a51524cc4c3a5383f7bdab979a012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86200000000" + +def test_send_native_change(client): + inp1 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/0/0"), + amount=12300000, + prev_hash=TXHASH_091446, + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + ) + out1 = proto.TxOutputType( + address="2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp", + amount=5000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + address_n=parse_path("84'/1'/0'/1/0"), + script_type=proto.OutputScriptType.PAYTOWITNESS, + amount=12300000 - 11000 - 5000000, + ) + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_091446), + request_input(0, TXHASH_091446), + request_output(0, TXHASH_091446), + request_output(1, TXHASH_091446), + request_input(0), + request_output(0), + request_output(1), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1, out2], prev_txes=TX_API ) - def test_send_both(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("49'/1'/0'/1/0"), - # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX - amount=111145789, - prev_hash=TXHASH_091446, - prev_index=1, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, + assert ( + serialized_tx.hex() + == "010000000001018a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b024730440220067675423ca6a0be3ddd5e13da00a9433775041e5cebc838873d2686f1d2840102201a5819e0312e6451d6b6180689101bce995685a51524cc4c3a5383f7bdab979a012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86200000000" + ) + + +def test_send_both(client): + inp1 = proto.TxInputType( + address_n=parse_path("49'/1'/0'/1/0"), + # 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX + amount=111145789, + prev_hash=TXHASH_091446, + prev_index=1, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + ) + inp2 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/1/0"), + amount=7289000, + prev_hash=TXHASH_65b811, + prev_index=1, + script_type=proto.InputScriptType.SPENDWITNESS, + ) + out1 = proto.TxOutputType( + address="tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc", + amount=12300000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + out2 = proto.TxOutputType( + # address_n=parse_path("44'/1'/0'/0/0"), + # script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, + address="2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc", + script_type=proto.OutputScriptType.PAYTOADDRESS, + amount=45600000, + ) + out3 = proto.TxOutputType( + address="mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q", + amount=111145789 + 7289000 - 11000 - 12300000 - 45600000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_input(1), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(2), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_091446), + request_input(0, TXHASH_091446), + request_output(0, TXHASH_091446), + request_output(1, TXHASH_091446), + request_input(1), + request_meta(TXHASH_65b811), + request_input(0, TXHASH_65b811), + request_output(0, TXHASH_65b811), + request_output(1, TXHASH_65b811), + request_input(0), + request_input(1), + request_output(0), + request_output(1), + request_output(2), + request_input(0), + request_input(1), + request_finished(), + ] ) - inp2 = proto.TxInputType( - address_n=parse_path("84'/1'/0'/1/0"), - amount=7289000, - prev_hash=TXHASH_65b811, - prev_index=1, - script_type=proto.InputScriptType.SPENDWITNESS, - ) - out1 = proto.TxOutputType( - address="tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc", - amount=12300000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - out2 = proto.TxOutputType( - # address_n=parse_path("44'/1'/0'/0/0"), - # script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, - address="2N6UeBoqYEEnybg4cReFYDammpsyDw8R2Mc", - script_type=proto.OutputScriptType.PAYTOADDRESS, - amount=45600000, - ) - out3 = proto.TxOutputType( - address="mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q", - amount=111145789 + 7289000 - 11000 - 12300000 - 45600000, - script_type=proto.OutputScriptType.PAYTOADDRESS, + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1, inp2], [out1, out2, out3], prev_txes=TX_API ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_input(1), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(2), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_091446), - request_input(0, TXHASH_091446), - request_output(0, TXHASH_091446), - request_output(1, TXHASH_091446), - request_input(1), - request_meta(TXHASH_65b811), - request_input(0, TXHASH_65b811), - request_output(0, TXHASH_65b811), - request_output(1, TXHASH_65b811), - request_input(0), - request_input(1), - request_output(0), - request_output(1), - request_output(2), - request_input(0), - request_input(1), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1, inp2], [out1, out2, out3], prev_txes=TX_API - ) + assert ( + serialized_tx.hex() + == "010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090100000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff03e0aebb0000000000160014a579388225827d9f2fe9014add644487808c695d00cdb7020000000017a91491233e24a9bf8dbb19c1187ad876a9380c12e787870d859b03000000001976a914a579388225827d9f2fe9014add644487808c695d88ac02483045022100ead79ee134f25bb585b48aee6284a4bb14e07f03cc130253e83450d095515e5202201e161e9402c8b26b666f2b67e5b668a404ef7e57858ae9a6a68c3837e65fdc69012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7902463043021f585c54a84dc7326fa60e22729accd41153c7dd4725bd4c8f751aa3a8cd8d6a0220631bfd83fc312cc6d5d129572a25178696d81eaf50c8c3f16c6121be4f4c029d012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f00000000" + ) - assert ( - serialized_tx.hex() - == "010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090100000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff03e0aebb0000000000160014a579388225827d9f2fe9014add644487808c695d00cdb7020000000017a91491233e24a9bf8dbb19c1187ad876a9380c12e787870d859b03000000001976a914a579388225827d9f2fe9014add644487808c695d88ac02483045022100ead79ee134f25bb585b48aee6284a4bb14e07f03cc130253e83450d095515e5202201e161e9402c8b26b666f2b67e5b668a404ef7e57858ae9a6a68c3837e65fdc69012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7902463043021f585c54a84dc7326fa60e22729accd41153c7dd4725bd4c8f751aa3a8cd8d6a0220631bfd83fc312cc6d5d129572a25178696d81eaf50c8c3f16c6121be4f4c029d012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f00000000" + +@pytest.mark.multisig +def test_send_multisig_1(client): + nodes = [ + btc.get_public_node(client, parse_path(f"49'/1'/{index}'"), coin_name="Testnet") + 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, + ) + + inp1 = proto.TxInputType( + address_n=parse_path("49'/1'/1'/0/0"), + prev_hash=TXHASH_9c3192, + prev_index=1, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + multisig=multisig, + amount=1610436, + ) + + out1 = proto.TxOutputType( + address="tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy", + amount=1605000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_9c3192), + request_input(0, TXHASH_9c3192), + request_output(0, TXHASH_9c3192), + request_output(1, TXHASH_9c3192), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + signatures, _ = btc.sign_tx(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) + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_9c3192), + request_input(0, TXHASH_9c3192), + request_output(0, TXHASH_9c3192), + request_output(1, TXHASH_9c3192), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1], prev_txes=TX_API ) - @pytest.mark.multisig - def test_send_multisig_1(self, client): - nodes = [ - btc.get_public_node( - client, parse_path(f"49'/1'/{index}'"), coin_name="Testnet" - ) - 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, + assert ( + serialized_tx.hex() + == "01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200208d398cfb58a1d9cdb59ccbce81559c095e8c6f4a3e64966ca385078d9879f95effffffff01887d180000000000220020c5f4a0a4ea7c0392efe0a9670a73264cffa90b19107cd8a8e9750ff93c77fdfb0400483045022100dd6342c65197af27d7894d8b8b88b16b568ee3b5ebfdc55fdfb7caa9650e3b4c02200c7074a5bcb0068f63d9014c7cd2b0490aba75822d315d41aad444e9b86adf5201483045022100e7e6c2d21109512ba0609e93903e84bfb7731ac3962ee2c1cad54a7a30ff99a20220421497930226c39fc3834e8d6da3fc876516239518b0e82e2dc1e3c46271a17c01695221021630971f20fa349ba940a6ba3706884c41579cd760c89901374358db5dd545b92102f2ff4b353702d2bb03d4c494be19d77d0ab53d16161b53fbcaf1afeef4ad0cb52103e9b6b1c691a12ce448f1aedbbd588e064869c79fbd760eae3b8cd8a5f1a224db53ae00000000" + ) + + +@pytest.mark.multisig +def test_send_multisig_2(client): + nodes = [ + btc.get_public_node(client, parse_path(f"84'/1'/{index}'"), coin_name="Testnet") + for index in range(1, 4) + ] + multisig = proto.MultisigRedeemScriptType( + nodes=[deserialize(n.xpub) for n in nodes], + address_n=[0, 1], + signatures=[b"", b"", b""], + m=2, + ) + + inp1 = proto.TxInputType( + address_n=parse_path("84'/1'/2'/0/1"), + prev_hash=TXHASH_f41cbe, + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + multisig=multisig, + amount=1605000, + ) + + out1 = proto.TxOutputType( + address="tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z", + amount=1604000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_f41cbe), + request_input(0, TXHASH_f41cbe), + request_output(0, TXHASH_f41cbe), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + signatures, _ = btc.sign_tx(client, "Testnet", [inp1], [out1], prev_txes=TX_API) + # store signature + inp1.multisig.signatures[1] = signatures[0] + # sign with first key + inp1.address_n[2] = H_(1) + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_f41cbe), + request_input(0, TXHASH_f41cbe), + request_output(0, TXHASH_f41cbe), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1], prev_txes=TX_API ) - inp1 = proto.TxInputType( - address_n=parse_path("49'/1'/1'/0/0"), - prev_hash=TXHASH_9c3192, - prev_index=1, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - multisig=multisig, - amount=1610436, + assert ( + serialized_tx.hex() + == "010000000001012812fe3916f228cda6c7b57d5464541265a63ad118f430a805eeec8bddbe1cf40000000000ffffffff01a0791800000000002200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a10400473044022001b7f4f21a8ddcd5e0faaaee3b95515bf8b84f2a7cbfdf66996c64123617a5cf02202fc6a776a7225420dbca759ad4ac83a61d15bf8d2883b6bf1aa31de7437f9b6e0147304402206c4125c1189a3b3e93a77cdf54c60c0538b80e5a03ec74e6ac776dfa77706ee4022035be14de76259b9d8a24863131a06a65b95df02f7d3ace90d52b37e8d94b167f0169522103bab8ecdd9ae2c51a0dc858f4c751b27533143bf6013ba1725ba8a4ecebe7de8c21027d5e55696c875308b03f2ca3d8637f51d3e35da9456a5187aa14b3de8a89534f2103b78eabaea8b3a4868be4f4bb96d6f66973f7081faa7f1cafba321444611c241e53ae00000000" + ) + + +@pytest.mark.multisig +def test_send_multisig_3_change(client): + nodes = [ + btc.get_public_node(client, parse_path(f"84'/1'/{index}'"), coin_name="Testnet") + for index in range(1, 4) + ] + multisig = proto.MultisigRedeemScriptType( + nodes=[deserialize(n.xpub) for n in nodes], + address_n=[1, 0], + signatures=[b"", b"", b""], + m=2, + ) + multisig2 = proto.MultisigRedeemScriptType( + nodes=[deserialize(n.xpub) for n in nodes], + address_n=[1, 1], + signatures=[b"", b"", b""], + m=2, + ) + + inp1 = proto.TxInputType( + address_n=parse_path("84'/1'/1'/1/0"), + prev_hash=TXHASH_c93480, + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + multisig=multisig, + amount=1604000, + ) + + out1 = proto.TxOutputType( + address_n=parse_path("84'/1'/1'/1/1"), + amount=1603000, + multisig=multisig2, + script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_c93480), + request_input(0, TXHASH_c93480), + request_output(0, TXHASH_c93480), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + signatures, _ = btc.sign_tx(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) + out1.address_n[2] = H_(3) + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_c93480), + request_input(0, TXHASH_c93480), + request_output(0, TXHASH_c93480), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1], prev_txes=TX_API ) - out1 = proto.TxOutputType( - address="tb1qch62pf820spe9mlq49ns5uexfnl6jzcezp7d328fw58lj0rhlhasge9hzy", - amount=1605000, - script_type=proto.OutputScriptType.PAYTOADDRESS, + assert ( + serialized_tx.hex() + == "01000000000101fc7901dd033f8c02da14f3ac916b6498036b80b4a0b4dc124e02c2bb408034c90000000000ffffffff01b87518000000000017a914536250d41937e5b641082447580ff6a8e46c122a870400473044022003c26107a5a47f1f900ef8aa758977530cd13ea37a33971abae8d75cac2f9f34022039e2b8c2c1d0c24ff4fc026652e1f27ad8e3ed6c9bf485f61d9aa691cb57830801483045022100963b0dc0ab46e963a66ab6e69e5e41bac6c4fedc127cac12c560b029d54fe87402205b3bcdcf313dccd78e5dce0540e7d3c8cc1bf83f13c1f9f01811eb791fd35c8101695221039dba3a72f5dc3cad17aa924b5a03c34561465f997d0cb15993f2ca2c0be771c42103cd39f3f08bbd508dce4d307d57d0c70c258c285878bfda579fa260acc738c25d2102cd631ba95beca1d64766f5540885092d0bb384a3c13b6c3a5334d0ebacf51b9553ae00000000" + ) + + +@pytest.mark.multisig +def test_send_multisig_4_change(client): + nodes = [ + btc.get_public_node(client, parse_path(f"49'/1'/{index}'"), coin_name="Testnet") + for index in range(1, 4) + ] + multisig = proto.MultisigRedeemScriptType( + nodes=[deserialize(n.xpub) for n in nodes], + address_n=[1, 1], + signatures=[b"", b"", b""], + m=2, + ) + multisig2 = proto.MultisigRedeemScriptType( + nodes=[deserialize(n.xpub) for n in nodes], + address_n=[1, 2], + signatures=[b"", b"", b""], + m=2, + ) + + inp1 = proto.TxInputType( + address_n=parse_path("49'/1'/1'/1/1"), + prev_hash=TXHASH_31bc1c, + prev_index=0, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + multisig=multisig, + amount=1603000, + ) + + out1 = proto.TxOutputType( + address_n=parse_path("49'/1'/1'/1/2"), + amount=1602000, + multisig=multisig2, + script_type=proto.OutputScriptType.PAYTOWITNESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_31bc1c), + request_input(0, TXHASH_31bc1c), + request_output(0, TXHASH_31bc1c), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + signatures, _ = btc.sign_tx(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) + out1.address_n[2] = H_(3) + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_31bc1c), + request_input(0, TXHASH_31bc1c), + request_output(0, TXHASH_31bc1c), + request_input(0), + request_output(0), + request_input(0), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1], [out1], prev_txes=TX_API ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_9c3192), - request_input(0, TXHASH_9c3192), - request_output(0, TXHASH_9c3192), - request_output(1, TXHASH_9c3192), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - signatures, _ = btc.sign_tx( - 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) - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_9c3192), - request_input(0, TXHASH_9c3192), - request_output(0, TXHASH_9c3192), - request_output(1, TXHASH_9c3192), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1], prev_txes=TX_API - ) + assert ( + serialized_tx.hex() + == "01000000000101e5918f661488bb7f0a7d04fc1dad61b5d0bad5167a05b3a637e36ace881cbc310000000023220020fa6c73de618ec134eeec0c16f6dd04d46d4347e9a4fd0a95fd7938403a4949f9ffffffff01d071180000000000220020bcea2324dacbcde5a9db90cc26b8df9cbc72010e05cb68cf034df6f0e05239a2040047304402206bbddb45f12e31e77610fd85b50a83bad4426433b1c4860b1c5ddc0a69f803720220087b0607daab14830f4b4941f16b953b38e606ad70029bac24af7267f93c4242014730440220551a0cb6b0d5b3fa0cfd0b07bb5d751494b827b1c6a08702186696cfbc18278302204f37c382876c4117cca656654599b508f2d55fc3b083dc938e3cd8491b29719601695221036a5ec3abd10501409092246fe59c6d7a15fff1a933479483c3ba98b866c5b9742103559be875179d44e438db2c74de26e0bc9842cbdefd16018eae8a2ed989e474722103067b56aad037cd8b5f569b21f9025b76470a72dc69457813d2b76e98dc0cd01a53ae00000000" + ) - assert ( - serialized_tx.hex() - == "01000000000101be0210025c5be68a473f6a38bf53b53bc88d5c46567616026dc056e72b92319c01000000232200208d398cfb58a1d9cdb59ccbce81559c095e8c6f4a3e64966ca385078d9879f95effffffff01887d180000000000220020c5f4a0a4ea7c0392efe0a9670a73264cffa90b19107cd8a8e9750ff93c77fdfb0400483045022100dd6342c65197af27d7894d8b8b88b16b568ee3b5ebfdc55fdfb7caa9650e3b4c02200c7074a5bcb0068f63d9014c7cd2b0490aba75822d315d41aad444e9b86adf5201483045022100e7e6c2d21109512ba0609e93903e84bfb7731ac3962ee2c1cad54a7a30ff99a20220421497930226c39fc3834e8d6da3fc876516239518b0e82e2dc1e3c46271a17c01695221021630971f20fa349ba940a6ba3706884c41579cd760c89901374358db5dd545b92102f2ff4b353702d2bb03d4c494be19d77d0ab53d16161b53fbcaf1afeef4ad0cb52103e9b6b1c691a12ce448f1aedbbd588e064869c79fbd760eae3b8cd8a5f1a224db53ae00000000" + +# Ensure that if there is a non-multisig input, then a multisig output +# will not be identified as a change output. +def test_multisig_mismatch_inputs_single(client): + # m/84'/1'/0' for "alcohol woman abuse ..." seed. + node_int = deserialize( + "Vpub5kFDCYhiYuAzjk7TBQPNFffbexHF7iAd8AVVgHQKUany7e6NQvthgk86d7DfH57DY2dwBK4PyVTDDaS1r2gjkdyJyUYGoV9qNujGSrW9Dpe" + ) + + # m/84'/1'/0' for "all all ... all" seed. + node_ext = deserialize( + "Vpub5jR76XyyhBaQXPSRf3PBeY3gF914d9sf7DWFVhMESEQMCdNv35XiVvp8gZsFXAv222VPHLNnAEXxMPG8DPiSuhAXfEydBf55LTLBGHCDzH2" + ) + + # tb1qpzmgzpcumztvmpu3q27wwdggqav26j9dgks92pvnne2lz9ferxgssmhzlq + multisig_in = proto.MultisigRedeemScriptType( + nodes=[node_int, node_ext], address_n=[0, 0], signatures=[b"", b""], m=1 + ) + + multisig_out = proto.MultisigRedeemScriptType( + nodes=[node_int, node_ext], address_n=[1, 0], signatures=[b"", b""], m=1 + ) + + inp1 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/0/0"), + amount=12300000, + prev_hash=TXHASH_091446, + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + ) + + inp2 = proto.TxInputType( + address_n=parse_path("84'/1'/0'/0/0"), + prev_hash=TXHASH_a345b8, + prev_index=0, + script_type=proto.InputScriptType.SPENDWITNESS, + multisig=multisig_in, + amount=100, + ) + + out1 = proto.TxOutputType( + address="2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp", + amount=5000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + out2 = proto.TxOutputType( + address_n=parse_path("84'/1'/0'/1/0"), + script_type=proto.OutputScriptType.PAYTOWITNESS, + multisig=multisig_out, + amount=12300000 + 100 - 5000000 - 10000, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_input(1), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + # Ensure that the multisig output is not identified as a change output. + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_091446), + request_input(0, TXHASH_091446), + request_output(0, TXHASH_091446), + request_output(1, TXHASH_091446), + request_input(1), + request_meta(TXHASH_a345b8), + request_input(0, TXHASH_a345b8), + request_output(0, TXHASH_a345b8), + request_input(0), + request_input(1), + request_output(0), + request_output(1), + request_input(0), + request_input(1), + request_finished(), + ] ) - @pytest.mark.multisig - def test_send_multisig_2(self, client): - nodes = [ - btc.get_public_node( - client, parse_path(f"84'/1'/{index}'"), coin_name="Testnet" - ) - for index in range(1, 4) - ] - multisig = proto.MultisigRedeemScriptType( - nodes=[deserialize(n.xpub) for n in nodes], - address_n=[0, 1], - signatures=[b"", b"", b""], - m=2, + _, serialized_tx = btc.sign_tx( + client, "Testnet", [inp1, inp2], [out1, out2], prev_txes=TX_API ) - inp1 = proto.TxInputType( - address_n=parse_path("84'/1'/2'/0/1"), - prev_hash=TXHASH_f41cbe, - prev_index=0, - script_type=proto.InputScriptType.SPENDWITNESS, - multisig=multisig, - amount=1605000, - ) - - out1 = proto.TxOutputType( - address="tb1qr6xa5v60zyt3ry9nmfew2fk5g9y3gerkjeu6xxdz7qga5kknz2ssld9z2z", - amount=1604000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_f41cbe), - request_input(0, TXHASH_f41cbe), - request_output(0, TXHASH_f41cbe), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - signatures, _ = btc.sign_tx( - client, "Testnet", [inp1], [out1], prev_txes=TX_API - ) - # store signature - inp1.multisig.signatures[1] = signatures[0] - # sign with first key - inp1.address_n[2] = H_(1) - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_f41cbe), - request_input(0, TXHASH_f41cbe), - request_output(0, TXHASH_f41cbe), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "010000000001012812fe3916f228cda6c7b57d5464541265a63ad118f430a805eeec8bddbe1cf40000000000ffffffff01a0791800000000002200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a10400473044022001b7f4f21a8ddcd5e0faaaee3b95515bf8b84f2a7cbfdf66996c64123617a5cf02202fc6a776a7225420dbca759ad4ac83a61d15bf8d2883b6bf1aa31de7437f9b6e0147304402206c4125c1189a3b3e93a77cdf54c60c0538b80e5a03ec74e6ac776dfa77706ee4022035be14de76259b9d8a24863131a06a65b95df02f7d3ace90d52b37e8d94b167f0169522103bab8ecdd9ae2c51a0dc858f4c751b27533143bf6013ba1725ba8a4ecebe7de8c21027d5e55696c875308b03f2ca3d8637f51d3e35da9456a5187aa14b3de8a89534f2103b78eabaea8b3a4868be4f4bb96d6f66973f7081faa7f1cafba321444611c241e53ae00000000" - ) - - @pytest.mark.multisig - def test_send_multisig_3_change(self, client): - nodes = [ - btc.get_public_node( - client, parse_path(f"84'/1'/{index}'"), coin_name="Testnet" - ) - for index in range(1, 4) - ] - multisig = proto.MultisigRedeemScriptType( - nodes=[deserialize(n.xpub) for n in nodes], - address_n=[1, 0], - signatures=[b"", b"", b""], - m=2, - ) - multisig2 = proto.MultisigRedeemScriptType( - nodes=[deserialize(n.xpub) for n in nodes], - address_n=[1, 1], - signatures=[b"", b"", b""], - m=2, - ) - - inp1 = proto.TxInputType( - address_n=parse_path("84'/1'/1'/1/0"), - prev_hash=TXHASH_c93480, - prev_index=0, - script_type=proto.InputScriptType.SPENDWITNESS, - multisig=multisig, - amount=1604000, - ) - - out1 = proto.TxOutputType( - address_n=parse_path("84'/1'/1'/1/1"), - amount=1603000, - multisig=multisig2, - script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_c93480), - request_input(0, TXHASH_c93480), - request_output(0, TXHASH_c93480), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - signatures, _ = btc.sign_tx( - 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) - out1.address_n[2] = H_(3) - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_c93480), - request_input(0, TXHASH_c93480), - request_output(0, TXHASH_c93480), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "01000000000101fc7901dd033f8c02da14f3ac916b6498036b80b4a0b4dc124e02c2bb408034c90000000000ffffffff01b87518000000000017a914536250d41937e5b641082447580ff6a8e46c122a870400473044022003c26107a5a47f1f900ef8aa758977530cd13ea37a33971abae8d75cac2f9f34022039e2b8c2c1d0c24ff4fc026652e1f27ad8e3ed6c9bf485f61d9aa691cb57830801483045022100963b0dc0ab46e963a66ab6e69e5e41bac6c4fedc127cac12c560b029d54fe87402205b3bcdcf313dccd78e5dce0540e7d3c8cc1bf83f13c1f9f01811eb791fd35c8101695221039dba3a72f5dc3cad17aa924b5a03c34561465f997d0cb15993f2ca2c0be771c42103cd39f3f08bbd508dce4d307d57d0c70c258c285878bfda579fa260acc738c25d2102cd631ba95beca1d64766f5540885092d0bb384a3c13b6c3a5334d0ebacf51b9553ae00000000" - ) - - @pytest.mark.multisig - def test_send_multisig_4_change(self, client): - nodes = [ - btc.get_public_node( - client, parse_path(f"49'/1'/{index}'"), coin_name="Testnet" - ) - for index in range(1, 4) - ] - multisig = proto.MultisigRedeemScriptType( - nodes=[deserialize(n.xpub) for n in nodes], - address_n=[1, 1], - signatures=[b"", b"", b""], - m=2, - ) - multisig2 = proto.MultisigRedeemScriptType( - nodes=[deserialize(n.xpub) for n in nodes], - address_n=[1, 2], - signatures=[b"", b"", b""], - m=2, - ) - - inp1 = proto.TxInputType( - address_n=parse_path("49'/1'/1'/1/1"), - prev_hash=TXHASH_31bc1c, - prev_index=0, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - multisig=multisig, - amount=1603000, - ) - - out1 = proto.TxOutputType( - address_n=parse_path("49'/1'/1'/1/2"), - amount=1602000, - multisig=multisig2, - script_type=proto.OutputScriptType.PAYTOWITNESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_31bc1c), - request_input(0, TXHASH_31bc1c), - request_output(0, TXHASH_31bc1c), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - signatures, _ = btc.sign_tx( - 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) - out1.address_n[2] = H_(3) - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_31bc1c), - request_input(0, TXHASH_31bc1c), - request_output(0, TXHASH_31bc1c), - request_input(0), - request_output(0), - request_input(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1], [out1], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "01000000000101e5918f661488bb7f0a7d04fc1dad61b5d0bad5167a05b3a637e36ace881cbc310000000023220020fa6c73de618ec134eeec0c16f6dd04d46d4347e9a4fd0a95fd7938403a4949f9ffffffff01d071180000000000220020bcea2324dacbcde5a9db90cc26b8df9cbc72010e05cb68cf034df6f0e05239a2040047304402206bbddb45f12e31e77610fd85b50a83bad4426433b1c4860b1c5ddc0a69f803720220087b0607daab14830f4b4941f16b953b38e606ad70029bac24af7267f93c4242014730440220551a0cb6b0d5b3fa0cfd0b07bb5d751494b827b1c6a08702186696cfbc18278302204f37c382876c4117cca656654599b508f2d55fc3b083dc938e3cd8491b29719601695221036a5ec3abd10501409092246fe59c6d7a15fff1a933479483c3ba98b866c5b9742103559be875179d44e438db2c74de26e0bc9842cbdefd16018eae8a2ed989e474722103067b56aad037cd8b5f569b21f9025b76470a72dc69457813d2b76e98dc0cd01a53ae00000000" - ) - - # Ensure that if there is a non-multisig input, then a multisig output - # will not be identified as a change output. - def test_multisig_mismatch_inputs_single(self, client): - # m/84'/1'/0' for "alcohol woman abuse ..." seed. - node_int = deserialize( - "Vpub5kFDCYhiYuAzjk7TBQPNFffbexHF7iAd8AVVgHQKUany7e6NQvthgk86d7DfH57DY2dwBK4PyVTDDaS1r2gjkdyJyUYGoV9qNujGSrW9Dpe" - ) - - # m/84'/1'/0' for "all all ... all" seed. - node_ext = deserialize( - "Vpub5jR76XyyhBaQXPSRf3PBeY3gF914d9sf7DWFVhMESEQMCdNv35XiVvp8gZsFXAv222VPHLNnAEXxMPG8DPiSuhAXfEydBf55LTLBGHCDzH2" - ) - - # tb1qpzmgzpcumztvmpu3q27wwdggqav26j9dgks92pvnne2lz9ferxgssmhzlq - multisig_in = proto.MultisigRedeemScriptType( - nodes=[node_int, node_ext], address_n=[0, 0], signatures=[b"", b""], m=1 - ) - - multisig_out = proto.MultisigRedeemScriptType( - nodes=[node_int, node_ext], address_n=[1, 0], signatures=[b"", b""], m=1 - ) - - inp1 = proto.TxInputType( - address_n=parse_path("84'/1'/0'/0/0"), - amount=12300000, - prev_hash=TXHASH_091446, - prev_index=0, - script_type=proto.InputScriptType.SPENDWITNESS, - ) - - inp2 = proto.TxInputType( - address_n=parse_path("84'/1'/0'/0/0"), - prev_hash=TXHASH_a345b8, - prev_index=0, - script_type=proto.InputScriptType.SPENDWITNESS, - multisig=multisig_in, - amount=100, - ) - - out1 = proto.TxOutputType( - address="2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp", - amount=5000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - out2 = proto.TxOutputType( - address_n=parse_path("84'/1'/0'/1/0"), - script_type=proto.OutputScriptType.PAYTOWITNESS, - multisig=multisig_out, - amount=12300000 + 100 - 5000000 - 10000, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_input(1), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - # Ensure that the multisig output is not identified as a change output. - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_091446), - request_input(0, TXHASH_091446), - request_output(0, TXHASH_091446), - request_output(1, TXHASH_091446), - request_input(1), - request_meta(TXHASH_a345b8), - request_input(0, TXHASH_a345b8), - request_output(0, TXHASH_a345b8), - request_input(0), - request_input(1), - request_output(0), - request_output(1), - request_input(0), - request_input(1), - request_finished(), - ] - ) - - _, serialized_tx = btc.sign_tx( - client, "Testnet", [inp1, inp2], [out1, out2], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff48e37c58a68ab4899400dc0950a661817ea7bac3e4556044c685b35957b845a30000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987f43c6f0000000000220020733ecfbbe7e47a74dde6c7645b60cdf627e90a585cde7733bc7fdaf9fe30b37402473044022037dc98b16be542a6e3e1ab32007a74192c43f2498170cc5e1dffb6847e3663e402206715102d0eb59e6461a97c78eb40a8679a04a8921fdafef25f0d3d16cc65de39012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f8620300473044022070a24bcb00041cbed465f1f546bc59e1e353a6e182393932d5ba96e20bc32ef702202ddc76a97c01465692d5b0a0a61d653f64b9ea833af1810022110fd4d505ff950147512103505f0d82bbdd251511591b34f36ad5eea37d3220c2b81a1189084431ddb3aa3d2103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86252ae00000000" - ) + assert ( + serialized_tx.hex() + == "010000000001028a44999c07bba32df1cacdc50987944e68e3205b4429438fdde35c76024614090000000000ffffffff48e37c58a68ab4899400dc0950a661817ea7bac3e4556044c685b35957b845a30000000000ffffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987f43c6f0000000000220020733ecfbbe7e47a74dde6c7645b60cdf627e90a585cde7733bc7fdaf9fe30b37402473044022037dc98b16be542a6e3e1ab32007a74192c43f2498170cc5e1dffb6847e3663e402206715102d0eb59e6461a97c78eb40a8679a04a8921fdafef25f0d3d16cc65de39012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f8620300473044022070a24bcb00041cbed465f1f546bc59e1e353a6e182393932d5ba96e20bc32ef702202ddc76a97c01465692d5b0a0a61d653f64b9ea833af1810022110fd4d505ff950147512103505f0d82bbdd251511591b34f36ad5eea37d3220c2b81a1189084431ddb3aa3d2103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86252ae00000000" + ) diff --git a/tests/device_tests/test_msg_signtx_zcash.py b/tests/device_tests/test_msg_signtx_zcash.py index 5572d66fbe..9510e6d9ce 100644 --- a/tests/device_tests/test_msg_signtx_zcash.py +++ b/tests/device_tests/test_msg_signtx_zcash.py @@ -52,246 +52,249 @@ TXHASH_v4 = bytes.fromhex( "5d8de67264b08eecc8e3bee19a11a7f54a2bce1dc4f2a699538e372ae92e9c0f" ) +pytestmark = [pytest.mark.altcoin, pytest.mark.zcash] -@pytest.mark.altcoin -@pytest.mark.zcash -class TestMsgSigntxZcash: - def test_v3_not_supported(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, +def test_v3_not_supported(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, pytest.raises(TrezorFailure, match="DataError"): + btc.sign_tx( + client, + "Zcash Testnet", + [inp1], + [out1], + version=3, + version_group_id=0x03C48270, + branch_id=0x5BA81B19, + prev_txes=TX_API, ) - out1 = proto.TxOutputType( - address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z", - amount=300000000 - 1940, - script_type=proto.OutputScriptType.PAYTOADDRESS, + +def test_one_one_fee_sapling(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( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_e38206), + request_input(0, TXHASH_e38206), + request_input(1, TXHASH_e38206), + request_output(0, TXHASH_e38206), + request_output(1, TXHASH_e38206), + request_extra_data(0, 1, TXHASH_e38206), + request_input(0), + request_output(0), + request_finished(), + ] ) - with client, pytest.raises(TrezorFailure, match="DataError"): - btc.sign_tx( - client, - "Zcash Testnet", - [inp1], - [out1], - version=3, - version_group_id=0x03C48270, - branch_id=0x5BA81B19, - prev_txes=TX_API, - ) - - 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, + _, serialized_tx = btc.sign_tx( + client, + "Zcash Testnet", + [inp1], + [out1], + version=4, + version_group_id=0x892F2085, + branch_id=0x76B809BB, + prev_txes=TX_API, ) - out1 = proto.TxOutputType( - address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z", - amount=300000000 - 1940, - script_type=proto.OutputScriptType.PAYTOADDRESS, + # Accepted by network: tx 0cef132c1d6d67f11cfa48f7fca3209da29cf872ac782354bedb686e61a17a78 + assert ( + serialized_tx.hex() + == "0400008085202f890168039326c180fa7b1e999392e25a3ec6a8aec83c11b787ddb1746922020682e3000000006b483045022100f28298891f48706697a6f898ac18e39ce2c7cebe547b585d51cc22d80b1b21a602201a807b8a18544832d95d1e3ada82c0617bc6d97d3f24d1fb4801ac396647aa880121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000000000000000000000000000000000" + ) + + +def test_version_group_id_missing(client): + 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 pytest.raises(TrezorFailure, match="Version group ID must be set."): + btc.sign_tx( + client, + "Zcash Testnet", + [inp1], + [out1], + version=4, + prev_txes=TX_API, ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_e38206), - request_input(0, TXHASH_e38206), - request_input(1, TXHASH_e38206), - request_output(0, TXHASH_e38206), - request_output(1, TXHASH_e38206), - request_extra_data(0, 1, TXHASH_e38206), - request_input(0), - request_output(0), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, - "Zcash Testnet", - [inp1], - [out1], - version=4, - version_group_id=0x892F2085, - branch_id=0x76B809BB, - prev_txes=TX_API, - ) +def test_spend_old_versions(client): + # inputs are NOT OWNED by this seed + input_v1 = proto.TxInputType( + address_n=parse_path("m/44h/1h/0h/0/0"), + amount=123000000, + prev_hash=TXHASH_v1, + prev_index=0, + ) + input_v2 = proto.TxInputType( + address_n=parse_path("m/44h/1h/0h/0/1"), + amount=49990000, + prev_hash=TXHASH_v2, + prev_index=0, + ) + input_v3 = proto.TxInputType( + address_n=parse_path("m/44h/1h/0h/0/2"), + amount=300000000, + prev_hash=TXHASH_v3, + prev_index=1, + ) + input_v4 = proto.TxInputType( + address_n=parse_path("m/44h/1h/0h/0/3"), + amount=100000, + prev_hash=TXHASH_v4, + prev_index=0, + ) - # Accepted by network: tx 0cef132c1d6d67f11cfa48f7fca3209da29cf872ac782354bedb686e61a17a78 - assert ( - serialized_tx.hex() - == "0400008085202f890168039326c180fa7b1e999392e25a3ec6a8aec83c11b787ddb1746922020682e3000000006b483045022100f28298891f48706697a6f898ac18e39ce2c7cebe547b585d51cc22d80b1b21a602201a807b8a18544832d95d1e3ada82c0617bc6d97d3f24d1fb4801ac396647aa880121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000000000000000000000000000000000" + inputs = [input_v1, input_v2, input_v3, input_v4] + + for i, txi in enumerate(inputs, 1): + txdata = TX_API[txi.prev_hash] + assert txdata.version == i + + output = proto.TxOutputType( + address="tmNvfeKR5PkcQazLEqddTskFr6Ev9tsovfQ", + amount=sum(txi.amount for txi in inputs), + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + _, serialized_tx = btc.sign_tx( + client, + "Zcash Testnet", + inputs, + [output], + version=4, + version_group_id=0x892F2085, + branch_id=0x76B809BB, + prev_txes=TX_API, ) - def test_version_group_id_missing(self, client): - 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, + assert ( + serialized_tx.hex() + == "0400008085202f890446828054c6c81a8c370c47dc1cfd6f1b200af5623ac3d5b62501121b74ae91fb000000006b483045022100d40e85efbadd378fc603dc8b11c70774086de631fe5b1418ac2b95a478f86507022072e999d8ddd75a0b33bd2adcc88e7234e6251b9e73c9223e7c59e0d1f8d1ff220121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffffef42e249deb8e7bc1d5ec7c4590c70c5b89734b2b896c72ad6469d95190ed303000000006b483045022100917d96445d64c80f9569cb9ca45c04c9b6d7b0fda6b9fd0b1d311837366c699202202cd6140489cf38b5d97ed271ba28603f4693c2a36113cc6ec423301f077c5a8e01210294e3e5e77e22eea0e4c0d30d89beb4db7f69b4bf1ae709e411d6a06618b8f852ffffffff6cb78ae689ae1334f4b03c6f613b280c70088b963f1c965f814081d1298841f9010000006a473044022058768c74c9b1698070636388d7d2ae8223748f13b0a5f402716e4d49fc5bc5f30220658d1e6095dcfbe66669b4141d23af28c9ed5bae73480889429b41742be85f32012103f5008445568548bd745a3dedccc6048969436bf1a49411f60938ff1938941f14ffffffff0f9c2ee92a378e5399a6f2c41dce2b4af5a7119ae1bee3c8ec8eb06472e68d5d000000006b483045022100e64853d86bed039c4edce4abaf80d41486cd21c63bec79c0308ea05a351663e302206732aa22a5dee7bd7f3cc8268faebe31a08abadb4b7e3a4257509bc7baa052b60121029ad0b9519779c540b34fa8d11d24d14a5475546bfa28c7de50573d22a503ce21ffffffff01d0c7321c000000001976a91490ede9de4bed6e39008375eace793949de9a533288ac00000000000000000000000000000000000000" + ) + + +@pytest.mark.skip_t1 +def test_external_presigned(client): + inp1 = proto.TxInputType( + # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu + address_n=parse_path("m/44h/1h/0h/0/0"), + amount=300000000, + prev_hash=TXHASH_e38206, + prev_index=0, + ) + + inp2 = proto.TxInputType( + # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu + # address_n=parse_path("m/44h/1h/0h/0/0"), + amount=300000000, + prev_hash=TXHASH_aaf51e, + prev_index=1, + script_type=proto.InputScriptType.EXTERNAL, + script_pubkey=bytes.fromhex( + "76a914a579388225827d9f2fe9014add644487808c695d88ac" + ), + script_sig=bytes.fromhex( + "47304402202495a38e5b368569a1a0c9fc95aa7e57a0dd5ae43f51300d7222dc139015233d022047833eaa571578f72c8468c8b537b36410388b7eb5001d75d1f4b954e1997d590121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" + ), + ) + + out1 = proto.TxOutputType( + address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z", + amount=300000000 + 300000000 - 1940, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_input(1), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_e38206), + request_input(0, TXHASH_e38206), + request_input(1, TXHASH_e38206), + request_output(0, TXHASH_e38206), + request_output(1, TXHASH_e38206), + request_extra_data(0, 1, TXHASH_e38206), + request_input(1), + request_meta(TXHASH_aaf51e), + request_input(0, TXHASH_aaf51e), + request_output(0, TXHASH_aaf51e), + request_output(1, TXHASH_aaf51e), + request_extra_data(0, 1, TXHASH_aaf51e), + request_input(0), + request_input(1), + request_output(0), + request_finished(), + ] ) - with pytest.raises(TrezorFailure, match="Version group ID must be set."): - btc.sign_tx( - client, - "Zcash Testnet", - [inp1], - [out1], - version=4, - prev_txes=TX_API, - ) - - def test_spend_old_versions(self, client): - # inputs are NOT OWNED by this seed - input_v1 = proto.TxInputType( - address_n=parse_path("m/44h/1h/0h/0/0"), - amount=123000000, - prev_hash=TXHASH_v1, - prev_index=0, - ) - input_v2 = proto.TxInputType( - address_n=parse_path("m/44h/1h/0h/0/1"), - amount=49990000, - prev_hash=TXHASH_v2, - prev_index=0, - ) - input_v3 = proto.TxInputType( - address_n=parse_path("m/44h/1h/0h/0/2"), - amount=300000000, - prev_hash=TXHASH_v3, - prev_index=1, - ) - input_v4 = proto.TxInputType( - address_n=parse_path("m/44h/1h/0h/0/3"), - amount=100000, - prev_hash=TXHASH_v4, - prev_index=0, + _, serialized_tx = btc.sign_tx( + client, + "Zcash Testnet", + [inp1, inp2], + [out1], + version=4, + version_group_id=0x892F2085, + branch_id=0x76B809BB, + prev_txes=TX_API, ) - inputs = [input_v1, input_v2, input_v3, input_v4] - - for i, txi in enumerate(inputs, 1): - txdata = TX_API[txi.prev_hash] - assert txdata.version == i - - output = proto.TxOutputType( - address="tmNvfeKR5PkcQazLEqddTskFr6Ev9tsovfQ", - amount=sum(txi.amount for txi in inputs), - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - _, serialized_tx = btc.sign_tx( - client, - "Zcash Testnet", - inputs, - [output], - version=4, - version_group_id=0x892F2085, - branch_id=0x76B809BB, - prev_txes=TX_API, - ) - - assert ( - serialized_tx.hex() - == "0400008085202f890446828054c6c81a8c370c47dc1cfd6f1b200af5623ac3d5b62501121b74ae91fb000000006b483045022100d40e85efbadd378fc603dc8b11c70774086de631fe5b1418ac2b95a478f86507022072e999d8ddd75a0b33bd2adcc88e7234e6251b9e73c9223e7c59e0d1f8d1ff220121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffffef42e249deb8e7bc1d5ec7c4590c70c5b89734b2b896c72ad6469d95190ed303000000006b483045022100917d96445d64c80f9569cb9ca45c04c9b6d7b0fda6b9fd0b1d311837366c699202202cd6140489cf38b5d97ed271ba28603f4693c2a36113cc6ec423301f077c5a8e01210294e3e5e77e22eea0e4c0d30d89beb4db7f69b4bf1ae709e411d6a06618b8f852ffffffff6cb78ae689ae1334f4b03c6f613b280c70088b963f1c965f814081d1298841f9010000006a473044022058768c74c9b1698070636388d7d2ae8223748f13b0a5f402716e4d49fc5bc5f30220658d1e6095dcfbe66669b4141d23af28c9ed5bae73480889429b41742be85f32012103f5008445568548bd745a3dedccc6048969436bf1a49411f60938ff1938941f14ffffffff0f9c2ee92a378e5399a6f2c41dce2b4af5a7119ae1bee3c8ec8eb06472e68d5d000000006b483045022100e64853d86bed039c4edce4abaf80d41486cd21c63bec79c0308ea05a351663e302206732aa22a5dee7bd7f3cc8268faebe31a08abadb4b7e3a4257509bc7baa052b60121029ad0b9519779c540b34fa8d11d24d14a5475546bfa28c7de50573d22a503ce21ffffffff01d0c7321c000000001976a91490ede9de4bed6e39008375eace793949de9a533288ac00000000000000000000000000000000000000" - ) - - @pytest.mark.skip_t1 - def test_external_presigned(self, client): - inp1 = proto.TxInputType( - # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu - address_n=parse_path("m/44h/1h/0h/0/0"), - amount=300000000, - prev_hash=TXHASH_e38206, - prev_index=0, - ) - - inp2 = proto.TxInputType( - # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu - # address_n=parse_path("m/44h/1h/0h/0/0"), - amount=300000000, - prev_hash=TXHASH_aaf51e, - prev_index=1, - script_type=proto.InputScriptType.EXTERNAL, - script_pubkey=bytes.fromhex( - "76a914a579388225827d9f2fe9014add644487808c695d88ac" - ), - script_sig=bytes.fromhex( - "47304402202495a38e5b368569a1a0c9fc95aa7e57a0dd5ae43f51300d7222dc139015233d022047833eaa571578f72c8468c8b537b36410388b7eb5001d75d1f4b954e1997d590121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" - ), - ) - - out1 = proto.TxOutputType( - address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z", - amount=300000000 + 300000000 - 1940, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_input(1), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_e38206), - request_input(0, TXHASH_e38206), - request_input(1, TXHASH_e38206), - request_output(0, TXHASH_e38206), - request_output(1, TXHASH_e38206), - request_extra_data(0, 1, TXHASH_e38206), - request_input(1), - request_meta(TXHASH_aaf51e), - request_input(0, TXHASH_aaf51e), - request_output(0, TXHASH_aaf51e), - request_output(1, TXHASH_aaf51e), - request_extra_data(0, 1, TXHASH_aaf51e), - request_input(0), - request_input(1), - request_output(0), - request_finished(), - ] - ) - - _, serialized_tx = btc.sign_tx( - client, - "Zcash Testnet", - [inp1, inp2], - [out1], - version=4, - version_group_id=0x892F2085, - branch_id=0x76B809BB, - prev_txes=TX_API, - ) - - assert ( - serialized_tx.hex() - == "0400008085202f890268039326c180fa7b1e999392e25a3ec6a8aec83c11b787ddb1746922020682e3000000006a473044022007efbf539f8d612d8e140c6af2289b447c34e3d36edd75d539f269fe5526878302206830f6b0398494bca09afdd967fedcd016f49468711cfcd7aafd9a128ee568d20121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffffdc754d63eff4698ee321476872519c53f14cfe58c9425c7ee464c206461ef5aa010000006a47304402202495a38e5b368569a1a0c9fc95aa7e57a0dd5ae43f51300d7222dc139015233d022047833eaa571578f72c8468c8b537b36410388b7eb5001d75d1f4b954e1997d590121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c3ec323000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000000000000000000000000000000000" - ) + assert ( + serialized_tx.hex() + == "0400008085202f890268039326c180fa7b1e999392e25a3ec6a8aec83c11b787ddb1746922020682e3000000006a473044022007efbf539f8d612d8e140c6af2289b447c34e3d36edd75d539f269fe5526878302206830f6b0398494bca09afdd967fedcd016f49468711cfcd7aafd9a128ee568d20121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffffdc754d63eff4698ee321476872519c53f14cfe58c9425c7ee464c206461ef5aa010000006a47304402202495a38e5b368569a1a0c9fc95aa7e57a0dd5ae43f51300d7222dc139015233d022047833eaa571578f72c8468c8b537b36410388b7eb5001d75d1f4b954e1997d590121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c3ec323000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000000000000000000000000000000000" + ) diff --git a/tests/device_tests/test_msg_verifymessage.py b/tests/device_tests/test_msg_verifymessage.py index 54d04e1890..b24564e1ff 100644 --- a/tests/device_tests/test_msg_verifymessage.py +++ b/tests/device_tests/test_msg_verifymessage.py @@ -21,201 +21,206 @@ import pytest from trezorlib import btc -class TestMsgVerifymessage: - def test_message_long(self, client): - ret = btc.verify_message( - client, - "Bitcoin", - "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", - bytes.fromhex( - "205ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed" - ), - "VeryLongMessage!" * 64, - ) - assert ret is True +def test_message_long(client): + ret = btc.verify_message( + client, + "Bitcoin", + "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", + bytes.fromhex( + "205ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed" + ), + "VeryLongMessage!" * 64, + ) + assert ret is True - def test_message_testnet(self, client): - ret = btc.verify_message( - client, - "Testnet", - "mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL", - bytes.fromhex( - "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" - ), - "This is an example of a signed message.", - ) - assert ret is True - @pytest.mark.altcoin - def test_message_grs(self, client): - ret = btc.verify_message( - client, - "Groestlcoin", - "Fj62rBJi8LvbmWu2jzkaUX1NFXLEqDLoZM", - base64.b64decode( - "INOYaa/jj8Yxz3mD5k+bZfUmjkjB9VzoV4dNG7+RsBUyK30xL7I9yMgWWVvsL46C5yQtxtZY0cRRk7q9N6b+YTM=" - ), - "test", - ) - assert ret is True +def test_message_testnet(client): + ret = btc.verify_message( + client, + "Testnet", + "mirio8q3gtv7fhdnmb3TpZ4EuafdzSs7zL", + bytes.fromhex( + "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" + ), + "This is an example of a signed message.", + ) + assert ret is True - def test_message_verify(self, client): - res = btc.verify_message( - client, - "Bitcoin", - "1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T", - bytes.fromhex( - "1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2" - ), - "This is an example of a signed message.", - ) - assert res is True - # uncompressed pubkey - FAIL - wrong sig - res = btc.verify_message( - client, - "Bitcoin", - "1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T", - bytes.fromhex( - "1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c800" - ), - "This is an example of a signed message.", - ) - assert res is False +@pytest.mark.altcoin +def test_message_grs(client): + ret = btc.verify_message( + client, + "Groestlcoin", + "Fj62rBJi8LvbmWu2jzkaUX1NFXLEqDLoZM", + base64.b64decode( + "INOYaa/jj8Yxz3mD5k+bZfUmjkjB9VzoV4dNG7+RsBUyK30xL7I9yMgWWVvsL46C5yQtxtZY0cRRk7q9N6b+YTM=" + ), + "test", + ) + assert ret is True - # uncompressed pubkey - FAIL - wrong msg - res = btc.verify_message( - client, - "Bitcoin", - "1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T", - bytes.fromhex( - "1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2" - ), - "This is an example of a signed message!", - ) - assert res is False - # compressed pubkey - OK - res = btc.verify_message( - client, - "Bitcoin", - "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", - bytes.fromhex( - "1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf" - ), - "This is an example of a signed message.", - ) - assert res is True +def test_message_verify(client): + res = btc.verify_message( + client, + "Bitcoin", + "1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T", + bytes.fromhex( + "1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2" + ), + "This is an example of a signed message.", + ) + assert res is True - # compressed pubkey - FAIL - wrong sig - res = btc.verify_message( - client, - "Bitcoin", - "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", - bytes.fromhex( - "1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaa00" - ), - "This is an example of a signed message.", - ) - assert res is False + # uncompressed pubkey - FAIL - wrong sig + res = btc.verify_message( + client, + "Bitcoin", + "1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T", + bytes.fromhex( + "1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c800" + ), + "This is an example of a signed message.", + ) + assert res is False - # compressed pubkey - FAIL - wrong msg - res = btc.verify_message( - client, - "Bitcoin", - "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", - bytes.fromhex( - "1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf" - ), - "This is an example of a signed message!", - ) - assert res is False + # uncompressed pubkey - FAIL - wrong msg + res = btc.verify_message( + client, + "Bitcoin", + "1JwSSubhmg6iPtRjtyqhUYYH7bZg3Lfy1T", + bytes.fromhex( + "1ba77e01a9e17ba158b962cfef5f13dfed676ffc2b4bada24e58f784458b52b97421470d001d53d5880cf5e10e76f02be3e80bf21e18398cbd41e8c3b4af74c8c2" + ), + "This is an example of a signed message!", + ) + assert res is False - # trezor pubkey - OK - res = btc.verify_message( - client, - "Bitcoin", - "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", - bytes.fromhex( - "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" - ), - "This is an example of a signed message.", - ) - assert res is True + # compressed pubkey - OK + res = btc.verify_message( + client, + "Bitcoin", + "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", + bytes.fromhex( + "1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf" + ), + "This is an example of a signed message.", + ) + assert res is True - # trezor pubkey - FAIL - wrong sig - res = btc.verify_message( - client, - "Bitcoin", - "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", - bytes.fromhex( - "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00" - ), - "This is an example of a signed message.", - ) - assert res is False + # compressed pubkey - FAIL - wrong sig + res = btc.verify_message( + client, + "Bitcoin", + "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", + bytes.fromhex( + "1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaa00" + ), + "This is an example of a signed message.", + ) + assert res is False - # trezor pubkey - FAIL - wrong msg - res = btc.verify_message( - client, - "Bitcoin", - "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", - bytes.fromhex( - "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" - ), - "This is an example of a signed message!", - ) - assert res is False + # compressed pubkey - FAIL - wrong msg + res = btc.verify_message( + client, + "Bitcoin", + "1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8", + bytes.fromhex( + "1f44e3e461f7ca9f57c472ce1a28214df1de1dadefb6551a32d1907b80c74d5a1fbfd6daaba12dd8cb06699ce3f6941fbe0f3957b5802d13076181046e741eaaaf" + ), + "This is an example of a signed message!", + ) + assert res is False - @pytest.mark.altcoin - def test_message_verify_bcash(self, client): - res = btc.verify_message( - client, - "Bcash", - "bitcoincash:qqj22md58nm09vpwsw82fyletkxkq36zxyxh322pru", - bytes.fromhex( - "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" - ), - "This is an example of a signed message.", - ) - assert res is True + # trezor pubkey - OK + res = btc.verify_message( + client, + "Bitcoin", + "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", + bytes.fromhex( + "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" + ), + "This is an example of a signed message.", + ) + assert res is True - def test_verify_bitcoind(self, client): - res = btc.verify_message( - client, - "Bitcoin", - "1KzXE97kV7DrpxCViCN3HbGbiKhzzPM7TQ", - bytes.fromhex( - "1cc694f0f23901dfe3603789142f36a3fc582d0d5c0ec7215cf2ccd641e4e37228504f3d4dc3eea28bbdbf5da27c49d4635c097004d9f228750ccd836a8e1460c0" - ), - u"\u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy", - ) + # trezor pubkey - FAIL - wrong sig + res = btc.verify_message( + client, + "Bitcoin", + "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", + bytes.fromhex( + "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00" + ), + "This is an example of a signed message.", + ) + assert res is False - assert res is True + # trezor pubkey - FAIL - wrong msg + res = btc.verify_message( + client, + "Bitcoin", + "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", + bytes.fromhex( + "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" + ), + "This is an example of a signed message!", + ) + assert res is False - def test_verify_utf(self, client): - words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" - words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" - res_nfkd = btc.verify_message( - client, - "Bitcoin", - "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", - bytes.fromhex( - "20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" - ), - words_nfkd, - ) +@pytest.mark.altcoin +def test_message_verify_bcash(client): + res = btc.verify_message( + client, + "Bcash", + "bitcoincash:qqj22md58nm09vpwsw82fyletkxkq36zxyxh322pru", + bytes.fromhex( + "209e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" + ), + "This is an example of a signed message.", + ) + assert res is True - res_nfc = btc.verify_message( - client, - "Bitcoin", - "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", - bytes.fromhex( - "20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" - ), - words_nfc, - ) - assert res_nfkd is True - assert res_nfc is True +def test_verify_bitcoind(client): + res = btc.verify_message( + client, + "Bitcoin", + "1KzXE97kV7DrpxCViCN3HbGbiKhzzPM7TQ", + bytes.fromhex( + "1cc694f0f23901dfe3603789142f36a3fc582d0d5c0ec7215cf2ccd641e4e37228504f3d4dc3eea28bbdbf5da27c49d4635c097004d9f228750ccd836a8e1460c0" + ), + u"\u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy", + ) + + assert res is True + + +def test_verify_utf(client): + words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" + words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" + + res_nfkd = btc.verify_message( + client, + "Bitcoin", + "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", + bytes.fromhex( + "20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" + ), + words_nfkd, + ) + + res_nfc = btc.verify_message( + client, + "Bitcoin", + "14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e", + bytes.fromhex( + "20d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" + ), + words_nfc, + ) + + assert res_nfkd is True + assert res_nfc is True diff --git a/tests/device_tests/test_msg_verifymessage_segwit.py b/tests/device_tests/test_msg_verifymessage_segwit.py index f31ae3d220..6622684b5d 100644 --- a/tests/device_tests/test_msg_verifymessage_segwit.py +++ b/tests/device_tests/test_msg_verifymessage_segwit.py @@ -17,90 +17,92 @@ from trezorlib import btc -class TestMsgVerifymessageSegwit: - def test_message_long(self, client): - ret = btc.verify_message( - client, - "Bitcoin", - "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", - bytes.fromhex( - "245ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed" - ), - "VeryLongMessage!" * 64, - ) - assert ret is True +def test_message_long(client): + ret = btc.verify_message( + client, + "Bitcoin", + "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", + bytes.fromhex( + "245ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed" + ), + "VeryLongMessage!" * 64, + ) + assert ret is True - def test_message_testnet(self, client): - ret = btc.verify_message( - client, - "Testnet", - "2N4VkePSzKH2sv5YBikLHGvzUYvfPxV6zS9", - bytes.fromhex( - "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" - ), - "This is an example of a signed message.", - ) - assert ret is True - def test_message_verify(self, client): - res = btc.verify_message( - client, - "Bitcoin", - "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", - bytes.fromhex( - "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" - ), - "This is an example of a signed message.", - ) - assert res is True +def test_message_testnet(client): + ret = btc.verify_message( + client, + "Testnet", + "2N4VkePSzKH2sv5YBikLHGvzUYvfPxV6zS9", + bytes.fromhex( + "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" + ), + "This is an example of a signed message.", + ) + assert ret is True - # trezor pubkey - FAIL - wrong sig - res = btc.verify_message( - client, - "Bitcoin", - "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", - bytes.fromhex( - "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00" - ), - "This is an example of a signed message.", - ) - assert res is False - # trezor pubkey - FAIL - wrong msg - res = btc.verify_message( - client, - "Bitcoin", - "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", - bytes.fromhex( - "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" - ), - "This is an example of a signed message!", - ) - assert res is False +def test_message_verify(client): + res = btc.verify_message( + client, + "Bitcoin", + "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", + bytes.fromhex( + "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" + ), + "This is an example of a signed message.", + ) + assert res is True - def test_verify_utf(self, client): - words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" - words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" + # trezor pubkey - FAIL - wrong sig + res = btc.verify_message( + client, + "Bitcoin", + "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", + bytes.fromhex( + "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00" + ), + "This is an example of a signed message.", + ) + assert res is False - res_nfkd = btc.verify_message( - client, - "Bitcoin", - "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", - bytes.fromhex( - "24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" - ), - words_nfkd, - ) + # trezor pubkey - FAIL - wrong msg + res = btc.verify_message( + client, + "Bitcoin", + "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", + bytes.fromhex( + "249e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" + ), + "This is an example of a signed message!", + ) + assert res is False - res_nfc = btc.verify_message( - client, - "Bitcoin", - "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", - bytes.fromhex( - "24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" - ), - words_nfc, - ) - assert res_nfkd is True - assert res_nfc is True +def test_verify_utf(client): + words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" + words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" + + res_nfkd = btc.verify_message( + client, + "Bitcoin", + "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", + bytes.fromhex( + "24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" + ), + words_nfkd, + ) + + res_nfc = btc.verify_message( + client, + "Bitcoin", + "3CwYaeWxhpXXiHue3ciQez1DLaTEAXcKa1", + bytes.fromhex( + "24d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" + ), + words_nfc, + ) + + assert res_nfkd is True + assert res_nfc is True diff --git a/tests/device_tests/test_msg_verifymessage_segwit_native.py b/tests/device_tests/test_msg_verifymessage_segwit_native.py index fa2ffed43c..6b7025b07f 100644 --- a/tests/device_tests/test_msg_verifymessage_segwit_native.py +++ b/tests/device_tests/test_msg_verifymessage_segwit_native.py @@ -17,90 +17,92 @@ from trezorlib import btc -class TestMsgVerifymessageSegwitNative: - def test_message_long(self, client): - ret = btc.verify_message( - client, - "Bitcoin", - "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", - bytes.fromhex( - "285ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed" - ), - "VeryLongMessage!" * 64, - ) - assert ret is True +def test_message_long(client): + ret = btc.verify_message( + client, + "Bitcoin", + "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", + bytes.fromhex( + "285ff795c29aef7538f8b3bdb2e8add0d0722ad630a140b6aefd504a5a895cbd867cbb00981afc50edd0398211e8d7c304bb8efa461181bc0afa67ea4a720a89ed" + ), + "VeryLongMessage!" * 64, + ) + assert ret is True - def test_message_testnet(self, client): - ret = btc.verify_message( - client, - "Testnet", - "tb1qyjjkmdpu7metqt5r36jf872a34syws336p3n3p", - bytes.fromhex( - "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" - ), - "This is an example of a signed message.", - ) - assert ret is True - def test_message_verify(self, client): - res = btc.verify_message( - client, - "Bitcoin", - "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", - bytes.fromhex( - "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" - ), - "This is an example of a signed message.", - ) - assert res is True +def test_message_testnet(client): + ret = btc.verify_message( + client, + "Testnet", + "tb1qyjjkmdpu7metqt5r36jf872a34syws336p3n3p", + bytes.fromhex( + "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" + ), + "This is an example of a signed message.", + ) + assert ret is True - # trezor pubkey - FAIL - wrong sig - res = btc.verify_message( - client, - "Bitcoin", - "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", - bytes.fromhex( - "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00" - ), - "This is an example of a signed message.", - ) - assert res is False - # trezor pubkey - FAIL - wrong msg - res = btc.verify_message( - client, - "Bitcoin", - "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", - bytes.fromhex( - "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" - ), - "This is an example of a signed message!", - ) - assert res is False +def test_message_verify(client): + res = btc.verify_message( + client, + "Bitcoin", + "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", + bytes.fromhex( + "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" + ), + "This is an example of a signed message.", + ) + assert res is True - def test_verify_utf(self, client): - words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" - words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" + # trezor pubkey - FAIL - wrong sig + res = btc.verify_message( + client, + "Bitcoin", + "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", + bytes.fromhex( + "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be00" + ), + "This is an example of a signed message.", + ) + assert res is False - res_nfkd = btc.verify_message( - client, - "Bitcoin", - "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", - bytes.fromhex( - "28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" - ), - words_nfkd, - ) + # trezor pubkey - FAIL - wrong msg + res = btc.verify_message( + client, + "Bitcoin", + "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", + bytes.fromhex( + "289e23edf0e4e47ff1dec27f32cd78c50e74ef018ee8a6adf35ae17c7a9b0dd96f48b493fd7dbab03efb6f439c6383c9523b3bbc5f1a7d158a6af90ab154e9be80" + ), + "This is an example of a signed message!", + ) + assert res is False - res_nfc = btc.verify_message( - client, - "Bitcoin", - "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", - bytes.fromhex( - "28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" - ), - words_nfc, - ) - assert res_nfkd is True - assert res_nfc is True +def test_verify_utf(client): + words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a" + words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f" + + res_nfkd = btc.verify_message( + client, + "Bitcoin", + "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", + bytes.fromhex( + "28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" + ), + words_nfkd, + ) + + res_nfc = btc.verify_message( + client, + "Bitcoin", + "bc1qyjjkmdpu7metqt5r36jf872a34syws33s82q2j", + bytes.fromhex( + "28d0ec02ed8da8df23e7fe9e680e7867cc290312fe1c970749d8306ddad1a1eda41c6a771b13d495dd225b13b0a9d0f915a984ee3d0703f92287bf8009fbb9f7d6" + ), + words_nfc, + ) + + assert res_nfkd is True + assert res_nfc is True diff --git a/tests/device_tests/test_multisig.py b/tests/device_tests/test_multisig.py index 42acaad1e5..3804d78911 100644 --- a/tests/device_tests/test_multisig.py +++ b/tests/device_tests/test_multisig.py @@ -37,300 +37,301 @@ TXHASH_fbbff7 = bytes.fromhex( "fbbff7f3c85f8067453d7c062bd5efb8ad839953376ae5eceaf92774102c6e39" ) +pytestmark = pytest.mark.multisig -class TestMultisig: - @pytest.mark.multisig - def test_2_of_3(self, client): - nodes = [ - btc.get_public_node(client, parse_path(f"48'/0'/{index}'/0'")).node - for index in range(1, 4) - ] - multisig = proto.MultisigRedeemScriptType( - nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2 +def test_2_of_3(client): + nodes = [ + btc.get_public_node(client, parse_path(f"48'/0'/{index}'/0'")).node + for index in range(1, 4) + ] + + multisig = proto.MultisigRedeemScriptType( + nodes=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/0"), + amount=100000, + prev_hash=TXHASH_c6091a, + prev_index=1, + script_type=proto.InputScriptType.SPENDMULTISIG, + multisig=multisig, + ) + + out1 = proto.TxOutputType( + address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss", + amount=100000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_c6091a), + request_input(0, TXHASH_c6091a), + request_output(0, TXHASH_c6091a), + request_output(1, TXHASH_c6091a), + request_input(0), + request_output(0), + request_output(0), + request_finished(), + ] ) - # Let's go to sign with key 1 + + # Now we have first signature + signatures1, _ = btc.sign_tx( + client, "Bitcoin", [inp1], [out1], prev_txes=TX_API + ) + + assert ( + signatures1[0].hex() + == "30450221009276eea820aa54a24bd9f1a056cb09a15f50c0816570a7c7878bd1c5ee7248540220677d200aec5e2f25bcf4000bdfab3faa9e1746d7f80c4ae4bfa1f5892eb5dcbf" + ) + + # --------------------------------------- + # Let's do second signature using 3rd key + + multisig = proto.MultisigRedeemScriptType( + nodes=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/0"), + amount=100000, + prev_hash=TXHASH_c6091a, + prev_index=1, + script_type=proto.InputScriptType.SPENDMULTISIG, + multisig=multisig, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_c6091a), + request_input(0, TXHASH_c6091a), + request_output(0, TXHASH_c6091a), + request_output(1, TXHASH_c6091a), + request_input(0), + request_output(0), + request_output(0), + request_finished(), + ] + ) + signatures2, serialized_tx = btc.sign_tx( + client, "Bitcoin", [inp3], [out1], prev_txes=TX_API + ) + + assert ( + signatures2[0].hex() + == "3045022100c2a9fbfbff1be87036d8a6a22745512b158154f7f3d8f4cad4ba7ed130b37b83022058f5299b4c26222588dcc669399bd88b6f2bc6e04b48276373683853187a4fd6" + ) + + assert ( + serialized_tx.hex() + == "010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fdfe00004830450221009276eea820aa54a24bd9f1a056cb09a15f50c0816570a7c7878bd1c5ee7248540220677d200aec5e2f25bcf4000bdfab3faa9e1746d7f80c4ae4bfa1f5892eb5dcbf01483045022100c2a9fbfbff1be87036d8a6a22745512b158154f7f3d8f4cad4ba7ed130b37b83022058f5299b4c26222588dcc669399bd88b6f2bc6e04b48276373683853187a4fd6014c69522103dc0ff15b9c85c0d2c87099758bf47d36229c2514aeefcf8dea123f0f93c679762102bfe426e8671601ad46d54d09ee15aa035610d36d411961c87474908d403fbc122102a5d57129c6c96df663ad29492aa18605dad97231e043be8a92f9406073815c5d53aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000" + ) + + +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_15_of_15(client): + node = btc.get_public_node( + client, parse_path("48h/0h/1h/0h"), coin_name="Bitcoin" + ).node + pubs = [proto.HDNodePathType(node=node, address_n=[0, 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("48'/0'/1'/0'/0/0"), - amount=100000, - prev_hash=TXHASH_c6091a, + address_n=parse_path(f"48h/0h/1h/0h/0/{x}"), + amount=20000, + prev_hash=TXHASH_6189e3, prev_index=1, script_type=proto.InputScriptType.SPENDMULTISIG, multisig=multisig, ) - out1 = proto.TxOutputType( - address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss", - amount=100000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_c6091a), - request_input(0, TXHASH_c6091a), - request_output(0, TXHASH_c6091a), - request_output(1, TXHASH_c6091a), - request_input(0), - request_output(0), - request_output(0), - request_finished(), - ] - ) - - # Now we have first signature - signatures1, _ = btc.sign_tx( + sig, serialized_tx = btc.sign_tx( client, "Bitcoin", [inp1], [out1], prev_txes=TX_API ) + signatures[x] = sig[0] - assert ( - signatures1[0].hex() - == "30450221009276eea820aa54a24bd9f1a056cb09a15f50c0816570a7c7878bd1c5ee7248540220677d200aec5e2f25bcf4000bdfab3faa9e1746d7f80c4ae4bfa1f5892eb5dcbf" - ) + assert ( + tx_hash(serialized_tx).hex() + == "63b16e3107df552c5c74bb5d91bb8fcd0069bac461fb42ebef982c5b2cfc4cf4" + ) - # --------------------------------------- - # Let's do second signature using 3rd key - multisig = proto.MultisigRedeemScriptType( - nodes=nodes, - address_n=[0, 0], - signatures=[ - signatures1[0], - b"", - b"", - ], # Fill signature from previous signing process - m=2, - ) +@pytest.mark.setup_client(mnemonic=MNEMONIC12) +def test_missing_pubkey(client): + node = btc.get_public_node( + client, parse_path("48h/0h/1h/0h/0"), coin_name="Bitcoin" + ).node - # Let's do a second signature with key 3 - inp3 = proto.TxInputType( - address_n=parse_path("48'/0'/3'/0'/0/0"), - amount=100000, - prev_hash=TXHASH_c6091a, - prev_index=1, - script_type=proto.InputScriptType.SPENDMULTISIG, - multisig=multisig, - ) + multisig = proto.MultisigRedeemScriptType( + pubkeys=[ + proto.HDNodePathType(node=node, address_n=[1]), + proto.HDNodePathType(node=node, address_n=[2]), + proto.HDNodePathType(node=node, address_n=[3]), + ], + signatures=[b"", b"", b""], + m=2, + ) - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_c6091a), - request_input(0, TXHASH_c6091a), - request_output(0, TXHASH_c6091a), - request_output(1, TXHASH_c6091a), - request_input(0), - request_output(0), - request_output(0), - request_finished(), - ] - ) - signatures2, serialized_tx = btc.sign_tx( - client, "Bitcoin", [inp3], [out1], prev_txes=TX_API - ) + # Let's go to sign with key 10, which is NOT in pubkeys + inp1 = proto.TxInputType( + address_n=parse_path("48h/0h/1h/0h/0/10"), + amount=100000, + prev_hash=TXHASH_c6091a, + prev_index=1, + script_type=proto.InputScriptType.SPENDMULTISIG, + multisig=multisig, + ) - assert ( - signatures2[0].hex() - == "3045022100c2a9fbfbff1be87036d8a6a22745512b158154f7f3d8f4cad4ba7ed130b37b83022058f5299b4c26222588dcc669399bd88b6f2bc6e04b48276373683853187a4fd6" - ) + out1 = proto.TxOutputType( + address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss", + amount=100000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) - assert ( - serialized_tx.hex() - == "010000000152ba4dfcde9c4bed88f55479cdea03e711ae586e9a89352a98230c4cdf1a09c601000000fdfe00004830450221009276eea820aa54a24bd9f1a056cb09a15f50c0816570a7c7878bd1c5ee7248540220677d200aec5e2f25bcf4000bdfab3faa9e1746d7f80c4ae4bfa1f5892eb5dcbf01483045022100c2a9fbfbff1be87036d8a6a22745512b158154f7f3d8f4cad4ba7ed130b37b83022058f5299b4c26222588dcc669399bd88b6f2bc6e04b48276373683853187a4fd6014c69522103dc0ff15b9c85c0d2c87099758bf47d36229c2514aeefcf8dea123f0f93c679762102bfe426e8671601ad46d54d09ee15aa035610d36d411961c87474908d403fbc122102a5d57129c6c96df663ad29492aa18605dad97231e043be8a92f9406073815c5d53aeffffffff01a0860100000000001976a91412e8391ad256dcdc023365978418d658dfecba1c88ac00000000" - ) + with pytest.raises(TrezorFailure) as exc: + btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API) - @pytest.mark.multisig - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_15_of_15(self, client): - node = btc.get_public_node( - client, parse_path("48h/0h/1h/0h"), coin_name="Bitcoin" - ).node - pubs = [proto.HDNodePathType(node=node, address_n=[0, x]) for x in range(15)] + if client.features.model == "1": + assert exc.value.message.endswith("Failed to derive scriptPubKey") + else: + assert exc.value.message.endswith("Pubkey not found in multisig script") - signatures = [b""] * 15 - out1 = proto.TxOutputType( - address="17kTB7qSk3MupQxWdiv5ZU3zcrZc2Azes1", - amount=10000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) +def test_attack_change_input(client): + """ + In Phases 1 and 2 the attacker replaces a non-multisig input + `input_real` with a multisig input `input_fake`, which allows the + attacker to provide a 1-of-2 multisig change address. When `input_real` + is provided in the signing phase, an error must occur. + """ + address_n = parse_path("48'/1'/0'/1'/0/0") + attacker_multisig_public_key = bytes.fromhex( + "03653a148b68584acb97947344a7d4fd6a6f8b8485cad12987ff8edac874268088" + ) - for x in range(15): - multisig = proto.MultisigRedeemScriptType( - pubkeys=pubs, signatures=signatures, m=15 - ) + input_real = proto.TxInputType( + address_n=address_n, + prev_hash=TXHASH_fbbff7, + prev_index=1, + script_type=proto.InputScriptType.SPENDP2SHWITNESS, + amount=1000000, + ) - inp1 = proto.TxInputType( - address_n=parse_path(f"48h/0h/1h/0h/0/{x}"), - amount=20000, - prev_hash=TXHASH_6189e3, - prev_index=1, - script_type=proto.InputScriptType.SPENDMULTISIG, - multisig=multisig, - ) + multisig_fake = proto.MultisigRedeemScriptType( + m=1, + nodes=[ + btc.get_public_node(client, address_n, coin_name="Testnet").node, + proto.HDNodeType( + depth=0, + fingerprint=0, + child_num=0, + chain_code=bytes(32), + public_key=attacker_multisig_public_key, + ), + ], + address_n=[], + ) - with client: - sig, serialized_tx = btc.sign_tx( - client, "Bitcoin", [inp1], [out1], prev_txes=TX_API - ) - signatures[x] = sig[0] + input_fake = proto.TxInputType( + address_n=address_n, + prev_hash=input_real.prev_hash, + prev_index=input_real.prev_index, + script_type=input_real.script_type, + multisig=multisig_fake, + amount=input_real.amount, + ) - assert ( - tx_hash(serialized_tx).hex() - == "63b16e3107df552c5c74bb5d91bb8fcd0069bac461fb42ebef982c5b2cfc4cf4" - ) + output_payee = proto.TxOutputType( + address="n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi", + amount=1000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) - @pytest.mark.multisig - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_missing_pubkey(self, client): - node = btc.get_public_node( - client, parse_path("48h/0h/1h/0h/0"), coin_name="Bitcoin" - ).node + output_change = proto.TxOutputType( + address_n=address_n, + amount=input_real.amount - output_payee.amount - 1000, + script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, + multisig=multisig_fake, + ) - multisig = proto.MultisigRedeemScriptType( - pubkeys=[ - proto.HDNodePathType(node=node, address_n=[1]), - proto.HDNodePathType(node=node, address_n=[2]), - proto.HDNodePathType(node=node, address_n=[3]), - ], - signatures=[b"", b"", b""], - m=2, - ) + attack_count = 3 - # Let's go to sign with key 10, which is NOT in pubkeys - inp1 = proto.TxInputType( - address_n=parse_path("48h/0h/1h/0h/0/10"), - amount=100000, - prev_hash=TXHASH_c6091a, - prev_index=1, - script_type=proto.InputScriptType.SPENDMULTISIG, - multisig=multisig, - ) + def attack_processor(msg): + nonlocal attack_count + # replace the first input_real with input_fake + if attack_count > 0 and msg.tx.inputs and msg.tx.inputs[0] == input_real: + msg.tx.inputs[0] = input_fake + attack_count -= 1 + return msg - out1 = proto.TxOutputType( - address="12iyMbUb4R2K3gre4dHSrbu5azG5KaqVss", - amount=100000, - script_type=proto.OutputScriptType.PAYTOADDRESS, + with client: + client.set_filter(proto.TxAck, attack_processor) + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_fbbff7), + request_input(0, TXHASH_fbbff7), + request_output(0, TXHASH_fbbff7), + request_output(1, TXHASH_fbbff7), + request_input(0), + request_output(0), + request_output(1), + request_input(0), + proto.Failure(code=proto.FailureType.ProcessError), + ] ) with pytest.raises(TrezorFailure) as exc: - btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API) - - if client.features.model == "1": - assert exc.value.message.endswith("Failed to derive scriptPubKey") - else: - assert exc.value.message.endswith("Pubkey not found in multisig script") - - def test_attack_change_input(self, client): - """ - In Phases 1 and 2 the attacker replaces a non-multisig input - `input_real` with a multisig input `input_fake`, which allows the - attacker to provide a 1-of-2 multisig change address. When `input_real` - is provided in the signing phase, an error must occur. - """ - address_n = parse_path("48'/1'/0'/1'/0/0") - attacker_multisig_public_key = bytes.fromhex( - "03653a148b68584acb97947344a7d4fd6a6f8b8485cad12987ff8edac874268088" - ) - - input_real = proto.TxInputType( - address_n=address_n, - prev_hash=TXHASH_fbbff7, - prev_index=1, - script_type=proto.InputScriptType.SPENDP2SHWITNESS, - amount=1000000, - ) - - multisig_fake = proto.MultisigRedeemScriptType( - m=1, - nodes=[ - btc.get_public_node(client, address_n, coin_name="Testnet").node, - proto.HDNodeType( - depth=0, - fingerprint=0, - child_num=0, - chain_code=bytes(32), - public_key=attacker_multisig_public_key, - ), - ], - address_n=[], - ) - - input_fake = proto.TxInputType( - address_n=address_n, - prev_hash=input_real.prev_hash, - prev_index=input_real.prev_index, - script_type=input_real.script_type, - multisig=multisig_fake, - amount=input_real.amount, - ) - - output_payee = proto.TxOutputType( - address="n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi", - amount=1000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - output_change = proto.TxOutputType( - address_n=address_n, - amount=input_real.amount - output_payee.amount - 1000, - script_type=proto.OutputScriptType.PAYTOP2SHWITNESS, - multisig=multisig_fake, - ) - - attack_count = 3 - - def attack_processor(msg): - nonlocal attack_count - # replace the first input_real with input_fake - if attack_count > 0 and msg.tx.inputs and msg.tx.inputs[0] == input_real: - msg.tx.inputs[0] = input_fake - attack_count -= 1 - return msg - - with client: - client.set_filter(proto.TxAck, attack_processor) - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_fbbff7), - request_input(0, TXHASH_fbbff7), - request_output(0, TXHASH_fbbff7), - request_output(1, TXHASH_fbbff7), - request_input(0), - request_output(0), - request_output(1), - request_input(0), - proto.Failure(code=proto.FailureType.ProcessError), - ] + btc.sign_tx( + client, + "Testnet", + [input_real], + [output_payee, output_change], + prev_txes=TxCache("Testnet"), ) + # must not produce this tx: + # 01000000000101396e2c107427f9eaece56a37539983adb8efd52b067c3d4567805fc8f3f7bffb01000000171600147a876a07b366f79000b441335f2907f777a0280bffffffff02e8030000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac703a0f000000000017a914a1261837f1b40e84346b1504ffe294e402965f2687024830450221009ff835e861be4e36ca1f2b6224aee2f253dfb9f456b13e4b1724bb4aaff4c9c802205e10679c2ead85743119f468cba5661f68b7da84dd2d477a7215fef98516f1f9012102af12ddd0d55e4fa2fcd084148eaf5b0b641320d0431d63d1e9a90f3cbd0d540700000000 - with pytest.raises(TrezorFailure) as exc: - btc.sign_tx( - client, - "Testnet", - [input_real], - [output_payee, output_change], - prev_txes=TxCache("Testnet"), - ) - # must not produce this tx: - # 01000000000101396e2c107427f9eaece56a37539983adb8efd52b067c3d4567805fc8f3f7bffb01000000171600147a876a07b366f79000b441335f2907f777a0280bffffffff02e8030000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac703a0f000000000017a914a1261837f1b40e84346b1504ffe294e402965f2687024830450221009ff835e861be4e36ca1f2b6224aee2f253dfb9f456b13e4b1724bb4aaff4c9c802205e10679c2ead85743119f468cba5661f68b7da84dd2d477a7215fef98516f1f9012102af12ddd0d55e4fa2fcd084148eaf5b0b641320d0431d63d1e9a90f3cbd0d540700000000 - - assert exc.value.code == proto.FailureType.ProcessError - assert exc.value.message.endswith("Transaction has changed during signing") + assert exc.value.code == proto.FailureType.ProcessError + assert exc.value.message.endswith("Transaction has changed during signing") diff --git a/tests/device_tests/test_multisig_change.py b/tests/device_tests/test_multisig_change.py index 2bd5a99c2e..c822ba57ce 100644 --- a/tests/device_tests/test_multisig_change.py +++ b/tests/device_tests/test_multisig_change.py @@ -40,422 +40,415 @@ TXHASH_b0946d = bytes.fromhex( "b0946dc27ba308a749b11afecc2018980af18f79e89ad6b080b58220d856f739" ) +pytestmark = [pytest.mark.multisig, pytest.mark.setup_client(mnemonic=MNEMONIC12)] -class TestMultisigChange: - node_ext1 = bip32.deserialize( - "xpub69qexv5TppjJQtXwSGeGXNtgGWyUzvsHACMt4Rr61Be4CmCf55eFcuXX828aySNuNR7hQYUCvUgZpioNxfs2HTAZWUUSFywhErg7JfTPv3Y" + +NODE_EXT1 = bip32.deserialize( + "xpub69qexv5TppjJQtXwSGeGXNtgGWyUzvsHACMt4Rr61Be4CmCf55eFcuXX828aySNuNR7hQYUCvUgZpioNxfs2HTAZWUUSFywhErg7JfTPv3Y" +) +# m/1 => 02c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e +# m/2 => 0375b9dfaad928ce1a7eed88df7c084e67d99e9ab74332419458a9a45779706801 + +NODE_EXT2 = bip32.deserialize( + "xpub69qexv5TppjJRiLLK2K1FZNCFcErkXprCo3jabCXMiqX5CFF4LHedwcXvXkTuBL9tFLWVxuGWrdeerXjiWpC1gynTNUaySDsr8SU5xMpj5R" +) +# m/1 => 0388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c1 +# m/2 => 03a04f945d5a3685729dde697d574076de4bdf38e904f813b22a851548e1110fc0 + +NODE_EXT3 = bip32.deserialize( + "xpub69qexv5TppjJVYtxFKSBFxcVGyaC8VJDa1RugAYwEDLVUBuaXrVgznvQB44piM8MRerfVf1pNCBK1L1NzhyKd4Ay25BVZX3S8twWfZDxmz7" +) +# m/1 => 02e0c21e2a7cf00b94c5421725acff97f9826598b91f2340c5ddda730caca7d648 +# m/2 => 03928301ffb8c0d7a364b794914c716ba3107cc78a6fe581028b0d8638b22e8573 + +NODE_INT = bip32.deserialize( + "xpub69qexv5TppjJNEK5bfX8vQ6ASXDUQ5PohSajrHgeknHZ4SJipn7edmpRmiiBLLDtPur71mekZFazhgas8rkUMnS7quk5qp64TLLV8ShrxZJ" +) +# m/1 => 03f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff35 +# m/2 => 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3 + +# ext1 + ext2 + int +# redeemscript (2 of 3): 522102c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e210388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c1210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a653ae +# multisig address: 2N9W4z9AhAPaHghtqVQPbaTAGHdbrhKeBQw +# tx: 16c6c8471b8db7a628f2b2bb86bfeefae1766463ce8692438c7fd3fce3f43ce5 +# input 0: 0.5 BTC + +# ext1 + int + ext2 +# redeemscript (2 of 3): 522102c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6210388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c153ae +# multisig address: 2NDBG6QXQLtnQ3jRGkrqo53BiCeXfQXLdj4 +# tx: d80c34ee14143a8bf61125102b7ef594118a3796cad670fa8ee15080ae155318 +# input 0: 0.345 BTC + +# ext1 + ext3 + int +# redeemscript (2 of 3): 522102c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e2102e0c21e2a7cf00b94c5421725acff97f9826598b91f2340c5ddda730caca7d648210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a653ae +# multisig address: 2MvwPWfp2XPU3S1cMwgEMKBPUw38VP5SBE4 +# tx: b0946dc27ba308a749b11afecc2018980af18f79e89ad6b080b58220d856f739 +# input 1: 0.555 BTC + +multisig_in1 = proto.MultisigRedeemScriptType( + nodes=[NODE_EXT2, NODE_EXT1, NODE_INT], + address_n=[0, 0], + signatures=[b"", b"", b""], + m=2, +) + +multisig_in2 = proto.MultisigRedeemScriptType( + nodes=[NODE_EXT1, NODE_EXT2, NODE_INT], + address_n=[0, 1], + signatures=[b"", b"", b""], + m=2, +) + +multisig_in3 = proto.MultisigRedeemScriptType( + nodes=[NODE_EXT1, NODE_EXT3, NODE_INT], + address_n=[0, 1], + signatures=[b"", b"", b""], + m=2, +) + +# 2N9W4z9AhAPaHghtqVQPbaTAGHdbrhKeBQw +INP1 = proto.TxInputType( + address_n=[H_(45), 0, 0, 0], + amount=50000000, + prev_hash=TXHASH_16c6c8, + prev_index=1, + script_type=proto.InputScriptType.SPENDMULTISIG, + multisig=multisig_in1, +) + +# 2NDBG6QXQLtnQ3jRGkrqo53BiCeXfQXLdj4 +INP2 = proto.TxInputType( + address_n=[H_(45), 0, 0, 1], + amount=34500000, + prev_hash=TXHASH_d80c34, + prev_index=0, + script_type=proto.InputScriptType.SPENDMULTISIG, + multisig=multisig_in2, +) + +# 2MvwPWfp2XPU3S1cMwgEMKBPUw38VP5SBE4 +INP3 = proto.TxInputType( + address_n=[H_(45), 0, 0, 1], + amount=55500000, + prev_hash=TXHASH_b0946d, + prev_index=0, + script_type=proto.InputScriptType.SPENDMULTISIG, + multisig=multisig_in3, +) + +def _responses(INP1, INP2, change=0): + resp = [ + request_input(0), + request_input(1), + request_output(0), + ] + if change != 1: + resp.append(proto.ButtonRequest(code=B.ConfirmOutput)) + resp.append(request_output(1)) + if change != 2: + resp.append(proto.ButtonRequest(code=B.ConfirmOutput)) + resp += [ + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(INP1.prev_hash), + request_input(0, INP1.prev_hash), + request_output(0, INP1.prev_hash), + request_output(1, INP1.prev_hash), + request_input(1), + request_meta(INP2.prev_hash), + request_input(0, INP2.prev_hash), + request_output(0, INP2.prev_hash), + request_output(1, INP2.prev_hash), + 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(), + ] + return resp + + +# both outputs are external +def test_external_external(client): + out1 = proto.TxOutputType( + address="1F8yBZB2NZhPZvJekhjTwjhQRRvQeTjjXr", + amount=40000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, ) - # m/1 => 02c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e - # m/2 => 0375b9dfaad928ce1a7eed88df7c084e67d99e9ab74332419458a9a45779706801 - node_ext2 = bip32.deserialize( - "xpub69qexv5TppjJRiLLK2K1FZNCFcErkXprCo3jabCXMiqX5CFF4LHedwcXvXkTuBL9tFLWVxuGWrdeerXjiWpC1gynTNUaySDsr8SU5xMpj5R" + out2 = proto.TxOutputType( + address="1H7uXJQTVwXca2BXF2opTrvuZapk8Cm8zY", + amount=44000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, ) - # m/1 => 0388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c1 - # m/2 => 03a04f945d5a3685729dde697d574076de4bdf38e904f813b22a851548e1110fc0 - node_ext3 = bip32.deserialize( - "xpub69qexv5TppjJVYtxFKSBFxcVGyaC8VJDa1RugAYwEDLVUBuaXrVgznvQB44piM8MRerfVf1pNCBK1L1NzhyKd4Ay25BVZX3S8twWfZDxmz7" + with client: + client.set_expected_responses(_responses(INP1, INP2)) + _, serialized_tx = btc.sign_tx( + client, + "Bitcoin", + [INP1, INP2], + [out1, out2], + prev_txes=TX_API, + ) + + assert ( + serialized_tx.hex() + == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000" ) - # m/1 => 02e0c21e2a7cf00b94c5421725acff97f9826598b91f2340c5ddda730caca7d648 - # m/2 => 03928301ffb8c0d7a364b794914c716ba3107cc78a6fe581028b0d8638b22e8573 - node_int = bip32.deserialize( - "xpub69qexv5TppjJNEK5bfX8vQ6ASXDUQ5PohSajrHgeknHZ4SJipn7edmpRmiiBLLDtPur71mekZFazhgas8rkUMnS7quk5qp64TLLV8ShrxZJ" + +# first external, second internal +def test_external_internal(client): + out1 = proto.TxOutputType( + address="1F8yBZB2NZhPZvJekhjTwjhQRRvQeTjjXr", + amount=40000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, ) - # m/1 => 03f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff35 - # m/2 => 038caebd6f753bbbd2bb1f3346a43cd32140648583673a31d62f2dfb56ad0ab9e3 - # ext1 + ext2 + int - # redeemscript (2 of 3): 522102c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e210388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c1210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a653ae - # multisig address: 2N9W4z9AhAPaHghtqVQPbaTAGHdbrhKeBQw - # tx: 16c6c8471b8db7a628f2b2bb86bfeefae1766463ce8692438c7fd3fce3f43ce5 - # input 0: 0.5 BTC + out2 = proto.TxOutputType( + address_n=parse_path("45'/0/1/1"), + amount=44000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) - # ext1 + int + ext2 - # redeemscript (2 of 3): 522102c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a6210388460dc439f4c8f5bcfc268c36e11b4375cad5c3535c336cfdf8c32c3afad5c153ae - # multisig address: 2NDBG6QXQLtnQ3jRGkrqo53BiCeXfQXLdj4 - # tx: d80c34ee14143a8bf61125102b7ef594118a3796cad670fa8ee15080ae155318 - # input 0: 0.345 BTC + with client: + client.set_expected_responses( + _responses(INP1, INP2, change=2) + ) + _, serialized_tx = btc.sign_tx( + client, + "Bitcoin", + [INP1, INP2], + [out1, out2], + prev_txes=TX_API, + ) - # ext1 + ext3 + int - # redeemscript (2 of 3): 522102c0d0c5fee952620757c6128dbf327c996cd72ed3358d15d6518a1186099bc15e2102e0c21e2a7cf00b94c5421725acff97f9826598b91f2340c5ddda730caca7d648210338d78612e990f2eea0c426b5e48a8db70b9d7ed66282b3b26511e0b1c75515a653ae - # multisig address: 2MvwPWfp2XPU3S1cMwgEMKBPUw38VP5SBE4 - # tx: b0946dc27ba308a749b11afecc2018980af18f79e89ad6b080b58220d856f739 - # input 1: 0.555 BTC + assert ( + serialized_tx.hex() + == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000" + ) - multisig_in1 = proto.MultisigRedeemScriptType( - nodes=[node_ext2, node_ext1, node_int], - address_n=[0, 0], + +# first internal, second external +def test_internal_external(client): + out1 = proto.TxOutputType( + address_n=parse_path("45'/0/1/0"), + amount=40000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + out2 = proto.TxOutputType( + address="1H7uXJQTVwXca2BXF2opTrvuZapk8Cm8zY", + amount=44000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + _responses(INP1, INP2, change=1) + ) + _, serialized_tx = btc.sign_tx( + client, + "Bitcoin", + [INP1, INP2], + [out1, out2], + prev_txes=TX_API, + ) + + assert ( + serialized_tx.hex() + == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000" + ) + + +# both outputs are external +def test_multisig_external_external(client): + out1 = proto.TxOutputType( + address="3B23k4kFBRtu49zvpG3Z9xuFzfpHvxBcwt", + amount=40000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + out2 = proto.TxOutputType( + address="3PkXLsY7AUZCrCKGvX8FfP2EawowUBMbcg", + amount=44000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses(_responses(INP1, INP2)) + _, serialized_tx = btc.sign_tx( + client, + "Bitcoin", + [INP1, INP2], + [out1, out2], + prev_txes=TX_API, + ) + + assert ( + serialized_tx.hex() + == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" + ) + + +# inputs match, change matches (first is change) +def test_multisig_change_match_first(client): + multisig_out1 = proto.MultisigRedeemScriptType( + nodes=[NODE_EXT2, NODE_EXT1, NODE_INT], + address_n=[1, 0], signatures=[b"", b"", b""], m=2, ) - multisig_in2 = proto.MultisigRedeemScriptType( - nodes=[node_ext1, node_ext2, node_int], - address_n=[0, 1], + out1 = proto.TxOutputType( + address_n=[H_(45), 0, 1, 0], + multisig=multisig_out1, + amount=40000000, + script_type=proto.OutputScriptType.PAYTOMULTISIG, + ) + + out2 = proto.TxOutputType( + address="3PkXLsY7AUZCrCKGvX8FfP2EawowUBMbcg", + amount=44000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + _responses(INP1, INP2, change=1) + ) + _, serialized_tx = btc.sign_tx( + client, + "Bitcoin", + [INP1, INP2], + [out1, out2], + prev_txes=TX_API, + ) + + assert ( + serialized_tx.hex() + == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" + ) + + +# inputs match, change matches (second is change) +def test_multisig_change_match_second(client): + multisig_out2 = proto.MultisigRedeemScriptType( + nodes=[NODE_EXT1, NODE_EXT2, NODE_INT], + address_n=[1, 1], signatures=[b"", b"", b""], m=2, ) - multisig_in3 = proto.MultisigRedeemScriptType( - nodes=[node_ext1, node_ext3, node_int], - address_n=[0, 1], + out1 = proto.TxOutputType( + address="3B23k4kFBRtu49zvpG3Z9xuFzfpHvxBcwt", + amount=40000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + out2 = proto.TxOutputType( + address_n=[H_(45), 0, 1, 1], + multisig=multisig_out2, + amount=44000000, + script_type=proto.OutputScriptType.PAYTOMULTISIG, + ) + + with client: + client.set_expected_responses( + _responses(INP1, INP2, change=2) + ) + _, serialized_tx = btc.sign_tx( + client, + "Bitcoin", + [INP1, INP2], + [out1, out2], + prev_txes=TX_API, + ) + + assert ( + serialized_tx.hex() + == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" + ) + + +# inputs match, change mismatches (second tries to be change but isn't) +def test_multisig_mismatch_change(client): + multisig_out2 = proto.MultisigRedeemScriptType( + nodes=[NODE_EXT1, NODE_INT, NODE_EXT3], + address_n=[1, 0], signatures=[b"", b"", b""], m=2, ) - # 2N9W4z9AhAPaHghtqVQPbaTAGHdbrhKeBQw - inp1 = proto.TxInputType( - address_n=[H_(45), 0, 0, 0], - amount=50000000, - prev_hash=TXHASH_16c6c8, - prev_index=1, - script_type=proto.InputScriptType.SPENDMULTISIG, - multisig=multisig_in1, + out1 = proto.TxOutputType( + address="3B23k4kFBRtu49zvpG3Z9xuFzfpHvxBcwt", + amount=40000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, ) - # 2NDBG6QXQLtnQ3jRGkrqo53BiCeXfQXLdj4 - inp2 = proto.TxInputType( - address_n=[H_(45), 0, 0, 1], - amount=34500000, - prev_hash=TXHASH_d80c34, - prev_index=0, - script_type=proto.InputScriptType.SPENDMULTISIG, - multisig=multisig_in2, + out2 = proto.TxOutputType( + address_n=[H_(45), 0, 1, 0], + multisig=multisig_out2, + amount=44000000, + script_type=proto.OutputScriptType.PAYTOMULTISIG, ) - # 2MvwPWfp2XPU3S1cMwgEMKBPUw38VP5SBE4 - inp3 = proto.TxInputType( - address_n=[H_(45), 0, 0, 1], - amount=55500000, - prev_hash=TXHASH_b0946d, - prev_index=0, - script_type=proto.InputScriptType.SPENDMULTISIG, - multisig=multisig_in3, + with client: + client.set_expected_responses(_responses(INP1, INP2)) + _, serialized_tx = btc.sign_tx( + client, + "Bitcoin", + [INP1, INP2], + [out1, out2], + prev_txes=TX_API, + ) + + assert ( + serialized_tx.hex() + == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b40047304402207f9992cc0230527faf54ec6bd233307db82bc8fac039dcee418bc6feb4e96a3a02206bb4cb157ad27c123277328a877572563a45d70b844d9ab07cc42238112f8c2a014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b400473044022078a41bfa87d72d6ba810d84bf568b5a29acf8b851ba6c3a8dbff079b34a7feb0022037b770c776db0b6c883c38a684a121b90a59ed1958774cbf64de70e53e29639f014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914e6a3e2fbadb7f559f8d20c46aceae78c96fcf1d18700000000" ) - def _responses(self, inp1, inp2, change=0): - resp = [ - request_input(0), - request_input(1), - request_output(0), - ] - if change != 1: - resp.append(proto.ButtonRequest(code=B.ConfirmOutput)) - resp.append(request_output(1)) - if change != 2: - resp.append(proto.ButtonRequest(code=B.ConfirmOutput)) - resp += [ - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(inp1.prev_hash), - request_input(0, inp1.prev_hash), - request_output(0, inp1.prev_hash), - request_output(1, inp1.prev_hash), - request_input(1), - request_meta(inp2.prev_hash), - request_input(0, inp2.prev_hash), - request_output(0, inp2.prev_hash), - request_output(1, inp2.prev_hash), - 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(), - ] - return resp - # both outputs are external - @pytest.mark.multisig - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_external_external(self, client): - out1 = proto.TxOutputType( - address="1F8yBZB2NZhPZvJekhjTwjhQRRvQeTjjXr", - amount=40000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, +# inputs mismatch, change matches with first input +def test_multisig_mismatch_inputs(client): + multisig_out1 = proto.MultisigRedeemScriptType( + nodes=[NODE_EXT2, NODE_EXT1, NODE_INT], + address_n=[1, 0], + signatures=[b"", b"", b""], + m=2, + ) + + out1 = proto.TxOutputType( + address_n=[H_(45), 0, 1, 0], + multisig=multisig_out1, + amount=40000000, + script_type=proto.OutputScriptType.PAYTOMULTISIG, + ) + + out2 = proto.TxOutputType( + address="3PkXLsY7AUZCrCKGvX8FfP2EawowUBMbcg", + amount=65000000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses(_responses(INP1, INP3)) + _, serialized_tx = btc.sign_tx( + client, + "Bitcoin", + [INP1, INP3], + [out1, out2], + prev_txes=TX_API, ) - out2 = proto.TxOutputType( - address="1H7uXJQTVwXca2BXF2opTrvuZapk8Cm8zY", - amount=44000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses(self._responses(self.inp1, self.inp2)) - _, serialized_tx = btc.sign_tx( - client, - "Bitcoin", - [self.inp1, self.inp2], - [out1, out2], - prev_txes=TX_API, - ) - - assert ( - serialized_tx.hex() - == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000" - ) - - # first external, second internal - @pytest.mark.multisig - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_external_internal(self, client): - out1 = proto.TxOutputType( - address="1F8yBZB2NZhPZvJekhjTwjhQRRvQeTjjXr", - amount=40000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - out2 = proto.TxOutputType( - address_n=parse_path("45'/0/1/1"), - amount=44000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - self._responses(self.inp1, self.inp2, change=2) - ) - _, serialized_tx = btc.sign_tx( - client, - "Bitcoin", - [self.inp1, self.inp2], - [out1, out2], - prev_txes=TX_API, - ) - - assert ( - serialized_tx.hex() - == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000" - ) - - # first internal, second external - @pytest.mark.multisig - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_internal_external(self, client): - out1 = proto.TxOutputType( - address_n=parse_path("45'/0/1/0"), - amount=40000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - out2 = proto.TxOutputType( - address="1H7uXJQTVwXca2BXF2opTrvuZapk8Cm8zY", - amount=44000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - self._responses(self.inp1, self.inp2, change=1) - ) - _, serialized_tx = btc.sign_tx( - client, - "Bitcoin", - [self.inp1, self.inp2], - [out1, out2], - prev_txes=TX_API, - ) - - assert ( - serialized_tx.hex() - == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022064f13801744a6c21b694f62cdb5d834e852f13ecf85ed4d0a56ba279571c24e3022010fab4cb05bdd7b24c8376dda4f62a418548eea6eb483e58675fa06e0d5c642c014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b4004730440220727b2522268f913acd213c507d7801b146e5b6cef666ad44b769c26d6c762e4d022021c0c2e9e8298dee2a490d956f7ab1b2d3160c1e37a50cc6d19a5e62eb484fc9014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a6202000000001976a9149b139230e4fe91c05a37ec334dc8378f3dbe377088ac00639f02000000001976a914b0d05a10926a7925508febdbab9a5bd4cda8c8f688ac00000000" - ) - - # both outputs are external - @pytest.mark.multisig - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_multisig_external_external(self, client): - out1 = proto.TxOutputType( - address="3B23k4kFBRtu49zvpG3Z9xuFzfpHvxBcwt", - amount=40000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - out2 = proto.TxOutputType( - address="3PkXLsY7AUZCrCKGvX8FfP2EawowUBMbcg", - amount=44000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses(self._responses(self.inp1, self.inp2)) - _, serialized_tx = btc.sign_tx( - client, - "Bitcoin", - [self.inp1, self.inp2], - [out1, out2], - prev_txes=TX_API, - ) - - assert ( - serialized_tx.hex() - == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" - ) - - # inputs match, change matches (first is change) - @pytest.mark.multisig - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_multisig_change_match_first(self, client): - multisig_out1 = proto.MultisigRedeemScriptType( - nodes=[self.node_ext2, self.node_ext1, self.node_int], - address_n=[1, 0], - signatures=[b"", b"", b""], - m=2, - ) - - out1 = proto.TxOutputType( - address_n=[H_(45), 0, 1, 0], - multisig=multisig_out1, - amount=40000000, - script_type=proto.OutputScriptType.PAYTOMULTISIG, - ) - - out2 = proto.TxOutputType( - address="3PkXLsY7AUZCrCKGvX8FfP2EawowUBMbcg", - amount=44000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses( - self._responses(self.inp1, self.inp2, change=1) - ) - _, serialized_tx = btc.sign_tx( - client, - "Bitcoin", - [self.inp1, self.inp2], - [out1, out2], - prev_txes=TX_API, - ) - - assert ( - serialized_tx.hex() - == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" - ) - - # inputs match, change matches (second is change) - @pytest.mark.multisig - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_multisig_change_match_second(self, client): - multisig_out2 = proto.MultisigRedeemScriptType( - nodes=[self.node_ext1, self.node_ext2, self.node_int], - address_n=[1, 1], - signatures=[b"", b"", b""], - m=2, - ) - - out1 = proto.TxOutputType( - address="3B23k4kFBRtu49zvpG3Z9xuFzfpHvxBcwt", - amount=40000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - out2 = proto.TxOutputType( - address_n=[H_(45), 0, 1, 1], - multisig=multisig_out2, - amount=44000000, - script_type=proto.OutputScriptType.PAYTOMULTISIG, - ) - - with client: - client.set_expected_responses( - self._responses(self.inp1, self.inp2, change=2) - ) - _, serialized_tx = btc.sign_tx( - client, - "Bitcoin", - [self.inp1, self.inp2], - [out1, out2], - prev_txes=TX_API, - ) - - assert ( - serialized_tx.hex() - == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b400473044022059394e0dfcb2d2f4a6108703f801545ca5a820c0ac6a1859d0a3854813de55fa02207b6a57d70b82932ff58163336c461653a2dc82c78ed8157159e5178ac7325390014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b40047304402205a911685f5b974b2fc4a19d5ce056218773a4d20b5eaae2c2f9594929308182002201e03449f5a8813ec19f408bf1b6f4f334886d6fcf9920e300fd7678ef0724f81014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" - ) - - # inputs match, change mismatches (second tries to be change but isn't) - @pytest.mark.multisig - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_multisig_mismatch_change(self, client): - multisig_out2 = proto.MultisigRedeemScriptType( - nodes=[self.node_ext1, self.node_int, self.node_ext3], - address_n=[1, 0], - signatures=[b"", b"", b""], - m=2, - ) - - out1 = proto.TxOutputType( - address="3B23k4kFBRtu49zvpG3Z9xuFzfpHvxBcwt", - amount=40000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - out2 = proto.TxOutputType( - address_n=[H_(45), 0, 1, 0], - multisig=multisig_out2, - amount=44000000, - script_type=proto.OutputScriptType.PAYTOMULTISIG, - ) - - with client: - client.set_expected_responses(self._responses(self.inp1, self.inp2)) - _, serialized_tx = btc.sign_tx( - client, - "Bitcoin", - [self.inp1, self.inp2], - [out1, out2], - prev_txes=TX_API, - ) - - assert ( - serialized_tx.hex() - == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b40047304402207f9992cc0230527faf54ec6bd233307db82bc8fac039dcee418bc6feb4e96a3a02206bb4cb157ad27c123277328a877572563a45d70b844d9ab07cc42238112f8c2a014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff185315ae8050e18efa70d6ca96378a1194f57e2b102511f68b3a1414ee340cd800000000b400473044022078a41bfa87d72d6ba810d84bf568b5a29acf8b851ba6c3a8dbff079b34a7feb0022037b770c776db0b6c883c38a684a121b90a59ed1958774cbf64de70e53e29639f014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103ed1fd93989595d7ad4b488efd05a22c0239482c9a20923f2f214a38e54f6c41a2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948700639f020000000017a914e6a3e2fbadb7f559f8d20c46aceae78c96fcf1d18700000000" - ) - - # inputs mismatch, change matches with first input - @pytest.mark.multisig - @pytest.mark.setup_client(mnemonic=MNEMONIC12) - def test_multisig_mismatch_inputs(self, client): - multisig_out1 = proto.MultisigRedeemScriptType( - nodes=[self.node_ext2, self.node_ext1, self.node_int], - address_n=[1, 0], - signatures=[b"", b"", b""], - m=2, - ) - - out1 = proto.TxOutputType( - address_n=[H_(45), 0, 1, 0], - multisig=multisig_out1, - amount=40000000, - script_type=proto.OutputScriptType.PAYTOMULTISIG, - ) - - out2 = proto.TxOutputType( - address="3PkXLsY7AUZCrCKGvX8FfP2EawowUBMbcg", - amount=65000000, - script_type=proto.OutputScriptType.PAYTOADDRESS, - ) - - with client: - client.set_expected_responses(self._responses(self.inp1, self.inp3)) - _, serialized_tx = btc.sign_tx( - client, - "Bitcoin", - [self.inp1, self.inp3], - [out1, out2], - prev_txes=TX_API, - ) - - assert ( - serialized_tx.hex() - == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100d907b9339951c96ef4515ef7aff8b3c28c4c8c5875d7421aa1de9f3a94e3508302205cdc311a6c91dfbb74f1a9a940a994a65dbfb0cf6dedcaaaeee839e0b8fd016d014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff39f756d82082b580b0d69ae8798ff10a981820ccfe1ab149a708a37bc26d94b000000000b500483045022100fdad4a47d15f47cc364fe0cbed11b1ced1f9ef210bc1bd413ec4384f630c63720220752e4f09ea4e5e6623f5ebe89b3983ec6e5702f63f9bce696f10b2d594d23532014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103b6321a1194e5cc47b6b7edc3f67a096e6f71ccb72440f84f390b6e98df0ea8ec2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948740d2df030000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" - ) + assert ( + serialized_tx.hex() + == "0100000002e53cf4e3fcd37f8c439286ce636476e1faeebf86bbb2f228a6b78d1b47c8c61601000000b500483045022100d907b9339951c96ef4515ef7aff8b3c28c4c8c5875d7421aa1de9f3a94e3508302205cdc311a6c91dfbb74f1a9a940a994a65dbfb0cf6dedcaaaeee839e0b8fd016d014c69522103dc07026aacb5918dac4e09f9da8290d0ae22161699636c22cace78082116a7792103e70db185fad69c2971f0107a42930e5d82a9ed3a11b922a96fdfc4124b63e54c2103f3fe007a1e34ac76c1a2528e9149f90f9f93739929797afab6a8e18d682fa71053aeffffffff39f756d82082b580b0d69ae8798ff10a981820ccfe1ab149a708a37bc26d94b000000000b500483045022100fdad4a47d15f47cc364fe0cbed11b1ced1f9ef210bc1bd413ec4384f630c63720220752e4f09ea4e5e6623f5ebe89b3983ec6e5702f63f9bce696f10b2d594d23532014c6952210297ad8a5df42f9e362ef37d9a4ddced89d8f7a143690649aa0d0ff049c7daca842103b6321a1194e5cc47b6b7edc3f67a096e6f71ccb72440f84f390b6e98df0ea8ec2103f91460d79e4e463d7d90cb75254bcd62b515a99a950574c721efdc5f711dff3553aeffffffff02005a62020000000017a91466528dd543f94d162c8111d2ec248d25ba9b90948740d2df030000000017a914f1fc92c0aed1712911c70a2e09ac15ff0922652f8700000000" + ) diff --git a/tests/device_tests/test_op_return.py b/tests/device_tests/test_op_return.py index bdde2adb18..312f99262f 100644 --- a/tests/device_tests/test_op_return.py +++ b/tests/device_tests/test_op_return.py @@ -31,102 +31,103 @@ TXHASH_d5f65e = bytes.fromhex( ) -class TestOpReturn: - def test_opreturn(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/0'/0'/0/2"), - amount=390000, - prev_hash=TXHASH_d5f65e, - prev_index=0, +def test_opreturn(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/0'/0'/0/2"), + amount=390000, + prev_hash=TXHASH_d5f65e, + prev_index=0, + ) + + out1 = proto.TxOutputType( + address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", + amount=390000 - 10000, + script_type=proto.OutputScriptType.PAYTOADDRESS, + ) + + out2 = proto.TxOutputType( + op_return_data=b"test of the op_return data", + amount=0, + script_type=proto.OutputScriptType.PAYTOOPRETURN, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + proto.ButtonRequest(code=B.ConfirmOutput), + request_output(1), + proto.ButtonRequest(code=B.ConfirmOutput), + proto.ButtonRequest(code=B.SignTx), + request_input(0), + request_meta(TXHASH_d5f65e), + request_input(0, TXHASH_d5f65e), + request_input(1, TXHASH_d5f65e), + request_output(0, TXHASH_d5f65e), + request_input(0), + request_output(0), + request_output(1), + request_output(0), + request_output(1), + request_finished(), + ] + ) + _, serialized_tx = btc.sign_tx( + client, "Bitcoin", [inp1], [out1, out2], prev_txes=TX_API ) - out1 = proto.TxOutputType( - address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", - amount=390000 - 10000, - script_type=proto.OutputScriptType.PAYTOADDRESS, + assert ( + serialized_tx.hex() + == "010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b483045022100bc36e1227b334e856c532bbef86d30a96823a5f2461738f4dbf969dfbcf1b40b022078c5353ec9a4bce2bb05bd1ec466f2ab379c1aad926e208738407bba4e09784b012103330236b68aa6fdcaca0ea72e11b360c84ed19a338509aa527b678a7ec9076882ffffffff0260cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000000000001c6a1a74657374206f6620746865206f705f72657475726e206461746100000000" + ) + + +def test_nonzero_opreturn(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/0'/10'/0/5"), + amount=390000, + prev_hash=TXHASH_d5f65e, + prev_index=0, + ) + + out1 = proto.TxOutputType( + op_return_data=b"test of the op_return data", + amount=10000, + script_type=proto.OutputScriptType.PAYTOOPRETURN, + ) + + with client: + client.set_expected_responses( + [request_input(0), request_output(0), proto.Failure()] ) - out2 = proto.TxOutputType( - op_return_data=b"test of the op_return data", - amount=0, - script_type=proto.OutputScriptType.PAYTOOPRETURN, + with pytest.raises( + TrezorFailure, match="OP_RETURN output with non-zero amount" + ): + btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API) + + +def test_opreturn_address(client): + inp1 = proto.TxInputType( + address_n=parse_path("44'/0'/0'/0/2"), + amount=390000, + prev_hash=TXHASH_d5f65e, + prev_index=0, + ) + + out1 = proto.TxOutputType( + address_n=parse_path("44'/0'/0'/1/2"), + amount=0, + op_return_data=b"OMNI TRANSACTION GOES HERE", + script_type=proto.OutputScriptType.PAYTOOPRETURN, + ) + + with client: + client.set_expected_responses( + [request_input(0), request_output(0), proto.Failure()] ) - - with client: - client.set_expected_responses( - [ - request_input(0), - request_output(0), - proto.ButtonRequest(code=B.ConfirmOutput), - request_output(1), - proto.ButtonRequest(code=B.ConfirmOutput), - proto.ButtonRequest(code=B.SignTx), - request_input(0), - request_meta(TXHASH_d5f65e), - request_input(0, TXHASH_d5f65e), - request_input(1, TXHASH_d5f65e), - request_output(0, TXHASH_d5f65e), - request_input(0), - request_output(0), - request_output(1), - request_output(0), - request_output(1), - request_finished(), - ] - ) - _, serialized_tx = btc.sign_tx( - client, "Bitcoin", [inp1], [out1, out2], prev_txes=TX_API - ) - - assert ( - serialized_tx.hex() - == "010000000182488650ef25a58fef6788bd71b8212038d7f2bbe4750bc7bcb44701e85ef6d5000000006b483045022100bc36e1227b334e856c532bbef86d30a96823a5f2461738f4dbf969dfbcf1b40b022078c5353ec9a4bce2bb05bd1ec466f2ab379c1aad926e208738407bba4e09784b012103330236b68aa6fdcaca0ea72e11b360c84ed19a338509aa527b678a7ec9076882ffffffff0260cc0500000000001976a914de9b2a8da088824e8fe51debea566617d851537888ac00000000000000001c6a1a74657374206f6620746865206f705f72657475726e206461746100000000" - ) - - def test_nonzero_opreturn(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/0'/10'/0/5"), - amount=390000, - prev_hash=TXHASH_d5f65e, - prev_index=0, - ) - - out1 = proto.TxOutputType( - op_return_data=b"test of the op_return data", - amount=10000, - script_type=proto.OutputScriptType.PAYTOOPRETURN, - ) - - with client: - client.set_expected_responses( - [request_input(0), request_output(0), proto.Failure()] - ) - - with pytest.raises( - TrezorFailure, match="OP_RETURN output with non-zero amount" - ): - btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API) - - def test_opreturn_address(self, client): - inp1 = proto.TxInputType( - address_n=parse_path("44'/0'/0'/0/2"), - amount=390000, - prev_hash=TXHASH_d5f65e, - prev_index=0, - ) - - out1 = proto.TxOutputType( - address_n=parse_path("44'/0'/0'/1/2"), - amount=0, - op_return_data=b"OMNI TRANSACTION GOES HERE", - script_type=proto.OutputScriptType.PAYTOOPRETURN, - ) - - with client: - client.set_expected_responses( - [request_input(0), request_output(0), proto.Failure()] - ) - with pytest.raises( - TrezorFailure, match="Output's address_n provided but not expected." - ): - btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API) + with pytest.raises( + TrezorFailure, match="Output's address_n provided but not expected." + ): + btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TX_API) diff --git a/tests/device_tests/tezos/test_getaddress.py b/tests/device_tests/tezos/test_getaddress.py index fc31e2e547..508502e738 100644 --- a/tests/device_tests/tezos/test_getaddress.py +++ b/tests/device_tests/tezos/test_getaddress.py @@ -23,12 +23,11 @@ from trezorlib.tools import parse_path @pytest.mark.altcoin @pytest.mark.tezos @pytest.mark.skip_t1 -class TestMsgTezosGetAddress: - def test_tezos_get_address(self, client): - path = parse_path("m/44'/1729'/0'") - address = get_address(client, path, show_display=True) - assert address == "tz1Kef7BSg6fo75jk37WkKRYSnJDs69KVqt9" +def test_tezos_get_address(client): + path = parse_path("m/44'/1729'/0'") + address = get_address(client, path, show_display=True) + assert address == "tz1Kef7BSg6fo75jk37WkKRYSnJDs69KVqt9" - path = parse_path("m/44'/1729'/1'") - address = get_address(client, path, show_display=True) - assert address == "tz1ekQapZCX4AXxTJhJZhroDKDYLHDHegvm1" + path = parse_path("m/44'/1729'/1'") + address = get_address(client, path, show_display=True) + assert address == "tz1ekQapZCX4AXxTJhJZhroDKDYLHDHegvm1" diff --git a/tests/device_tests/tezos/test_getpublickey.py b/tests/device_tests/tezos/test_getpublickey.py index e220dad8e8..dc378f2b65 100644 --- a/tests/device_tests/tezos/test_getpublickey.py +++ b/tests/device_tests/tezos/test_getpublickey.py @@ -23,12 +23,11 @@ from trezorlib.tools import parse_path @pytest.mark.altcoin @pytest.mark.tezos @pytest.mark.skip_t1 -class TestMsgTezosGetPublicKey: - def test_tezos_get_public_key(self, client): - path = parse_path("m/44'/1729'/0'") - pk = get_public_key(client, path) - assert pk == "edpkttLhEbVfMC3DhyVVFzdwh8ncRnEWiLD1x8TAuPU7vSJak7RtBX" +def test_tezos_get_public_key(client): + path = parse_path("m/44'/1729'/0'") + pk = get_public_key(client, path) + assert pk == "edpkttLhEbVfMC3DhyVVFzdwh8ncRnEWiLD1x8TAuPU7vSJak7RtBX" - path = parse_path("m/44'/1729'/1'") - pk = get_public_key(client, path) - assert pk == "edpkuTPqWjcApwyD3VdJhviKM5C13zGk8c4m87crgFarQboF3Mp56f" + path = parse_path("m/44'/1729'/1'") + pk = get_public_key(client, path) + assert pk == "edpkuTPqWjcApwyD3VdJhviKM5C13zGk8c4m87crgFarQboF3Mp56f" diff --git a/tests/device_tests/tezos/test_sign_tx.py b/tests/device_tests/tezos/test_sign_tx.py index 1cec7f9dc7..ba9281638a 100644 --- a/tests/device_tests/tezos/test_sign_tx.py +++ b/tests/device_tests/tezos/test_sign_tx.py @@ -24,443 +24,437 @@ TEZOS_PATH = parse_path("m/44'/1729'/0'") TEZOS_PATH_10 = parse_path("m/44'/1729'/10'") TEZOS_PATH_15 = parse_path("m/44'/1729'/15'") +pytestmark = [ + pytest.mark.altcoin, + pytest.mark.tezos, + pytest.mark.skip_t1, +] -@pytest.mark.altcoin -@pytest.mark.tezos -@pytest.mark.skip_t1 -class TestMsgTezosSignTx: - def test_tezos_sign_tx_proposal(self, client): - with client: - resp = tezos.sign_tx( - client, - TEZOS_PATH_10, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "dee04042c0832d68a43699b2001c0a38065436eb05e578071a763e1972d0bc81", - "proposal": { - "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - "period": 17, - "proposals": [ - "dfa974df171c2dad9a9b8f25d99af41fd9702ce5d04521d2f9943c84d88aa572" - ], - }, - }, - ), - ) - assert ( - resp.signature - == "edsigtfY16R32k2WVMYfFr7ymnro4ib5zMckk28vsuViYNN77DJAvCJLRNArd9L531pUCxT4YdcvCvBym5dhcZ1rknEVm6yZ8bB" - ) - assert ( - resp.sig_op_contents.hex() - == "dee04042c0832d68a43699b2001c0a38065436eb05e578071a763e1972d0bc8105005f450441f41ee11eee78a31d1e1e55627c783bd60000001100000020dfa974df171c2dad9a9b8f25d99af41fd9702ce5d04521d2f9943c84d88aa5723b12621296a679b3a74ea790df5347995a76e20a09e76590baaacf4e09341965a04123f5cbbba8427f045b5f7d59157a3098e44839babe7c247d19b58bbb2405" - ) - assert ( - resp.operation_hash == "opLqntFUu984M7LnGsFvfGW6kWe9QjAz4AfPDqQvwJ1wPM4Si4c" - ) - - def test_tezos_sign_tx_multiple_proposals(self, client): - with client: - resp = tezos.sign_tx( - client, - TEZOS_PATH_10, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "7e0be36a90c663c73c60da3889ffefff1383fb65cc29f0639f173d8f95a52df7", - "proposal": { - "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - "period": 17, - "proposals": [ - "2a6ff28ab4d0ccb18f7129aaaf9a4b8027d794f2562849665fdb6999db2a4e57", - "47cd60c09ab8437cc9fe19add494dce1b9844100f660f02ce77510a0c66d2762", - ], - }, - }, - ), - ) - - assert ( - resp.signature - == "edsigu6GAjhiWAQ64ctWTGEDYAZ16tYzLgzWzqc4CUyixK4FGRE8YUBVzFaVJ2fUCexZjZLMLdiNZGcUdzeL1bQhZ2h5oLrh7pA" - ) - assert ( - resp.sig_op_contents.hex() - == "7e0be36a90c663c73c60da3889ffefff1383fb65cc29f0639f173d8f95a52df705005f450441f41ee11eee78a31d1e1e55627c783bd600000011000000402a6ff28ab4d0ccb18f7129aaaf9a4b8027d794f2562849665fdb6999db2a4e5747cd60c09ab8437cc9fe19add494dce1b9844100f660f02ce77510a0c66d2762f813361ac00ada7e3256f23973ae25b112229476a3cb3e506fe929ea1e9358299fed22178d1be689cddeedd1f303abfef859b664f159a528576a1c807079f005" - ) - assert ( - resp.operation_hash == "onobSyNgiitGXxSVFJN6949MhUomkkxvH4ZJ2owgWwNeDdntF9Y" - ) - - def test_tezos_sing_tx_ballot_yay(self, client): +def test_tezos_sign_tx_proposal(client): + with client: resp = tezos.sign_tx( client, TEZOS_PATH_10, dict_to_proto( messages.TezosSignTx, { - "branch": "3a8f60c4cd394cee5b50136c7fc8cb157e8aaa476a9e5c68709be6fc1cdb5395", - "ballot": { - "source": "0002298c03ed7d454a101eb7022bc95f7e5f41ac78", - "period": 2, - "proposal": "def7ed9c84af23ab37ebb60dd83cd103d1272ad6c63d4c05931567e65ed027e3", - "ballot": 0, - }, - }, - ), - ) - - assert ( - resp.signature - == "edsigtkxNm6YXwtV24DqeuimeZFTeFCn2jDYheSsXT4rHMcEjNvzsiSo55nVyVsQxtEe8M7U4PWJWT4rGYYGckQCgtkNJkd2roX" - ) - - def test_tezos_sing_tx_ballot_nay(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH_10, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "3a8f60c4cd394cee5b50136c7fc8cb157e8aaa476a9e5c68709be6fc1cdb5395", - "ballot": { - "source": "0002298c03ed7d454a101eb7022bc95f7e5f41ac78", - "period": 2, - "proposal": "def7ed9c84af23ab37ebb60dd83cd103d1272ad6c63d4c05931567e65ed027e3", - "ballot": 1, - }, - }, - ), - ) - assert ( - resp.signature - == "edsigtqLaizfF6Cfc2JQL7TrsyniGhpZEojZAKMFW6AeudaUoU8KGXEHJH69Q4Lf27qFyUSTfbeHNnnCt69SGEPWkmpkgkgqMbL" - ) - - def test_tezos_sing_tx_ballot_pass(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH_10, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "3a8f60c4cd394cee5b50136c7fc8cb157e8aaa476a9e5c68709be6fc1cdb5395", - "ballot": { - "source": "0002298c03ed7d454a101eb7022bc95f7e5f41ac78", - "period": 2, - "proposal": "def7ed9c84af23ab37ebb60dd83cd103d1272ad6c63d4c05931567e65ed027e3", - "ballot": 2, - }, - }, - ), - ) - - assert ( - resp.signature - == "edsigu6YX7EegPwrpcEbdNQsNhrRiEagBNGJBmFamP4mixZZw1UynhahGQ8RNiZLSUVLERUZwygrsSVenBqXGt9VnknTxtzjKzv" - ) - - def test_tezos_sign_tx_tranasaction(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH_10, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "3b85532b5a468cd26b6d3c7e762ae53b795d19c6db4838ed2750df8e063aedb8", - "transaction": { + "branch": "dee04042c0832d68a43699b2001c0a38065436eb05e578071a763e1972d0bc81", + "proposal": { "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - "fee": 10000, - "counter": 274, - "gas_limit": 20000, - "storage_limit": 0, - "amount": 100000, - "destination": { - "tag": 0, - "hash": "003325df8851047421605ae7d6b09b49f70c8ce460", - }, + "period": 17, + "proposals": [ + "dfa974df171c2dad9a9b8f25d99af41fd9702ce5d04521d2f9943c84d88aa572" + ], }, }, ), ) - assert ( - resp.signature - == "edsigtvRTDegGy83x5AHQwhzPAbKteJ7MsLukhLRS9RLMRX5UdmtV1xiHEhQCUrGNv6h9CbV1cvuUVzRgLd6Af4XfVQgGkkYUuY" - ) - assert ( - resp.sig_op_contents.hex() - == "3b85532b5a468cd26b6d3c7e762ae53b795d19c6db4838ed2750df8e063aedb86c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9202a09c0100a08d0600003325df8851047421605ae7d6b09b49f70c8ce46000acdcd3df9daaa79c7345c068ffddc2113047fc00c1eed3503838d15fc6690821ee6eaa1e67b4a8d40dcf30a9ec456bbbda18ef2bcc021053d7d8c3f1473df809" - ) - assert ( - resp.operation_hash == "oon8PNUsPETGKzfESv1Epv4535rviGS7RdCfAEKcPvzojrcuufb" - ) - def test_tezos_sign_tx_delegation(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH_15, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "447d51450749763989c1aa5e1939aae623abb5a050f9cf1c04c247d91ca67593", - "delegation": { - "source": "0002eca091abc1e0f5c38a155c1313c410b47e1549", - "fee": 20000, - "counter": 458069, - "gas_limit": 20000, - "storage_limit": 0, - "delegate": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - }, - }, - ), - ) - assert ( - resp.signature - == "edsigu2ZsDXXm7RzMF2oSKHK54ZfSUPvU2jekJBQmAprMe8ksnofMScKd3Kc3RTTExwzaJGENzoe94ZDiW86eWWnWBTPNw2xu5m" - ) - assert ( - resp.sig_op_contents.hex() - == "447d51450749763989c1aa5e1939aae623abb5a050f9cf1c04c247d91ca675936e0002eca091abc1e0f5c38a155c1313c410b47e1549a09c01d5fa1ba09c0100ff005f450441f41ee11eee78a31d1e1e55627c783bd6dbd53f9129387e82548e5d20b1479a46a876ac7516001fae01488dfbe9dcfc732cb8664d52fd7e1bc25a9845714131fd498ef65ea91f84e180688a41e06fe700" - ) - assert ( - resp.operation_hash == "op79C1tR7wkUgYNid2zC1WNXmGorS38mTXZwtAjmCQm2kG7XG59" - ) + assert ( + resp.signature + == "edsigtfY16R32k2WVMYfFr7ymnro4ib5zMckk28vsuViYNN77DJAvCJLRNArd9L531pUCxT4YdcvCvBym5dhcZ1rknEVm6yZ8bB" + ) + assert ( + resp.sig_op_contents.hex() + == "dee04042c0832d68a43699b2001c0a38065436eb05e578071a763e1972d0bc8105005f450441f41ee11eee78a31d1e1e55627c783bd60000001100000020dfa974df171c2dad9a9b8f25d99af41fd9702ce5d04521d2f9943c84d88aa5723b12621296a679b3a74ea790df5347995a76e20a09e76590baaacf4e09341965a04123f5cbbba8427f045b5f7d59157a3098e44839babe7c247d19b58bbb2405" + ) + assert resp.operation_hash == "opLqntFUu984M7LnGsFvfGW6kWe9QjAz4AfPDqQvwJ1wPM4Si4c" - def test_tezos_sign_tx_origination(self, client): + +def test_tezos_sign_tx_multiple_proposals(client): + with client: resp = tezos.sign_tx( client, TEZOS_PATH_10, dict_to_proto( messages.TezosSignTx, { - "branch": "927ac7cd7969bde606e7537712584eb0d34fc52d9f5a88cc908994d817170a16", - "origination": { + "branch": "7e0be36a90c663c73c60da3889ffefff1383fb65cc29f0639f173d8f95a52df7", + "proposal": { "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - "fee": 20000, - "counter": 276, - "gas_limit": 20000, - "storage_limit": 10000, - "balance": 100000, - "script": "0000001c02000000170500036805010368050202000000080316053d036d03420000000a010000000568656c6c6f", + "period": 17, + "proposals": [ + "2a6ff28ab4d0ccb18f7129aaaf9a4b8027d794f2562849665fdb6999db2a4e57", + "47cd60c09ab8437cc9fe19add494dce1b9844100f660f02ce77510a0c66d2762", + ], }, }, ), ) - assert ( - resp.signature - == "edsigtcAamBz7cL8whbLvaeMNYUdsQieh6RADrzWLCPhDjzqn7JtdX9Yy4vYWKcpMnycY6YTMWCAYMegPaKMNJVM4zbxypALAyN" - ) - assert ( - resp.sig_op_contents.hex() - == "927ac7cd7969bde606e7537712584eb0d34fc52d9f5a88cc908994d817170a166d005f450441f41ee11eee78a31d1e1e55627c783bd6a09c019402a09c01904ea08d06000000001c02000000170500036805010368050202000000080316053d036d03420000000a010000000568656c6c6f2151774735e1659a7d0f54659e98fbcbd86a667717a9a2a9961292a170e5e8d1608a1dbf805a03981be2f7389ba1738841ac8b1069fe5978a72d441a97de3505" - ) - assert ( - resp.operation_hash == "onmq9FFZzvG2zghNdr1bgv9jzdbzNycXjSSNmCVhXCGSnV3WA9g" - ) - def test_tezos_sign_tx_reveal(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "f26502c204619c4bdab2e59efc50c79bc0136d781304b8f7fad389263550300e", - "reveal": { - "source": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", - "fee": 20000, - "counter": 564560, - "gas_limit": 20000, - "storage_limit": 0, - "public_key": "00200da2c0200927dd8168b2b62e1322637521fcefb3184e61c1c3123c7c00bb95", - }, - "transaction": { - "source": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", - "fee": 50000, - "counter": 564561, - "gas_limit": 20000, - "storage_limit": 0, - "amount": 100000, - "destination": { - "tag": 0, - "hash": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - }, - }, - }, - ), - ) - assert ( - resp.signature - == "edsigtcqDr47paEVgr8X8gmvFt9UnNWACkMVCGdVFZ2yUq849oxmTbx2FqjToveUNwNujC9qmoi5kXWy78qZY2d5Qeryx6kCbGs" - ) - assert ( - resp.sig_op_contents.hex() - == "f26502c204619c4bdab2e59efc50c79bc0136d781304b8f7fad389263550300e6b00001e65c88ae6317cd62a638c8abd1e71c83c8475a09c01d0ba22a09c010000200da2c0200927dd8168b2b62e1322637521fcefb3184e61c1c3123c7c00bb956c00001e65c88ae6317cd62a638c8abd1e71c83c8475d08603d1ba22a09c0100a08d0600005f450441f41ee11eee78a31d1e1e55627c783bd60026690d65407d6cda03cde8e3c17a22ffd0351f78c18c500f3997cbe311e12e6cc4b5ff40b339c7fba8b4c7d62329ea45da662340113a6da98b7510b40042f204" - ) - assert ( - resp.operation_hash == "oo9JFiWTnTSvUZfajMNwQe1VyFN2pqwiJzZPkpSAGfGD57Z6mZJ" - ) + assert ( + resp.signature + == "edsigu6GAjhiWAQ64ctWTGEDYAZ16tYzLgzWzqc4CUyixK4FGRE8YUBVzFaVJ2fUCexZjZLMLdiNZGcUdzeL1bQhZ2h5oLrh7pA" + ) + assert ( + resp.sig_op_contents.hex() + == "7e0be36a90c663c73c60da3889ffefff1383fb65cc29f0639f173d8f95a52df705005f450441f41ee11eee78a31d1e1e55627c783bd600000011000000402a6ff28ab4d0ccb18f7129aaaf9a4b8027d794f2562849665fdb6999db2a4e5747cd60c09ab8437cc9fe19add494dce1b9844100f660f02ce77510a0c66d2762f813361ac00ada7e3256f23973ae25b112229476a3cb3e506fe929ea1e9358299fed22178d1be689cddeedd1f303abfef859b664f159a528576a1c807079f005" + ) + assert resp.operation_hash == "onobSyNgiitGXxSVFJN6949MhUomkkxvH4ZJ2owgWwNeDdntF9Y" - def test_tezos_smart_contract_delegation(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH_10, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "49eead995833934ee2571c6cd6439897ee71b72a9e4d22f127e0c3d4ca69ba15", - "transaction": { - "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - "fee": 10000, - "counter": 278, - "gas_limit": 25822, - "storage_limit": 0, - "amount": 0, - "destination": { - "tag": 1, - "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", - }, - "parameters_manager": { - "set_delegate": "005f450441f41ee11eee78a31d1e1e55627c783bd6" - }, - }, - }, - ), - ) - assert ( - resp.signature - == "edsigtw8uSW99pT4GUd1mS14DbczxVfTCJrKBy6bMckBknwAxwAF53yBXnQAZwZ9WWMKyGmbta8RgPs262b7hGGNxFyTM8zdPBd" - ) - assert ( - resp.sig_op_contents.hex() - == "49eead995833934ee2571c6cd6439897ee71b72a9e4d22f127e0c3d4ca69ba156c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9602dec901000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff020000002f020000002a0320053d036d0743035d0a00000015005f450441f41ee11eee78a31d1e1e55627c783bd60346034e031bb2534eb5478c31d5ffbc13b4692a7f2b73aad16e2d8e0f7068110955aa9480a6432775ba301f24bc20e4c12cffc9fd1f27b44204f830ea7f4dec23a18e25450d" - ) - assert ( - resp.operation_hash == "oo75gfQGGPEPChXZzcPPAGtYqCpsg2BS5q9gmhrU3NQP7CEffpU" - ) - def test_tezos_kt_remove_delegation(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH_10, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "77a1800dd37b54f61755bd97b2a6759627c53a5f8afb00bdcf8255b5d23eff44", - "transaction": { - "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - "fee": 10000, - "counter": 279, - "gas_limit": 25822, - "storage_limit": 0, - "amount": 0, - "destination": { - "tag": 1, - "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", - }, - "parameters_manager": {"cancel_delegate": True}, - }, +def test_tezos_sing_tx_ballot_yay(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "3a8f60c4cd394cee5b50136c7fc8cb157e8aaa476a9e5c68709be6fc1cdb5395", + "ballot": { + "source": "0002298c03ed7d454a101eb7022bc95f7e5f41ac78", + "period": 2, + "proposal": "def7ed9c84af23ab37ebb60dd83cd103d1272ad6c63d4c05931567e65ed027e3", + "ballot": 0, }, - ), - ) - assert ( - resp.signature - == "edsigtqZZd8r2cww5GvTpaJANizYyAAB8n2sByKJWYwgEQQu6gjzSi7mQ7NAxbwsCaHGUS3F87oDJ1J5mz8SM8KYVidQj1NUz8E" - ) - assert ( - resp.sig_op_contents.hex() - == "77a1800dd37b54f61755bd97b2a6759627c53a5f8afb00bdcf8255b5d23eff446c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9702dec901000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff0200000013020000000e0320053d036d053e035d034e031b87b6a5f01c0689f8f453f2b23582a2891792087197e01276648eec734850999e54e9edd687efb9297e24a96d126dc1e6636e772aeab80d5bc6b3f9b55aa3a701" - ) - assert ( - resp.operation_hash == "ootMi1tXbfoVgFyzJa8iXyR4mnHd5TxLm9hmxVzMVRkbyVjKaHt" - ) + }, + ), + ) - def test_tezos_smart_contract_transfer(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH_10, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "442b86e27a7b79d893262b4daee229818f71073827570c74fa3aa1da7929d16d", - "transaction": { - "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - "fee": 10000, - "counter": 280, - "gas_limit": 36000, - "storage_limit": 0, - "amount": 0, - "destination": { - "tag": 1, - "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", - }, - "parameters_manager": { - "transfer": { - "amount": 20000, - "destination": { - "tag": 0, - "hash": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - }, - } - }, - }, - }, - ), - ) - assert ( - resp.signature - == "edsigtaY4HzLQ2oVDqnUAzbkSjGMQVBNHnBLq5t4TmVnsdAG8W4FWzeEnWbJXRQSTUKme3sXijve9vmDyAtim7HXeu9XhFJDrMo" - ) - assert ( - resp.sig_op_contents.hex() - == "442b86e27a7b79d893262b4daee229818f71073827570c74fa3aa1da7929d16d6c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9802a09902000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff020000003902000000340320053d036d0743035d0a00000015005f450441f41ee11eee78a31d1e1e55627c783bd6031e0743036a00a0b802034f034d031b14dc70ef8db46c4b8f53e387ff3d642644af458f757ab85f9291727dc18bb09d7ec5790136b8cc428b165aec9cf628eeefc90aad526dc75e2aab203e57b8920f" - ) - assert ( - resp.operation_hash == "ooRGGtCmoQDgB36XvQqmM7govc3yb77YDUoa7p2QS7on27wGRns" - ) + assert ( + resp.signature + == "edsigtkxNm6YXwtV24DqeuimeZFTeFCn2jDYheSsXT4rHMcEjNvzsiSo55nVyVsQxtEe8M7U4PWJWT4rGYYGckQCgtkNJkd2roX" + ) - def test_tezos_smart_contract_transfer_to_contract(self, client): - resp = tezos.sign_tx( - client, - TEZOS_PATH_10, - dict_to_proto( - messages.TezosSignTx, - { - "branch": "8c696f9eb98cd641e33b680f424f7334b903d2b0108f0f896e73e921c44bf4c9", - "transaction": { - "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", - "fee": 4813, - "counter": 272, - "gas_limit": 44725, - "storage_limit": 0, - "amount": 0, - "destination": { - "tag": 1, - "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", - }, - "parameters_manager": { - "transfer": { - "amount": 200, - "destination": { - "tag": 1, - "hash": "8b83360512c6045c1185f8000de41302e23a220c00", - }, - } - }, + +def test_tezos_sing_tx_ballot_nay(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "3a8f60c4cd394cee5b50136c7fc8cb157e8aaa476a9e5c68709be6fc1cdb5395", + "ballot": { + "source": "0002298c03ed7d454a101eb7022bc95f7e5f41ac78", + "period": 2, + "proposal": "def7ed9c84af23ab37ebb60dd83cd103d1272ad6c63d4c05931567e65ed027e3", + "ballot": 1, + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtqLaizfF6Cfc2JQL7TrsyniGhpZEojZAKMFW6AeudaUoU8KGXEHJH69Q4Lf27qFyUSTfbeHNnnCt69SGEPWkmpkgkgqMbL" + ) + + +def test_tezos_sing_tx_ballot_pass(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "3a8f60c4cd394cee5b50136c7fc8cb157e8aaa476a9e5c68709be6fc1cdb5395", + "ballot": { + "source": "0002298c03ed7d454a101eb7022bc95f7e5f41ac78", + "period": 2, + "proposal": "def7ed9c84af23ab37ebb60dd83cd103d1272ad6c63d4c05931567e65ed027e3", + "ballot": 2, + }, + }, + ), + ) + + assert ( + resp.signature + == "edsigu6YX7EegPwrpcEbdNQsNhrRiEagBNGJBmFamP4mixZZw1UynhahGQ8RNiZLSUVLERUZwygrsSVenBqXGt9VnknTxtzjKzv" + ) + + +def test_tezos_sign_tx_tranasaction(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "3b85532b5a468cd26b6d3c7e762ae53b795d19c6db4838ed2750df8e063aedb8", + "transaction": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 10000, + "counter": 274, + "gas_limit": 20000, + "storage_limit": 0, + "amount": 100000, + "destination": { + "tag": 0, + "hash": "003325df8851047421605ae7d6b09b49f70c8ce460", }, }, - ), - ) - assert ( - resp.sig_op_contents.hex() - == "8c696f9eb98cd641e33b680f424f7334b903d2b0108f0f896e73e921c44bf4c96c005f450441f41ee11eee78a31d1e1e55627c783bd6cd259002b5dd02000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff020000005502000000500320053d036d0743036e0a00000016018b83360512c6045c1185f8000de41302e23a220c000555036c0200000015072f02000000090200000004034f032702000000000743036a008803034f034d031b911b8e7f22acdacc78e6d40566636a7029773c9ebfa741bb94bb58fb9e705d3ad695ac24fd1a58943c3070e9c38b0660671adb478233ae31005cd9139c84a80b" - ) - assert ( - resp.signature - == "edsigtrnr4jXpPZK1yFVGtsapR4VHKp9Gnz1Uj7G4AdAXVn8ug16tgUx5u3TsyYJFp9MzENKuVqotaEwco3JhAhKpbjxbBQhEsT" - ) - assert ( - resp.operation_hash == "opUE4xNkiUyYmJwUUgAab9xqHE66FXEc6VNZq4ZXDiBJcYwqNJX" - ) + }, + ), + ) + assert ( + resp.signature + == "edsigtvRTDegGy83x5AHQwhzPAbKteJ7MsLukhLRS9RLMRX5UdmtV1xiHEhQCUrGNv6h9CbV1cvuUVzRgLd6Af4XfVQgGkkYUuY" + ) + assert ( + resp.sig_op_contents.hex() + == "3b85532b5a468cd26b6d3c7e762ae53b795d19c6db4838ed2750df8e063aedb86c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9202a09c0100a08d0600003325df8851047421605ae7d6b09b49f70c8ce46000acdcd3df9daaa79c7345c068ffddc2113047fc00c1eed3503838d15fc6690821ee6eaa1e67b4a8d40dcf30a9ec456bbbda18ef2bcc021053d7d8c3f1473df809" + ) + assert resp.operation_hash == "oon8PNUsPETGKzfESv1Epv4535rviGS7RdCfAEKcPvzojrcuufb" + + +def test_tezos_sign_tx_delegation(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_15, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "447d51450749763989c1aa5e1939aae623abb5a050f9cf1c04c247d91ca67593", + "delegation": { + "source": "0002eca091abc1e0f5c38a155c1313c410b47e1549", + "fee": 20000, + "counter": 458069, + "gas_limit": 20000, + "storage_limit": 0, + "delegate": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + }, + }, + ), + ) + assert ( + resp.signature + == "edsigu2ZsDXXm7RzMF2oSKHK54ZfSUPvU2jekJBQmAprMe8ksnofMScKd3Kc3RTTExwzaJGENzoe94ZDiW86eWWnWBTPNw2xu5m" + ) + assert ( + resp.sig_op_contents.hex() + == "447d51450749763989c1aa5e1939aae623abb5a050f9cf1c04c247d91ca675936e0002eca091abc1e0f5c38a155c1313c410b47e1549a09c01d5fa1ba09c0100ff005f450441f41ee11eee78a31d1e1e55627c783bd6dbd53f9129387e82548e5d20b1479a46a876ac7516001fae01488dfbe9dcfc732cb8664d52fd7e1bc25a9845714131fd498ef65ea91f84e180688a41e06fe700" + ) + assert resp.operation_hash == "op79C1tR7wkUgYNid2zC1WNXmGorS38mTXZwtAjmCQm2kG7XG59" + + +def test_tezos_sign_tx_origination(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "927ac7cd7969bde606e7537712584eb0d34fc52d9f5a88cc908994d817170a16", + "origination": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 20000, + "counter": 276, + "gas_limit": 20000, + "storage_limit": 10000, + "balance": 100000, + "script": "0000001c02000000170500036805010368050202000000080316053d036d03420000000a010000000568656c6c6f", + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtcAamBz7cL8whbLvaeMNYUdsQieh6RADrzWLCPhDjzqn7JtdX9Yy4vYWKcpMnycY6YTMWCAYMegPaKMNJVM4zbxypALAyN" + ) + assert ( + resp.sig_op_contents.hex() + == "927ac7cd7969bde606e7537712584eb0d34fc52d9f5a88cc908994d817170a166d005f450441f41ee11eee78a31d1e1e55627c783bd6a09c019402a09c01904ea08d06000000001c02000000170500036805010368050202000000080316053d036d03420000000a010000000568656c6c6f2151774735e1659a7d0f54659e98fbcbd86a667717a9a2a9961292a170e5e8d1608a1dbf805a03981be2f7389ba1738841ac8b1069fe5978a72d441a97de3505" + ) + assert resp.operation_hash == "onmq9FFZzvG2zghNdr1bgv9jzdbzNycXjSSNmCVhXCGSnV3WA9g" + + +def test_tezos_sign_tx_reveal(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "f26502c204619c4bdab2e59efc50c79bc0136d781304b8f7fad389263550300e", + "reveal": { + "source": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", + "fee": 20000, + "counter": 564560, + "gas_limit": 20000, + "storage_limit": 0, + "public_key": "00200da2c0200927dd8168b2b62e1322637521fcefb3184e61c1c3123c7c00bb95", + }, + "transaction": { + "source": "00001e65c88ae6317cd62a638c8abd1e71c83c8475", + "fee": 50000, + "counter": 564561, + "gas_limit": 20000, + "storage_limit": 0, + "amount": 100000, + "destination": { + "tag": 0, + "hash": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + }, + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtcqDr47paEVgr8X8gmvFt9UnNWACkMVCGdVFZ2yUq849oxmTbx2FqjToveUNwNujC9qmoi5kXWy78qZY2d5Qeryx6kCbGs" + ) + assert ( + resp.sig_op_contents.hex() + == "f26502c204619c4bdab2e59efc50c79bc0136d781304b8f7fad389263550300e6b00001e65c88ae6317cd62a638c8abd1e71c83c8475a09c01d0ba22a09c010000200da2c0200927dd8168b2b62e1322637521fcefb3184e61c1c3123c7c00bb956c00001e65c88ae6317cd62a638c8abd1e71c83c8475d08603d1ba22a09c0100a08d0600005f450441f41ee11eee78a31d1e1e55627c783bd60026690d65407d6cda03cde8e3c17a22ffd0351f78c18c500f3997cbe311e12e6cc4b5ff40b339c7fba8b4c7d62329ea45da662340113a6da98b7510b40042f204" + ) + assert resp.operation_hash == "oo9JFiWTnTSvUZfajMNwQe1VyFN2pqwiJzZPkpSAGfGD57Z6mZJ" + + +def test_tezos_smart_contract_delegation(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "49eead995833934ee2571c6cd6439897ee71b72a9e4d22f127e0c3d4ca69ba15", + "transaction": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 10000, + "counter": 278, + "gas_limit": 25822, + "storage_limit": 0, + "amount": 0, + "destination": { + "tag": 1, + "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", + }, + "parameters_manager": { + "set_delegate": "005f450441f41ee11eee78a31d1e1e55627c783bd6" + }, + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtw8uSW99pT4GUd1mS14DbczxVfTCJrKBy6bMckBknwAxwAF53yBXnQAZwZ9WWMKyGmbta8RgPs262b7hGGNxFyTM8zdPBd" + ) + assert ( + resp.sig_op_contents.hex() + == "49eead995833934ee2571c6cd6439897ee71b72a9e4d22f127e0c3d4ca69ba156c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9602dec901000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff020000002f020000002a0320053d036d0743035d0a00000015005f450441f41ee11eee78a31d1e1e55627c783bd60346034e031bb2534eb5478c31d5ffbc13b4692a7f2b73aad16e2d8e0f7068110955aa9480a6432775ba301f24bc20e4c12cffc9fd1f27b44204f830ea7f4dec23a18e25450d" + ) + assert resp.operation_hash == "oo75gfQGGPEPChXZzcPPAGtYqCpsg2BS5q9gmhrU3NQP7CEffpU" + + +def test_tezos_kt_remove_delegation(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "77a1800dd37b54f61755bd97b2a6759627c53a5f8afb00bdcf8255b5d23eff44", + "transaction": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 10000, + "counter": 279, + "gas_limit": 25822, + "storage_limit": 0, + "amount": 0, + "destination": { + "tag": 1, + "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", + }, + "parameters_manager": {"cancel_delegate": True}, + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtqZZd8r2cww5GvTpaJANizYyAAB8n2sByKJWYwgEQQu6gjzSi7mQ7NAxbwsCaHGUS3F87oDJ1J5mz8SM8KYVidQj1NUz8E" + ) + assert ( + resp.sig_op_contents.hex() + == "77a1800dd37b54f61755bd97b2a6759627c53a5f8afb00bdcf8255b5d23eff446c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9702dec901000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff0200000013020000000e0320053d036d053e035d034e031b87b6a5f01c0689f8f453f2b23582a2891792087197e01276648eec734850999e54e9edd687efb9297e24a96d126dc1e6636e772aeab80d5bc6b3f9b55aa3a701" + ) + assert resp.operation_hash == "ootMi1tXbfoVgFyzJa8iXyR4mnHd5TxLm9hmxVzMVRkbyVjKaHt" + + +def test_tezos_smart_contract_transfer(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "442b86e27a7b79d893262b4daee229818f71073827570c74fa3aa1da7929d16d", + "transaction": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 10000, + "counter": 280, + "gas_limit": 36000, + "storage_limit": 0, + "amount": 0, + "destination": { + "tag": 1, + "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", + }, + "parameters_manager": { + "transfer": { + "amount": 20000, + "destination": { + "tag": 0, + "hash": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + }, + } + }, + }, + }, + ), + ) + assert ( + resp.signature + == "edsigtaY4HzLQ2oVDqnUAzbkSjGMQVBNHnBLq5t4TmVnsdAG8W4FWzeEnWbJXRQSTUKme3sXijve9vmDyAtim7HXeu9XhFJDrMo" + ) + assert ( + resp.sig_op_contents.hex() + == "442b86e27a7b79d893262b4daee229818f71073827570c74fa3aa1da7929d16d6c005f450441f41ee11eee78a31d1e1e55627c783bd6904e9802a09902000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff020000003902000000340320053d036d0743035d0a00000015005f450441f41ee11eee78a31d1e1e55627c783bd6031e0743036a00a0b802034f034d031b14dc70ef8db46c4b8f53e387ff3d642644af458f757ab85f9291727dc18bb09d7ec5790136b8cc428b165aec9cf628eeefc90aad526dc75e2aab203e57b8920f" + ) + assert resp.operation_hash == "ooRGGtCmoQDgB36XvQqmM7govc3yb77YDUoa7p2QS7on27wGRns" + + +def test_tezos_smart_contract_transfer_to_contract(client): + resp = tezos.sign_tx( + client, + TEZOS_PATH_10, + dict_to_proto( + messages.TezosSignTx, + { + "branch": "8c696f9eb98cd641e33b680f424f7334b903d2b0108f0f896e73e921c44bf4c9", + "transaction": { + "source": "005f450441f41ee11eee78a31d1e1e55627c783bd6", + "fee": 4813, + "counter": 272, + "gas_limit": 44725, + "storage_limit": 0, + "amount": 0, + "destination": { + "tag": 1, + "hash": "c116a6c74bf00a5839b593838215fe1fcf2db59c00", + }, + "parameters_manager": { + "transfer": { + "amount": 200, + "destination": { + "tag": 1, + "hash": "8b83360512c6045c1185f8000de41302e23a220c00", + }, + } + }, + }, + }, + ), + ) + assert ( + resp.sig_op_contents.hex() + == "8c696f9eb98cd641e33b680f424f7334b903d2b0108f0f896e73e921c44bf4c96c005f450441f41ee11eee78a31d1e1e55627c783bd6cd259002b5dd02000001c116a6c74bf00a5839b593838215fe1fcf2db59c00ff020000005502000000500320053d036d0743036e0a00000016018b83360512c6045c1185f8000de41302e23a220c000555036c0200000015072f02000000090200000004034f032702000000000743036a008803034f034d031b911b8e7f22acdacc78e6d40566636a7029773c9ebfa741bb94bb58fb9e705d3ad695ac24fd1a58943c3070e9c38b0660671adb478233ae31005cd9139c84a80b" + ) + assert ( + resp.signature + == "edsigtrnr4jXpPZK1yFVGtsapR4VHKp9Gnz1Uj7G4AdAXVn8ug16tgUx5u3TsyYJFp9MzENKuVqotaEwco3JhAhKpbjxbBQhEsT" + ) + assert resp.operation_hash == "opUE4xNkiUyYmJwUUgAab9xqHE66FXEc6VNZq4ZXDiBJcYwqNJX"