ct_swap.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2024 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen-wallet
  9. # https://gitlab.com/mmgen/mmgen-wallet
  10. """
  11. test.cmdtest_d.ct_swap: asset swap tests for the cmdtest.py test suite
  12. """
  13. from .ct_regtest import CmdTestRegtest, rt_data, dfl_wcls, rt_pw
  14. rtFundAmt = rtFee = None # ruff
  15. sample1 = '=:ETH.ETH:0x86d526d6624AbC0178cF7296cD538Ecc080A95F1:0/1/0'
  16. sample2 = '00010203040506'
  17. class CmdTestSwap(CmdTestRegtest):
  18. bdb_wallet = True
  19. networks = ('btc',)
  20. tmpdir_nums = [37]
  21. cmd_group_in = (
  22. ('setup', 'regtest (Bob and Alice) mode setup'),
  23. ('subgroup.init_bob', []),
  24. ('subgroup.fund_bob', ['init_bob']),
  25. ('subgroup.data', ['init_bob']),
  26. ('stop', 'stopping regtest daemon'),
  27. )
  28. cmd_subgroups = {
  29. 'init_bob': (
  30. 'creating Bob’s MMGen wallet and tracking wallet',
  31. ('walletgen_bob', 'wallet generation (Bob)'),
  32. ('addrgen_bob', 'address generation (Bob)'),
  33. ('addrimport_bob', 'importing Bob’s addresses'),
  34. ),
  35. 'fund_bob': (
  36. 'funding Bob’s wallet',
  37. ('fund_bob', 'funding Bob’s wallet'),
  38. ('bob_bal1', 'Bob’s balance'),
  39. ),
  40. 'data': (
  41. 'OP_RETURN data operations',
  42. ('data_tx1_create', 'Creating a transaction with OP_RETURN data (hex-encoded ascii)'),
  43. ('data_tx1_sign', 'Signing the transaction'),
  44. ('data_tx1_send', 'Sending the transaction'),
  45. ('data_tx1_chk', 'Checking the sent transaction'),
  46. ('generate3', 'Generate 3 blocks'),
  47. ('data_tx2_do', 'Creating and sending a transaction with OP_RETURN data (binary)'),
  48. ('data_tx2_chk', 'Checking the sent transaction'),
  49. ('generate3', 'Generate 3 blocks'),
  50. ),
  51. }
  52. def __init__(self, trunner, cfgs, spawn):
  53. super().__init__(trunner, cfgs, spawn)
  54. gldict = globals()
  55. for k in rt_data:
  56. gldict[k] = rt_data[k]['btc']
  57. @property
  58. def sid(self):
  59. return self._user_sid('bob')
  60. def addrgen_bob(self):
  61. return self.addrgen('bob', mmtypes=['S', 'B'])
  62. def addrimport_bob(self):
  63. return self.addrimport('bob', mmtypes=['S', 'B'])
  64. def fund_bob(self):
  65. return self.fund_wallet('bob', 'B', rtFundAmt)
  66. def data_tx1_create(self):
  67. return self._data_tx_create('1', 'B:2', 'B:3', 'data', sample1)
  68. def _data_tx_create(self, src, dest, chg, pfx, sample):
  69. t = self.spawn(
  70. 'mmgen-txcreate',
  71. ['-d', self.tmpdir, '-B', '--bob', f'{self.sid}:{dest},1', f'{self.sid}:{chg}', f'{pfx}:{sample}'])
  72. return self.txcreate_ui_common(t, menu=[], inputs='1', interactive_fee='3s')
  73. def data_tx1_sign(self):
  74. return self._data_tx_sign()
  75. def _data_tx_sign(self):
  76. fn = self.get_file_with_ext('rawtx')
  77. t = self.spawn('mmgen-txsign', ['-d', self.tmpdir, '--bob', fn])
  78. t.view_tx('v')
  79. t.passphrase(dfl_wcls.desc, rt_pw)
  80. t.do_comment(None)
  81. t.expect('(Y/n): ', 'y')
  82. t.written_to_file('Signed transaction')
  83. return t
  84. def data_tx1_send(self):
  85. return self._data_tx_send()
  86. def _data_tx_send(self):
  87. fn = self.get_file_with_ext('sigtx')
  88. t = self.spawn('mmgen-txsend', ['-q', '-d', self.tmpdir, '--bob', fn])
  89. t.expect('view: ', 'n')
  90. t.expect('(y/N): ', '\n')
  91. t.expect('to confirm: ', 'YES\n')
  92. t.written_to_file('Sent transaction')
  93. return t
  94. def data_tx1_chk(self):
  95. return self._data_tx_chk(sample1.encode().hex())
  96. def data_tx2_do(self):
  97. return self._data_tx_do('2', 'B:4', 'B:5', 'hexdata', sample2, 'v')
  98. def data_tx2_chk(self):
  99. return self._data_tx_chk(sample2)
  100. def _data_tx_do(self, src, dest, chg, pfx, sample, view):
  101. t = self.user_txdo(
  102. user = 'bob',
  103. fee = rtFee[0],
  104. outputs_cl = [f'{self.sid}:{dest},1', f'{self.sid}:{chg}', f'{pfx}:{sample}'],
  105. outputs_list = src,
  106. add_comment = 'Transaction with OP_RETURN data',
  107. return_early = True)
  108. t.view_tx(view)
  109. if view == 'v':
  110. t.expect(sample)
  111. t.expect('amount:')
  112. t.passphrase(dfl_wcls.desc, rt_pw)
  113. t.written_to_file('Signed transaction')
  114. self._do_confirm_send(t)
  115. t.expect('Transaction sent')
  116. return t
  117. def _data_tx_chk(self, sample):
  118. mp = self._get_mempool(do_msg=True)
  119. assert len(mp) == 1
  120. self.write_to_tmpfile('data_tx1_id', mp[0]+'\n')
  121. tx_hex = self._do_cli(['getrawtransaction', mp[0]])
  122. tx = self._do_cli(['decoderawtransaction', tx_hex], decode_json=True)
  123. v0 = tx['vout'][0]
  124. assert v0['scriptPubKey']['hex'] == f'6a{(len(sample) // 2):02x}{sample}'
  125. assert v0['scriptPubKey']['type'] == 'nulldata'
  126. assert v0['value'] == "0.00000000"
  127. return 'ok'
  128. def generate3(self):
  129. return self.generate(3)