From b230b43d4bba77c2e78a515a1ea64b8cb64706f1 Mon Sep 17 00:00:00 2001 From: MMGen Date: Fri, 9 Mar 2018 11:29:58 +0000 Subject: [PATCH] MMGEN_DEBUG_ALL env var; tw display and other fixes --- mmgen/addr.py | 4 ++-- mmgen/common.py | 8 ++++++- mmgen/crypto.py | 4 ++-- mmgen/globalvars.py | 1 + mmgen/main_wallet.py | 22 ++++++++++-------- mmgen/opts.py | 7 +++++- mmgen/tw.py | 22 +++++++++--------- test/mmgen_pexpect.py | 2 +- test/test.py | 52 ++++++++++++++++++++++++++++--------------- 9 files changed, 78 insertions(+), 44 deletions(-) diff --git a/mmgen/addr.py b/mmgen/addr.py index 7c86de6c..6613a98b 100755 --- a/mmgen/addr.py +++ b/mmgen/addr.py @@ -28,7 +28,7 @@ from mmgen.obj import * pnm = g.proj_name def dmsg_sc(desc,data): - if g.debug_addrlist: Msg('sc_debug_{}: {}'.format(desc,data)) + if g.debug_addrlist: Msg(u'sc_debug_{}: {}'.format(desc,data)) class AddrGenerator(MMGenObject): def __new__(cls,addr_type): @@ -446,7 +446,7 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file dmsg('Key {:>03}: {}'.format(pos,e.passwd)) out.append(e) - if g.debug: Msg('generate():\n{}'.format(e.pformat())) + if g.debug_addrlist: Msg('generate():\n{}'.format(e.pformat())) qmsg('\r{}: {} {}{} generated{}'.format( self.al_id.hl(),t_addrs,self.gen_desc,suf(t_addrs,self.gen_desc_pl),' '*15)) diff --git a/mmgen/common.py b/mmgen/common.py index 9973badd..93e14ac2 100755 --- a/mmgen/common.py +++ b/mmgen/common.py @@ -20,12 +20,18 @@ common.py: Common imports for all MMGen scripts """ -import sys +import sys,os from mmgen.globalvars import g import mmgen.opts as opts from mmgen.opts import opt from mmgen.util import * +def set_debug_all(): + if os.getenv('MMGEN_DEBUG_ALL'): + for name in g.env_opts: + if name[:11] == 'MMGEN_DEBUG': + os.environ[name] = '1' + def help_notes(k): from mmgen.seed import SeedSource return { diff --git a/mmgen/crypto.py b/mmgen/crypto.py index c1e6b9ab..ae85ee59 100755 --- a/mmgen/crypto.py +++ b/mmgen/crypto.py @@ -45,8 +45,8 @@ def sha256_rounds(s,n): def scramble_seed(seed,scramble_key,hash_rounds): import hmac scr_seed = hmac.new(seed,scramble_key,sha256).digest() - fs = 'Seed: {}\nScramble key: {}\nScrambled seed: {}' - dmsg(fs.format(hexlify(seed),scramble_key,hexlify(scr_seed))) + fs = u'Seed: {}\nScramble key: {}\nScrambled seed: {}' + dmsg(fs.format(hexlify(seed),scramble_key.decode('utf8'),hexlify(scr_seed))) return sha256_rounds(scr_seed,hash_rounds) def encrypt_seed(seed,key): diff --git a/mmgen/globalvars.py b/mmgen/globalvars.py index ffb1c546..4054dc38 100755 --- a/mmgen/globalvars.py +++ b/mmgen/globalvars.py @@ -138,6 +138,7 @@ class g(object): ) env_opts = ( 'MMGEN_BOGUS_WALLET_DATA', + 'MMGEN_DEBUG_ALL', 'MMGEN_DEBUG', 'MMGEN_DEBUG_OPTS', 'MMGEN_DEBUG_RPC', diff --git a/mmgen/main_wallet.py b/mmgen/main_wallet.py index db7e3e98..7d7b82f9 100755 --- a/mmgen/main_wallet.py +++ b/mmgen/main_wallet.py @@ -142,11 +142,9 @@ if invoked_as == 'passchg': if getattr(ss_out.ssdata,k) != getattr(ss_in.ssdata,k)]): die(1,'Password, hash preset and label are unchanged. Taking no action') -m1 = yellow('Confirmation of default wallet update') -m2 = 'update the default wallet' -m3 = 'Make this wallet your default and move it to the data directory?' - if invoked_as == 'passchg' and ss_in.infile.dirname == g.data_dir: + m1 = yellow('Confirmation of default wallet update') + m2 = 'update the default wallet' confirm_or_exit(m1,m2,exit_msg='Password not changed') ss_out.write_to_file(desc='New wallet',outdir=g.data_dir) msg('Securely deleting old wallet') @@ -156,13 +154,19 @@ if invoked_as == 'passchg' and ss_in.infile.dirname == g.data_dir: check_output(sd_cmd + [ss_in.infile.name]) except: ymsg("WARNING: '{}' command failed, using regular file delete instead".format(sd_cmd[0])) -# msg('Command output: {}\nReturn value {}'.format(e.output,e.returncode)) os.unlink(ss_in.infile.name) -elif invoked_as == 'gen' and not find_file_in_dir(Wallet,g.data_dir) \ - and not opt.stdout and keypress_confirm(m3,default_yes=True): - ss_out.write_to_file(outdir=g.data_dir) else: - ss_out.write_to_file() + try: + assert invoked_as == 'gen','dw' + assert not opt.stdout,'dw' + assert not find_file_in_dir(Wallet,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' + except Exception as e: + if e[0] != 'dw': raise + ss_out.write_to_file() + else: + ss_out.write_to_file(outdir=g.data_dir) if invoked_as == 'passchg': if ss_out.ssdata.passwd == ss_in.ssdata.passwd: diff --git a/mmgen/opts.py b/mmgen/opts.py index 3e04bb64..834b6d25 100755 --- a/mmgen/opts.py +++ b/mmgen/opts.py @@ -58,7 +58,6 @@ def opt_preproc_debug(short_opts,long_opts,skipped_opts,uopts,args): for e in d: Msg(' {:<20}: {}'.format(*e)) def opt_postproc_debug(): - opt.verbose,opt.quiet = True,None a = [k for k in dir(opt) if k[:2] != '__' and getattr(opt,k) != None] b = [k for k in dir(opt) if k[:2] != '__' and getattr(opt,k) == None] Msg(' Opts after processing:') @@ -164,6 +163,7 @@ def override_from_cfg_file(cfg_data): def override_from_env(): from mmgen.util import set_for_type for name in g.env_opts: + if name == 'MMGEN_DEBUG_ALL': continue idx,invert_bool = ((6,False),(14,True))[name[:14]=='MMGEN_DISABLE_'] val = os.getenv(name) # os.getenv() returns None if env var is unset if val: # exclude empty string values too @@ -237,6 +237,9 @@ def init(opts_f,add_opts=[],opt_filter=None): if opt.version: Die(0,version_info) + from mmgen.common import set_debug_all + set_debug_all() + # === Interaction with global vars begins here === # NB: user opt --data-dir is actually g.data_dir_root @@ -313,6 +316,8 @@ def init(opts_f,add_opts=[],opt_filter=None): ymsg("Warning: config file options have changed! See '{}' for details".format(g.cfg_file+'.sample')) my_raw_input('Hit ENTER to continue: ') + if g.debug and g.prog_name != 'test.py': + opt.verbose,opt.quiet = True,None if g.debug_opts: opt_postproc_debug() # We don't need this data anymore diff --git a/mmgen/tw.py b/mmgen/tw.py index c8020a57..fe31dff8 100755 --- a/mmgen/tw.py +++ b/mmgen/tw.py @@ -104,7 +104,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program. 'age': lambda i: 0 - i.confs, 'amt': lambda i: i.amt, 'txid': lambda i: '{} {:04}'.format(i.txid,i.vout), - 'mmid': lambda i: i.twmmid.sort_key + 'twmmid': lambda i: i.twmmid.sort_key } key = key or self.sort_key if key not in sort_funcs: @@ -142,12 +142,14 @@ watch-only wallet using '{}-addrimport' and then re-run this program. col1_w = max(3,len(str(len(unsp)))+1) # num + ')' mmid_w = max(len(('',i.twmmid)[i.twmmid.type=='mmgen']) for i in unsp) or 12 # DEADBEEF:S:1 max_acct_w = max(len(i.label) for i in unsp) + mmid_w + 1 - addr_w = min(max(len(i.addr) for i in unsp)+(0,1+max_acct_w)[self.show_mmid],self.cols-45) - acct_w = min(max_acct_w, max(24,int(addr_w-10))) + max_btcaddr_w = max(len(i.addr) for i in unsp) + min_addr_w = self.cols - 38 + addr_w = min(max_btcaddr_w + (0,1+max_acct_w)[self.show_mmid],min_addr_w) + acct_w = min(max_acct_w, max(24,addr_w-10)) btaddr_w = addr_w - acct_w - 1 label_w = acct_w - mmid_w - 1 - tx_w = max(11,min(64, self.cols-addr_w-28-col1_w)) - txdots = ('','...')[tx_w < 64] + tx_w = min(64,self.cols-addr_w-28-col1_w) # min=7 + txdots = ('','..')[tx_w < 64] for i in unsp: i.skip = None if self.group and (self.sort_key in ('addr','txid','twmmid')): @@ -162,13 +164,13 @@ watch-only wallet using '{}-addrimport' and then re-run this program. out += [green('Chain: {}'.format(g.chain.upper()))] fs = ' {:%s} {:%s} {:2} {} {} {:<}' % (col1_w,tx_w) out += [fs.format('Num', - 'TX id'.ljust(tx_w - 5) + ' Vout', '', - 'Address'.ljust(addr_w+3), - 'Amt({})'.format(g.coin).ljust(10), + 'TXid'.ljust(tx_w - 5) + ' Vout', '', + 'Address'.ljust(addr_w), + 'Amt({})'.format(g.coin).ljust(12), ('Confs','Age(d)')[self.show_days])] for n,i in enumerate(unsp): - addr_dots = '|' + '.'*33 + addr_dots = '|' + '.'*(addr_w-1) mmid_disp = MMGenID.fmtc('.'*mmid_w if i.skip=='addr' else i.twmmid if i.twmmid.type=='mmgen' else 'Non-{}'.format(g.proj_name),width=mmid_w,color=True) @@ -284,7 +286,7 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen msg('{}\n{}\n{}'.format(self.fmt_display,prompt,p)) else: msg('Label could not be added\n{}\n{}'.format(prompt,p)) - elif reply == 'M': self.do_sort('mmid'); self.show_mmid = True + elif reply == 'M': self.do_sort('twmmid'); self.show_mmid = True elif reply == 'm': self.show_mmid = not self.show_mmid elif reply == 'p': msg('') diff --git a/test/mmgen_pexpect.py b/test/mmgen_pexpect.py index c033bd2e..b7691df0 100755 --- a/test/mmgen_pexpect.py +++ b/test/mmgen_pexpect.py @@ -67,7 +67,7 @@ def my_expect(p,s,t='',delay=send_delay,regex=False,nonl=False,silent=False): sys.exit(1) debug_pexpect_msg(p) - if opt.debug or (opt.verbose and type(s) != str): + if opt.verbose and type(s) != str: msg_r(' ==> {} '.format(ret)) if ret == -1: diff --git a/test/test.py b/test/test.py index 4d428d89..5e8ecd1f 100755 --- a/test/test.py +++ b/test/test.py @@ -31,6 +31,8 @@ from mmgen.common import * from mmgen.test import * from mmgen.protocol import CoinProtocol +set_debug_all() + g.quiet = False # if 'quiet' was set in config file, disable here os.environ['MMGEN_QUIET'] = '0' # and for the spawned scripts @@ -115,7 +117,6 @@ opts_data = lambda: { -b, --buf-keypress Use buffered keypresses as with real human input -c, --print-cmdline Print the command line of each spawned command -C, --coverage Produce code coverage info using trace module --d, --debug-scripts Turn on debugging output in executed scripts -x, --debug-pexpect Produce debugging output for pexpect calls -D, --direct-exec Bypass pexpect and execute a command directly (for debugging only) @@ -182,12 +183,17 @@ def randbool(): return hexlify(os.urandom(1))[1] in '12345678' def get_segwit_bool(): return randbool() if opt.segwit_random else True if opt.segwit or opt.bech32 else False + def disable_debug(): - ds = os.getenv('MMGEN_DEBUG') - if ds is not None: os.environ['MMGEN_DEBUG'] = '' - return ds -def restore_debug(ds): - if ds is not None: os.environ['MMGEN_DEBUG'] = ds + global save_debug + save_debug = {} + for k in g.env_opts: + if k[:11] == 'MMGEN_DEBUG': + save_debug[k] = os.getenv(k) + os.environ[k] = '' +def restore_debug(): + for k in save_debug: + os.environ[k] = save_debug[k] or '' cfgs = { '15': { @@ -957,8 +963,6 @@ def get_segwit_arg(cfg): # Tell spawned programs they're running in the test suite os.environ['MMGEN_TEST_SUITE'] = '1' -if opt.debug_scripts: os.environ['MMGEN_DEBUG'] = '1' - if opt.exact_output: def msg(s): pass vmsg = vmsg_r = msg_r = msg @@ -1099,7 +1103,7 @@ def create_fake_unspent_entry(coinaddr,al_id=None,idx=None,lbl=None,non_mmgen=Fa 'address': coinaddr, 'spendable': False, 'scriptPubKey': '{}{}{}'.format(spk_beg,coinaddr.hex,spk_end), - 'confirmations': getrandnum(4) % 50000 + 'confirmations': getrandnum(3) / 2 # max: 8388608 (7 digits) } labels = [ @@ -1479,7 +1483,7 @@ class MMGenTestSuite(object): def walletchk(self,name,wf,pf,desc='MMGen wallet',add_args=[],sid=None,pw=False,extra_desc=''): args = [] hp = cfg['hash_preset'] if 'hash_preset' in cfg else '1' - wf_arg = ([],[wf])[bool(wf)] + wf_arg = [wf] if wf else [] t = MMGenExpect(name,'mmgen-walletchk', add_args+args+['-p',hp]+wf_arg, extra_desc=extra_desc) @@ -1520,7 +1524,7 @@ class MMGenTestSuite(object): extra_args + ([],['--type='+str(mmtype)])[bool(mmtype)] + ([],[wf])[bool(wf)] + - ([],[id_str])[bool(id_str)] + + ([id_str] if id_str else []) + [cfg['{}_idx_list'.format(cmd_pfx)]], extra_desc='({})'.format(mmtype) if mmtype in ('segwit','bech32') else '') t.license() @@ -1563,7 +1567,7 @@ class MMGenTestSuite(object): vmsg('This is a simulation, so no addresses were actually imported into the tracking\nwallet') t.ok(exit_val=1) - def txcreate_common(self, name, + def txcreate_common(self,name, sources=['1'], non_mmgen_input='', do_label=False, @@ -1610,6 +1614,10 @@ class MMGenTestSuite(object): for num in tx_data: t.expect('Continue anyway? (y/N): ','y') t.expect(r"'q'=quit view, .*?:.",'M', regex=True) + if name == 'txcreate': + t.expect(r"'q'=quit view, .*?:.",'D', regex=True) + t.expect(r"'q'=quit view, .*?:.",'m', regex=True) + t.expect(r"'q'=quit view, .*?:.",'g', regex=True) t.expect(r"'q'=quit view, .*?:.",'q', regex=True) outputs_list = [(addrs_per_wallet+1)*i + 1 for i in range(len(tx_data))] if non_mmgen_input: outputs_list.append(len(tx_data)*(addrs_per_wallet+1) + 1) @@ -1649,7 +1657,10 @@ class MMGenTestSuite(object): t.expect('Edit transaction comment? (y/N): ','\n') for cnum,desc in (('1','incognito data'),('3','MMGen wallet'),('4','MMGen wallet')): t.passphrase(desc,cfgs[cnum]['wpasswd']) - t.expect("Type uppercase 'YES' to confirm: ",'YES\n') + m = ('YES','YES, I REALLY WANT TO DO THIS')[g.debug] + t.expect("'{}' to confirm: ".format(m),m+'\n') + if g.debug: + t.written_to_file('Transaction') else: t.expect('Add a comment to transaction? (y/N): ','\n') t.expect('Save transaction? (y/N): ','y') @@ -2277,9 +2288,10 @@ class MMGenTestSuite(object): def ref_tool_decrypt(self,name): f = os.path.join(ref_dir,ref_enc_fn) + disable_debug() t = MMGenExpect(name,'mmgen-tool', ['-q','decrypt',f,'outfile=-','hash_preset=1']) + restore_debug() t.passphrase('user data',tool_enc_passwd) -# t.expect("Type uppercase 'YES' to confirm: ",'YES\n') # comment out with popen_spawn t.expect(NL,nonl=True) import re o = re.sub('\r\n','\n',t.read()) @@ -2399,6 +2411,8 @@ class MMGenTestSuite(object): fn = os.path.join(self.regtest_user_dir(user), '{}{}{}[{}].addrs'.format(sid,altcoin_pfx,id_strs[desc],addr_range)) t = MMGenExpect(name,'mmgen-addrimport', ['--quiet','--'+user,'--batch',fn],extra_desc='('+desc+')') + if g.debug: + t.expect("Type uppercase 'YES' to confirm: ",'YES\n') t.expect('Importing') t.expect('{} addresses imported'.format(num_addrs)) t.ok() @@ -2564,9 +2578,9 @@ class MMGenTestSuite(object): t.ok() def regtest_get_mempool(self,name): - ds = disable_debug() + disable_debug() ret = MMGenExpect(name,'mmgen-regtest',['show_mempool']).read() - restore_debug(ds) + restore_debug() from ast import literal_eval return literal_eval(ret) @@ -2590,13 +2604,13 @@ class MMGenTestSuite(object): @staticmethod def gen_pairs(n): - ds = disable_debug() + disable_debug() ret = [subprocess.check_output( ['python',os.path.join('cmds','mmgen-tool'),'--testnet=1'] + (['--type=compressed'],[])[i==0] + ['-r0','randpair'] ).split() for i in range(n)] - restore_debug(ds) + restore_debug() return ret def regtest_bob_pre_import(self,name): @@ -2607,6 +2621,8 @@ class MMGenTestSuite(object): def regtest_user_import(self,name,user,args): t = MMGenExpect(name,'mmgen-addrimport',['--quiet','--'+user]+args) + if g.debug: + t.expect("Type uppercase 'YES' to confirm: ",'YES\n') t.expect('Importing') t.expect('OK') t.ok()