From c45ca3314c4ce4169a4c1b02be863acce9466f7d Mon Sep 17 00:00:00 2001 From: grdddj Date: Thu, 28 Apr 2022 19:51:45 +0200 Subject: [PATCH] chore(tests): add on-chain-valid test vectors for Zcash v5 --- tests/device_tests/zcash/test_sign_tx.py | 291 ++++++++++++++++++++--- tests/ui_tests/fixtures.json | 7 +- 2 files changed, 265 insertions(+), 33 deletions(-) diff --git a/tests/device_tests/zcash/test_sign_tx.py b/tests/device_tests/zcash/test_sign_tx.py index 7d5e1cff4..6937b62b0 100644 --- a/tests/device_tests/zcash/test_sign_tx.py +++ b/tests/device_tests/zcash/test_sign_tx.py @@ -17,6 +17,7 @@ import pytest from trezorlib import btc, messages +from trezorlib.debuglink import TrezorClientDebugLink as Client from trezorlib.exceptions import TrezorFailure from trezorlib.tools import parse_path @@ -27,14 +28,31 @@ B = messages.ButtonRequestType TXHASH_aaf51e = bytes.fromhex( "aaf51e4606c264e47e5c42c958fe4cf1539c5172684721e38e69f4ef634d75dc" ) -TXHASH_e38206 = bytes.fromhex( +TXHASH_e38206 = bytes.fromhex( # FAKE TX "e3820602226974b1dd87b7113cc8aea8c63e5ae29293991e7bfa80c126930368" ) +TXHASH_f9231f = bytes.fromhex( + "f9231f2d6cdcd86b4892c95a5d2045bacd81f4060e8127073456fbb7b7b51568" +) +TXHASH_c5309b = bytes.fromhex( + "c5309bd6a18f6bf374918b1c96e872af02e80d678c53d37547de03048ace79bf" +) +TXHASH_431b68 = bytes.fromhex( + "431b68c170799a1ba9a936f9bde4ba1fb5606b0ab0a770012875a23d23ba72a3" +) +TXHASH_4b6cec = bytes.fromhex( + "4b6cecb81c825180786ebe07b65bcc76078afc5be0f1c64e08d764005012380d" +) + +# This exact VERSION_GROUP_ID is absolutely necessary for a valid v5 transaction +# BRANCH_ID could maybe change +VERSION_GROUP_ID = 0x26A7270A +BRANCH_ID = 0xC2D6D0B4 pytestmark = [pytest.mark.altcoin, pytest.mark.zcash, pytest.mark.skip_t1] -def test_version_group_id_missing(client): +def test_version_group_id_missing(client: Client): inp1 = messages.TxInputType( # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu address_n=parse_path("m/44h/1h/0h/0/0"), @@ -58,18 +76,114 @@ def test_version_group_id_missing(client): ) -def test_one_one(client): +def test_spend_v4_input(client: Client): + # 4b6cecb81c825180786ebe07b65bcc76078afc5be0f1c64e08d764005012380d is a v4 tx + + inp1 = messages.TxInputType( + # tmAgYbANTzZp7YoMkRbbaemQETgV5GkBEjF + address_n=parse_path("m/44h/1h/0h/0/7"), + amount=989_680, + prev_hash=TXHASH_4b6cec, + prev_index=0, + ) + + out1 = messages.TxOutputType( + # m/44h/1h/0h/0/9 + address="tmBMyeJebzkP5naji8XUKqLyL1NDwNkgJFt", + amount=989_680 - 10_000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + with client: + client.set_expected_responses( + [ + request_input(0), + request_output(0), + messages.ButtonRequest(code=B.ConfirmOutput), + messages.ButtonRequest(code=B.SignTx), + request_input(0), + request_output(0), + request_finished(), + ] + ) + + _, serialized_tx = btc.sign_tx( + client, + "Zcash Testnet", + [inp1], + [out1], + version=5, + version_group_id=VERSION_GROUP_ID, + branch_id=BRANCH_ID, + ) + + # Accepted by network: txid = b29b1f27763e8caf9fe51f33a6a7daf138438b5278efcd60941782244e35b19e + assert ( + serialized_tx.hex() + == "050000800a27a726b4d0d6c20000000000000000010d3812500064d7084ec6f1e05bfc8a0776cc5bb607be6e788051821cb8ec6c4b000000006b483045022100cc6efc5678eefec9dd95a890e5961be3e8fc64ea6654959873316fcd2d523d36022036036e2e23071812319d170484926bc641d54028613acaa28b1fd2530013a3400121035169c4d6a36b6c4f3e210f46d329efa1cb7a67ffce7d62062d4a8a17c23756e1ffffffff01e0f20e00000000001976a9141215d421cb8cec1dea62cbd9e4e07c01520d873f88ac000000" + ) + + +def test_send_to_multisig(client: Client): inp1 = messages.TxInputType( # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu - address_n=parse_path("m/44h/1h/0h/0/0"), - amount=300000000, - prev_hash=TXHASH_e38206, + address_n=parse_path("m/44h/1h/0h/0/8"), + amount=1_000_000, + prev_hash=bytes.fromhex( + "d8cfa377012ca0b8d856586693b530835bf2fa14add0380e24ec6755bed5b931" + ), prev_index=0, ) out1 = messages.TxOutputType( - address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z", - amount=300000000 - 1940, + address="t2PQpjcfpYHK1bcXZcSaTbg5cQRV93B2NRY", + amount=1_000_000 - 19_400, + 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_output(0), + request_finished(), + ] + ) + + _, serialized_tx = btc.sign_tx( + client, + "Zcash Testnet", + [inp1], + [out1], + version=5, + version_group_id=VERSION_GROUP_ID, + branch_id=BRANCH_ID, + ) + + # Accepted by network: txid = 431b68c170799a1ba9a936f9bde4ba1fb5606b0ab0a770012875a23d23ba72a3 + assert ( + serialized_tx.hex() + == "050000800a27a726b4d0d6c200000000000000000131b9d5be5567ec240e38d0ad14faf25b8330b593665856d8b8a02c0177a3cfd8000000006a4730440220578ca11522b12ab2048b5c81a2ef788cccfacdb42d08efb31a802ee75909c38c02202fd12addfae4822141821b14a012828c7a4a46cc02de777101d1b8ee14128070012103260dc4925b14addb52b4e62c698b99d2318f3d909477a081ae8e5d94dc3c66d8ffffffff0178f60e000000000017a914b8f771de8bbdcfee76e0dbf76f1005f2028bf3e787000000" + ) + + +def test_spend_v5_input(client: Client): + inp1 = messages.TxInputType( + # tmBMyeJebzkP5naji8XUKqLyL1NDwNkgJFt + address_n=parse_path("m/44h/1h/0h/0/9"), + amount=4_154_120, + prev_hash=TXHASH_f9231f, + prev_index=0, + ) + + out1 = messages.TxOutputType( + # m/44h/1h/0h/0/0 + address="tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu", + amount=4_154_120 - 19_400, script_type=messages.OutputScriptType.PAYTOADDRESS, ) @@ -86,38 +200,42 @@ def test_one_one(client): ] ) - btc.sign_tx( + _, serialized_tx = btc.sign_tx( client, "Zcash Testnet", [inp1], [out1], version=5, - version_group_id=0x892F2085, - branch_id=0x76B809BB, + version_group_id=VERSION_GROUP_ID, + branch_id=BRANCH_ID, ) - # TODO: send tx to testnet - # TODO: check serialized_tx + # Accepted by network: txid = c5309bd6a18f6bf374918b1c96e872af02e80d678c53d37547de03048ace79bf + assert ( + serialized_tx.hex() + == "050000800a27a726b4d0d6c20000000000000000016815b5b7b7fb56340727810e06f481cdba45205d5ac992486bd8dc6c2d1f23f9000000006a47304402201fc2effdaa338d4fd42a018debed2c8a170c57c7763faabf9596ea408961cc5b02200dd35764d2797723c73f2984c5ea49522d4558ca3c5143e95235f522f65c84b5012102b3397d76b093624981b3c3a279c79496d16820f821528b9e403bdfc162b34c3cffffffff0140173f00000000001976a914a579388225827d9f2fe9014add644487808c695d88ac000000" + ) -def test_one_two(client): +def test_one_two(client: Client): inp1 = messages.TxInputType( # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu address_n=parse_path("m/44h/1h/0h/0/0"), - amount=300000000, - prev_hash=TXHASH_e38206, + amount=4_134_720, + prev_hash=TXHASH_c5309b, prev_index=0, ) out1 = messages.TxOutputType( - address="tmNvfeKR5PkcQazLEqddTskFr6Ev9tsovfQ", - amount=100000000, + # m/44h/1h/0h/0/8 + address="tmCYEhUmZGpzyFrhUdKqwt64DrPqkFNChxx", + amount=1_000_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) out2 = messages.TxOutputType( address_n=parse_path("m/44h/1h/0h/0/0"), - amount=200000000 - 2000, + amount=4_134_720 - 1_000_000 - 2_000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) @@ -136,21 +254,24 @@ def test_one_two(client): ] ) - btc.sign_tx( + _, serialized_tx = btc.sign_tx( client, "Zcash Testnet", [inp1], [out1, out2], version=5, - version_group_id=0x892F2085, - branch_id=0x76B809BB, + version_group_id=VERSION_GROUP_ID, + branch_id=BRANCH_ID, ) - # TODO: send tx to testnet - # TODO: check serialized_tx + # Accepted by network: txid = d8cfa377012ca0b8d856586693b530835bf2fa14add0380e24ec6755bed5b931 + assert ( + serialized_tx.hex() + == "050000800a27a726b4d0d6c2000000000000000001bf79ce8a0403de4775d3538c670de802af72e8961c8b9174f36b8fa1d69b30c5000000006b483045022100be78eccf801dda4dd33f9d4e04c2aae01022869d1d506d51669204ec269d71a90220394a51838faf40176058cf45fe7032be9c5c942e21aff35d7dbe4b96ab5e0a500121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff0240420f00000000001976a9141efeae5c937bfc7f095a06aabdb5476a5d6d19db88ac30cd2f00000000001976a914a579388225827d9f2fe9014add644487808c695d88ac000000" + ) -def test_external_presigned(client): +def test_external_presigned(client: Client): inp1 = messages.TxInputType( # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu address_n=parse_path("m/44h/1h/0h/0/0"), @@ -196,7 +317,7 @@ def test_external_presigned(client): ] ) - btc.sign_tx( + _, serialized_tx = btc.sign_tx( client, "Zcash Testnet", [inp1, inp2], @@ -206,11 +327,14 @@ def test_external_presigned(client): branch_id=0x76B809BB, ) - # TODO: send tx to testnet - # TODO: check serialized + # FAKE tx + assert ( + serialized_tx.hex() + == "0500008085202f89bb09b87600000000000000000268039326c180fa7b1e999392e25a3ec6a8aec83c11b787ddb1746922020682e3000000006a473044022033bdf8ca157ae0583f6f17bab3ee440a3cbfc664caa33ee93c26adde27cb5160022062ba9e410a1a45289fafb4d31b5704938a2262a311be1104418a15660f5281cf0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffffdc754d63eff4698ee321476872519c53f14cfe58c9425c7ee464c206461ef5aa010000006b48304502210090020ba5d1c945145f04e940c4b6026a24d2b9e58e7ae53834eca6f606e457e4022040d214cb7ad2bd2cff14bac8d7b8eab0bb603c239a962ecd8535ea49ca25071e0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c3ec323000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac000000" + ) -def test_refuse_replacement_tx(client): +def test_refuse_replacement_tx(client: Client): inp1 = messages.TxInputType( address_n=parse_path("m/44h/1h/0h/0/4"), amount=174998, @@ -253,6 +377,111 @@ def test_refuse_replacement_tx(client): [inp1], [out1, out2], version=5, - version_group_id=0x892F2085, - branch_id=0x76B809BB, + version_group_id=VERSION_GROUP_ID, + branch_id=BRANCH_ID, ) + + +def test_spend_multisig(client: Client): + # Cloned from tests/device_tests/bitcoin/test_multisig.py::test_2_of_3 + + nodes = [ + btc.get_public_node( + client, parse_path(f"m/48h/1h/{index}h/0h"), coin_name="Zcash Testnet" + ).node + for index in range(1, 4) + ] + + multisig = messages.MultisigRedeemScriptType( + nodes=nodes, address_n=[0, 0], signatures=[b"", b"", b""], m=2 + ) + # Let's go to sign with key 1 + inp1 = messages.TxInputType( + address_n=parse_path("m/48h/1h/1h/0h/0/0"), + amount=980_600, + prev_hash=TXHASH_431b68, + prev_index=0, + script_type=messages.InputScriptType.SPENDMULTISIG, + multisig=multisig, + ) + + out1 = messages.TxOutputType( + # m/44h/1h/0h/0/4 + address="tmHRQfcNVCZnjY8g6X7Yp6Tcpx8M5gy4Joj", + amount=980_600 - 10_000, + script_type=messages.OutputScriptType.PAYTOADDRESS, + ) + + # Expected responses are the same for both two signings + expected_responses = [ + request_input(0), + request_output(0), + messages.ButtonRequest(code=B.ConfirmOutput), + messages.ButtonRequest(code=B.SignTx), + request_input(0), + request_output(0), + request_finished(), + ] + + with client: + client.set_expected_responses(expected_responses) + signatures1, _ = btc.sign_tx( + client, + "Zcash Testnet", + [inp1], + [out1], + version=5, + version_group_id=VERSION_GROUP_ID, + branch_id=BRANCH_ID, + ) + + assert ( + signatures1[0].hex() + == "3045022100d1f91921391ca4a985cbe080ce8be71f1b8ceba6049151bffe7dc6cc27a4a4d80220082fb171f7536779cd216f0508e0205039b2f20988d05455dac9bc22bc713005" + ) + + # Now we have first signature + + multisig = messages.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 = messages.TxInputType( + address_n=parse_path("m/48h/1h/3h/0h/0/0"), + amount=980_600, + prev_hash=TXHASH_431b68, + prev_index=0, + script_type=messages.InputScriptType.SPENDMULTISIG, + multisig=multisig, + ) + + with client: + client.set_expected_responses(expected_responses) + signatures2, serialized_tx = btc.sign_tx( + client, + "Zcash Testnet", + [inp3], + [out1], + version=5, + version_group_id=VERSION_GROUP_ID, + branch_id=BRANCH_ID, + ) + + assert ( + signatures2[0].hex() + == "3044022058bb0b1ac0d6b62b6f86bdb32879e9240369387282e73a96cb6fbeba56f5493e02206dabb42fc4ce4f5d97bc641f353e7351949695d8e6383764e76eebe572cc33fc" + ) + + # Accepted by network: txid = 38f6771c8deabc3a8b960e0c8b6aa464ddfab469e7298e91a7900101f7b60880 + assert ( + serialized_tx.hex() + == "050000800a27a726b4d0d6c2000000000000000001a372ba233da275280170a7b00a6b60b51fbae4bdf936a9a91b9a7970c1681b4300000000fdfd0000483045022100d1f91921391ca4a985cbe080ce8be71f1b8ceba6049151bffe7dc6cc27a4a4d80220082fb171f7536779cd216f0508e0205039b2f20988d05455dac9bc22bc71300501473044022058bb0b1ac0d6b62b6f86bdb32879e9240369387282e73a96cb6fbeba56f5493e02206dabb42fc4ce4f5d97bc641f353e7351949695d8e6383764e76eebe572cc33fc014c69522103725d6c5253f2040a9a73af24bcc196bf302d6cc94374dd7197b138e10912670121038924e94fff15302a3fb45ad4fc0ed17178800f0f1c2bdacb1017f4db951aa9f12102aae8affd0eb8e1181d665daef4de1828f23053c548ec9bafc3a787f558aa014153aeffffffff0168cf0e00000000001976a914548cb80e45b1d36312fe0cb075e5e337e3c54cef88ac000000" + ) diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index c4cf8e780..5c152e67b 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -1602,9 +1602,12 @@ "TT_webauthn-test_msg_webauthn.py::test_add_remove": "3219e5ad2719319e74b5c75b1096ca7e3d30467215c15f57e57e475afdaa188f", "TT_webauthn-test_u2f_counter.py::test_u2f_counter": "19f77e2d284431da5fadac938f5822c1a6b17c07ee6c801085efd84974f3163f", "TT_zcash-test_sign_tx.py::test_external_presigned": "08a22a49793201f8387a085a554f006387d1df1b37ed8a34bef7aa79b363b44b", -"TT_zcash-test_sign_tx.py::test_one_one": "b8aff4ae3c9b417acadf1ede52d7d45870dd4ef1f9251bf8e8f2ebf5280b9f3b", -"TT_zcash-test_sign_tx.py::test_one_two": "d59aa3d5d03a276a31d3023c8214af940dbb8dec3cd686576608881965789fcb", +"TT_zcash-test_sign_tx.py::test_one_two": "7e6477901163c130cae31651507d4b1821169e09f03e857e42015fb8f56da583", "TT_zcash-test_sign_tx.py::test_refuse_replacement_tx": "1c100ce4b7c1e47e72428f390de0846c1ff933e9f07894872644a369a9422738", +"TT_zcash-test_sign_tx.py::test_send_to_multisig": "53142c4999ed465e00b61114b5a158eb39918be2af2ad229881d7909dcf0f7b6", +"TT_zcash-test_sign_tx.py::test_spend_multisig": "82d482d56cfdfcbc300d7f064da1dd1df640d4dacb6e9fc85aa54ca28df44c89", +"TT_zcash-test_sign_tx.py::test_spend_v4_input": "7bef51a2759d8d28821c027310f92b98d68f89cbc832f1778dc81aad8fdd5dd2", +"TT_zcash-test_sign_tx.py::test_spend_v5_input": "68c9959e01d4fe4021909f50a02b152471ef86bf9013c65481d6abf4c0568ebd", "TT_zcash-test_sign_tx.py::test_version_group_id_missing": "c09de07fbbf1e047442180e2facb5482d06a1a428891b875b7dd93c9e4704ae1", "TTui2_binance-test_get_address.py::test_binance_get_address[m-44h-714h-0h-0-0-bnb1hgm0p7khfk85zpz-68e2cb5a": "f03b50df7f4a161078fa903c44f37272961b70358d4014d30a12888e1fd2caf1", "TTui2_binance-test_get_address.py::test_binance_get_address[m-44h-714h-0h-0-1-bnb1egswqkszzfc2uq7-1adfb691": "f03b50df7f4a161078fa903c44f37272961b70358d4014d30a12888e1fd2caf1",