From 7684db4702a85a136821961efd67ccde925e56d8 Mon Sep 17 00:00:00 2001 From: Yura Pakhuchiy Date: Sun, 8 Jul 2018 02:09:20 +0700 Subject: [PATCH] Add Groestlcoin transaction signing tests --- ....wallet.segwit.signtx.native_p2wpkh_grs.py | 222 +++++++++++++++++ ...wallet.segwit.signtx.p2wpkh_in_p2sh_grs.py | 231 ++++++++++++++++++ tests/test_apps.wallet.signtx_grs.py | 106 ++++++++ 3 files changed, 559 insertions(+) create mode 100644 tests/test_apps.wallet.segwit.signtx.native_p2wpkh_grs.py create mode 100644 tests/test_apps.wallet.segwit.signtx.p2wpkh_in_p2sh_grs.py create mode 100644 tests/test_apps.wallet.signtx_grs.py diff --git a/tests/test_apps.wallet.segwit.signtx.native_p2wpkh_grs.py b/tests/test_apps.wallet.segwit.signtx.native_p2wpkh_grs.py new file mode 100644 index 0000000000..ee862960d2 --- /dev/null +++ b/tests/test_apps.wallet.segwit.signtx.native_p2wpkh_grs.py @@ -0,0 +1,222 @@ +from common import * + +from trezor.utils import chunks +from trezor.crypto import bip32, bip39 +from trezor.messages.SignTx import SignTx +from trezor.messages.TxInputType import TxInputType +from trezor.messages.TxOutputType import TxOutputType +from trezor.messages.TxRequest import TxRequest +from trezor.messages.TxAck import TxAck +from trezor.messages.TransactionType import TransactionType +from trezor.messages.RequestType import TXINPUT, TXOUTPUT, TXFINISHED +from trezor.messages.TxRequestDetailsType import TxRequestDetailsType +from trezor.messages.TxRequestSerializedType import TxRequestSerializedType +from trezor.messages import InputScriptType +from trezor.messages import OutputScriptType + +from apps.common import coins +from apps.wallet.sign_tx import signing + +# https://groestlsight-test.groestlcoin.org/api/tx/9b5c4859a8a31e69788cb4402812bb28f14ad71cbd8c60b09903478bc56f79a3 +class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase): + # pylint: disable=C0301 + + def test_send_native_p2wpkh(self): + + coin = coins.by_name('Groestlcoin Testnet') + + seed = bip39.seed(' '.join(['all'] * 12), '') + root = bip32.from_seed(seed, coin.curve_name) + + inp1 = TxInputType( + # 84'/1'/0'/0/0" - tgrs1qkvwu9g3k2pdxewfqr7syz89r3gj557l3ued7ja + address_n=[84 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 0, 0], + amount=12300000, + prev_hash=unhexlify('4f2f857f39ed1afe05542d058fb0be865a387446e32fc876d086203f483f61d1'), + prev_index=0, + script_type=InputScriptType.SPENDWITNESS, + sequence=0xfffffffe, + multisig=None, + ) + out1 = TxOutputType( + address='2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e', + amount=5000000, + script_type=OutputScriptType.PAYTOADDRESS, + address_n=[], + multisig=None, + ) + out2 = TxOutputType( + address='tgrs1qejqxwzfld7zr6mf7ygqy5s5se5xq7vmt9lkd57', + script_type=OutputScriptType.PAYTOADDRESS, + amount=12300000 - 11000 - 5000000, + address_n=[], + multisig=None, + ) + tx = SignTx(coin_name='Groestlcoin Testnet', version=None, lock_time=650713, inputs_count=1, outputs_count=2) + + messages = [ + None, + + # check fee + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None)), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(outputs=[out1])), + + signing.UiConfirmOutput(out1, coin), + True, + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(outputs=[out2])), + + signing.UiConfirmOutput(out2, coin), + True, + + signing.UiConfirmTotal(12300000 - 11000, 11000, coin), + True, + + # sign tx + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( + # returned serialized inp1 + serialized_tx=unhexlify('01000000000101d1613f483f2086d076c82fe34674385a86beb08f052d5405fe1aed397f852f4f0000000000feffffff'), + )), + TxAck(tx=TransactionType(outputs=[out1])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=TxRequestSerializedType( + # returned serialized out1 + serialized_tx=unhexlify('02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987'), + signature_index=None, + signature=None, + )), + TxAck(tx=TransactionType(outputs=[out2])), + + # segwit + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( + # returned serialized out2 + serialized_tx=unhexlify('a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b'), + signature_index=None, + signature=None, + )), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXFINISHED, details=None, serialized=TxRequestSerializedType( + serialized_tx=unhexlify('02483045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f862d9ed0900'), + signature_index=0, + signature=unhexlify('3045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3'), + )), + ] + + signer = signing.sign_tx(tx, root) + for request, response in chunks(messages, 2): + self.assertEqualEx(signer.send(request), response) + with self.assertRaises(StopIteration): + signer.send(None) + + def test_send_native_p2wpkh_change(self): + + coin = coins.by_name('Groestlcoin Testnet') + + seed = bip39.seed(' '.join(['all'] * 12), '') + root = bip32.from_seed(seed, coin.curve_name) + + inp1 = TxInputType( + # 84'/1'/0'/0/0" - tgrs1qkvwu9g3k2pdxewfqr7syz89r3gj557l3ued7ja + address_n=[84 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 0, 0], + amount=12300000, + prev_hash=unhexlify('4f2f857f39ed1afe05542d058fb0be865a387446e32fc876d086203f483f61d1'), + prev_index=0, + script_type=InputScriptType.SPENDWITNESS, + sequence=0xfffffffe, + multisig=None, + ) + out1 = TxOutputType( + address='2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e', + amount=5000000, + script_type=OutputScriptType.PAYTOADDRESS, + address_n=[], + multisig=None, + ) + out2 = TxOutputType( + address=None, + address_n=[84 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 1, 0], + script_type=OutputScriptType.PAYTOWITNESS, + amount=12300000 - 11000 - 5000000, + multisig=None, + ) + tx = SignTx(coin_name='Groestlcoin Testnet', version=None, lock_time=650713, inputs_count=1, outputs_count=2) + + messages = [ + None, + + # check fee + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None)), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(outputs=[out1])), + + signing.UiConfirmOutput(out1, coin), + True, + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(outputs=[out2])), + + signing.UiConfirmTotal(5000000, 11000, coin), + True, + + # sign tx + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( + # returned serialized inp1 + serialized_tx=unhexlify('01000000000101d1613f483f2086d076c82fe34674385a86beb08f052d5405fe1aed397f852f4f0000000000feffffff'), + )), + # the out has to be cloned not to send the same object which was modified + TxAck(tx=TransactionType(outputs=[TxOutputType(**out1.__dict__)])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=TxRequestSerializedType( + # returned serialized out1 + serialized_tx=unhexlify('02404b4c000000000017a9147a55d61848e77ca266e79a39bfc85c580a6426c987'), + signature_index=None, + signature=None, + )), + TxAck(tx=TransactionType(outputs=[TxOutputType(**out2.__dict__)])), + + # segwit + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( + # returned serialized out2 + serialized_tx=unhexlify('a8386f0000000000160014cc8067093f6f843d6d3e22004a4290cd0c0f336b'), + signature_index=None, + signature=None, + )), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXFINISHED, details=None, serialized=TxRequestSerializedType( + serialized_tx=unhexlify('02483045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f862d9ed0900'), + signature_index=0, + signature=unhexlify('3045022100ea8780bc1e60e14e945a80654a41748bbf1aa7d6f2e40a88d91dfc2de1f34bd10220181a474a3420444bd188501d8d270736e1e9fe379da9970de992ff445b0972e3'), + )), + ] + + signer = signing.sign_tx(tx, root) + for request, response in chunks(messages, 2): + self.assertEqualEx(signer.send(request), response) + with self.assertRaises(StopIteration): + signer.send(None) + + def assertEqualEx(self, a, b): + # hack to avoid adding __eq__ to signing.Ui* classes + if ((isinstance(a, signing.UiConfirmOutput) and isinstance(b, signing.UiConfirmOutput)) or + (isinstance(a, signing.UiConfirmTotal) and isinstance(b, signing.UiConfirmTotal))): + return self.assertEqual(a.__dict__, b.__dict__) + else: + return self.assertEqual(a, b) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_apps.wallet.segwit.signtx.p2wpkh_in_p2sh_grs.py b/tests/test_apps.wallet.segwit.signtx.p2wpkh_in_p2sh_grs.py new file mode 100644 index 0000000000..fb30454672 --- /dev/null +++ b/tests/test_apps.wallet.segwit.signtx.p2wpkh_in_p2sh_grs.py @@ -0,0 +1,231 @@ +from common import * + +from trezor.utils import chunks +from trezor.crypto import bip32, bip39 +from trezor.messages.SignTx import SignTx +from trezor.messages.TxInputType import TxInputType +from trezor.messages.TxOutputType import TxOutputType +from trezor.messages.TxRequest import TxRequest +from trezor.messages.TxAck import TxAck +from trezor.messages.TransactionType import TransactionType +from trezor.messages.RequestType import TXINPUT, TXOUTPUT, TXFINISHED +from trezor.messages.TxRequestDetailsType import TxRequestDetailsType +from trezor.messages.TxRequestSerializedType import TxRequestSerializedType +from trezor.messages import InputScriptType +from trezor.messages import OutputScriptType + +from apps.common import coins +from apps.wallet.sign_tx import signing + +# https://groestlsight-test.groestlcoin.org/api/tx/4ce0220004bdfe14e3dd49fd8636bcb770a400c0c9e9bff670b6a13bb8f15c72 +class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase): + # pylint: disable=C0301 + + def test_send_p2wpkh_in_p2sh(self): + + coin = coins.by_name('Groestlcoin Testnet') + + seed = bip39.seed(' '.join(['all'] * 12), '') + root = bip32.from_seed(seed, coin.curve_name) + + inp1 = TxInputType( + # 49'/1'/0'/1/0" - 2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7 + address_n=[49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 1, 0], + amount=123456789, + prev_hash=unhexlify('09a48bce2f9d5c6e4f0cb9ea1b32d0891855e8acfe5334f9ebd72b9ad2de60cf'), + prev_index=0, + script_type=InputScriptType.SPENDP2SHWITNESS, + sequence=0xfffffffe, + multisig=None, + ) + out1 = TxOutputType( + address='mvbu1Gdy8SUjTenqerxUaZyYjmvedc787y', + amount=12300000, + script_type=OutputScriptType.PAYTOADDRESS, + address_n=[], + multisig=None, + ) + out2 = TxOutputType( + address='2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7', + script_type=OutputScriptType.PAYTOADDRESS, + amount=123456789 - 11000 - 12300000, + address_n=[], + multisig=None, + ) + tx = SignTx(coin_name='Groestlcoin Testnet', version=None, lock_time=650756, inputs_count=1, outputs_count=2) + + messages = [ + None, + + # check fee + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None)), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(outputs=[out1])), + + signing.UiConfirmOutput(out1, coin), + True, + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(outputs=[out2])), + + signing.UiConfirmOutput(out2, coin), + True, + + signing.UiConfirmTotal(123445789, 11000, coin), + True, + + # sign tx + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( + # returned serialized inp1 + serialized_tx=unhexlify('01000000000101cf60ded29a2bd7ebf93453feace8551889d0321beab90c4f6e5c9d2fce8ba4090000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5feffffff'), + )), + TxAck(tx=TransactionType(outputs=[out1])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=TxRequestSerializedType( + # returned serialized out1 + serialized_tx=unhexlify('02e0aebb00000000001976a914a579388225827d9f2fe9014add644487808c695d88ac'), + signature_index=None, + signature=None, + )), + TxAck(tx=TransactionType(outputs=[out2])), + + # segwit + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( + # returned serialized out2 + serialized_tx=unhexlify('3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'), + signature_index=None, + signature=None, + )), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXFINISHED, details=None, serialized=TxRequestSerializedType( + serialized_tx=unhexlify('02483045022100b7ce2972bcbc3a661fe320ba901e680913b2753fcb47055c9c6ba632fc4acf81022001c3cfd6c2fe92eb60f5176ce0f43707114dd7223da19c56f2df89c13c2fef80012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7904ee0900'), + signature_index=0, + signature=unhexlify('3045022100b7ce2972bcbc3a661fe320ba901e680913b2753fcb47055c9c6ba632fc4acf81022001c3cfd6c2fe92eb60f5176ce0f43707114dd7223da19c56f2df89c13c2fef80'), + )), + ] + + signer = signing.sign_tx(tx, root) + for request, response in chunks(messages, 2): + self.assertEqualEx(signer.send(request), response) + with self.assertRaises(StopIteration): + signer.send(None) + + def test_send_p2wpkh_in_p2sh_change(self): + + coin = coins.by_name('Groestlcoin Testnet') + + seed = bip39.seed(' '.join(['all'] * 12), '') + root = bip32.from_seed(seed, coin.curve_name) + + inp1 = TxInputType( + # 49'/1'/0'/1/0" - 2N1LGaGg836mqSQqiuUBLfcyGBhyZYBtBZ7 + address_n=[49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 1, 0], + amount=123456789, + prev_hash=unhexlify('09a48bce2f9d5c6e4f0cb9ea1b32d0891855e8acfe5334f9ebd72b9ad2de60cf'), + prev_index=0, + script_type=InputScriptType.SPENDP2SHWITNESS, + sequence=0xfffffffe, + multisig=None, + ) + out1 = TxOutputType( + address='mvbu1Gdy8SUjTenqerxUaZyYjmvedc787y', + amount=12300000, + script_type=OutputScriptType.PAYTOADDRESS, + address_n=[], + multisig=None, + ) + out2 = TxOutputType( + address_n=[49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 1, 0], + script_type=OutputScriptType.PAYTOP2SHWITNESS, + amount=123456789 - 11000 - 12300000, + address=None, + multisig=None, + ) + tx = SignTx(coin_name='Groestlcoin Testnet', version=None, lock_time=650756, inputs_count=1, outputs_count=2) + + messages = [ + None, + + # check fee + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None)), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), + serialized=None), + TxAck(tx=TransactionType(outputs=[out1])), + + signing.UiConfirmOutput(out1, coin), + True, + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), + serialized=None), + TxAck(tx=TransactionType(outputs=[out2])), + + signing.UiConfirmTotal(12300000, 11000, coin), + True, + + # sign tx + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), + serialized=None), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), + serialized=TxRequestSerializedType( + # returned serialized inp1 + serialized_tx=unhexlify( + '01000000000101cf60ded29a2bd7ebf93453feace8551889d0321beab90c4f6e5c9d2fce8ba4090000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5feffffff'), + )), + # the out has to be cloned not to send the same object which was modified + TxAck(tx=TransactionType(outputs=[TxOutputType(**out1.__dict__)])), + + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), + serialized=TxRequestSerializedType( + # returned serialized out1 + serialized_tx=unhexlify( + '02e0aebb00000000001976a914a579388225827d9f2fe9014add644487808c695d88ac'), + signature_index=None, + signature=None, + )), + TxAck(tx=TransactionType(outputs=[TxOutputType(**out2.__dict__)])), + + # segwit + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), + serialized=TxRequestSerializedType( + # returned serialized out2 + serialized_tx=unhexlify( + '3df39f060000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'), + signature_index=None, + signature=None, + )), + TxAck(tx=TransactionType(inputs=[inp1])), + + TxRequest(request_type=TXFINISHED, details=None, serialized=TxRequestSerializedType( + serialized_tx=unhexlify('02483045022100b7ce2972bcbc3a661fe320ba901e680913b2753fcb47055c9c6ba632fc4acf81022001c3cfd6c2fe92eb60f5176ce0f43707114dd7223da19c56f2df89c13c2fef80012103e7bfe10708f715e8538c92d46ca50db6f657bbc455b7494e6a0303ccdb868b7904ee0900'), + signature_index=0, + signature=unhexlify('3045022100b7ce2972bcbc3a661fe320ba901e680913b2753fcb47055c9c6ba632fc4acf81022001c3cfd6c2fe92eb60f5176ce0f43707114dd7223da19c56f2df89c13c2fef80'), + )), + ] + + signer = signing.sign_tx(tx, root) + for request, response in chunks(messages, 2): + self.assertEqualEx(signer.send(request), response) + with self.assertRaises(StopIteration): + signer.send(None) + + def assertEqualEx(self, a, b): + # hack to avoid adding __eq__ to signing.Ui* classes + if ((isinstance(a, signing.UiConfirmOutput) and isinstance(b, signing.UiConfirmOutput)) or + (isinstance(a, signing.UiConfirmTotal) and isinstance(b, signing.UiConfirmTotal))): + return self.assertEqual(a.__dict__, b.__dict__) + else: + return self.assertEqual(a, b) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_apps.wallet.signtx_grs.py b/tests/test_apps.wallet.signtx_grs.py new file mode 100644 index 0000000000..e22a6fe1d4 --- /dev/null +++ b/tests/test_apps.wallet.signtx_grs.py @@ -0,0 +1,106 @@ +from common import * + +from trezor.utils import chunks +from trezor.crypto import bip32, bip39 +from trezor.messages.SignTx import SignTx +from trezor.messages.TxInputType import TxInputType +from trezor.messages.TxOutputType import TxOutputType +from trezor.messages.TxOutputBinType import TxOutputBinType +from trezor.messages.TxRequest import TxRequest +from trezor.messages.TxAck import TxAck +from trezor.messages.TransactionType import TransactionType +from trezor.messages.RequestType import TXINPUT, TXOUTPUT, TXMETA, TXFINISHED +from trezor.messages.TxRequestDetailsType import TxRequestDetailsType +from trezor.messages.TxRequestSerializedType import TxRequestSerializedType +from trezor.messages import OutputScriptType + +from apps.common import coins +from apps.wallet.sign_tx import signing + + +class TestSignTx_GRS(unittest.TestCase): + # pylint: disable=C0301 + + def test_one_one_fee(self): + # http://groestlsight.groestlcoin.org/tx/f56521b17b828897f72b30dd21b0192fd942342e89acbb06abf1d446282c30f5 + # ptx1: http://groestlsight.groestlcoin.org/api/tx/cb74c8478c5814742c87cffdb4a21231869888f8042fb07a90e015a9db1f9d4a + + coin = coins.by_name('Groestlcoin') + + ptx1 = TransactionType(version=1, lock_time=2160993, inputs_cnt=1, outputs_cnt=1, extra_data_len=0) + pinp1 = TxInputType(script_sig=unhexlify('48304502210096a287593b1212a188e778596eb8ecd4cc169b93a4d115226460d8e3deae431c02206c78ec09b3df977f04a6df5eb53181165c4ea5a0b35f826551349130f879d6b8012102cf5126ff54e38a80a919579d7091cafe24840eab1d30fe2b4d59bdd9d267cad8'), + prev_hash=unhexlify('7dc74a738c50c2ae1228ce9890841e5355fd6d7f2c1367e0a74403ab60db3224'), + prev_index=0, + script_type=None, + sequence=4294967294) + pout1 = TxOutputBinType(script_pubkey=unhexlify('76a914172b4e06e9b7881a48d2ee8062b495d0b2517fe888ac'), + amount=210016) + + inp1 = TxInputType(address_n=[44 | 0x80000000, 17 | 0x80000000, 0 | 0x80000000, 0, 2], # FXHDsC5ZqWQHkDmShzgRVZ1MatpWhwxTAA + prev_hash=unhexlify('cb74c8478c5814742c87cffdb4a21231869888f8042fb07a90e015a9db1f9d4a'), + prev_index=0, + amount=None, + script_type=None, + multisig=None, + sequence=None) + out1 = TxOutputType(address='FtM4zAn9aVYgHgxmamWBgWPyZsb6RhvkA9', + amount=210016 - 192, + script_type=OutputScriptType.PAYTOADDRESS, + address_n=[], + multisig=None) + tx = SignTx(coin_name='Groestlcoin', version=None, lock_time=None, inputs_count=1, outputs_count=1) + + messages = [ + None, + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None)), + TxAck(tx=TransactionType(inputs=[inp1])), + TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=unhexlify('cb74c8478c5814742c87cffdb4a21231869888f8042fb07a90e015a9db1f9d4a')), serialized=None), + TxAck(tx=ptx1), + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=unhexlify('cb74c8478c5814742c87cffdb4a21231869888f8042fb07a90e015a9db1f9d4a')), serialized=None), + TxAck(tx=TransactionType(inputs=[pinp1])), + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=unhexlify('cb74c8478c5814742c87cffdb4a21231869888f8042fb07a90e015a9db1f9d4a')), serialized=None), + TxAck(tx=TransactionType(bin_outputs=[pout1])), + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(outputs=[out1])), + signing.UiConfirmOutput(out1, coin), + True, + signing.UiConfirmTotal(210016 - 192, 192, coin), + True, + # ButtonRequest(code=ButtonRequest_ConfirmOutput), + # ButtonRequest(code=ButtonRequest_SignTx), + TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(inputs=[inp1])), + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None), + TxAck(tx=TransactionType(outputs=[out1])), + TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=TxRequestSerializedType( + signature_index=0, + signature=unhexlify('304402201fb96d20d0778f54520ab59afe70d5fb20e500ecc9f02281cf57934e8029e8e10220383d5a3e80f2e1eb92765b6da0f23d454aecbd8236f083d483e9a74302368761'), + serialized_tx=unhexlify('01000000014a9d1fdba915e0907ab02f04f88898863112a2b4fdcf872c7414588c47c874cb000000006a47304402201fb96d20d0778f54520ab59afe70d5fb20e500ecc9f02281cf57934e8029e8e10220383d5a3e80f2e1eb92765b6da0f23d454aecbd8236f083d483e9a7430236876101210331693756f749180aeed0a65a0fab0625a2250bd9abca502282a4cf0723152e67ffffffff'))), + TxAck(tx=TransactionType(outputs=[out1])), + TxRequest(request_type=TXFINISHED, details=None, serialized=TxRequestSerializedType( + signature_index=None, + signature=None, + serialized_tx=unhexlify('01a0330300000000001976a914fe40329c95c5598ac60752a5310b320cb52d18e688ac00000000'), + )), + ] + + seed = bip39.seed(' '.join(['all'] * 12), '') + root = bip32.from_seed(seed, coin.curve_name) + + signer = signing.sign_tx(tx, root) + for request, response in chunks(messages, 2): + self.assertEqualEx(signer.send(request), response) + with self.assertRaises(StopIteration): + signer.send(None) + + def assertEqualEx(self, a, b): + # hack to avoid adding __eq__ to signing.Ui* classes + if ((isinstance(a, signing.UiConfirmOutput) and isinstance(b, signing.UiConfirmOutput)) or + (isinstance(a, signing.UiConfirmTotal) and isinstance(b, signing.UiConfirmTotal))): + return self.assertEqual(a.__dict__, b.__dict__) + else: + return self.assertEqual(a, b) + + +if __name__ == '__main__': + unittest.main()