file.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
  4. # Copyright (C)2013-2022 The MMGen Project <mmgen@tuta.io>
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. tool.file: Address and transaction file routines for the 'mmgen-tool' utility
  20. """
  21. from .common import tool_cmd_base,options_annot_str
  22. class tool_cmd(tool_cmd_base):
  23. "utilities for viewing/checking MMGen address and transaction files"
  24. need_proto = True
  25. def __init__(self,cmdname=None,proto=None,mmtype=None):
  26. if cmdname == 'txview':
  27. self.need_amt = True
  28. super().__init__(cmdname=cmdname,proto=proto,mmtype=mmtype)
  29. def _file_chksum(self,mmgen_addrfile,obj):
  30. from ..opts import opt
  31. verbose,yes,quiet = [bool(i) for i in (opt.verbose,opt.yes,opt.quiet)]
  32. opt.verbose,opt.yes,opt.quiet = (False,True,True)
  33. ret = obj(self.proto,mmgen_addrfile)
  34. opt.verbose,opt.yes,opt.quiet = (verbose,yes,quiet)
  35. if verbose:
  36. from ..util import msg,capfirst
  37. if ret.al_id.mmtype.name == 'password':
  38. msg('Passwd fmt: {}\nPasswd len: {}\nID string: {}'.format(
  39. capfirst(ret.pw_info[ret.pw_fmt].desc),
  40. ret.pw_len,
  41. ret.pw_id_str ))
  42. else:
  43. msg(f'Base coin: {ret.base_coin} {capfirst(ret.network)}')
  44. msg(f'MMType: {capfirst(ret.al_id.mmtype.name)}')
  45. msg( f'List length: {len(ret.data)}')
  46. return ret.chksum
  47. def addrfile_chksum(self,mmgen_addrfile:str):
  48. "compute checksum for MMGen address file"
  49. from ..addrlist import AddrList
  50. return self._file_chksum(mmgen_addrfile,AddrList)
  51. def keyaddrfile_chksum(self,mmgen_keyaddrfile:str):
  52. "compute checksum for MMGen key-address file"
  53. from ..addrlist import KeyAddrList
  54. return self._file_chksum(mmgen_keyaddrfile,KeyAddrList)
  55. def passwdfile_chksum(self,mmgen_passwdfile:str):
  56. "compute checksum for MMGen password file"
  57. from ..passwdlist import PasswordList
  58. return self._file_chksum(mmgen_passwdfile,PasswordList)
  59. async def txview(
  60. self,
  61. varargs_call_sig = { # hack to allow for multiple filenames
  62. 'args': (
  63. 'mmgen_tx_file(s)',
  64. 'pager',
  65. 'terse',
  66. 'sort',
  67. 'filesort' ),
  68. 'dfls': ( False, False, 'addr', 'mtime' ),
  69. 'annots': {
  70. 'mmgen_tx_file(s)': str,
  71. 'pager': 'send output to pager',
  72. 'terse': 'produce compact tabular output',
  73. 'sort': 'sort order for transaction inputs and outputs ' + options_annot_str(['addr','raw']),
  74. 'filesort': 'file sort order ' + options_annot_str(['mtime','ctime','atime']),
  75. }
  76. },
  77. *infiles,
  78. **kwargs ):
  79. "display specified raw or signed MMGen transaction files in human-readable form"
  80. terse = bool(kwargs.get('terse'))
  81. tx_sort = kwargs.get('sort') or 'addr'
  82. file_sort = kwargs.get('filesort') or 'mtime'
  83. from ..filename import MMGenFileList
  84. from ..tx import completed,CompletedTX
  85. flist = MMGenFileList( infiles, base_class=completed.Completed, proto=self.proto )
  86. flist.sort_by_age( key=file_sort ) # in-place sort
  87. async def process_file(f):
  88. return (await CompletedTX(
  89. filename = f.name,
  90. quiet_open = True)).info.format( terse=terse, sort=tx_sort )
  91. return ('—'*77+'\n').join([await process_file(f) for f in flist]).rstrip()