From 973c7be78d2fec8c37001ac2f973e4ec4304d55f Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Thu, 28 May 2020 10:13:37 +0000 Subject: [PATCH] string formatting, whitespace, minor fixes and cleanups throughout --- mmgen/crypto.py | 23 +++--- mmgen/globalvars.py | 6 +- mmgen/main_wallet.py | 36 ++++---- mmgen/opts.py | 2 +- mmgen/tool.py | 14 ++-- mmgen/wallet.py | 132 +++++++++++++++++++----------- test/tooltest.py | 3 - test/tooltest2.py | 6 +- test/unit_tests_d/ut_rpc.py | 20 +++-- test/unit_tests_d/ut_seedsplit.py | 2 +- 10 files changed, 143 insertions(+), 101 deletions(-) diff --git a/mmgen/crypto.py b/mmgen/crypto.py index 60d5ebe8..cd965d56 100755 --- a/mmgen/crypto.py +++ b/mmgen/crypto.py @@ -203,19 +203,18 @@ def add_user_random(rand_bytes,desc): else: return rand_bytes -def get_hash_preset_from_user(hp=g.hash_preset,desc='data'): - prompt = """Enter hash preset for {}, - or hit ENTER to accept the default value ('{}'): """.format(desc,hp) +def get_hash_preset_from_user(hp=g.dfl_hash_preset,desc='data'): + prompt = f'Enter hash preset for {desc},\n or hit ENTER to accept the default value ({hp!r}): ' while True: ret = my_raw_input(prompt) if ret: - if ret in g.hash_presets.keys(): + if ret in g.hash_presets: return ret else: - m = 'Invalid input. Valid choices are {}' - msg(m.format(', '.join(sorted(g.hash_presets.keys())))) + msg('Invalid input. Valid choices are {}'.format(', '.join(g.hash_presets))) continue - else: return hp + else: + return hp _salt_len,_sha256_len,_nonce_len = 32,32,32 @@ -226,15 +225,15 @@ def mmgen_encrypt(data,desc='data',hash_preset=''): hp = hash_preset or ( opt.hash_preset if 'hash_preset' in opt.set_by_user else get_hash_preset_from_user('3',desc)) m = ('user-requested','default')[hp=='3'] - vmsg('Encrypting {}'.format(desc)) - qmsg("Using {} hash preset of '{}'".format(m,hp)) + vmsg(f'Encrypting {desc}') + qmsg(f'Using {m} hash preset of {hp!r}') passwd = get_new_passphrase(desc,{}) key = make_key(passwd,salt,hp) enc_d = encrypt_data(sha256(nonce+data).digest() + nonce + data, key, iv, desc=desc) return salt+iv+enc_d def mmgen_decrypt(data,desc='data',hash_preset=''): - vmsg('Preparing to decrypt {}'.format(desc)) + vmsg(f'Preparing to decrypt {desc}') dstart = _salt_len + g.aesctr_iv_len salt = data[:_salt_len] iv = data[_salt_len:dstart] @@ -242,8 +241,8 @@ def mmgen_decrypt(data,desc='data',hash_preset=''): hp = hash_preset or ( opt.hash_preset if 'hash_preset' in opt.set_by_user else get_hash_preset_from_user('3',desc)) m = ('user-requested','default')[hp=='3'] - qmsg("Using {} hash preset of '{}'".format(m,hp)) - passwd = get_mmgen_passphrase(desc) + qmsg(f'Using {m} hash preset of {hp!r}') + passwd = get_passphrase(desc) key = make_key(passwd,salt,hp) dec_d = decrypt_data(enc_d,key,iv,desc) if dec_d[:_sha256_len] == sha256(dec_d[_sha256_len:]).digest(): diff --git a/mmgen/globalvars.py b/mmgen/globalvars.py index acfdd4fb..b6804aef 100755 --- a/mmgen/globalvars.py +++ b/mmgen/globalvars.py @@ -62,9 +62,9 @@ class GlobalContext: # Variables - these might be altered at runtime: - user_entropy = '' - hash_preset = '3' - usr_randchars = 30 + user_entropy = b'' + hash_preset = '3' + usr_randchars = 30 tx_fee_adj = Decimal('1.0') tx_confs = 3 diff --git a/mmgen/main_wallet.py b/mmgen/main_wallet.py index a9488d4c..1f2186a2 100755 --- a/mmgen/main_wallet.py +++ b/mmgen/main_wallet.py @@ -198,21 +198,27 @@ if invoked_as != 'gen': gmsg_r('Processing output wallet' + ('\n',' ')[invoked_as == 'seedsplit']) if invoked_as == 'subgen': - ss_out = Wallet(seed_bin=ss_in.seed.subseed(ss_idx,print_msg=True).data) + ss_out = Wallet( seed_bin = ss_in.seed.subseed(ss_idx,print_msg=True).data ) elif invoked_as == 'seedsplit': shares = ss_in.seed.split(sss.count,sss.id,master_share) seed_out = shares.get_share_by_idx(sss.idx,base_seed=True) msg(seed_out.get_desc(ui=True)) ss_out = Wallet(seed=seed_out) else: - ss_out = Wallet(ss=ss_in,passchg=invoked_as=='passchg') + ss_out = Wallet( + ss = ss_in, + passchg = invoked_as == 'passchg' ) if invoked_as == 'gen': - qmsg("This wallet's Seed ID: {}".format(ss_out.seed.sid.hl())) + qmsg(f"This wallet's Seed ID: {ss_out.seed.sid.hl()}") if invoked_as == 'passchg': - if not (opt.force_update or [k for k in ('passwd','hash_preset','label') - if getattr(ss_out.ssdata,k) != getattr(ss_in.ssdata,k)]): + def data_changed(attrs): + for attr in attrs: + if getattr(ss_out.ssdata,attr) != getattr(ss_in.ssdata,attr): + return True + return False + if not ( opt.force_update or data_changed(('passwd','hash_preset','label')) ): die(1,'Password, hash preset and label are unchanged. Taking no action') if invoked_as == 'passchg' and ss_in.infile.dirname == g.data_dir: @@ -226,18 +232,20 @@ if invoked_as == 'passchg' and ss_in.infile.dirname == g.data_dir: try: run(wipe_cmd + [ss_in.infile.name],check=True) except: - ymsg("WARNING: '{}' command failed, using regular file delete instead".format(wipe_cmd[0])) + ymsg(f'WARNING: {wipe_cmd[0]!r} command failed, using regular file delete instead') os.unlink(ss_in.infile.name) else: try: - assert invoked_as == 'gen','dw' - assert not opt.outdir,'dw' - assert not opt.stdout,'dw' - assert not find_file_in_dir(MMGenWallet,g.data_dir),'dw' - m = 'Make this wallet your default and move it to the data directory?' - assert keypress_confirm(m,default_yes=True),'dw' + assert invoked_as == 'gen', 'dw' + assert not opt.outdir, 'dw' + assert not opt.stdout, 'dw' + assert not find_file_in_dir( MMGenWallet, g.data_dir ), 'dw' + assert keypress_confirm( + 'Make this wallet your default and move it to the data directory?', + default_yes = True ), 'dw' except Exception as e: - if e.args[0] != 'dw': raise + if str(e) != 'dw': + raise ss_out.write_to_file() else: ss_out.write_to_file(outdir=g.data_dir) @@ -248,4 +256,4 @@ if invoked_as == 'passchg': else: msg('Wallet passphrase has changed') if ss_out.ssdata.hash_preset != ss_in.ssdata.hash_preset: - msg("Hash preset has been changed to '{}'".format(ss_out.ssdata.hash_preset)) + msg(f'Hash preset has been changed to {ss_out.ssdata.hash_preset!r}') diff --git a/mmgen/opts.py b/mmgen/opts.py index 6516d2e6..b5ed4297 100755 --- a/mmgen/opts.py +++ b/mmgen/opts.py @@ -31,7 +31,7 @@ import mmgen.share.Opts from .util import * def usage(): - Die(1,'USAGE: {} {}'.format(g.prog_name,usage_txt)) + Die(1,f'USAGE: {g.prog_name} {usage_txt}') def version(): Die(0,fmt(""" diff --git a/mmgen/tool.py b/mmgen/tool.py index c6b0260c..4b2ca9ab 100755 --- a/mmgen/tool.py +++ b/mmgen/tool.py @@ -636,11 +636,13 @@ class MMGenToolCmdFile(MMGenToolCmds): "utilities for viewing/checking MMGen address and transaction files" def _file_chksum(self,mmgen_addrfile,objname): + verbose = opt.verbose + opt.verbose = False opt.yes = True opt.quiet = True from .addr import AddrList,KeyAddrList,PasswordList ret = locals()[objname](self.proto,mmgen_addrfile) - if opt.verbose: + if verbose: if ret.al_id.mmtype.name == 'password': fs = 'Passwd fmt: {}\nPasswd len: {}\nID string: {}' msg(fs.format(capfirst(ret.pw_info[ret.pw_fmt].desc),ret.pw_len,ret.pw_id_str)) @@ -1117,15 +1119,17 @@ class MMGenToolCmdMonero(MMGenToolCmds): gmsg('\n{}ing {} wallet{}'.format(op.desc,dl,suf(dl))) from .daemon import MoneroWalletDaemon - wd = MoneroWalletDaemon(opt.outdir or '.',test_suite=g.test_suite) + wd = MoneroWalletDaemon( + wallet_dir = opt.outdir or '.', + test_suite = g.test_suite ) wd.restart() from .rpc import MoneroWalletRPCClient c = MoneroWalletRPCClient( - host = g.monero_wallet_rpc_host, + host = wd.host, port = wd.rpc_port, - user = g.monero_wallet_rpc_user, - passwd = g.monero_wallet_rpc_password) + user = wd.user, + passwd = wd.passwd ) wallets_processed = 0 for n,d in enumerate(data): # [d.sec,d.wallet_passwd,d.viewkey,d.addr] diff --git a/mmgen/wallet.py b/mmgen/wallet.py index 3e3eeda5..1f28cf92 100755 --- a/mmgen/wallet.py +++ b/mmgen/wallet.py @@ -30,8 +30,7 @@ from .seed import Seed def check_usr_seed_len(seed_len): if opt.seed_len != seed_len and 'seed_len' in opt.set_by_user: - m = "ERROR: requested seed length ({}) doesn't match seed length of source ({})" - die(1,m.format((opt.seed_len,seed_len))) + die(1,f"ERROR: requested seed length ({opt.seed_len}) doesn't match seed length of source ({seed_len})") def _is_mnemonic(s,fmt): oq_save = opt.quiet @@ -66,8 +65,15 @@ class Wallet(MMGenObject,metaclass=WalletMeta): class WalletData(MMGenObject): pass - def __new__(cls,fn=None,ss=None,seed_bin=None,seed=None, - passchg=False,in_data=None,ignore_in_fmt=False,in_fmt=None): + def __new__(cls, + fn = None, + ss = None, + seed_bin = None, + seed = None, + passchg = False, + in_data = None, + ignore_in_fmt = False, + in_fmt = None ): in_fmt = in_fmt or opt.in_fmt @@ -115,9 +121,17 @@ class Wallet(MMGenObject,metaclass=WalletMeta): return me - def __init__(self,fn=None,ss=None,seed_bin=None,seed=None, - passchg=False,in_data=None,ignore_in_fmt=False,in_fmt=None): + def __init__(self, + fn = None, + ss = None, + seed_bin = None, + seed = None, + passchg = False, + in_data = None, + ignore_in_fmt = False, + in_fmt = None ): + self.passwd_file = opt.passwd_file self.ssdata = self.WalletData() self.msg = {} self.in_data = in_data @@ -168,7 +182,7 @@ class Wallet(MMGenObject,metaclass=WalletMeta): while True: if self._decrypt(): break - if opt.passwd_file: + if self.passwd_file: die(2,'Passphrase from password file, so exiting') msg('Trying again...') @@ -295,20 +309,20 @@ an empty passphrase, just hit ENTER twice. if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'hash_preset'): old_hp = self.ss_in.ssdata.hash_preset if opt.keep_hash_preset: - qmsg("Reusing hash preset '{}' at user request".format(old_hp)) + qmsg(f'Reusing hash preset {old_hp!r} at user request') self.ssdata.hash_preset = old_hp elif 'hash_preset' in opt.set_by_user: hp = self.ssdata.hash_preset = opt.hash_preset - qmsg("Using hash preset '{}' requested on command line".format(opt.hash_preset)) + qmsg(f'Using hash preset {opt.hash_preset!r} requested on command line') else: # Prompt, using old value as default hp = self._get_hash_preset_from_user(old_hp,desc_suf) if (not opt.keep_hash_preset) and self.op == 'pwchg_new': - m = ("changed to '{}'".format(hp),'unchanged')[hp==old_hp] - qmsg('Hash preset {}'.format(m)) + m = (f'changed to {hp!r}','unchanged')[hp==old_hp] + qmsg(f'Hash preset {m}') elif 'hash_preset' in opt.set_by_user: self.ssdata.hash_preset = opt.hash_preset - qmsg("Using hash preset '{}' requested on command line".format(opt.hash_preset)) + qmsg(f'Using hash preset {opt.hash_preset!r} requested on command line') else: self._get_hash_preset_from_user(opt.hash_preset,desc_suf) @@ -318,21 +332,23 @@ an empty passphrase, just hit ENTER twice. ('','new ')[self.op in ('new','conv')], self.desc ) - if opt.passwd_file: - w = pwfile_reuse_warning() - pw = ' '.join(get_words_from_file(opt.passwd_file,desc,quiet=w)) + if self.passwd_file: + pw = ' '.join(get_words_from_file( + self.passwd_file, + desc, + quiet = pwfile_reuse_warning(self.passwd_file) )) elif opt.echo_passphrase: - pw = ' '.join(get_words_from_user('Enter {}: '.format(desc))) + pw = ' '.join(get_words_from_user(f'Enter {desc}: ')) else: for i in range(g.passwd_max_tries): - pw = ' '.join(get_words_from_user('Enter {}: '.format(desc))) - pw2 = ' '.join(get_words_from_user('Repeat passphrase: ')) - dmsg('Passphrases: [{}] [{}]'.format(pw,pw2)) - if pw == pw2: + pw = ' '.join(get_words_from_user(f'Enter {desc}: ')) + pw_chk = ' '.join(get_words_from_user('Repeat passphrase: ')) + dmsg(f'Passphrases: [{pw}] [{pw_chk}]') + if pw == pw_chk: vmsg('Passphrases match'); break else: msg('Passphrases do not match. Try again.') else: - die(2,'User failed to duplicate passphrase in {} attempts'.format(g.passwd_max_tries)) + die(2,f'User failed to duplicate passphrase in {g.passwd_max_tries} attempts') if pw == '': qmsg('WARNING: Empty passphrase') @@ -345,9 +361,11 @@ an empty passphrase, just hit ENTER twice. self.desc, ('',' '+desc_suf)[bool(desc_suf)] ) - if opt.passwd_file: - w = pwfile_reuse_warning() - ret = ' '.join(get_words_from_file(opt.passwd_file,desc,quiet=w)) + if self.passwd_file: + ret = ' '.join(get_words_from_file( + self.passwd_file, + desc, + quiet = pwfile_reuse_warning(self.passwd_file) )) else: ret = ' '.join(get_words_from_user('Enter {}: '.format(desc))) self.ssdata.passwd = ret @@ -691,11 +709,20 @@ class MMGenWallet(WalletEnc): desc = g.proj_name + ' wallet' ext = 'mmdat' + def __init__(self,*args,**kwargs): + if opt.label: + self.label = MMGenWalletLabel( + opt.label, + msg = "Error in option '--label'" ) + else: + self.label = None + super().__init__(*args,**kwargs) + def _get_label_from_user(self,old_lbl=''): - d = "to reuse the label '{}'".format(old_lbl.hl()) if old_lbl else 'for no label' - p = 'Enter a wallet label, or hit ENTER {}: '.format(d) + prompt = 'Enter a wallet label, or hit ENTER {}: '.format( + f'to reuse the label {old_lbl.hl()!r}' if old_lbl else 'for no label' ) while True: - msg_r(p) + msg_r(prompt) ret = my_raw_input('') if ret: self.ssdata.label = MMGenWalletLabel(ret,on_fail='return') @@ -713,20 +740,20 @@ class MMGenWallet(WalletEnc): if hasattr(self,'ss_in') and hasattr(self.ss_in.ssdata,'label'): old_lbl = self.ss_in.ssdata.label if opt.keep_label: - qmsg("Reusing label '{}' at user request".format(old_lbl.hl())) + qmsg(f'Reusing label {old_lbl.hl()!r} at user request') self.ssdata.label = old_lbl - elif opt.label: - qmsg("Using label '{}' requested on command line".format(opt.label.hl())) - lbl = self.ssdata.label = opt.label + elif self.label: + qmsg(f'Using label {self.label.hl()!r} requested on command line') + lbl = self.ssdata.label = self.label else: # Prompt, using old value as default lbl = self._get_label_from_user(old_lbl) if (not opt.keep_label) and self.op == 'pwchg_new': - m = ("changed to '{}'".format(lbl),'unchanged')[lbl==old_lbl] - qmsg('Label {}'.format(m)) - elif opt.label: - qmsg("Using label '{}' requested on command line".format(opt.label.hl())) - self.ssdata.label = opt.label + m = (f'changed to {lbl!r}','unchanged')[lbl==old_lbl] + qmsg(f'Label {m}') + elif self.label: + qmsg(f'Using label {self.label.hl()!r} requested on command line') + self.ssdata.label = self.label else: self._get_label_from_user() @@ -797,7 +824,7 @@ class MMGenWallet(WalletEnc): hash_params = list(map(int,hpdata[1:])) if hash_params != get_hash_params(d.hash_preset): - msg("Hash parameters '{}' don't match hash preset '{}'".format(' '.join(hash_params),d.hash_preset)) + msg(f"Hash parameters {' '.join(hash_params)!r} don't match hash preset {d.hash_preset!r}") return False lmin,foo,lmax = sorted(baseconv.seedlen_map_rev['b58']) # 22,33,44 @@ -866,19 +893,24 @@ class Brainwallet(WalletEnc): def _decrypt(self): d = self.ssdata - # Don't set opt.seed_len! In txsign, BW seed len might differ from other seed srcs if opt.brain_params: - seed_len,d.hash_preset = self.get_bw_params() + """ + Don't set opt.seed_len! When using multiple wallets, BW seed len might differ from others + """ + bw_seed_len,d.hash_preset = self.get_bw_params() else: if 'seed_len' not in opt.set_by_user: - m1 = 'Using default seed length of {} bits\n' - m2 = 'If this is not what you want, use the --seed-len option' - qmsg((m1+m2).format(yellow(str(opt.seed_len)))) + qmsg(f'Using default seed length of {yellow(str(opt.seed_len))} bits\n' + + 'If this is not what you want, use the --seed-len option' ) self._get_hash_preset() - seed_len = opt.seed_len + bw_seed_len = opt.seed_len qmsg_r('Hashing brainwallet data. Please wait...') # Use buflen arg of scrypt.hash() to get seed of desired length - seed = scrypt_hash_passphrase(self.brainpasswd.encode(),b'',d.hash_preset,buflen=seed_len//8) + seed = scrypt_hash_passphrase( + self.brainpasswd.encode(), + b'', + d.hash_preset, + buflen = bw_seed_len // 8 ) qmsg('Done') self.seed = Seed(seed) msg('Seed ID: {}'.format(self.seed.sid)) @@ -922,19 +954,19 @@ to exit and re-run the program with the '--old-incog-fmt' option. def _incog_data_size_chk(self): # valid sizes: 56, 64, 72 dlen = len(self.fmt_data) - valid_dlen = self._get_incog_data_len(opt.seed_len) + seed_len = opt.seed_len + valid_dlen = self._get_incog_data_len(seed_len) if dlen == valid_dlen: return True else: if opt.old_incog_fmt: msg('WARNING: old-style incognito format requested. Are you sure this is correct?') - m = 'Invalid incognito data size ({} bytes) for this seed length ({} bits)' - msg(m.format(dlen,opt.seed_len)) - msg('Valid data size for this seed length: {} bytes'.format(valid_dlen)) + msg(f'Invalid incognito data size ({dlen} bytes) for this seed length ({seed_len} bits)') + msg(f'Valid data size for this seed length: {valid_dlen} bytes') for sl in g.seed_lens: if dlen == self._get_incog_data_len(sl): - die(1,'Valid seed length for this data size: {} bits'.format(sl)) - msg('This data size ({} bytes) is invalid for all available seed lengths'.format(dlen)) + die(1,f'Valid seed length for this data size: {sl} bits') + msg(f'This data size ({dlen} bytes) is invalid for all available seed lengths') return False def _encrypt (self): diff --git a/test/tooltest.py b/test/tooltest.py index abeac04b..e10cb211 100755 --- a/test/tooltest.py +++ b/test/tooltest.py @@ -360,11 +360,8 @@ class MMGenToolTestCmds(object): def pubhex2redeem_script(self,name,f1,f2,f3): # from above addr = read_from_file(f3).strip() tu.run_cmd_out(name,addr,add_opts=type_segwit_arg,fn_idx=3) - type_save = opt.type - opt.type = 'segwit' rs = read_from_tmpfile(cfg,'privhex2pubhex3.out').strip() tu.run_cmd_out('pubhex2addr',rs,add_opts=type_segwit_arg,fn_idx=3,hush=True) - opt.type = type_save addr1 = read_from_tmpfile(cfg,'pubhex2addr3.out').strip() addr2 = read_from_tmpfile(cfg,'randpair3.out').split()[1] cmp_or_die(addr1,addr2) diff --git a/test/tooltest2.py b/test/tooltest2.py index 16a3b5bf..1cd0dbb2 100755 --- a/test/tooltest2.py +++ b/test/tooltest2.py @@ -953,11 +953,11 @@ async def do_group(gid): continue await run_test(gid,cname) -def do_cmd_in_group(cmd): +async def do_cmd_in_group(cmd): for gid in tests: for cname in tests[gid]: if cname == cmd: - run_test(gid,cname) + await run_test(gid,cname) return True return False @@ -1026,7 +1026,7 @@ async def main(): if cmd in tests: await do_group(cmd) else: - if not do_cmd_in_group(cmd): + if not await do_cmd_in_group(cmd): die(1,f'{cmd!r}: not a recognized test or test group') else: for garg in tests: diff --git a/test/unit_tests_d/ut_rpc.py b/test/unit_tests_d/ut_rpc.py index 04285a87..1cb02bad 100755 --- a/test/unit_tests_d/ut_rpc.py +++ b/test/unit_tests_d/ut_rpc.py @@ -92,22 +92,24 @@ class unit_tests: if not opt.no_daemon_autostart: md.start() - g.monero_wallet_rpc_password = 'passwOrd' - mwd = MoneroWalletDaemon(wallet_dir='test/trash',test_suite=True) - mwd.start() + wd = MoneroWalletDaemon( + wallet_dir = 'test/trash', + passwd = 'ut_rpc_passw0rd', + test_suite = True ) + wd.start() c = MoneroWalletRPCClient( - host = g.monero_wallet_rpc_host, - port = mwd.rpc_port, - user = g.monero_wallet_rpc_user, - passwd = g.monero_wallet_rpc_password) + host = wd.host, + port = wd.rpc_port, + user = wd.user, + passwd = wd.passwd ) await c.call('get_version') gmsg('OK') - mwd.wait = False - mwd.stop() + wd.wait = False + wd.stop() if not opt.no_daemon_stop: md.wait = False diff --git a/test/unit_tests_d/ut_seedsplit.py b/test/unit_tests_d/ut_seedsplit.py index b4a7f613..4fc980c6 100755 --- a/test/unit_tests_d/ut_seedsplit.py +++ b/test/unit_tests_d/ut_seedsplit.py @@ -11,7 +11,7 @@ class unit_test(object): from mmgen.seed import Seed,SeedShareList from mmgen.obj import SeedShareIdx - g.debug_subseed = opt.verbose + g.debug_subseed = bool(opt.verbose) def basic_ops(master_idx): test_data = {