from common import * from trezor.utils import chunks from trezor.crypto import bip39 from trezor.messages import SignTx from trezor.messages import TxAckInput from trezor.messages import TxAckInputWrapper from trezor.messages import TxInput from trezor.messages import TxAckOutput from trezor.messages import TxAckOutputWrapper from trezor.messages import TxOutput from trezor.messages import TxAckPrevMeta from trezor.messages import PrevTx from trezor.messages import TxAckPrevInput from trezor.messages import TxAckPrevInputWrapper from trezor.messages import PrevInput from trezor.messages import TxAckPrevOutput from trezor.messages import TxAckPrevOutputWrapper from trezor.messages import PrevOutput from trezor.messages import TxRequest from trezor.enums.RequestType import TXINPUT, TXOUTPUT, TXMETA, TXFINISHED from trezor.messages import TxRequestDetailsType from trezor.messages import TxRequestSerializedType from trezor.enums import AmountUnit from trezor.enums import OutputScriptType from apps.common import coins from apps.common.keychain import Keychain from apps.bitcoin.keychain import get_schemas_for_coin from apps.bitcoin.sign_tx import decred, helpers EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray()) coin_decred = coins.by_name("Decred Testnet") ptx1 = PrevTx(version=1, lock_time=0, inputs_count=1, outputs_count=2, extra_data_len=0) pinp1 = PrevInput( script_sig=unhexlify( "47304402207d127d59a44187952d9d0de94ad34a19dd9a84beb124fd8a3fb439c862544d3202206618f321385c30bda96fb01ce03f70a269d78a301c0b0c2e3e3689dfae3f4733012102ae1f6b51086bd753f072f94eb8ffe6806d3570c088a3ede46c678b6ea47d1675" ), prev_hash=unhexlify( "21012b08c5077036460e8f75bbc57beb11d7bc30e7ad224ad5e67d15bd086500" ), prev_index=2, sequence=0xFFFF_FFFF, ) pout1 = PrevOutput( script_pubkey=unhexlify("76a914e4111051ae0349ab5589cf2b7e125c6da694a1a188ac"), amount=153_185_001, decred_script_version=0, ) pout2 = PrevOutput( script_pubkey=unhexlify("76a914dc1a98d791735eb9a8715a2a219c23680edcedad88ac"), amount=200_000_000, decred_script_version=0, ) @unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin") class TestSignTxDecred(unittest.TestCase): # pylint: disable=C0301 def test_one_one_fee(self): inp1 = TxInput( address_n=[44 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 0, 0], prev_hash=unhexlify( "4d8acde26d5efc7f5df1b3cdada6b11027616520c883e09c919b88f0f0cb6410" ), prev_index=1, amount=200_000_000, multisig=None, sequence=0xFFFF_FFFF, ) out1 = TxOutput( address="TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz", amount=200_000_000 - 100_000, script_type=OutputScriptType.PAYTOADDRESS, multisig=None, ) tx = SignTx( coin_name="Decred Testnet", version=1, lock_time=0, inputs_count=1, outputs_count=1, ) # precomputed tx weight is 864 fee_rate = 100_000 / (864 / 4) messages = [ None, TxRequest( request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( serialized_tx=unhexlify("0100000001") ), ), TxAckInput(tx=TxAckInputWrapper(input=inp1)), TxRequest( request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( serialized_tx=unhexlify( "1064cbf0f0889b919ce083c82065612710b1a6adcdb3f15d7ffc5e6de2cd8a4d0100000000ffffffff01" ) ), ), TxAckOutput(tx=TxAckOutputWrapper(output=out1)), helpers.UiConfirmOutput(out1, coin_decred, AmountUnit.BITCOIN), True, helpers.UiConfirmTotal( 200_000_000, 100_000, fee_rate, coin_decred, AmountUnit.BITCOIN ), True, TxRequest( request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( serialized_tx=unhexlify( "603bea0b0000000000001976a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac0000000000000000" ) ), ), TxAckInput(tx=TxAckInputWrapper(input=inp1)), TxRequest( request_type=TXMETA, details=TxRequestDetailsType( request_index=None, tx_hash=unhexlify( "4d8acde26d5efc7f5df1b3cdada6b11027616520c883e09c919b88f0f0cb6410" ), ), serialized=EMPTY_SERIALIZED, ), TxAckPrevMeta(tx=ptx1), TxRequest( request_type=TXINPUT, details=TxRequestDetailsType( request_index=0, tx_hash=unhexlify( "4d8acde26d5efc7f5df1b3cdada6b11027616520c883e09c919b88f0f0cb6410" ), ), serialized=EMPTY_SERIALIZED, ), TxAckPrevInput(tx=TxAckPrevInputWrapper(input=pinp1)), TxRequest( request_type=TXOUTPUT, details=TxRequestDetailsType( request_index=0, tx_hash=unhexlify( "4d8acde26d5efc7f5df1b3cdada6b11027616520c883e09c919b88f0f0cb6410" ), ), serialized=EMPTY_SERIALIZED, ), TxAckPrevOutput(tx=TxAckPrevOutputWrapper(output=pout1)), TxRequest( request_type=TXOUTPUT, details=TxRequestDetailsType( request_index=1, tx_hash=unhexlify( "4d8acde26d5efc7f5df1b3cdada6b11027616520c883e09c919b88f0f0cb6410" ), ), serialized=EMPTY_SERIALIZED, ), TxAckPrevOutput(tx=TxAckPrevOutputWrapper(output=pout2)), TxRequest( request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType(serialized_tx=unhexlify("01")), ), TxAckInput(tx=TxAckInputWrapper(input=inp1)), TxRequest( request_type=TXFINISHED, details=TxRequestDetailsType(request_index=None, tx_hash=None), serialized=TxRequestSerializedType( signature_index=0, signature=unhexlify( "304402205ea5a0aec7e405eb3c792165f103f61f8ef862e76a2b0146bec1082b243cfbff022061e307113d389b969313bbee2c9a149fad4afdf715e8bd78df579438ef692814" ), serialized_tx=unhexlify( "00c2eb0b0000000000000000ffffffff6a47304402205ea5a0aec7e405eb3c792165f103f61f8ef862e76a2b0146bec1082b243cfbff022061e307113d389b969313bbee2c9a149fad4afdf715e8bd78df579438ef6928140121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" ), ), ), ] seed = bip39.seed( " ".join(["all"] * 12), "", ) ns = get_schemas_for_coin(coin_decred) keychain = Keychain(seed, coin_decred.curve_name, ns) signer = decred.Decred(tx, keychain, coin_decred, None).signer() for request, response in chunks(messages, 2): res = signer.send(request) if isinstance(res, tuple): _, res = res self.assertEqual(res, response) with self.assertRaises(StopIteration): signer.send(None) def test_purchase_ticket(self): inp1 = TxInput( address_n=[44 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 0, 0], prev_hash=unhexlify( "4d8acde26d5efc7f5df1b3cdada6b11027616520c883e09c919b88f0f0cb6410" ), prev_index=1, amount=200_000_000, multisig=None, sequence=0xFFFF_FFFF, ) out1 = TxOutput( address="TscqTv1he8MZrV321SfRghw7LFBCJDKB3oz", amount=200_000_000 - 100_000, script_type=OutputScriptType.PAYTOADDRESS, multisig=None, ) out2 = TxOutput( address_n=[44 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 0, 0], amount=200_000_000, script_type=OutputScriptType.PAYTOADDRESS, multisig=None, ) out3 = TxOutput( address="TsR28UZRprhgQQhzWns2M6cAwchrNVvbYq2", amount=0, script_type=OutputScriptType.PAYTOADDRESS, multisig=None, ) tx = SignTx( coin_name="Decred Testnet", version=1, lock_time=0, inputs_count=1, outputs_count=3, decred_staking_ticket=True, ) # precomputed tx weight is 1188 fee_rate = 100_000 / (1188 / 4) messages = [ None, TxRequest( request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( serialized_tx=unhexlify("0100000001") ), ), TxAckInput(tx=TxAckInputWrapper(input=inp1)), TxRequest( request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( serialized_tx=unhexlify( "1064cbf0f0889b919ce083c82065612710b1a6adcdb3f15d7ffc5e6de2cd8a4d0100000000ffffffff03" ) ), ), TxAckOutput(tx=TxAckOutputWrapper(output=out1)), helpers.UiConfirmDecredSSTXSubmission( out1, coin_decred, AmountUnit.BITCOIN ), True, TxRequest( request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=TxRequestSerializedType( serialized_tx=unhexlify( "603bea0b0000000000001aba76a914819d291a2f7fbf770e784bfd78b5ce92c58e95ea88ac" ) ), ), TxAckOutput(tx=TxAckOutputWrapper(output=out2)), TxRequest( request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=2, tx_hash=None), serialized=TxRequestSerializedType( serialized_tx=unhexlify( "00000000000000000000206a1edc1a98d791735eb9a8715a2a219c23680edcedad00c2eb0b000000000058" ) ), ), TxAckOutput(tx=TxAckOutputWrapper(output=out3)), helpers.UiConfirmTotal( 200_000_000, 100_000, fee_rate, coin_decred, AmountUnit.BITCOIN ), True, TxRequest( request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( serialized_tx=unhexlify( "000000000000000000001abd76a914000000000000000000000000000000000000000088ac0000000000000000" ) ), ), TxAckInput(tx=TxAckInputWrapper(input=inp1)), TxRequest( request_type=TXMETA, details=TxRequestDetailsType( request_index=None, tx_hash=unhexlify( "4d8acde26d5efc7f5df1b3cdada6b11027616520c883e09c919b88f0f0cb6410" ), ), serialized=EMPTY_SERIALIZED, ), TxAckPrevMeta(tx=ptx1), TxRequest( request_type=TXINPUT, details=TxRequestDetailsType( request_index=0, tx_hash=unhexlify( "4d8acde26d5efc7f5df1b3cdada6b11027616520c883e09c919b88f0f0cb6410" ), ), serialized=EMPTY_SERIALIZED, ), TxAckPrevInput(tx=TxAckPrevInputWrapper(input=pinp1)), TxRequest( request_type=TXOUTPUT, details=TxRequestDetailsType( request_index=0, tx_hash=unhexlify( "4d8acde26d5efc7f5df1b3cdada6b11027616520c883e09c919b88f0f0cb6410" ), ), serialized=EMPTY_SERIALIZED, ), TxAckPrevOutput(tx=TxAckPrevOutputWrapper(output=pout1)), TxRequest( request_type=TXOUTPUT, details=TxRequestDetailsType( request_index=1, tx_hash=unhexlify( "4d8acde26d5efc7f5df1b3cdada6b11027616520c883e09c919b88f0f0cb6410" ), ), serialized=EMPTY_SERIALIZED, ), TxAckPrevOutput(tx=TxAckPrevOutputWrapper(output=pout2)), TxRequest( request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType(serialized_tx=unhexlify("01")), ), TxAckInput(tx=TxAckInputWrapper(input=inp1)), TxRequest( request_type=TXFINISHED, details=TxRequestDetailsType(), serialized=TxRequestSerializedType( signature_index=0, signature=unhexlify( "3045022100b3a11ff4befcc035623de7665aaa76dacc9252e53aabf2a5d61238151e696532022004cbcc537c1d539e04c823140bac4524bdba09f528f5c4b76f3f1022b7dc0ad4" ), serialized_tx=unhexlify( "00c2eb0b0000000000000000ffffffff6b483045022100b3a11ff4befcc035623de7665aaa76dacc9252e53aabf2a5d61238151e696532022004cbcc537c1d539e04c823140bac4524bdba09f528f5c4b76f3f1022b7dc0ad40121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0" ), ), ), ] seed = bip39.seed( " ".join(["all"] * 12), "", ) ns = get_schemas_for_coin(coin_decred) keychain = Keychain(seed, coin_decred.curve_name, ns) signer = decred.Decred(tx, keychain, coin_decred, None).signer() for request, response in chunks(messages, 2): res = signer.send(request) if isinstance(res, tuple): _, res = res self.assertEqual(res, response) with self.assertRaises(StopIteration): signer.send(None) if __name__ == "__main__": unittest.main()