main_addrgen.py 5.7 KB

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