online.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2025 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. proto.btc.tx.online: Bitcoin online signed transaction class
  12. """
  13. from ....tx import online as TxBase
  14. from ....util import msg, die
  15. from ....color import orange
  16. from .signed import Signed
  17. class OnlineSigned(Signed, TxBase.OnlineSigned):
  18. async def send(self, prompt_user=True):
  19. self.check_correct_chain()
  20. if not self.cfg.bogus_send:
  21. if self.has_segwit_outputs() and not self.rpc.info('segwit_is_active'):
  22. die(2, 'Transaction has Segwit outputs, but this blockchain does not support Segwit'
  23. + ' at the current height')
  24. if self.fee > self.proto.max_tx_fee:
  25. die(2, 'Transaction fee ({}) greater than {} max_tx_fee ({} {})!'.format(
  26. self.fee,
  27. self.proto.name,
  28. self.proto.max_tx_fee,
  29. self.proto.coin))
  30. await self.status.display()
  31. if prompt_user:
  32. self.confirm_send()
  33. if self.cfg.bogus_send:
  34. m = 'BOGUS transaction NOT sent: {}'
  35. else:
  36. m = 'Transaction sent: {}'
  37. try:
  38. ret = await self.rpc.call('sendrawtransaction', self.serialized)
  39. except Exception as e:
  40. errmsg = str(e)
  41. nl = '\n'
  42. if errmsg.count('Signature must use SIGHASH_FORKID'):
  43. m = (
  44. 'The Aug. 1 2017 UAHF has activated on this chain.\n'
  45. 'Re-run the script with the --coin=bch option.')
  46. elif errmsg.count('Illegal use of SIGHASH_FORKID'):
  47. m = (
  48. 'The Aug. 1 2017 UAHF is not yet active on this chain.\n'
  49. 'Re-run the script without the --coin=bch option.')
  50. elif errmsg.count('non-final'):
  51. m = "Transaction with nLockTime {!r} can’t be included in this block!".format(
  52. self.info.strfmt_locktime(self.get_serialized_locktime()))
  53. else:
  54. m, nl = ('', '')
  55. msg(orange('\n'+errmsg))
  56. die(2, f'{m}{nl}Send of MMGen transaction {self.txid} failed')
  57. else:
  58. assert ret == self.coin_txid, 'txid mismatch (after sending)'
  59. msg(m.format(self.coin_txid.hl()))
  60. self.add_sent_timestamp()
  61. self.add_blockcount()
  62. return True
  63. def post_write(self):
  64. pass
  65. class Sent(TxBase.Sent, OnlineSigned):
  66. pass
  67. class AutomountOnlineSigned(TxBase.AutomountOnlineSigned, OnlineSigned):
  68. pass
  69. class AutomountSent(TxBase.AutomountSent, AutomountOnlineSigned):
  70. pass