base.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
  4. # Copyright (C)2013-2023 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
  9. # https://gitlab.com/mmgen/mmgen
  10. """
  11. wallet.base: wallet base class
  12. """
  13. import os
  14. from ..util import msg,die
  15. from ..objmethods import MMGenObject
  16. from . import Wallet,wallet_data,get_wallet_cls
  17. class WalletMeta(type):
  18. def __init__(cls,name,bases,namespace):
  19. t = cls.__module__.split('.')[-1]
  20. if t in wallet_data:
  21. for k,v in wallet_data[t]._asdict().items():
  22. setattr(cls,k,v)
  23. class wallet(MMGenObject,metaclass=WalletMeta):
  24. desc = 'MMGen seed source'
  25. file_mode = 'text'
  26. filename_api = True
  27. stdin_ok = False
  28. ask_tty = True
  29. no_tty = False
  30. op = None
  31. class WalletData(MMGenObject):
  32. pass
  33. def __init__(self,
  34. in_data = None,
  35. passwd_file = None ):
  36. self.passwd_file = None if passwd_file is False else (passwd_file or self.cfg.passwd_file)
  37. self.ssdata = self.WalletData()
  38. self.msg = {}
  39. self.in_data = in_data
  40. for c in reversed(self.__class__.__mro__):
  41. if hasattr(c,'_msg'):
  42. self.msg.update(c._msg)
  43. if hasattr(self,'seed'):
  44. self._encrypt()
  45. return
  46. elif hasattr(self,'infile') or self.in_data or not self.cfg.stdin_tty:
  47. self._deformat_once()
  48. self._decrypt_retry()
  49. else:
  50. if not self.stdin_ok:
  51. die(1,f'Reading from standard input not supported for {self.desc} format')
  52. self._deformat_retry()
  53. self._decrypt_retry()
  54. self.cfg._util.qmsg('Valid {} for Seed ID {}{}'.format(
  55. self.desc,
  56. self.seed.sid.hl(),
  57. (f', seed length {self.seed.bitlen}' if self.seed.bitlen != 256 else '')
  58. ))
  59. def _get_data(self):
  60. if hasattr(self,'infile'):
  61. from ..fileutil import get_data_from_file
  62. self.fmt_data = get_data_from_file(
  63. self.cfg,
  64. self.infile.name,
  65. self.desc,
  66. binary = self.file_mode=='binary' )
  67. elif self.in_data:
  68. self.fmt_data = self.in_data
  69. else:
  70. self.fmt_data = self._get_data_from_user(self.desc)
  71. def _get_data_from_user(self,desc):
  72. from ..ui import get_data_from_user
  73. return get_data_from_user( self.cfg, desc )
  74. def _deformat_once(self):
  75. self._get_data()
  76. if not self._deformat():
  77. die(2,'Invalid format for input data')
  78. def _deformat_retry(self):
  79. while True:
  80. self._get_data()
  81. if self._deformat():
  82. break
  83. msg('Trying again...')
  84. @classmethod
  85. def ext_to_cls(cls,ext,proto):
  86. return get_wallet_cls(ext=ext)
  87. def get_fmt_data(self):
  88. self._format()
  89. return self.fmt_data
  90. def write_to_file(self,outdir='',desc=''):
  91. self._format()
  92. kwargs = {
  93. 'desc': desc or self.desc,
  94. 'ask_tty': self.ask_tty,
  95. 'no_tty': self.no_tty,
  96. 'binary': self.file_mode == 'binary'
  97. }
  98. if outdir:
  99. # write_data_to_file(): outfile with absolute path overrides self.cfg.outdir
  100. of = os.path.abspath(os.path.join(outdir,self._filename()))
  101. from ..fileutil import write_data_to_file
  102. write_data_to_file(
  103. self.cfg,
  104. of if outdir else self._filename(),
  105. self.fmt_data,
  106. **kwargs )
  107. def check_usr_seed_len(self,bitlen=None):
  108. chk = bitlen or self.seed.bitlen
  109. if self.cfg.seed_len and self.cfg.seed_len != chk:
  110. die(1,f'ERROR: requested seed length ({self.cfg.seed_len}) doesn’t match seed length of source ({chk})')