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, ) details = proto.SignTx(lock_time=650756) _, serialized_tx = btc.sign_tx( client, "Groestlcoin Testnet", [inp1], [out1, out2], details=details ) assert ( serialized_tx.hex() == "01000000000101cf60ded29a2bd7ebf93453feace8551889d0321beab90c4f6e5c9d2fce8ba4090000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5feffffff02e0aebb00000000001976a914a579388225827d9f2fe9014add644487808c695d88ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100b7ce2972bcbc3a661fe320ba901e680913b2753fcb47055c9c6ba632fc4acf81022001c3cfd6c2fe92eb60f5176ce0f43707114dd7223da19c56f2df89c13c2fef80012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7904ee0900" )
def test_send_segwit_native_change(self): # https://blockbook-test.groestlcoin.org/tx/9b5c4859a8a31e69788cb4402812bb28f14ad71cbd8c60b09903478bc56f79a3 self.setup_mnemonic_allallall() inp1 = proto.TxInputType( address_n=parse_path("84'/1'/0'/0/0"), amount=12300000, prev_hash=bytes.fromhex( "4f2f857f39ed1afe05542d058fb0be865a387446e32fc876d086203f483f61d1" ), 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, ) details = proto.SignTx(lock_time=650713) _, serialized_tx = btc.sign_tx( self.client, "Groestlcoin Testnet", [inp1], [out1, out2], details=details ) 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, ) details = proto.SignTx(lock_time=650713) _, serialized_tx = btc.sign_tx( client, "Groestlcoin Testnet", [inp1], [out1, out2], details=details ) assert ( serialized_tx.hex() == "01000000000101d1613f483f2086d076c82fe34674385a86beb08f052d5405fe1aed397f852f4f0000000000feffffff02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b02483045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f862d9ed0900" )
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, ) details = proto.SignTx(version=4) with pytest.raises(TrezorFailure, match="Version group ID must be set."): btc.sign_tx( client, "Zcash Testnet", [inp1], [out1], details=details, prev_txes=TX_API, )
def test_timestamp_included(client): # tx: 3bf506c81ce84eda891679ddc797d162c17c60b15d6c0ac23be5e31369e7235f # input 0: 0.01 CPC # tx: f3a6e6411f1b2dffd76d2729bae8e056f8f9ecf8996d3f428e75a6f23f2c5e8c # input 0: 0.02 CPC inp1 = messages.TxInputType(address_n=parse_path("m/44'/289'/0'/0/0"), prev_hash=TXHASH_3bf506, prev_index=0) inp2 = messages.TxInputType(address_n=parse_path("m/44'/289'/0'/0/0"), prev_hash=TXHASH_f3a6e6, prev_index=1) out1 = messages.TxOutputType( address="CUGi8RGPWxbHM6FxF4eMEfqmQ6Bs5VjCdr", amount=3000000 - 20000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) with client: details = messages.SignTx(version=1, timestamp=0x5BCF5C66) _, timestamp_tx = btc.sign_tx( client, "Capricoin", [inp1, inp2], [out1], details=details, prev_txes=tx_cache("Capricoin"), ) # Accepted by network https://insight.capricoin.org/tx/1bf227e6e24fe1f8ac98849fe06a2c5b77762e906fcf7e82787675f7f3a10bb8 accepted_txhex = "01000000665ccf5b025f23e76913e3e53bc20a6c5db1607cc162d197c7dd791689da4ee81cc806f53b000000006b483045022100fce7ccbeb9524f36d118ebcfebcb133a05c236c4478e2051cfd5c9632920aee602206921b7be1a81f30cce3d8e7dba4597fc16a2761c42321c49d65eeacdfe3781250121021fcf98aee04939ec7df5762f426dc2d1db8026e3a73c3bbe44749dacfbb61230ffffffff8c5e2c3ff2a6758e423f6d99f8ecf9f856e0e8ba29276dd7ff2d1b1f41e6a6f3010000006a473044022015d967166fe9f89fbed8747328b1c4658aa1d7163e731c5fd5908feafe08e9a6022028af30801098418bd298cc60b143c52c48466f5791256721304b6eba4fdf0b3c0121021fcf98aee04939ec7df5762f426dc2d1db8026e3a73c3bbe44749dacfbb61230ffffffff01a0782d00000000001976a914818437acfd15780debd31f3fd21d4ca678bb36d188ac00000000" assert timestamp_tx.hex() == accepted_txhex
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, ) out1 = proto.TxOutputType( address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z", amount=300000000 - 1940, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: details = proto.SignTx( version=3, version_group_id=0x03C48270, branch_id=0x5BA81B19, ) with pytest.raises(TrezorFailure, match="DataError"): _, serialized_tx = btc.sign_tx( client, "Zcash Testnet", [inp1], [out1], details=details, prev_txes=TX_API, )
def test_timestamp_included(client): # tx: 41b29ad615d8eea40a4654a052d18bb10cd08f203c351f4d241f88b031357d3d # input 0: 0.1 PPC inp1 = messages.TxInputType( address_n=parse_path("m/44'/6'/0'/0/0"), amount=100000, prev_hash=TXHASH_41b29a, prev_index=0, ) out1 = messages.TxOutputType( address="PXtfyTjzgXSgTwK5AbszdHQSSxyQN3BLM5", amount=100000 - 10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) details = messages.SignTx(version=1, timestamp=0x5DC5448A) _, timestamp_tx = btc.sign_tx( client, "Peercoin", [inp1], [out1], details=details, prev_txes=TX_CACHE, ) # Accepted by network https://explorer.peercoin.net/api/getrawtransaction?txid=f7e3624c143b6a170cc44f9337d0fa8ea8564a211de9c077c6889d8c78f80909&decrypt=1 accepted_txhex = "010000008a44c55d013d7d3531b0881f244d1f353c208fd00cb18bd152a054460aa4eed815d69ab241000000006a473044022025c0ea702390c702c7ae8b5ea469820bea8d942c8c16439f8f0ba2e91e699efc02200db9b0a48fa2861695fa91df4831a4c7306587e5d2dc85419647f462717bc8f001210274cb0ee652d9457fbb0f3872d43155a6bc16f77bd5749d8826b53db443b1b278ffffffff01905f0100000000001976a914ff9a05654150fdc92b1655f49d7f2a8aaf6a3a2a88ac00000000" assert timestamp_tx.hex() == accepted_txhex
def test_send_segwit_p2sh(self): # https://blockbook-test.groestlcoin.org/tx/4ce0220004bdfe14e3dd49fd8636bcb770a400c0c9e9bff670b6a13bb8f15c72 self.setup_mnemonic_allallall() inp1 = proto.TxInputType( address_n=parse_path( "49'/1'/0'/1/0" ), # 2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7 amount=123456789, prev_hash=bytes.fromhex( "09a48bce2f9d5c6e4f0cb9ea1b32d0891855e8acfe5334f9ebd72b9ad2de60cf" ), 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, ) details = proto.SignTx(lock_time=650756) _, serialized_tx = btc.sign_tx( self.client, "Groestlcoin Testnet", [inp1], [out1, out2], details=details ) assert ( serialized_tx.hex() == "01000000000101cf60ded29a2bd7ebf93453feace8551889d0321beab90c4f6e5c9d2fce8ba4090000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5feffffff02e0aebb00000000001976a914a579388225827d9f2fe9014add644487808c695d88ac3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca8702483045022100b7ce2972bcbc3a661fe320ba901e680913b2753fcb47055c9c6ba632fc4acf81022001c3cfd6c2fe92eb60f5176ce0f43707114dd7223da19c56f2df89c13c2fef80012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7904ee0900" )
def sign_interactive(): coin = prompt("Coin name", default="Bitcoin") blockbook_host = prompt("Blockbook server", default="btc1.trezor.io") if not requests.get(f"https://{blockbook_host}/api").ok: raise click.ClickException("Could not connect to blockbook") blockbook_url = f"https://{blockbook_host}/api/tx-specific/" inputs, txes = _get_inputs_interactive(blockbook_url) outputs = _get_outputs_interactive() signtx = messages.SignTx() signtx.version = prompt("Transaction version", type=int, default=2) signtx.lock_time = prompt("Transaction locktime", type=int, default=0) result = { "coin_name": coin, "inputs": [to_dict(i, hexlify_bytes=True) for i in inputs], "outputs": [to_dict(o, hexlify_bytes=True) for o in outputs], "details": to_dict(signtx, hexlify_bytes=True), "prev_txes": { txhash: to_dict(txdata, hexlify_bytes=True) for txhash, txdata in txes.items() }, } print(json.dumps(result, sort_keys=True, indent=2))
def test_one_one_fee_sapling(self): self.setup_mnemonic_allallall() # prevout: 339c3e78610e229f65ebc3fa722016fcb9fbde7bc196d2d876604f5257ada19c:0 # input 1: 2.9999 KMD inp1 = proto.TxInputType( address_n=parse_path( "m/Komodo/0h/0/0"), # RDvyC66RQf7HKkUB5zyLKJhitV4ibzkKF5 amount=299990000, prev_hash=TXHASH_339c3e, prev_index=0, ) out1 = proto.TxOutputType( address="RDvyC66RQf7HKkUB5zyLKJhitV4ibzkKF5", amount=299990000 - 10000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with self.client: self.client.set_expected_responses([ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest( code=proto.ButtonRequestType.ConfirmOutput), proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ]) details = proto.SignTx( version=4, overwintered=True, version_group_id=0x892F2085, branch_id=0x76B809BB, ) _, serialized_tx = btc.sign_tx(self.client, "Komodo", [inp1], [out1], details=details, prev_txes=TX_API) # Accepted by network: tx 92b45f54cb7c3cdfc4a88dbf088dfcc7c1417ad0955f02712e136da7fd5343d6 assert ( serialized_tx.hex() == "0400008085202f89019ca1ad57524f6076d8d296c17bdefbb9fc162072fac3eb659f220e61783e9c33000000006a47304402206972af8ff4dec4074da9edb1a741114bebda9e686bb411dd6f388aafd81f0af2022060a05d0ea66d5b8632868b6a6d377ad1a8941385d628be4631b31cc246014b8501210235ad92bb4efda1e6794890f248fa26aab75906bd496c07a6a8532b62a5bd80f7ffffffff01e054e111000000001976a91433058d6bb20e9297fc0a518e2e0262e854496a6c88ac6be15c5c000000000000000000000000000000" )
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, ) 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, ) details = proto.SignTx( version=4, version_group_id=0x892F2085, branch_id=0x76B809BB, ) with client: _, serialized_tx = btc.sign_tx( client, "Zcash Testnet", inputs, [output], details=details, prev_txes=TX_API, ) assert ( serialized_tx.hex() == "0400008085202f890446828054c6c81a8c370c47dc1cfd6f1b200af5623ac3d5b62501121b74ae91fb000000006b483045022100d40e85efbadd378fc603dc8b11c70774086de631fe5b1418ac2b95a478f86507022072e999d8ddd75a0b33bd2adcc88e7234e6251b9e73c9223e7c59e0d1f8d1ff220121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffffef42e249deb8e7bc1d5ec7c4590c70c5b89734b2b896c72ad6469d95190ed303000000006b483045022100917d96445d64c80f9569cb9ca45c04c9b6d7b0fda6b9fd0b1d311837366c699202202cd6140489cf38b5d97ed271ba28603f4693c2a36113cc6ec423301f077c5a8e01210294e3e5e77e22eea0e4c0d30d89beb4db7f69b4bf1ae709e411d6a06618b8f852ffffffff6cb78ae689ae1334f4b03c6f613b280c70088b963f1c965f814081d1298841f9010000006a473044022058768c74c9b1698070636388d7d2ae8223748f13b0a5f402716e4d49fc5bc5f30220658d1e6095dcfbe66669b4141d23af28c9ed5bae73480889429b41742be85f32012103f5008445568548bd745a3dedccc6048969436bf1a49411f60938ff1938941f14ffffffff0f9c2ee92a378e5399a6f2c41dce2b4af5a7119ae1bee3c8ec8eb06472e68d5d000000006b483045022100e64853d86bed039c4edce4abaf80d41486cd21c63bec79c0308ea05a351663e302206732aa22a5dee7bd7f3cc8268faebe31a08abadb4b7e3a4257509bc7baa052b60121029ad0b9519779c540b34fa8d11d24d14a5475546bfa28c7de50573d22a503ce21ffffffff01d0c7321c000000001976a91490ede9de4bed6e39008375eace793949de9a533288ac00000000000000000000000000000000000000" )
def test_one_one_fee_sapling(self, client): # prevout: e3820602226974b1dd87b7113cc8aea8c63e5ae29293991e7bfa80c126930368:0 # input 1: 3.0 TAZ inp1 = proto.TxInputType( # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu address_n=parse_path("m/44h/1h/0h/0/0"), amount=300000000, prev_hash=TXHASH_e38206, prev_index=0, ) out1 = proto.TxOutputType( address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z", amount=300000000 - 1940, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses([ 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(), ]) details = proto.SignTx( version=4, version_group_id=0x892F2085, branch_id=0x76B809BB, ) _, serialized_tx = btc.sign_tx( client, "Zcash Testnet", [inp1], [out1], details=details, prev_txes=TX_API, ) # Accepted by network: tx 0cef132c1d6d67f11cfa48f7fca3209da29cf872ac782354bedb686e61a17a78 assert ( serialized_tx.hex() == "0400008085202f890168039326c180fa7b1e999392e25a3ec6a8aec83c11b787ddb1746922020682e3000000006b483045022100f28298891f48706697a6f898ac18e39ce2c7cebe547b585d51cc22d80b1b21a602201a807b8a18544832d95d1e3ada82c0617bc6d97d3f24d1fb4801ac396647aa880121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000000000000000000000000000000000" )
def test_one_one_fee_overwinter(self, client): # prevout: aaf51e4606c264e47e5c42c958fe4cf1539c5172684721e38e69f4ef634d75dc:1 # input 1: 3.0 TAZ inp1 = proto.TxInputType( # tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu address_n=parse_path("m/44h/1h/0h/0/0"), amount=300000000, prev_hash=TXHASH_aaf51e, prev_index=1, ) out1 = proto.TxOutputType( address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z", amount=300000000 - 1940, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: client.set_expected_responses([ request_input(0), 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_output(0), proto.ButtonRequest(code=B.ConfirmOutput), proto.ButtonRequest(code=B.SignTx), request_input(0), request_output(0), request_finished(), ]) details = proto.SignTx( version=3, version_group_id=0x03C48270, branch_id=0x5BA81B19, ) _, serialized_tx = btc.sign_tx( client, "Zcash Testnet", [inp1], [out1], details=details, prev_txes=TX_API, ) # Accepted by network: tx eda9b772c47f0c29310759960e0081c98707aa67a0a2738bcc71439fcf360675 assert ( serialized_tx.hex() == "030000807082c40301dc754d63eff4698ee321476872519c53f14cfe58c9425c7ee464c206461ef5aa010000006a47304402207e45f303b4e42be824513855eb21653e1d2749cd94dcd0f0613d3f85d4efd1e20220699ffbdbcad889af7ede5ce9febf7a5ef8f5619b2464824529974c400cffaebc0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac000000000000000000" )
def test_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, ) 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(), ]) details = proto.SignTx( version=4, version_group_id=0x892F2085, branch_id=0x76B809BB, lock_time=0x5D2A30B8, ) _, serialized_tx = btc.sign_tx(client, "Komodo", [inp1], [out1], details=details, prev_txes=TX_API) # Accepted by network: tx 7b28bd91119e9776f0d4ebd80e570165818a829bbf4477cd1afe5149dbcd34b1 assert ( serialized_tx.hex() == "0400008085202f89011d0f8e0c6ba2dcf8be8e5f9024771dceb4c8e4120fab8c072b8eec26b1c50728000000006a4730440220158c970ca2fc6bcc33026eb5366f0342f63b35d178f7efb334b1df78fe90b67202207bc4ff69f67cf843b08564a5adc77bf5593e28ab4d5104911824ac13fe885d8f012102a87aef7b1a8f676e452d6240767699719cd58b0261c822472c25df146938bca5ffffffff01d0359041000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acb8302a5d000000000000000000000000000000" )
def test_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, ) 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(), ] ) details = messages.SignTx(lock_time=lock_time) btc.sign_tx( client, "Bitcoin", [inp1], [out1], details=details, prev_txes=TX_CACHE_MAINNET, )
def sign_interactive(): coin = prompt("Coin name", default="Bitcoin") if coin in coins.tx_api: coin_data = coins.by_name[coin] txapi = coins.tx_api[coin] else: echo('Coin "%s" is not recognized.' % coin, err=True) echo("Supported coin types: %s" % ", ".join(coins.tx_api.keys()), err=True) sys.exit(1) inputs, txes = _get_inputs_interactive(coin_data, txapi) outputs = _get_outputs_interactive() if coin_data["bip115"]: current_block_height = txapi.current_height() # Zencash recommendation for the better protection block_height = current_block_height - 300 block_hash = txapi.get_block_hash(block_height) # Blockhash passed in reverse order block_hash = block_hash[::-1] for output in outputs: output.block_hash_bip115 = block_hash output.block_height_bip115 = block_height signtx = messages.SignTx() signtx.version = prompt("Transaction version", type=int, default=2) signtx.lock_time = prompt("Transaction locktime", type=int, default=0) if coin == "Capricoin": signtx.timestamp = prompt("Transaction timestamp", type=int) result = { "coin_name": coin, "inputs": [to_dict(i, hexlify_bytes=True) for i in inputs], "outputs": [to_dict(o, hexlify_bytes=True) for o in outputs], "details": to_dict(signtx, hexlify_bytes=True), "prev_txes": { txhash.hex(): to_dict(txdata, hexlify_bytes=True) for txhash, txdata in txes.items() }, } print(json.dumps(result, sort_keys=True, indent=2))
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, prev_index=0) out1 = messages.TxOutputType( address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", amount=1000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) details = messages.SignTx() setattr(details, field, value) name = field.replace("_", " ") with pytest.raises( TrezorFailure, match=r"(?i){} not enabled on this coin".format(name)): btc.sign_tx(client, "Bitcoin", [inp0], [out1], details, prev_txes=TX_CACHE_MAINNET)
def test_signtx_forbidden_fields(self, client, field, value): cache = TxCache("Bitcoin") inp0 = proto.TxInputType(address_n=[0], prev_hash=TXHASH_157041, prev_index=0) out1 = proto.TxOutputType( address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1", amount=1000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) details = proto.SignTx() setattr(details, field, value) name = field.replace("_", " ") with pytest.raises( TrezorFailure, match=r"(?i){} not enabled on this coin".format(name)): btc.sign_tx(client, "Bitcoin", [inp0], [out1], details, prev_txes=cache)
def test_timestamp_missing_prevtx(client): inp1 = messages.TxInputType( address_n=parse_path("m/44'/6'/0'/0/0"), amount=100000, prev_hash=TXHASH_41b29a, prev_index=0, ) out1 = messages.TxOutputType( address="PXtfyTjzgXSgTwK5AbszdHQSSxyQN3BLM5", amount=100000 - 10000, script_type=messages.OutputScriptType.PAYTOADDRESS, ) details = messages.SignTx(version=1, timestamp=0x5DC5448A) prevtx = TX_CACHE[TXHASH_41b29a] prevtx.timestamp = 0 with pytest.raises(TrezorFailure, match="Timestamp must be set."): btc.sign_tx( client, "Peercoin", [inp1], [out1], details=details, prev_txes={TXHASH_41b29a: prevtx}, ) prevtx.timestamp = None with pytest.raises(TrezorFailure, match="Timestamp must be set."): btc.sign_tx( client, "Peercoin", [inp1], [out1], details=details, prev_txes={TXHASH_41b29a: prevtx}, )
def sign_tx(self, required_data): signing_inputs = required_data['signing_inputs'] transaction_outputs = required_data['transaction_outputs'] signing_transactions = required_data['signing_transactions'] signing_address_types = required_data['signing_address_types'] scripts = [] for in_ in signing_inputs: service_xpub = deserialize(in_['service_xpub']) user_xpub = deserialize(self.as_xpub(in_['user_path'][:-1])) pointer = in_['pointer'] redeem_script = proto.MultisigRedeemScriptType( nodes=[user_xpub, service_xpub], address_n=[pointer], signatures=[b'', b''], m=2, csv=in_['subtype']) scripts.append(redeem_script) ins = [] for i, txin in enumerate(signing_inputs): in_ = proto.TxInputType( address_n=txin['user_path'], prev_hash=h2b(txin['txhash']), prev_index=txin['pt_idx'], script_type=proto.InputScriptType.SPENDP2SHWITNESS, multisig=scripts[i], amount=txin['satoshi'], sequence=txin['sequence']) in_.confidential = proto.TxConfidentialAsset( asset=h2b(txin['asset_id'])[::-1], amount_blind=h2b(txin['vbf']), asset_blind=h2b(txin['abf'])) ins.append(in_) values = [] in_vbfs = [] in_abfs = [] for txin in signing_inputs: in_vbfs.append(h2b(txin['vbf'])) in_abfs.append(h2b(txin['abf'])) values.append(txin['satoshi']) out_vbfs = [] out_abfs = [] for i, txout in enumerate(transaction_outputs): if txout['is_fee']: continue out_vbfs.append( os.urandom(32)) # TODO: check if HW is going to generate these out_abfs.append( os.urandom(32)) # TODO: check if HW is going to generate these values.append(txout['satoshi']) abfs = in_abfs + out_abfs vbfs = in_vbfs + out_vbfs[:-1] final_vbf = wally.asset_final_vbf(values, len(signing_inputs), b''.join(abfs), b''.join(vbfs)) out_vbfs[-1] = final_vbf outs = [] for i, txout in enumerate(transaction_outputs): if txout['is_fee']: out = proto.TxOutputType(address='', amount=txout['satoshi']) out.confidential = proto.TxConfidentialAsset( asset=h2b(txout['asset_id'])[::-1]) else: out = proto.TxOutputType( address=txout['address'], amount=txout['satoshi'], script_type=proto.OutputScriptType.PAYTOADDRESS) out.confidential = proto.TxConfidentialAsset( asset=h2b(txout['asset_id'])[::-1], amount_blind=out_vbfs[i], asset_blind=out_abfs[i], nonce_privkey=h2b(txout['eph_keypair_sec'])) outs.append(out) signatures, serialized_tx = btc.sign_tx( self.client, 'Elements', ins, outs, prev_txes=None, details=proto.SignTx(version=2, lock_time=required_data['transaction'] ['transaction_locktime'])) # with open('tx.txt', 'w') as f: # f.write(serialized_tx.hex()) asset_commitments = [] value_commitments = [] tx = wally.tx_from_bytes( serialized_tx, wally.WALLY_TX_FLAG_USE_WITNESS | wally.WALLY_TX_FLAG_USE_ELEMENTS) for i in range(wally.tx_get_num_outputs(tx)): asset_commitments.append(wally.tx_get_output_asset(tx, i)) value_commitments.append(wally.tx_get_output_value(tx, i)) out_abfs.append(b'\x00' * 32) # FIXME: GDK enforcing blinding factors for fee out_vbfs.append(b'\x00' * 32) return json.dumps({ 'signatures': [sig.hex() + '01' for sig in signatures], 'vbfs': [vbf.hex() for vbf in out_vbfs], 'abfs': [abf.hex() for abf in out_abfs], 'asset_commitments': [commitment.hex() for commitment in asset_commitments], 'value_commitments': [commitment.hex() for commitment in value_commitments] })
def make_signing_details(tx) -> m.SignTx: details_dict = { "version": tx.version, "lock_time": tx.lock_time, } return m.SignTx(**details_dict)
def test_one_one_rewards_claim(self, client): # prevout: 7b28bd91119e9776f0d4ebd80e570165818a829bbf4477cd1afe5149dbcd34b1:0 # input 1: 10.9997 KMD inp1 = proto.TxInputType( address_n=parse_path( "44'/141'/0'/0/0" ), # R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi amount=1099970000, prev_hash=TXHASH_7b28bd, prev_index=0, ) out1 = proto.TxOutputType( address="R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi", amount=1099970000 - 10000, script_type=proto.OutputScriptType.PAYTOADDRESS, ) # kmd interest, vout sum > vin sum out2 = proto.TxOutputType( address="R9HgJZo6JBKmPvhm7whLSR8wiHyZrEDVRi", amount=79605, script_type=proto.OutputScriptType.PAYTOADDRESS, ) with client: er = [ proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput), ] if client.features.model != "1": # extra screen for lock_time er += [proto.ButtonRequest(code=proto.ButtonRequestType.SignTx)] er += [ proto.ButtonRequest(code=proto.ButtonRequestType.SignTx), proto.TxRequest( request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0), ), proto.TxRequest( request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1), ), proto.TxRequest(request_type=proto.RequestType.TXFINISHED), ] client.set_expected_responses(er) details = proto.SignTx( version=4, version_group_id=0x892F2085, branch_id=0x76B809BB, lock_time=0x5D2AF1F2, ) _, serialized_tx = btc.sign_tx( client, "Komodo", [inp1], [out1, out2], details=details, prev_txes=TX_API, ) # Accepted by network: tx c775678ceb18277729b427c7acf2f8ce63ac02fc2366f47ce08a3f443ff0e059 assert ( serialized_tx.hex() == "0400008085202f8901b134cddb4951fe1acd7744bf9b828a816501570ed8ebd4f076979e1191bd287b000000006a4730440220483a58f5be3a147c773c663008c992a7fcea4d03bdf4c1d4bc0535c0d98ddf0602207b19d69140dd00c7a94f048c712aeaed55dfd27f581c7212d9cc5e476fe1dc9f012102a87aef7b1a8f676e452d6240767699719cd58b0261c822472c25df146938bca5ffffffff02c00e9041000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acf5360100000000001976a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388acf2f12a5d000000000000000000000000000000" )
def 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_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_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_output(0), proto.ButtonRequest(code=B.ConfirmOutput), proto.ButtonRequest(code=B.SignTx), 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(), ]) details = proto.SignTx( version=4, version_group_id=0x892F2085, branch_id=0x76B809BB, ) _, serialized_tx = btc.sign_tx( client, "Zcash Testnet", [inp1, inp2], [out1], details=details, prev_txes=TX_API, ) assert ( serialized_tx.hex() == "0400008085202f890268039326c180fa7b1e999392e25a3ec6a8aec83c11b787ddb1746922020682e3000000006a473044022007efbf539f8d612d8e140c6af2289b447c34e3d36edd75d539f269fe5526878302206830f6b0398494bca09afdd967fedcd016f49468711cfcd7aafd9a128ee568d20121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffffdc754d63eff4698ee321476872519c53f14cfe58c9425c7ee464c206461ef5aa010000006a47304402202495a38e5b368569a1a0c9fc95aa7e57a0dd5ae43f51300d7222dc139015233d022047833eaa571578f72c8468c8b537b36410388b7eb5001d75d1f4b954e1997d590121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c3ec323000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000000000000000000000000000000000" )
def sign_tx(self, tx): # Get this devices master key fingerprint master_key = btc.get_public_node(self.client, [0]) master_fp = get_xpub_fingerprint(master_key.xpub) # Do multiple passes for multisig passes = 1 p = 0 while p < passes: # Prepare inputs inputs = [] to_ignore = [ ] # Note down which inputs whose signatures we're going to ignore for input_num, (psbt_in, txin) in py_enumerate( list(zip(tx.inputs, tx.tx.vin))): txinputtype = proto.TxInputType() # Set the input stuff txinputtype.prev_hash = ser_uint256(txin.prevout.hash)[::-1] txinputtype.prev_index = txin.prevout.n txinputtype.sequence = txin.nSequence # Detrermine spend type scriptcode = b'' if psbt_in.non_witness_utxo: utxo = psbt_in.non_witness_utxo.vout[txin.prevout.n] txinputtype.script_type = proto.InputScriptType.SPENDADDRESS scriptcode = utxo.scriptPubKey txinputtype.amount = psbt_in.non_witness_utxo.vout[ txin.prevout.n].nValue elif psbt_in.witness_utxo: utxo = psbt_in.witness_utxo # Check if the output is p2sh if psbt_in.witness_utxo.is_p2sh(): txinputtype.script_type = proto.InputScriptType.SPENDP2SHWITNESS else: txinputtype.script_type = proto.InputScriptType.SPENDWITNESS scriptcode = psbt_in.witness_utxo.scriptPubKey txinputtype.amount = psbt_in.witness_utxo.nValue # Set the script if psbt_in.witness_script: scriptcode = psbt_in.witness_script elif psbt_in.redeem_script: scriptcode = psbt_in.redeem_script def ignore_input(): txinputtype.address_n = [0x80000000] inputs.append(txinputtype) to_ignore.append(input_num) # Check for multisig is_ms, multisig = parse_multisig(scriptcode) if is_ms: # Add to txinputtype txinputtype.multisig = multisig if psbt_in.non_witness_utxo: if utxo.is_p2sh: txinputtype.script_type = proto.InputScriptType.SPENDMULTISIG else: # Cannot sign bare multisig, ignore it ignore_input() continue elif not is_ms and psbt_in.non_witness_utxo and not utxo.is_p2pkh: # Cannot sign unknown spk, ignore it ignore_input() continue elif not is_ms and psbt_in.witness_utxo and psbt_in.witness_script: # Cannot sign unknown witness script, ignore it ignore_input() continue # Find key to sign with found = False our_keys = 0 for key in psbt_in.hd_keypaths.keys(): keypath = psbt_in.hd_keypaths[key] if keypath[ 0] == master_fp and key not in psbt_in.partial_sigs: if not found: txinputtype.address_n = keypath[1:] found = True our_keys += 1 # Determine if we need to do more passes to sign everything if our_keys > passes: passes = our_keys if not found: # This input is not one of ours ignore_input() continue # append to inputs inputs.append(txinputtype) # address version byte if self.is_testnet: p2pkh_version = b'\x6f' p2sh_version = b'\xc4' bech32_hrp = 'tb' else: p2pkh_version = b'\x00' p2sh_version = b'\x05' bech32_hrp = 'bc' # prepare outputs outputs = [] for out in tx.tx.vout: txoutput = proto.TxOutputType() txoutput.amount = out.nValue txoutput.script_type = proto.OutputScriptType.PAYTOADDRESS if out.is_p2pkh(): txoutput.address = to_address(out.scriptPubKey[3:23], p2pkh_version) elif out.is_p2sh(): txoutput.address = to_address(out.scriptPubKey[2:22], p2sh_version) else: wit, ver, prog = out.is_witness() if wit: txoutput.address = bech32.encode(bech32_hrp, ver, prog) else: raise TypeError("Output is not an address") # append to outputs outputs.append(txoutput) # Prepare prev txs prevtxs = {} for psbt_in in tx.inputs: if psbt_in.non_witness_utxo: prev = psbt_in.non_witness_utxo t = proto.TransactionType() t.version = prev.nVersion t.lock_time = prev.nLockTime for vin in prev.vin: i = proto.TxInputType() i.prev_hash = ser_uint256(vin.prevout.hash)[::-1] i.prev_index = vin.prevout.n i.script_sig = vin.scriptSig i.sequence = vin.nSequence t.inputs.append(i) for vout in prev.vout: o = proto.TxOutputBinType() o.amount = vout.nValue o.script_pubkey = vout.scriptPubKey t.bin_outputs.append(o) logging.debug(psbt_in.non_witness_utxo.hash) prevtxs[ser_uint256( psbt_in.non_witness_utxo.sha256)[::-1]] = t # Sign the transaction tx_details = proto.SignTx() tx_details.version = tx.tx.nVersion tx_details.lock_time = tx.tx.nLockTime if self.is_testnet: signed_tx = btc.sign_tx(self.client, "Testnet", inputs, outputs, tx_details, prevtxs) else: signed_tx = btc.sign_tx(self.client, "Bitcoin", inputs, outputs, tx_details, prevtxs) # Each input has one signature for input_num, (psbt_in, sig) in py_enumerate( list(zip(tx.inputs, signed_tx[0]))): if input_num in to_ignore: continue for pubkey in psbt_in.hd_keypaths.keys(): fp = psbt_in.hd_keypaths[pubkey][0] if fp == master_fp and pubkey not in psbt_in.partial_sigs: psbt_in.partial_sigs[pubkey] = sig + b'\x01' break p += 1 return {'psbt': tx.serialize()}
def sign_tx(sig_percent, client, coin_name, inputs, outputs, details=None, prev_txes=None): # set up a transactions dict txes = {None: trezor_proto.TransactionType(inputs=inputs, outputs=outputs)} # preload all relevant transactions ahead of time for inp in inputs: if inp.script_type not in ( trezor_proto.InputScriptType.SPENDP2SHWITNESS, trezor_proto.InputScriptType.SPENDWITNESS, trezor_proto.InputScriptType.EXTERNAL, ): try: prev_tx = prev_txes[inp.prev_hash] except Exception as e: raise ValueError("Could not retrieve prev_tx") from e if not isinstance(prev_tx, trezor_proto.TransactionType): raise ValueError("Invalid value for prev_tx") from None txes[inp.prev_hash] = prev_tx if details is None: signtx = trezor_proto.SignTx() else: signtx = details signtx.coin_name = coin_name signtx.inputs_count = len(inputs) signtx.outputs_count = len(outputs) res = client.call(signtx) # Prepare structure for signatures signatures = [None] * len(inputs) serialized_tx = b"" def copy_tx_meta(tx): tx_copy = trezor_proto.TransactionType(**tx) # clear fields tx_copy.inputs_cnt = len(tx.inputs) tx_copy.inputs = [] tx_copy.outputs_cnt = len(tx.bin_outputs or tx.outputs) tx_copy.outputs = [] tx_copy.bin_outputs = [] tx_copy.extra_data_len = len(tx.extra_data or b"") tx_copy.extra_data = None return tx_copy R = trezor_proto.RequestType percent = 0 # Used for signaling progress. 1-10 for inputs/outputs, 10-100 for sigs. sig_percent.emit(percent) while isinstance(res, trezor_proto.TxRequest): # If there's some part of signed transaction, let's add it if res.serialized: if res.serialized.serialized_tx: serialized_tx += res.serialized.serialized_tx if res.serialized.signature_index is not None: idx = res.serialized.signature_index sig = res.serialized.signature if signatures[idx] is not None: raise ValueError("Signature for index %d already filled" % idx) signatures[idx] = sig # emit completion percent percent = 10 + int(90 * (idx + 1) / len(signatures)) sig_percent.emit(percent) if res.request_type == R.TXFINISHED: break # Device asked for one more information, let's process it. current_tx = txes[res.details.tx_hash] if res.request_type == R.TXMETA: msg = copy_tx_meta(current_tx) res = client.call(trezor_proto.TxAck(tx=msg)) elif res.request_type == R.TXINPUT: if percent == 0 or (res.details.request_index > 0 and percent < 10): percent = 1 + int( 8 * (res.details.request_index + 1) / len(inputs)) sig_percent.emit(percent) msg = trezor_proto.TransactionType() msg.inputs = [current_tx.inputs[res.details.request_index]] res = client.call(trezor_proto.TxAck(tx=msg)) elif res.request_type == R.TXOUTPUT: # Update just one percent then display additional waiting message (emitting -1) if percent == 9: percent += 1 sig_percent.emit(percent) sig_percent.emit(-1) msg = trezor_proto.TransactionType() if res.details.tx_hash: msg.bin_outputs = [ current_tx.bin_outputs[res.details.request_index] ] else: msg.outputs = [current_tx.outputs[res.details.request_index]] res = client.call(trezor_proto.TxAck(tx=msg)) elif res.request_type == R.TXEXTRADATA: o, l = res.details.extra_data_offset, res.details.extra_data_len msg = trezor_proto.TransactionType() msg.extra_data = current_tx.extra_data[o:o + l] res = client.call(trezor_proto.TxAck(tx=msg)) if isinstance(res, trezor_proto.Failure): raise Exception("Signing failed") if not isinstance(res, trezor_proto.TxRequest): raise Exception("Unexpected message") if None in signatures: raise RuntimeError("Some signatures are missing!") return signatures, serialized_tx
in1_prev_hash_b = bytes.fromhex(in1_prev_hash) device = get_transport() client = TrezorClient(transport=device, ui=ui.ClickUI()) fw = client.features fw_min = min_version[fw.model] py_min = (3, 6, 0) tl_min = [0, 12, 0] if (fw_min > (fw.major_version, fw.minor_version, fw.patch_version) or tl_min > [int(i) for i in lib_version.split('.')] or py_min > py_ver): m = "Requires at least Python rev {}, trezorlib rev {}, and FW rev {}" print(m.format(py_min, tl_min, fw_min)) exit(1) signtx = proto.SignTx(version=tx_version, lock_time=tx_locktime) ins = [ proto.TxInputType(address_n=tools.parse_path(in1_addr_path), prev_hash=in1_prev_hash_b, prev_index=in1_prev_index, amount=in1_amount, script_type=proto.InputScriptType.SPENDWITNESS, sequence=sequence) ] outs = [ proto.TxOutputType(address=out1_address, amount=out1_amount, script_type=proto.OutputScriptType.PAYTOADDRESS) ]