From 4c4377d618f2e751073eb7a591159f4b9ca1677f Mon Sep 17 00:00:00 2001 From: philemon Date: Mon, 12 Jan 2015 14:41:17 +0300 Subject: [PATCH] Small changes in opts handling code --- mmgen/addr.py | 1 - mmgen/bitcoin.py | 8 +-- mmgen/config.py | 6 +- mmgen/crypto.py | 15 ++--- mmgen/main_addrgen.py | 4 +- mmgen/main_tool.py | 2 +- mmgen/main_txcreate.py | 8 +-- mmgen/main_txsend.py | 2 +- mmgen/main_txsign.py | 8 +-- mmgen/main_walletchk.py | 4 +- mmgen/main_walletgen.py | 4 +- mmgen/mnemonic.py | 18 ++--- mmgen/opt.py | 2 +- mmgen/opts.py | 141 ++++++++++++++++++++++------------------ mmgen/term.py | 2 +- mmgen/tool.py | 62 +++++++++--------- mmgen/tx.py | 2 +- mmgen/util.py | 20 +++--- test/test.py | 40 +++++++----- test/tooltest.py | 14 ++-- 20 files changed, 186 insertions(+), 177 deletions(-) diff --git a/mmgen/addr.py b/mmgen/addr.py index eb727007..ac33f5b7 100755 --- a/mmgen/addr.py +++ b/mmgen/addr.py @@ -90,7 +90,6 @@ def generate_addrs(seed, addrnums): seed = sha512(seed).digest() num += 1 # round - if opt.debug: print "Seed round %s: %s" % (num, hexlify(seed)) if num != addrnums[pos]: continue pos += 1 diff --git a/mmgen/bitcoin.py b/mmgen/bitcoin.py index 14e527f8..2dd3b659 100755 --- a/mmgen/bitcoin.py +++ b/mmgen/bitcoin.py @@ -79,10 +79,10 @@ def verify_addr(addr,verbose=False,return_hex=False): if step2[:8] == addr_hex[42:]: return addr_hex[2:42] if return_hex else True else: - if verbose: print "Invalid checksum in address '%s'" % addr + if verbose: Msg("Invalid checksum in address '%s'" % addr) break - if verbose: print "Invalid address '%s'" % addr + if verbose: Msg("Invalid address '%s'" % addr) return False @@ -134,8 +134,8 @@ def _b58_pad(s,a,b,pad,f,w): try: outlen = b[a.index(len(s))] except: - print "_b58_pad() accepts only %s %s bytes long "\ - "(input was %s bytes)" % (w,",".join([str(i) for i in a]),len(s)) + Msg("_b58_pad() accepts only %s %s bytes long "\ + "(input was %s bytes)" % (w,",".join([str(i) for i in a]),len(s))) return False out = f(s) diff --git a/mmgen/config.py b/mmgen/config.py index 9318e571..c6e5a20d 100755 --- a/mmgen/config.py +++ b/mmgen/config.py @@ -51,6 +51,9 @@ email = "" Cdates = '2013-2015' version = '0.7.9' +required_opts = [ # list must contain "usr_randchars" + "quiet","verbose","debug","outdir","echo_passphrase","passwd_file","usr_randchars" +] min_screen_width = 80 max_tx_comment_len = 72 @@ -74,9 +77,6 @@ mmenc_ext = "mmenc" default_wl = "electrum" #default_wl = "tirosh" -# If user opt is set, different global opt is set to 'True' -usr_set_vars = { "usr_randchars": "use_urandchars" } - # Global value sets user opt dfl_vars = "seed_len","hash_preset","usr_randchars","debug" diff --git a/mmgen/crypto.py b/mmgen/crypto.py index eee858c7..6ecd031a 100755 --- a/mmgen/crypto.py +++ b/mmgen/crypto.py @@ -90,7 +90,7 @@ def decrypt_seed(enc_seed, key, seed_id, key_id): # else: # qmsg("Generated IDs (Seed/Key): %s/%s" % (chk2,chk1)) - if opt.debug: print "Decrypted seed: %s" % hexlify(dec_seed) + if opt.debug: Msg("Decrypted seed: %s" % hexlify(dec_seed)) vmsg("OK") return dec_seed @@ -155,11 +155,10 @@ def make_key(passwd,salt,hash_preset, if from_what: what += " from " if opt.verbose or verbose: - msg_r("Generating %s%s.\nPlease wait..." % (what,from_what)) + msg_r("Generating %s%s..." % (what,from_what)) key = scrypt_hash_passphrase(passwd, salt, hash_preset) - if opt.verbose or verbose: - msg("done") - if opt.debug: print "Key: %s" % hexlify(key) + if opt.verbose or verbose: msg("done") + if opt.debug: Msg("Key: %s" % hexlify(key)) return key @@ -399,7 +398,7 @@ def _get_seed(infile,silent=False,seed_id=""): msg("Invalid %s file '%s'" % (source,infile)) sys.exit(2) - if opt.debug: print "Seed: %s" % hexlify(seed) + if opt.debug: Msg("Seed: %s" % hexlify(seed)) return seed @@ -415,9 +414,9 @@ def get_seed_retry(infile,seed_id=""): def _get_seed_from_brain_passphrase(words): bp = " ".join(words) - if opt.debug: print "Sanitized brain passphrase: %s" % bp + if opt.debug: Msg("Sanitized brain passphrase: %s" % bp) seed_len,hash_preset = get_from_brain_opt_params() - if opt.debug: print "Brainwallet l = %s, p = %s" % (seed_len,hash_preset) + if opt.debug: Msg("Brainwallet l = %s, p = %s" % (seed_len,hash_preset)) vmsg_r("Hashing brainwallet data. Please wait...") # Use buflen arg of scrypt.hash() to get seed of desired length seed = scrypt_hash_passphrase(bp, "", hash_preset, buflen=seed_len/8) diff --git a/mmgen/main_addrgen.py b/mmgen/main_addrgen.py index 30dfcc03..8cb21eea 100755 --- a/mmgen/main_addrgen.py +++ b/mmgen/main_addrgen.py @@ -118,8 +118,6 @@ cmd_args = opt.opts.init(opts_data,add_opts=["b16"]) if opt.show_hash_presets: show_hash_presets() if opt.from_incog_hex or opt.from_incog_hidden: opt.from_incog = True -if opt.debug: opt.opts.show_opts_and_cmd_args(cmd_args) - if len(cmd_args) == 1 and ( opt.from_mnemonic or opt.from_brain @@ -130,7 +128,7 @@ if len(cmd_args) == 1 and ( elif len(cmd_args) == 2: infile,addr_idx_arg = cmd_args check_infile(infile) -else: opt.opts.usage(opts_data) +else: opt.opts.usage() addr_idxs = parse_addr_idxs(addr_idx_arg) diff --git a/mmgen/main_tool.py b/mmgen/main_tool.py index 8becf2eb..06520046 100755 --- a/mmgen/main_tool.py +++ b/mmgen/main_tool.py @@ -48,7 +48,7 @@ command cmd_args = opt.opts.init(opts_data) if len(cmd_args) < 1: - opt.opts.usage(opts_data) + opt.opts.usage() sys.exit(1) command = cmd_args.pop(0) diff --git a/mmgen/main_txcreate.py b/mmgen/main_txcreate.py index 6ebca02c..84906723 100755 --- a/mmgen/main_txcreate.py +++ b/mmgen/main_txcreate.py @@ -334,8 +334,6 @@ def mmaddr2btcaddr(c,mmaddr,acct_data,ail): cmd_args = opt.opts.init(opts_data) -if opt.debug: show_opts_and_cmd_args(cmd_args) - if opt.comment_file: comment = get_tx_comment_from_file(opt.comment_file) @@ -394,8 +392,6 @@ if not opt.info: msg("Transaction fee too large: %s > %s" % (tx_fee,g.max_tx_fee)) sys.exit(2) -if opt.debug: show_opts_and_cmd_args(cmd_args) - if g.bogus_wallet_data: # for debugging purposes only import mmgen.rpc.data us = eval(get_data_from_file(g.bogus_wallet_data)) @@ -459,8 +455,8 @@ if change > 0: tx_out[change_addr] = float(change) tx_in = [{"txid":i.txid, "vout":i.vout} for i in sel_unspent] if opt.debug: - print "tx_in:", repr(tx_in) - print "tx_out:", repr(tx_out) + Msg("tx_in: " + repr(tx_in)) + Msg("tx_out: " + repr(tx_out)) if opt.comment_file: if keypress_confirm("Edit comment?",False): diff --git a/mmgen/main_txsend.py b/mmgen/main_txsend.py index 9c41f8c3..b7e807d0 100755 --- a/mmgen/main_txsend.py +++ b/mmgen/main_txsend.py @@ -42,7 +42,7 @@ cmd_args = opt.opts.init(opts_data) if len(cmd_args) == 1: infile = cmd_args[0]; check_infile(infile) -else: opt.opts.usage(opts_data) +else: opt.opts.usage() # Begin execution diff --git a/mmgen/main_txsign.py b/mmgen/main_txsign.py index 64749a65..4c74802b 100755 --- a/mmgen/main_txsign.py +++ b/mmgen/main_txsign.py @@ -147,7 +147,7 @@ def sign_transaction(c,tx_hex,tx_num_str,sig_data,keys=None): if keys: qmsg("Passing %s key%s to bitcoind" % (len(keys),suf(keys,"k"))) - if opt.debug: print "Keys:\n %s" % "\n ".join(keys) + if opt.debug: Msg("Keys:\n %s" % "\n ".join(keys)) msg_r("Signing transaction{}...".format(tx_num_str)) from mmgen.rpc import exceptions @@ -207,10 +207,10 @@ def check_maps_from_seeds(maplist,label,infiles,saved_seeds,return_keys=False): return ret def missing_keys_errormsg(addrs): - print """ + Msg(""" A key file must be supplied (or use the '--use-wallet-dat' option) for the following non-{} address{}:\n {}""".format( - g.proj_name,suf(addrs,"a"),"\n ".join(addrs)).strip() + g.proj_name,suf(addrs,"a"),"\n ".join(addrs)).strip()) def parse_mmgen_keyaddr_file(): @@ -287,7 +287,7 @@ for l in ( if opt.from_incog_hex or opt.from_incog_hidden: opt.from_incog = True -if not infiles: opt.opts.usage(opts_data) +if not infiles: opt.opts.usage() for i in infiles: check_infile(i) c = connect_to_bitcoind() diff --git a/mmgen/main_walletchk.py b/mmgen/main_walletchk.py index 5bc05173..4683f619 100755 --- a/mmgen/main_walletchk.py +++ b/mmgen/main_walletchk.py @@ -95,6 +95,8 @@ def export_to_hidden_incog(incog_enc): outfile,offset = opt.export_incog_hidden.split(",") #Already sanity-checked if opt.outdir: outfile = make_full_path(opt.outdir,outfile) + if opt.debug: + Msg("Incog data len %s, offset %s" % (len(incog_enc),offset)) check_data_fits_file_at_offset(outfile,int(offset),len(incog_enc),"write") if not opt.quiet: confirm_or_exit("","alter file '%s'" % outfile) @@ -112,7 +114,7 @@ cmd_args = opt.opts.init(opts_data) if opt.export_incog_hidden or opt.export_incog_hex: opt.export_incog = True -if len(cmd_args) != 1: opt.opts.usage(opts_data) +if len(cmd_args) != 1: opt.opts.usage() check_infile(cmd_args[0]) diff --git a/mmgen/main_walletgen.py b/mmgen/main_walletgen.py index 27416f30..0ee124c2 100755 --- a/mmgen/main_walletgen.py +++ b/mmgen/main_walletgen.py @@ -125,8 +125,6 @@ cmd_args = opt.opts.init(opts_data) if opt.show_hash_presets: show_hash_presets() -if opt.debug: opt.opts.show_opts_and_cmd_args(cmd_args) - if len(cmd_args) == 1: infile = cmd_args[0] check_infile(infile) @@ -140,7 +138,7 @@ if len(cmd_args) == 1: sys.exit(1) elif len(cmd_args) == 0: infile = "" -else: opt.opts.usage(opts_data) +else: opt.opts.usage() g.use_urandchars = True diff --git a/mmgen/mnemonic.py b/mmgen/mnemonic.py index 074e02b7..2aabe524 100755 --- a/mmgen/mnemonic.py +++ b/mmgen/mnemonic.py @@ -22,7 +22,7 @@ mnemonic.py: Mnemonic routines for the MMGen suite import sys from binascii import hexlify -from mmgen.util import msg,msg_r,make_chksum_8,Vmsg +from mmgen.util import msg,msg_r,make_chksum_8,Vmsg,Msg from mmgen.crypto import get_random import mmgen.config as g import mmgen.opt as opt @@ -107,24 +107,24 @@ def get_mnemonic_from_seed(seed, wl, label="", verbose=False): def check_wordlist(wl,label): - print "Wordlist: %s" % label.capitalize() + Msg("Wordlist: %s" % label.capitalize()) from hashlib import sha256 - print "Length: %i words" % len(wl) + Msg("Length: %i words" % len(wl)) new_chksum = sha256(" ".join(wl)).hexdigest()[:8] if new_chksum != wl_checksums[label]: - print "ERROR: Checksum mismatch. Computed: %s, Saved: %s" % \ - (new_chksum,wl_checksums[label]) + Msg("ERROR: Checksum mismatch. Computed: %s, Saved: %s" % \ + (new_chksum,wl_checksums[label])) sys.exit(3) - print "Checksum: %s (matches)" % new_chksum + Msg("Checksum: %s (matches)" % new_chksum) if (sorted(wl) == wl): - print "List is sorted" + Msg("List is sorted") else: - print "ERROR: List is not sorted!" + Msg("ERROR: List is not sorted!") sys.exit(3) from mmgen.mn_electrum import electrum_words as el @@ -146,4 +146,4 @@ def do_random_mn(nbytes,wordlist): wl = get_wordlist(wlname) mn = get_mnemonic_from_seed(r,wl,wordlist) Vmsg("%s wordlist mnemonic:" % (wlname.capitalize())) - print " ".join(mn) + Msg(" ".join(mn)) diff --git a/mmgen/opt.py b/mmgen/opt.py index 6437a7d8..0fca1719 100755 --- a/mmgen/opt.py +++ b/mmgen/opt.py @@ -17,6 +17,6 @@ # along with this program. If not, see . """ -opt.py: an empty namespace for the global opt variables +opt.py: a namespace for the global opt variables """ import opts diff --git a/mmgen/opts.py b/mmgen/opts.py index 4d47e8a5..39110348 100755 --- a/mmgen/opts.py +++ b/mmgen/opts.py @@ -17,24 +17,25 @@ # along with this program. If not, see . """ -opts.py: Further options processing after mmgen.share.Opts +opts.py: MMGen-specific options processing after general processing by share.Opts """ import sys import mmgen.config as g import mmgen.share.Opts import opt -from mmgen.util import msg,msgrepr_exit,msgrepr +from mmgen.util import msg,msgrepr_exit,msgrepr,Msg -def usage(opts_data): - print "USAGE: %s %s" % (opts_data['prog_name'], opts_data['usage']) +def usage(): + Msg("USAGE: %s %s" % (g.prog_name, usage_txt)) sys.exit(2) def print_version_info(): - print """ -'{g.prog_name}' version {g.version}. Part of the {g.proj_name} suite. -Copyright (C) {g.Cdates} by {g.author} {g.email}. -""".format(g=g).strip() + Msg(""" +{pnu} version {g.version}. Part of the {g.proj_name} suite, a Bitcoin +cold-storage solution for the command line. Copyright (C) {g.Cdates} +by {g.author} {g.email} +""".format(g=g,pnu=g.prog_name.upper()).strip()) def warn_incompatible_opts(incompat_list): bad = [k for k in opt.__dict__ if opt.__dict__[k] and k in incompat_list] @@ -43,13 +44,15 @@ def warn_incompatible_opts(incompat_list): ["--"+b.replace("_","-") for b in bad])) sys.exit(1) -def typeconvert_from_dfl(opts,opt): +def typeconvert_from_dfl(key): - vtype = type(g.__dict__[opt]) - if g.debug: print "Override opt: %-15s [%s]" % (opt,vtype) + vtype = type(g.__dict__[key]) + if g.debug: Msg("Override opt: %-15s [%s]" % (key,vtype)) + + global opt try: - opts[opt] = vtype(opts[opt]) + opt.__dict__[key] = vtype(opt.__dict__[key]) except: d = { 'int': 'an integer', @@ -57,9 +60,10 @@ def typeconvert_from_dfl(opts,opt): 'float': 'a float', 'bool': 'a boolean value', } - m = [d[k] for k in d if __builtins__[k] == vtype][0] - msg("'%s': invalid parameter for '--%s' option (not %s)" % - (opts[opt],opt.replace("_","-"),m)) + m = [d[k] for k in d if __builtins__[k] == vtype] + msgrepr_exit(key,vtype) + fs = "'%s': invalid parameter for '--%s' option (not %s)" + msg(fs % (opt.__dict__[key],opt.replace("_","-"),m)) sys.exit(1) def init(opts_data,add_opts=[]): @@ -67,39 +71,55 @@ def init(opts_data,add_opts=[]): if len(sys.argv) == 2 and sys.argv[1] == '--version': print_version_info(); sys.exit() - opts,args,short_opts,long_opts = mmgen.share.Opts.parse_opts(sys.argv,opts_data) + uopts,args,short_opts,long_opts = \ + mmgen.share.Opts.parse_opts(sys.argv,opts_data) if g.debug: - print "short opts: %s" % repr(short_opts) - print "long opts: %s" % repr(long_opts) - print "user-selected opts: %s" % repr(opts) - print "cmd args: %s" % repr(args) + d = ( + ("short opts", short_opts), + ("long opts", long_opts), + ("user-selected opts", uopts), + ("cmd args", args), + ) + for e in d: Msg("{:<20}: {}".format(*e)) - # check opts without modifying them - if not check_opts(opts,long_opts): sys.exit(1) + # Save this for usage() + global usage_txt + usage_txt = opts_data['usage'] - # If user opt is set, an opt in mmgen.config is set to 'True' - for v in g.usr_set_vars: - if v in opts: - g.__dict__[g.usr_set_vars[v]] = True + # We don't need this data anymore + del mmgen.share.Opts + for k in 'prog_name','desc','usage','options','notes': + if k in opts_data: del opts_data[k] + + # Remove all unneeded attributes from opt, our special global namespace + for k in dir(opt): + if k[:2] == "__": del opt.__dict__[k] + + # Transfer uopts into opt, setting required opts to None if not set by user + for o in [s.rstrip("=") for s in long_opts] + g.required_opts + add_opts: + opt.__dict__[o] = uopts[o] if o in uopts else None + + # check user-set opts without modifying them + if not check_opts(uopts): sys.exit(1) + + # A special case - do this here, before opt gets set from g.dfl_vars + if opt.usr_randchars: g.use_urandchars = True # If user opt is unset, set it to default value in mmgen.config (g): # If set, convert its type based on value in mmgen.config - for v in g.dfl_vars: - if v in opts: typeconvert_from_dfl(opts,v) - else: opts[v] = g.__dict__[v] + for k in g.dfl_vars: + if k in opt.__dict__ and opt.__dict__[k] != None: + typeconvert_from_dfl(k) + else: opt.__dict__[k] = g.__dict__[k] - if g.debug: print "opts after typeconvert: %s" % opts + if opt.debug: opt.verbose = True - # A hack, but harmless - extra_opts = [ - "quiet","verbose","debug", - "outdir","echo_passphrase","passwd_file" - ] + add_opts - - # Transfer opts into our custom namespace - for o in [s.rstrip("=") for s in long_opts] + extra_opts: - opt.__dict__[o] = opts[o] if o in opts else None + if g.debug: + Msg("opts after typeconvert:") + for k in opt.__dict__: + if opt.__dict__[k] != None and k != "opts": + msg(" %-18s: %s" % (k,opt.__dict__[k])) for l in ( ('from_incog_hidden','from_incog','from_seed','from_mnemonic','from_brain'), @@ -108,25 +128,17 @@ def init(opts_data,add_opts=[]): ('quiet','verbose') ): warn_incompatible_opts(l) - del mmgen.share.Opts return args -def show_opts_and_cmd_args(cmd_args): - print "Processed options:" - d = opt.__dict__ - for k in d: - if k[:2] != "__" and k != "opts" and d[k] != None: - msg("%-20s: %s" % (k, d[k])) - print "Cmd args: %s" % repr(cmd_args) - +# save for debugging def show_all_opts(): msg("Processed options:") d = opt.__dict__ - for k in d: - if k[:2] != "__" and k != "opts": - msg("%-20s: %s" % (k, d[k])) + for k in [o for o in d if o != "opts"]: + tstr = type(d[k]) if d[k] not in (None,False,True) else "" + msg("%-20s: %-8s %s" % (k, d[k], tstr)) -def check_opts(opts,long_opts): # Returns false if any check fails +def check_opts(usr_opts): # Returns false if any check fails def opt_splits(val,sep,n,what): sepword = "comma" if sep == "," else ( @@ -163,21 +175,22 @@ def check_opts(opts,long_opts): # Returns false if any check fails return False return True - for opt,val in opts.items(): + global opt + for key,val in [(k,getattr(opt,k)) for k in usr_opts]: - what = "parameter for '--%s' option" % opt.replace("_","-") + what = "parameter for '--%s' option" % key.replace("_","-") # Check for file existence and readability - if opt in ('keys_from_file','mmgen_keys_from_file', + if key in ('keys_from_file','mmgen_keys_from_file', 'passwd_file','keysforaddrs','comment_file'): from mmgen.util import check_infile check_infile(val) # exits on error continue - if opt == 'outdir': + if key == 'outdir': from mmgen.util import check_outdir check_outdir(val) # exits on error - elif opt == 'label': + elif key == 'label': if not opt_compares(len(val),"<=",g.max_wallet_label_len,"label length"): return False try: val.decode("ascii") @@ -187,8 +200,8 @@ def check_opts(opts,long_opts): # Returns false if any check fails w = "character in label" for ch in list(val): if not opt_is_in_list(ch,g.wallet_label_symbols,w): return False - elif opt == 'export_incog_hidden' or opt == 'from_incog_hidden': - if opt == 'from_incog_hidden': + elif key == 'export_incog_hidden' or key == 'from_incog_hidden': + if key == 'from_incog_hidden': if not opt_splits(val,",",3,what): return False infile,offset,seed_len = val.split(",") from mmgen.util import check_infile @@ -204,7 +217,7 @@ def check_opts(opts,long_opts): # Returns false if any check fails w = "offset " + what if not opt_is_int(offset,w): return False if not opt_compares(offset,">=",0,what): return False - elif opt == 'from_brain': + elif key == 'from_brain': if not opt_splits(val,",",2,what): return False l,p = val.split(",") w = "seed length " + what @@ -212,16 +225,16 @@ def check_opts(opts,long_opts): # Returns false if any check fails if not opt_is_in_list(int(l),g.seed_lens,w): return False w = "hash preset " + what if not opt_is_in_list(p,g.hash_presets.keys(),w): return False - elif opt == 'seed_len': + elif key == 'seed_len': if not opt_is_int(val,what): return False if not opt_is_in_list(int(val),g.seed_lens,what): return False - elif opt == 'hash_preset': + elif key == 'hash_preset': if not opt_is_in_list(val,g.hash_presets.keys(),what): return False - elif opt == 'usr_randchars': + elif key == 'usr_randchars': if not opt_is_int(val,what): return False if not opt_compares(val,">=",g.min_urandchars,what): return False if not opt_compares(val,"<=",g.max_urandchars,what): return False else: - if 'debug' in opts: print "check_opts(): No test for opt '%s'" % opt + if g.debug: Msg("check_opts(): No test for opt '%s'" % key) return True diff --git a/mmgen/term.py b/mmgen/term.py index 785bf08b..1beb8272 100755 --- a/mmgen/term.py +++ b/mmgen/term.py @@ -242,4 +242,4 @@ def do_pager(text): p.communicate(text+end+"\n") msg_r("\r") break - else: print text+end + else: Msg(text+end) diff --git a/mmgen/tool.py b/mmgen/tool.py index 1c6f5f87..dde7036d 100755 --- a/mmgen/tool.py +++ b/mmgen/tool.py @@ -153,8 +153,8 @@ cmd_help = """ """.format(pnm=g.proj_name) def tool_usage(prog_name, command): - print "USAGE: '%s %s%s'" % (prog_name, command, - (" "+" ".join(cmd_data[command]) if cmd_data[command] else "")) + Msg("USAGE: '%s %s%s'" % (prog_name, command, + (" "+" ".join(cmd_data[command]) if cmd_data[command] else ""))) def process_args(prog_name, command, cmd_args): c_args = [[i.split(" [")[0],i.split(" [")[1][:-1]] @@ -182,15 +182,15 @@ def process_args(prog_name, command, cmd_args): # print c_args; print c_kwargs; print u_args; print u_kwargs; sys.exit() if set(u_kwargs) > set(c_kwargs): - print "Invalid named argument" + Msg("Invalid named argument") sys.exit(1) def convert_type(arg,arg_name,arg_type): try: return __builtins__[arg_type](arg) except: - print "'%s': Invalid argument for argument %s ('%s' required)" % \ - (arg, arg_name, arg_type) + Msg("'%s': Invalid argument for argument %s ('%s' required)" % \ + (arg, arg_name, arg_type)) sys.exit(1) def convert_to_bool_maybe(arg, arg_type): @@ -244,8 +244,8 @@ def usage(cmd): tool_usage(g.prog_name, cmd) def hexdump(infile, cols=8, line_nums=True): - print pretty_hexdump(get_data_from_file(infile,dash=True,silent=True), - cols=cols, line_nums=line_nums) + Msg(pretty_hexdump(get_data_from_file(infile,dash=True,silent=True), + cols=cols, line_nums=line_nums)) def unhexdump(infile): sys.stdout.write(decode_pretty_hexdump( @@ -281,7 +281,7 @@ def b58randenc(): print_convert_results(r,enc,dec,"str") def randhex(nbytes='32'): - print ba.hexlify(get_random(int(nbytes))) + Msg(ba.hexlify(get_random(int(nbytes)))) def randwif(compressed=False): r_hex = ba.hexlify(get_random(32)) @@ -314,22 +314,22 @@ def mn_rand256(wordlist="electrum"): do_random_mn(32,wordlist) def hex2mn(s,wordlist="electrum"): import mmgen.mnemonic wl = get_wordlist(wordlist) - print " ".join(get_mnemonic_from_seed(ba.unhexlify(s), wl, wordlist)) + Msg(" ".join(get_mnemonic_from_seed(ba.unhexlify(s), wl, wordlist))) def mn2hex(s,wordlist="electrum"): import mmgen.mnemonic wl = get_wordlist(wordlist) - print ba.hexlify(get_seed_from_mnemonic(s.split(),wl,True)) + Msg(ba.hexlify(get_seed_from_mnemonic(s.split(),wl,True))) def b32tohex(s): b32a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" import mmgen.mnemonic - print baseNtohex(32,s,b32a) + Msg(baseNtohex(32,s,b32a)) def hextob32(s): b32a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" import mmgen.mnemonic - print "".join(hextobaseN(32,s,b32a)) + Msg("".join(hextobaseN(32,s,b32a))) def mn_stats(wordlist="electrum"): l = get_wordlist(wordlist) @@ -337,11 +337,11 @@ def mn_stats(wordlist="electrum"): def mn_printlist(wordlist="electrum"): wl = get_wordlist(wordlist) - print "\n".join(wl) + Msg("\n".join(wl)) -def id8(infile): print make_chksum_8(get_data_from_file(infile,dash=True,silent=True)) -def id6(infile): print make_chksum_6(get_data_from_file(infile,dash=True,silent=True)) -def str2id6(s): print make_chksum_6("".join(s.split())) +def id8(infile): Msg(make_chksum_8(get_data_from_file(infile,dash=True,silent=True))) +def id6(infile): Msg(make_chksum_6(get_data_from_file(infile,dash=True,silent=True))) +def str2id6(s): Msg(make_chksum_6("".join(s.split()))) # List MMGen addresses and their balances: def listaddresses(minconf=1,showempty=False,pager=False): @@ -391,7 +391,7 @@ def listaddresses(minconf=1,showempty=False,pager=False): o = "\n".join(out) if pager: do_pager(o) - else: print o + else: Msg(o) def getbalance(minconf=1): @@ -413,10 +413,10 @@ def getbalance(minconf=1): fs = "{:12} {:<%s} {:<%s} {:<}" % (16,16) mc,lbl = str(minconf),"confirms" - print fs.format("Wallet","Unconfirmed", - "<%s %s"%(mc,lbl),">=%s %s"%(mc,lbl)) + Msg(fs.format("Wallet","Unconfirmed","<%s %s"%(mc,lbl),">=%s %s"%(mc,lbl))) for key in sorted(accts.keys()): - print fs.format(key+":", *[str(trim_exponent(a))+" BTC" for a in accts[key]]) + Msg(fs.format(key+":", *[str(trim_exponent(a))+" BTC" + for a in accts[key]])) def txview(infile,pager=False,terse=False): c = connect_to_bitcoind() @@ -434,38 +434,38 @@ def keyaddrfile_chksum(infile): AddrInfo(infile,has_keys=True) def hexreverse(hex_str): - print ba.hexlify(decode_pretty_hexdump(hex_str)[::-1]) + Msg(ba.hexlify(decode_pretty_hexdump(hex_str)[::-1])) def hexlify(s): - print ba.hexlify(s) + Msg(ba.hexlify(s)) def sha256x2(s, file_input=False, hex_input=False): from hashlib import sha256 if file_input: b = get_data_from_file(s) elif hex_input: b = decode_pretty_hexdump(s) else: b = s - print sha256(sha256(b).digest()).hexdigest() + Msg(sha256(sha256(b).digest()).hexdigest()) def hexaddr2addr(hexaddr): - print bitcoin.hexaddr2addr(hexaddr) + Msg(bitcoin.hexaddr2addr(hexaddr)) def addr2hexaddr(addr): - print bitcoin.verify_addr(addr,return_hex=True) + Msg(bitcoin.verify_addr(addr,return_hex=True)) def pubkey2hexaddr(pubkeyhex): - print bitcoin.pubhex2hexaddr(pubkeyhex) + Msg(bitcoin.pubhex2hexaddr(pubkeyhex)) def pubkey2addr(pubkeyhex): - print bitcoin.hexaddr2addr(bitcoin.pubhex2hexaddr(pubkeyhex)) + Msg(bitcoin.hexaddr2addr(bitcoin.pubhex2hexaddr(pubkeyhex))) def privhex2addr(privkeyhex,compressed=False): - print bitcoin.privnum2addr(int(privkeyhex,16),compressed) + Msg(bitcoin.privnum2addr(int(privkeyhex,16),compressed)) def wif2hex(wif,compressed=False): - print bitcoin.wiftohex(wif,compressed) + Msg(bitcoin.wiftohex(wif,compressed)) def hex2wif(hexpriv,compressed=False): - print bitcoin.hextowif(hexpriv,compressed) + Msg(bitcoin.hextowif(hexpriv,compressed)) def encrypt(infile,outfile="",hash_preset=""): @@ -603,4 +603,4 @@ def rand2file(outfile, nbytes, threads=4, silent=False): q2.join() f.close() -def bytespec(s): print parse_nbytes(s) +def bytespec(s): Msg(parse_nbytes(s)) diff --git a/mmgen/tx.py b/mmgen/tx.py index aab9b9d7..687de16c 100755 --- a/mmgen/tx.py +++ b/mmgen/tx.py @@ -47,7 +47,7 @@ def normalize_btc_amt(amt): return False if opt.debug: - print "Decimal(amt): %s\nAs tuple: %s" % (amt,repr(ret.as_tuple())) + Msg("Decimal(amt): %s\nAs tuple: %s" % (amt,repr(ret.as_tuple()))) if ret.as_tuple()[-1] < -8: msg("%s: Too many decimal places in amount" % amt) diff --git a/mmgen/util.py b/mmgen/util.py index a13a0fa1..c867c8ad 100755 --- a/mmgen/util.py +++ b/mmgen/util.py @@ -178,9 +178,9 @@ def compare_checksums(chksum1, desc1, chksum2, desc2): return True else: if opt.debug: - print \ - "ERROR!\nComputed checksum %s (%s) doesn't match checksum %s (%s)" \ - % (desc1,chksum1,desc2,chksum2) + Msg( + "ERROR: Computed checksum %s (%s) doesn't match checksum %s (%s)" + % (desc1,chksum1,desc2,chksum2)) return False def get_default_wordlist(): @@ -289,7 +289,7 @@ def get_new_passphrase(what, passchg=False): for i in range(g.passwd_max_tries): pw = " ".join(_get_words_from_user("Enter {}: ".format(w))) pw2 = " ".join(_get_words_from_user("Repeat passphrase: ")) - if opt.debug: print "Passphrases: [%s] [%s]" % (pw,pw2) + if opt.debug: Msg("Passphrases: [%s] [%s]" % (pw,pw2)) if pw == pw2: vmsg("Passphrases match"); break else: msg("Passphrases do not match. Try again.") @@ -378,7 +378,7 @@ def write_to_file_or_stdout(outfile, data, what="data"): from mmgen.bitcoin import b58decode_pad,b58encode_pad def display_control_data(label,metadata,hash_preset,salt,enc_seed): - print "WALLET DATA" + Msg("WALLET DATA") fs = " {:18} {}" pw_empty = "yes" if metadata[3] == "E" else "no" for i in ( @@ -391,7 +391,7 @@ def display_control_data(label,metadata,hash_preset,salt,enc_seed): " ".join([str(i) for i in get_hash_params(hash_preset)]))), ("Passphrase empty?", pw_empty.capitalize()), ("Timestamp:", "%s UTC" % metadata[4]), - ): print fs.format(*i) + ): Msg(fs.format(*i)) fs = " {:6} {}" for i in ( @@ -401,7 +401,7 @@ def display_control_data(label,metadata,hash_preset,salt,enc_seed): ("Encrypted seed:", ""), (" b58:", b58encode_pad(enc_seed)), (" hex:", hexlify(enc_seed)) - ): print fs.format(*i) + ): Msg(fs.format(*i)) def write_wallet_to_file(seed, passwd, key_id, salt, enc_seed): @@ -480,7 +480,7 @@ def _check_chksum_6(chk,val,desc,infile): msg("Checksum: %s. Computed value: %s" % (chk,comp_chk)) sys.exit(2) elif opt.debug: - print "%s checksum passed: %s" % (desc.capitalize(),chk) + Msg("%s checksum passed: %s" % (desc.capitalize(),chk)) def get_data_from_wallet(infile,silent=False): @@ -530,7 +530,7 @@ def get_data_from_wallet(infile,silent=False): def _get_words_from_user(prompt): # split() also strips words = my_raw_input(prompt, echo=opt.echo_passphrase).split() - if opt.debug: print "Sanitized input: [%s]" % " ".join(words) + if opt.debug: Msg("Sanitized input: [%s]" % " ".join(words)) return words @@ -540,7 +540,7 @@ def _get_words_from_file(infile,what): # split() also strips words = f.read().split() f.close() - if opt.debug: print "Sanitized input: [%s]" % " ".join(words) + if opt.debug: Msg("Sanitized input: [%s]" % " ".join(words)) return words diff --git a/test/test.py b/test/test.py index e8ec12fd..08590fa5 100755 --- a/test/test.py +++ b/test/test.py @@ -155,8 +155,8 @@ cmd_data = OrderedDict([ ['keyaddrgen', (1,'key-address file generation', [[["mmdat"],1]])], ['txsign_keyaddr',(1,'transaction signing with key-address file', [[["akeys.mmenc","raw"],1]])], - ['walletgen2',(2,'wallet generation (2)', [])], -# ['walletgen2',(2,'wallet generation (2), 128-bit seed (WIP)', [])], +# ['walletgen2',(2,'wallet generation (2)', [])], + ['walletgen2',(2,'wallet generation (2), 128-bit seed', [])], ['addrgen2', (2,'address generation (2)', [[["mmdat"],2]])], ['txcreate2', (2,'transaction creation (2)', [[["addrs"],2]])], ['txsign2', (2,'transaction signing, two transactions',[[["mmdat","raw"],1],[["mmdat","raw"],2]])], @@ -215,18 +215,18 @@ opts_data = { 'desc': "Test suite for the MMGen suite", 'usage':"[options] [command or metacommand]", 'options': """ --h, --help Print this help message --b, --buf-keypress Use buffered keypresses as with real human input --d, --debug Produce debugging output --D, --direct-exec Bypass pexpect and execute a command directly (for - debugging only) --e, --exact-output Show the exact output of the MMGen script(s) being run --l, --list-cmds List and describe the tests and commands in the test suite --p, --pause Pause between tests, resuming on keypress --q, --quiet Produce minimal output. Suppress dependency info --s, --system Test scripts and modules installed on system rather than - those in the repo root --v, --verbose Produce more verbose output +-h, --help Print this help message +-b, --buf-keypress Use buffered keypresses as with real human input +-d, --debug-scripts Turn on debugging output in executed scripts +-D, --direct-exec Bypass pexpect and execute a command directly (for + debugging only) +-e, --exact-output Show the exact output of the MMGen script(s) being run +-l, --list-cmds List and describe the tests and commands in the test suite +-p, --pause Pause between tests, resuming on keypress +-q, --quiet Produce minimal output. Suppress dependency info +-s, --system Test scripts and modules installed on system rather than + those in the repo root +-v, --verbose Produce more verbose output """, 'notes': """ @@ -238,6 +238,8 @@ cmd_args = opt.opts.init(opts_data) if opt.system: sys.path.pop(0) +if opt.debug_scripts: os.environ["MMGEN_DEBUG"] = "1" + if opt.buf_keypress: send_delay = 0.3 else: @@ -651,9 +653,10 @@ class MMGenTestSuite(object): def generate_cmd_deps(self,fdeps): return [cfgs[str(n)]['dep_generators'][ext] for n,ext in fdeps] - def walletgen(self,name,brain=False): + def walletgen(self,name,brain=False,seed_len=None): args = ["-d",cfg['tmpdir'],"-p1","-r10"] + if seed_len: args += ["-l",str(seed_len)] # if 'seed_len' in cfg: args += ["-l",cfg['seed_len']] if brain: bwf = os.path.join(cfg['tmpdir'],cfg['bw_filename']) @@ -951,7 +954,7 @@ class MMGenTestSuite(object): ok() def walletgen2(self,name): - self.walletgen(name) + self.walletgen(name,seed_len=128) def addrgen2(self,name,walletfile): self.addrgen(name,walletfile) @@ -1111,5 +1114,6 @@ except: raise t = int(time.time()) - start_time -msg(green( - "All requested tests finished OK, elapsed time: %02i:%02i" % (t/60,t%60))) +sys.stderr.write(green( + "All requested tests finished OK, elapsed time: %02i:%02i\n" + % (t/60,t%60))) diff --git a/test/tooltest.py b/test/tooltest.py index 70c088dc..03e5f453 100755 --- a/test/tooltest.py +++ b/test/tooltest.py @@ -78,12 +78,12 @@ opts_data = { 'desc': "Test suite for the 'mmgen-tool' utility", 'usage':"[options] [command]", 'options': """ --h, --help Print this help message --d, --debug Produce debugging output --l, --list-cmds List and describe the tests and commands in the test suite --s, --system Test scripts and modules installed on system rather than - those in the repo root --v, --verbose Produce more verbose output +-h, --help Print this help message +-d, --debug-scripts Turn on debugging output in executed scripts +-l, --list-cmds List and describe the tests and commands in the test suite +-s, --system Test scripts and modules installed on system rather than + those in the repo root +-v, --verbose Produce more verbose output """, 'notes': """ @@ -95,7 +95,7 @@ cmd_args = opt.opts.init(opts_data,add_opts=["exact_output"]) if opt.system: sys.path.pop(0) -env = os.environ +if opt.debug_scripts: os.environ["MMGEN_DEBUG"] = "1" if opt.debug: opt.verbose = True