main_addrgen.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
  4. # Copyright (C)2013-2023 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. mmgen-addrgen: Generate a series or range of addresses from an MMGen
  20. deterministic wallet
  21. """
  22. import mmgen.opts as opts
  23. from .cfg import gc,Config
  24. from .addr import MMGenAddrType
  25. from .addrfile import AddrFile
  26. from .wallet import Wallet
  27. import mmgen.addrlist
  28. if gc.prog_name == 'mmgen-keygen':
  29. gen_what = 'keys'
  30. gen_clsname = 'KeyAddrList'
  31. gen_desc = 'secret keys'
  32. opt_filter = None
  33. note_addrkey = 'By default, both addresses and secret keys are generated.\n\n'
  34. else:
  35. gen_what = 'addresses'
  36. gen_clsname = 'AddrList'
  37. gen_desc = 'addresses'
  38. opt_filter = 'hbcdeEiHOkKlpzPqrStUv-'
  39. note_addrkey = ''
  40. opts_data = {
  41. 'sets': [('print_checksum',True,'quiet',True)],
  42. 'text': {
  43. 'desc': """
  44. Generate a range or list of {desc} from an {pnm} wallet,
  45. mnemonic, seed or brainwallet
  46. """.format(desc=gen_desc,pnm=gc.proj_name),
  47. 'usage':'[opts] [seed source] <index list or range(s)>',
  48. 'options': """
  49. -h, --help Print this help message
  50. --, --longhelp Print help message for long options (common options)
  51. -A, --no-addresses Print only secret keys, no addresses
  52. -c, --print-checksum Print address list checksum and exit
  53. -d, --outdir= d Output files to directory 'd' instead of working dir
  54. -e, --echo-passphrase Echo passphrase or mnemonic to screen upon entry
  55. -i, --in-fmt= f Input is from wallet format 'f' (see FMT CODES below)
  56. -H, --hidden-incog-input-params=f,o Read hidden incognito data from file
  57. 'f' at offset 'o' (comma-separated)
  58. -O, --old-incog-fmt Specify old-format incognito input
  59. -k, --use-internal-keccak-module Force use of the internal keccak module
  60. -K, --keygen-backend=n Use backend 'n' for public key generation. Options
  61. for {coin_id}: {kgs}
  62. -l, --seed-len= l Specify wallet seed length of 'l' bits. This option
  63. is required only for brainwallet and incognito inputs
  64. with non-standard (< {dsl}-bit) seed lengths.
  65. -p, --hash-preset= p Use the scrypt hash parameters defined by preset 'p'
  66. for password hashing (default: '{gc.dfl_hash_preset}')
  67. -z, --show-hash-presets Show information on available hash presets
  68. -P, --passwd-file= f Get wallet passphrase from file 'f'
  69. -q, --quiet Produce quieter output; suppress some warnings
  70. -r, --usr-randchars=n Get 'n' characters of additional randomness from user
  71. (min={cfg.min_urandchars}, max={cfg.max_urandchars}, default={cfg.usr_randchars})
  72. -S, --stdout Print {what} to stdout
  73. -t, --type=t Choose address type. Options: see ADDRESS TYPES below
  74. (default: {dmat})
  75. -U, --subwallet= U Generate {what} for subwallet 'U' (see SUBWALLETS
  76. below)
  77. -v, --verbose Produce more verbose output
  78. -x, --b16 Print secret keys in hexadecimal too
  79. """,
  80. 'notes': """
  81. NOTES FOR THIS COMMAND
  82. Address indexes are given as a comma-separated list and/or hyphen-separated
  83. range(s).
  84. {n_addrkey}If available, the libsecp256k1 library will be used for address generation.
  85. ADDRESS TYPES:
  86. {n_at}
  87. NOTES FOR ALL GENERATOR COMMANDS
  88. {n_sw}{n_pw}{n_bw}
  89. FMT CODES:
  90. {n_fmt}
  91. """
  92. },
  93. 'code': {
  94. 'options': lambda proto,help_notes,cfg,s: s.format(
  95. dmat=help_notes('dfl_mmtype'),
  96. kgs=help_notes('keygen_backends'),
  97. coin_id=help_notes('coin_id'),
  98. dsl=help_notes('dfl_seed_len'),
  99. pnm=gc.proj_name,
  100. what=gen_what,
  101. cfg=cfg,
  102. gc=gc,
  103. ),
  104. 'notes': lambda help_notes,s: s.format(
  105. n_addrkey=note_addrkey,
  106. n_sw=help_notes('subwallet')+'\n\n',
  107. n_pw=help_notes('passwd')+'\n\n',
  108. n_bw=help_notes('brainwallet'),
  109. n_fmt=help_notes('fmt_codes'),
  110. n_at=help_notes('address_types'),
  111. )
  112. }
  113. }
  114. cfg = Config( opts_data=opts_data, opt_filter=opt_filter, need_amt=False )
  115. proto = cfg._proto
  116. addr_type = MMGenAddrType(
  117. proto = proto,
  118. id_str = cfg.type or proto.dfl_mmtype,
  119. errmsg = f'{cfg.type!r}: invalid parameter for --type option' )
  120. if len(cfg._args) < 1:
  121. cfg._opts.usage()
  122. if cfg.keygen_backend:
  123. from .keygen import check_backend
  124. check_backend( cfg, proto, cfg.keygen_backend, cfg.type )
  125. idxs = mmgen.addrlist.AddrIdxList( fmt_str=cfg._args.pop() )
  126. from .fileutil import get_seed_file
  127. sf = get_seed_file(cfg,1)
  128. from .ui import do_license_msg
  129. do_license_msg(cfg)
  130. ss = Wallet(cfg,sf)
  131. ss_seed = ss.seed if cfg.subwallet is None else ss.seed.subseed(cfg.subwallet,print_msg=True)
  132. if cfg.no_addresses:
  133. gen_clsname = 'KeyList'
  134. al = getattr( mmgen.addrlist, gen_clsname )(
  135. cfg = cfg,
  136. proto = proto,
  137. seed = ss_seed,
  138. addr_idxs = idxs,
  139. mmtype = addr_type )
  140. af = al.get_file()
  141. af.format()
  142. if al.gen_addrs and cfg.print_checksum:
  143. Die(0,al.checksum)
  144. from .ui import keypress_confirm
  145. if al.gen_keys and keypress_confirm( cfg, 'Encrypt key list?' ):
  146. af.encrypt()
  147. af.write(
  148. binary = True,
  149. desc = f'encrypted {af.desc}' )
  150. else:
  151. af.write()