globalvars.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #!/usr/bin/env python3
  2. #
  3. # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
  4. # Copyright (C)2013-2021 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. globalvars.py: Constants and configuration options for the MMGen suite
  20. """
  21. import sys,os
  22. from decimal import Decimal
  23. from collections import namedtuple
  24. from .devtools import *
  25. from .base_obj import Lockable
  26. def die(exit_val,s=''):
  27. if s:
  28. sys.stderr.write(s+'\n')
  29. sys.exit(exit_val)
  30. class GlobalContext(Lockable):
  31. """
  32. Set global vars to default values
  33. Globals are overridden in this order:
  34. 1 - config file
  35. 2 - environmental vars
  36. 3 - command line
  37. """
  38. _set_ok = ('user_entropy','session')
  39. _reset_ok = ('stdout','stderr','accept_defaults')
  40. _use_class_attr = True
  41. # Constants:
  42. version = '0.12.199'
  43. release_date = 'February 2021'
  44. proj_name = 'MMGen'
  45. proj_url = 'https://github.com/mmgen/mmgen'
  46. prog_name = os.path.basename(sys.argv[0])
  47. author = 'The MMGen Project'
  48. email = '<mmgen@tuta.io>'
  49. Cdates = '2013-2021'
  50. keywords = 'Bitcoin, BTC, Ethereum, ETH, Monero, XMR, ERC20, cryptocurrency, wallet, BIP32, cold storage, offline, online, spending, open-source, command-line, Python, Linux, Bitcoin Core, bitcoind, hd, deterministic, hierarchical, secure, anonymous, Electrum, seed, mnemonic, brainwallet, Scrypt, utility, script, scriptable, blockchain, raw, transaction, permissionless, console, terminal, curses, ansi, color, tmux, remote, client, daemon, RPC, json, entropy, xterm, rxvt, PowerShell, MSYS, MSYS2, MinGW, MinGW64, MSWin, Armbian, Raspbian, Raspberry Pi, Orange Pi, BCash, BCH, Litecoin, LTC, altcoin, ZEC, Zcash, DASH, Dashpay, SHA256Compress, monerod, EMC, Emercoin, token, deploy, contract, gas, fee, smart contract, solidity, Parity, OpenEthereum, testnet, devmode, Kovan'
  51. max_int = 0xffffffff
  52. stdin_tty = sys.stdin.isatty()
  53. stdout = sys.stdout
  54. stderr = sys.stderr
  55. http_timeout = 60
  56. err_disp_timeout = 0.7
  57. short_disp_timeout = 0.3
  58. min_time_precision = 18
  59. # Variables - these might be altered at runtime:
  60. user_entropy = b''
  61. dfl_hash_preset = '3'
  62. dfl_seed_len = 256
  63. usr_randchars = 30
  64. tx_fee_adj = Decimal('1.0')
  65. tx_confs = 3
  66. # Constant vars - some of these might be overridden in opts.py, but they don't change thereafter
  67. coin = ''
  68. token = ''
  69. debug = False
  70. debug_opts = False
  71. debug_rpc = False
  72. debug_addrlist = False
  73. debug_subseed = False
  74. quiet = False
  75. no_license = False
  76. force_256_color = False
  77. testnet = False
  78. regtest = False
  79. accept_defaults = False
  80. use_internal_keccak_module = False
  81. # rpc:
  82. rpc_host = ''
  83. rpc_port = 0
  84. rpc_user = ''
  85. rpc_password = ''
  86. ignore_daemon_version = False
  87. monero_wallet_rpc_host = 'localhost'
  88. monero_wallet_rpc_user = 'monero'
  89. monero_wallet_rpc_password = ''
  90. rpc_fail_on_command = ''
  91. aiohttp_rpc_queue_len = 16
  92. session = None
  93. cached_balances = False
  94. # regtest:
  95. bob = False
  96. alice = False
  97. # test suite:
  98. bogus_wallet_data = ''
  99. bogus_send = False
  100. debug_utf8 = False
  101. traceback = False
  102. test_suite = False
  103. test_suite_regtest = False
  104. test_suite_popen_spawn = False
  105. terminal_width = 0
  106. mnemonic_entry_modes = {}
  107. color = bool(
  108. ( sys.stdout.isatty() and not os.getenv('MMGEN_TEST_SUITE_PEXPECT') ) or
  109. os.getenv('MMGEN_FORCE_COLOR')
  110. )
  111. for k in ('linux','win','msys'):
  112. if sys.platform[:len(k)] == k:
  113. platform = { 'linux':'linux', 'win':'win', 'msys':'win' }[k]
  114. break
  115. else:
  116. die(1,f'{sys.platform!r}: platform not supported by {proj_name}')
  117. if os.getenv('HOME'): # Linux or MSYS2
  118. home_dir = os.getenv('HOME')
  119. elif platform == 'win': # Windows without MSYS2 - not supported
  120. die(1,f'$HOME not set! {proj_name} for Windows must be run in MSYS2 environment')
  121. else:
  122. die(2,'$HOME is not set! Unable to determine home directory')
  123. # https://wiki.debian.org/Python:
  124. # Debian (Ubuntu) sys.prefix is '/usr' rather than '/usr/local, so add 'local'
  125. # This must match the configuration in setup.py
  126. shared_data_path = os.path.join(
  127. sys.prefix,
  128. *(['local','share'] if platform == 'linux' else ['share']),
  129. proj_name.lower()
  130. )
  131. data_dir_root,data_dir,cfg_file = None,None,None
  132. daemon_data_dir = '' # set by user
  133. # global var sets user opt:
  134. global_sets_opt = (
  135. 'minconf','usr_randchars','debug', 'quiet','tx_confs','tx_fee_adj','key_generator' )
  136. # user opt sets global var:
  137. opt_sets_global = (
  138. 'use_internal_keccak_module','subseeds','cached_balances' )
  139. # 'long' opts - opt sets global var
  140. common_opts = (
  141. 'color','no_license','testnet',
  142. 'rpc_host','rpc_port','rpc_user','rpc_password','rpc_backend','aiohttp_rpc_queue_len',
  143. 'monero_wallet_rpc_host','monero_wallet_rpc_user','monero_wallet_rpc_password',
  144. 'daemon_data_dir','force_256_color','regtest','coin','bob','alice',
  145. 'accept_defaults','token','ignore_daemon_version'
  146. )
  147. # opts initialized to None by opts.init() if not set by user
  148. required_opts = (
  149. 'quiet','verbose','debug','outdir','echo_passphrase','passwd_file','stdout',
  150. 'show_hash_presets','label','keep_passphrase','keep_hash_preset','yes',
  151. 'brain_params','b16','usr_randchars','coin','bob','alice','key_generator',
  152. 'hidden_incog_input_params','in_fmt','hash_preset','seed_len',
  153. )
  154. incompatible_opts = (
  155. ('help','longhelp'),
  156. ('bob','alice'),
  157. ('label','keep_label'),
  158. ('tx_id','info'),
  159. ('tx_id','terse_info'),
  160. ('batch','rescan'), # TODO: still incompatible?
  161. )
  162. cfg_file_opts = (
  163. 'color','debug','hash_preset','http_timeout','no_license','rpc_host','rpc_port',
  164. 'quiet','tx_fee_adj','usr_randchars','testnet','rpc_user','rpc_password',
  165. 'monero_wallet_rpc_host','monero_wallet_rpc_user','monero_wallet_rpc_password',
  166. 'daemon_data_dir','force_256_color','regtest','subseeds','mnemonic_entry_modes',
  167. 'btc_max_tx_fee','ltc_max_tx_fee','bch_max_tx_fee','eth_max_tx_fee',
  168. 'btc_ignore_daemon_version','bch_ignore_daemon_version','ltc_ignore_daemon_version',
  169. 'eth_ignore_daemon_version','etc_ignore_daemon_version',
  170. 'eth_mainnet_chain_name','eth_testnet_chain_name',
  171. 'max_tx_file_size','max_input_size'
  172. )
  173. # Supported environmental vars
  174. # The corresponding vars (lowercase, minus 'mmgen_') must be initialized in g
  175. # 'DISABLE_' env vars disable the corresponding var in g
  176. env_opts = (
  177. 'MMGEN_DEBUG_ALL', # special: there is no g.debug_all var
  178. 'MMGEN_TEST_SUITE',
  179. 'MMGEN_TEST_SUITE_REGTEST',
  180. 'MMGEN_TEST_SUITE_POPEN_SPAWN',
  181. 'MMGEN_TERMINAL_WIDTH',
  182. 'MMGEN_BOGUS_WALLET_DATA',
  183. 'MMGEN_BOGUS_SEND',
  184. 'MMGEN_DEBUG',
  185. 'MMGEN_DEBUG_OPTS',
  186. 'MMGEN_DEBUG_RPC',
  187. 'MMGEN_DEBUG_ADDRLIST',
  188. 'MMGEN_DEBUG_UTF8',
  189. 'MMGEN_DEBUG_SUBSEED',
  190. 'MMGEN_QUIET',
  191. 'MMGEN_FORCE_256_COLOR',
  192. 'MMGEN_MIN_URANDCHARS',
  193. 'MMGEN_NO_LICENSE',
  194. 'MMGEN_RPC_HOST',
  195. 'MMGEN_RPC_FAIL_ON_COMMAND',
  196. 'MMGEN_TESTNET',
  197. 'MMGEN_REGTEST',
  198. 'MMGEN_TRACEBACK',
  199. 'MMGEN_RPC_BACKEND',
  200. 'MMGEN_IGNORE_DAEMON_VERSION',
  201. 'MMGEN_USE_STANDALONE_SCRYPT_MODULE',
  202. 'MMGEN_DISABLE_COLOR',
  203. 'MMGEN_DISABLE_MSWIN_PW_WARNING',
  204. )
  205. infile_opts = (
  206. 'keys_from_file',
  207. 'mmgen_keys_from_file',
  208. 'passwd_file',
  209. 'keysforaddrs',
  210. 'comment_file',
  211. 'contract_data',
  212. )
  213. # Auto-typechecked and auto-set opts. These have no corresponding value in g.
  214. # First value in list is the default
  215. ov = namedtuple('autoset_opt_info',['type','choices'])
  216. autoset_opts = {
  217. 'fee_estimate_mode': ov('nocase_pfx', ['conservative','economical']),
  218. 'rpc_backend': ov('nocase_pfx', ['auto','httplib','curl','aiohttp','requests']),
  219. }
  220. if platform == 'win':
  221. autoset_opts['rpc_backend'].choices.remove('aiohttp')
  222. _skip_type_check = ('stdout','stderr')
  223. auto_typeset_opts = {
  224. 'seed_len': int,
  225. }
  226. min_screen_width = 80
  227. minconf = 1
  228. max_tx_file_size = 100000
  229. max_input_size = 1024 * 1024
  230. passwd_max_tries = 5
  231. max_urandchars = 80
  232. min_urandchars = 10
  233. seed_lens = 128,192,256
  234. scramble_hash_rounds = 10
  235. subseeds = 100
  236. mmenc_ext = 'mmenc'
  237. salt_len = 16
  238. aesctr_iv_len = 16
  239. aesctr_dfl_iv = int.to_bytes(1,aesctr_iv_len,'big')
  240. hincog_chk_len = 8
  241. key_generators = ('python-ecdsa','libsecp256k1') # '1','2'
  242. key_generator = 2 # libsecp256k1 is default
  243. force_standalone_scrypt_module = False
  244. # Scrypt params: 'id_num': [N, p, r] (N is an exponent of two)
  245. # NB: hashlib.scrypt in Python (>=v3.6) supports max N value of 14. This means that
  246. # for hash presets > 3 the standalone scrypt library must be used!
  247. hash_presets = {
  248. '1': [12, 8, 1],
  249. '2': [13, 8, 4],
  250. '3': [14, 8, 8],
  251. '4': [15, 8, 12],
  252. '5': [16, 8, 16],
  253. '6': [17, 8, 20],
  254. '7': [18, 8, 24],
  255. }
  256. if os.getenv('MMGEN_TEST_SUITE'):
  257. err_disp_timeout = 0.1
  258. short_disp_timeout = 0.1
  259. if os.getenv('MMGEN_TEST_SUITE_POPEN_SPAWN'):
  260. stdin_tty = True
  261. if prog_name == 'unit_tests.py':
  262. _set_ok += ('debug_subseed',)
  263. _reset_ok += ('force_standalone_scrypt_module','session')
  264. if os.getenv('MMGEN_DEBUG_ALL'):
  265. for name in env_opts:
  266. if name[:11] == 'MMGEN_DEBUG':
  267. os.environ[name] = '1'
  268. g = GlobalContext()