Browse Source

Code cleanups, small interface improvements

philemon 11 years ago
parent
commit
9dc54c414d
10 changed files with 103 additions and 83 deletions
  1. 1 0
      mmgen/config.py
  2. 9 7
      mmgen/crypto.py
  3. 14 14
      mmgen/main_addrgen.py
  4. 1 1
      mmgen/main_passchg.py
  5. 4 4
      mmgen/main_txcreate.py
  6. 25 23
      mmgen/main_txsign.py
  7. 7 7
      mmgen/main_walletchk.py
  8. 1 1
      mmgen/main_walletgen.py
  9. 19 16
      mmgen/tx.py
  10. 22 10
      mmgen/util.py

+ 1 - 0
mmgen/config.py

@@ -49,6 +49,7 @@ seedfile_exts = wallet_ext, seed_ext, mn_ext, brain_ext, incog_ext
 rawtx_ext    = "raw"
 rawtx_ext    = "raw"
 sigtx_ext    = "sig"
 sigtx_ext    = "sig"
 addrfile_ext = "addrs"
 addrfile_ext = "addrs"
+addrfile_chksum_ext = "chk"
 keyfile_ext  = "keys"
 keyfile_ext  = "keys"
 keylist_ext  = "keylist"
 keylist_ext  = "keylist"
 mmenc_ext    = "mmenc"
 mmenc_ext    = "mmenc"

+ 9 - 7
mmgen/crypto.py

@@ -119,11 +119,13 @@ def scrypt_hash_passphrase(passwd, salt, hash_preset, buflen=32):
 	return scrypt.hash(passwd, salt, 2**N, r, p, buflen=buflen)
 	return scrypt.hash(passwd, salt, 2**N, r, p, buflen=buflen)
 
 
 
 
-def make_key(passwd, salt, hash_preset, what="key"):
+def make_key(passwd, salt, hash_preset, what="key", verbose=False):
 
 
-	vmsg_r("Generating %s.  Please wait..." % what)
+	if g.verbose or verbose:
+		msg_r("Generating %s.  Please wait..." % what)
 	key = scrypt_hash_passphrase(passwd, salt, hash_preset)
 	key = scrypt_hash_passphrase(passwd, salt, hash_preset)
-	vmsg("done")
+	if g.verbose or verbose:
+		msg("done")
 	if g.debug: print "Key: %s" % hexlify(key)
 	if g.debug: print "Key: %s" % hexlify(key)
 	return key
 	return key
 
 
@@ -169,14 +171,14 @@ def get_random(length,opts):
 	from Crypto import Random
 	from Crypto import Random
 	os_rand = Random.new().read(length)
 	os_rand = Random.new().read(length)
 	if 'usr_randchars' in opts and opts['usr_randchars'] not in (0,-1):
 	if 'usr_randchars' in opts and opts['usr_randchars'] not in (0,-1):
-		kwhat = "a key from OS random data + "
+		kwhat = "a key from OS random data plus "
 		if not g.user_entropy:
 		if not g.user_entropy:
 			g.user_entropy = sha256(
 			g.user_entropy = sha256(
 				get_random_data_from_user(opts['usr_randchars'])).digest()
 				get_random_data_from_user(opts['usr_randchars'])).digest()
 			kwhat += "user entropy"
 			kwhat += "user entropy"
 		else:
 		else:
 			kwhat += "saved user entropy"
 			kwhat += "saved user entropy"
-		key = make_key(g.user_entropy, "", '2', what=kwhat)
+		key = make_key(g.user_entropy, "", '2', what=kwhat, verbose=True)
 		return encrypt_data(os_rand,key,what="random data",verify=False)
 		return encrypt_data(os_rand,key,what="random data",verify=False)
 	else:
 	else:
 		return os_rand
 		return os_rand
@@ -204,7 +206,7 @@ def get_seed_from_wallet(
 def get_seed_from_incog_wallet(
 def get_seed_from_incog_wallet(
 		infile,
 		infile,
 		opts,
 		opts,
-		prompt="{} wallet".format(g.proj_name),
+		prompt_what="{} incognito wallet".format(g.proj_name),
 		silent=False,
 		silent=False,
 		hex_input=False
 		hex_input=False
 	):
 	):
@@ -236,7 +238,7 @@ def get_seed_from_incog_wallet(
 	vmsg(cmessages['incog_iv_id_hidden' if "from_incog_hidden" in opts
 	vmsg(cmessages['incog_iv_id_hidden' if "from_incog_hidden" in opts
 			else 'incog_iv_id'])
 			else 'incog_iv_id'])
 
 
-	passwd = get_mmgen_passphrase(prompt,opts)
+	passwd = get_mmgen_passphrase(prompt_what,opts)
 
 
 	qmsg("Configured hash presets: %s" % " ".join(sorted(g.hash_presets)))
 	qmsg("Configured hash presets: %s" % " ".join(sorted(g.hash_presets)))
 	while True:
 	while True:

+ 14 - 14
mmgen/main_addrgen.py

@@ -35,9 +35,9 @@ what = "keys" if sys.argv[0].split("-")[-1] == "keygen" else "addresses"
 
 
 help_data = {
 help_data = {
 	'prog_name': g.prog_name,
 	'prog_name': g.prog_name,
-	'desc': """Generate a list or range of {} from an {g.proj_name} wallet,
+	'desc': """Generate a range or list of {} from an {g.proj_name} wallet,
                   mnemonic, seed or password""".format(what,g=g),
                   mnemonic, seed or password""".format(what,g=g),
-	'usage':"[opts] [infile] <address list>",
+	'usage':"[opts] [infile] <address range or list>",
 	'options': """
 	'options': """
 -h, --help              Print this help message{}
 -h, --help              Print this help message{}
 -d, --outdir=       d   Specify an alternate directory 'd' for output
 -d, --outdir=       d   Specify an alternate directory 'd' for output
@@ -50,7 +50,7 @@ help_data = {
                         (default: {g.seed_len})
                         (default: {g.seed_len})
 -p, --hash-preset=  p   Use scrypt.hash() parameters from preset 'p' when
 -p, --hash-preset=  p   Use scrypt.hash() parameters from preset 'p' when
                         hashing password (default: '{g.hash_preset}')
                         hashing password (default: '{g.hash_preset}')
--P, --passwd-file=  f   Get passphrase from file 'f'
+-P, --passwd-file=  f   Get MMGen wallet passphrase from file 'f'
 -q, --quiet             Suppress warnings; overwrite files without
 -q, --quiet             Suppress warnings; overwrite files without
                         prompting
                         prompting
 -S, --stdout            Print {what} to stdout
 -S, --stdout            Print {what} to stdout
@@ -159,8 +159,16 @@ addr_data_str    = format_addr_data(
 		addr_data, addr_data_chksum, seed_id, addr_idxs, opts)
 		addr_data, addr_data_chksum, seed_id, addr_idxs, opts)
 
 
 outfile_base = "{}[{}]".format(seed_id, fmt_addr_idxs(addr_idxs))
 outfile_base = "{}[{}]".format(seed_id, fmt_addr_idxs(addr_idxs))
+if 'addrs' in opts['gen_what']:
+	qmsg("Checksum for address data %s: %s" % (outfile_base,addr_data_chksum))
+	if 'save_checksum' in opts:
+		write_to_file(outfile_base+"."+g.addrfile_chksum_ext,
+			addr_data_chksum+"\n",opts,"address data checksum",True,True,False)
+	else:
+		qmsg("This checksum will be used to verify the address file in the future.")
+		qmsg("Record it to a safe location.")
 
 
-if 'flat_list' in opts and user_confirm("Encrypt key list?"):
+if 'flat_list' in opts and keypress_confirm("Encrypt key list?"):
 	addr_data_str = mmgen_encrypt(addr_data_str,"key list","",opts)
 	addr_data_str = mmgen_encrypt(addr_data_str,"key list","",opts)
 	enc_ext = "." + g.mmenc_ext
 	enc_ext = "." + g.mmenc_ext
 else: enc_ext = ""
 else: enc_ext = ""
@@ -176,15 +184,7 @@ else:
 	confirm_overwrite = False if g.quiet else True
 	confirm_overwrite = False if g.quiet else True
 	outfile = "%s.%s%s" % (outfile_base, (
 	outfile = "%s.%s%s" % (outfile_base, (
 		g.keylist_ext if 'flat_list' in opts else (
 		g.keylist_ext if 'flat_list' in opts else (
-		g.keyfile_ext if opts['gen_what'] == ("keys") else (
-		g.addrfile_ext if opts['gen_what'] == ("addrs") else "akeys"))), enc_ext)
+		g.keyfile_ext if opts['gen_what'] == ["keys"] else (
+		g.addrfile_ext if opts['gen_what'] == ["addrs"] else "akeys"))), enc_ext)
 	write_to_file(outfile,addr_data_str,opts,what,confirm_overwrite,True)
 	write_to_file(outfile,addr_data_str,opts,what,confirm_overwrite,True)
 
 
-if 'addrs' in opts['gen_what']:
-	msg("Checksum for address data {}: {}".format(outfile_base,addr_data_chksum))
-	if 'save_checksum' in opts:
-		a = "address data checksum"
-		write_to_file(outfile_base+".chk",addr_data_chksum,opts,a,False,True)
-	else:
-		qmsg("This checksum will be used to verify the address file in the future.")
-		qmsg("Record it to a safe location.")

+ 1 - 1
mmgen/main_passchg.py

@@ -41,7 +41,7 @@ help_data = {
 -L, --label=            l Change the wallet's label to 'l'
 -L, --label=            l Change the wallet's label to 'l'
 -p, --hash-preset=      p Change scrypt.hash() parameters to preset 'p'
 -p, --hash-preset=      p Change scrypt.hash() parameters to preset 'p'
                           (default: '{g.hash_preset}')
                           (default: '{g.hash_preset}')
--P, --passwd-file=      f Get new passphrase from file 'f'
+-P, --passwd-file=      f Get new MMGen wallet passphrase from file 'f'
 -r, --usr-randchars=    n Get 'n' characters of additional randomness from
 -r, --usr-randchars=    n Get 'n' characters of additional randomness from
                           user (min={g.min_urandchars}, max={g.max_urandchars})
                           user (min={g.min_urandchars}, max={g.max_urandchars})
 -q, --quiet               Suppress warnings; overwrite files without
 -q, --quiet               Suppress warnings; overwrite files without

+ 4 - 4
mmgen/main_txcreate.py

@@ -28,7 +28,7 @@ import mmgen.config as g
 from mmgen.Opts import *
 from mmgen.Opts import *
 from mmgen.license import *
 from mmgen.license import *
 from mmgen.tx import *
 from mmgen.tx import *
-from mmgen.util import msg, msg_r, user_confirm
+from mmgen.util import msg, msg_r, keypress_confirm
 
 
 help_data = {
 help_data = {
 	'prog_name': g.prog_name,
 	'prog_name': g.prog_name,
@@ -165,7 +165,7 @@ while True:
 
 
 	if mmaddrs and len(mmaddrs) < len(sel_unspent):
 	if mmaddrs and len(mmaddrs) < len(sel_unspent):
 		msg(txmsg['mixed_inputs'] % ", ".join(sorted(mmaddrs)))
 		msg(txmsg['mixed_inputs'] % ", ".join(sorted(mmaddrs)))
-		if not user_confirm("Accept?"):
+		if not keypress_confirm("Accept?"):
 			continue
 			continue
 
 
 	total_in = trim_exponent(sum([i.amount for i in sel_unspent]))
 	total_in = trim_exponent(sum([i.amount for i in sel_unspent]))
@@ -173,7 +173,7 @@ while True:
 
 
 	if change >= 0:
 	if change >= 0:
 		prompt = "Transaction produces %s BTC in change.  OK?" % change
 		prompt = "Transaction produces %s BTC in change.  OK?" % change
-		if user_confirm(prompt,default_yes=True):
+		if keypress_confirm(prompt,default_yes=True):
 			break
 			break
 	else:
 	else:
 		msg(txmsg['not_enough_btc'] % change)
 		msg(txmsg['not_enough_btc'] % change)
@@ -206,7 +206,7 @@ if reply and reply in "YyVv":
 	view_tx_data(c,[i.__dict__ for i in sel_unspent],tx_hex,b2m_map,pager=pager)
 	view_tx_data(c,[i.__dict__ for i in sel_unspent],tx_hex,b2m_map,pager=pager)
 
 
 prompt = "Save transaction?"
 prompt = "Save transaction?"
-if user_confirm(prompt,default_yes=True):
+if keypress_confirm(prompt,default_yes=True):
 	amt = send_amt or change
 	amt = send_amt or change
 	tx_id = make_chksum_6(unhexlify(tx_hex)).upper()
 	tx_id = make_chksum_6(unhexlify(tx_hex)).upper()
 	outfile = "tx_%s[%s].%s" % (tx_id,amt,g.rawtx_ext)
 	outfile = "tx_%s[%s].%s" % (tx_id,amt,g.rawtx_ext)

+ 25 - 23
mmgen/main_txsign.py

@@ -44,7 +44,7 @@ help_data = {
                          for online signing without an {pnm} seed source.
                          for online signing without an {pnm} seed source.
                          {pnm}-to-BTC mappings can optionally be verified
                          {pnm}-to-BTC mappings can optionally be verified
                          using address file(s) listed on the command line
                          using address file(s) listed on the command line
--P, --passwd-file=    f  Get passphrase from file 'f'
+-P, --passwd-file=    f  Get MMGen wallet or bitcoind passphrase from file 'f'
 -q, --quiet              Suppress warnings; overwrite files without
 -q, --quiet              Suppress warnings; overwrite files without
                          prompting
                          prompting
 -v, --verbose            Produce more verbose output
 -v, --verbose            Produce more verbose output
@@ -127,7 +127,12 @@ if 'keys_from_file' in opts:
 	keys_from_file = remove_comments(d.split("\n"))
 	keys_from_file = remove_comments(d.split("\n"))
 else: keys_from_file = []
 else: keys_from_file = []
 
 
-for tx_file in tx_files:
+tx_num_str = ""
+for tx_num,tx_file in enumerate(tx_files,1):
+	if len(tx_files) > 1:
+		msg("\nTransaction #%s of %s:" % (tx_num,len(tx_files)))
+		tx_num_str = " #%s" % tx_num
+
 	m = "" if 'tx_id' in opts else "transaction data"
 	m = "" if 'tx_id' in opts else "transaction data"
 	tx_data = get_lines_from_file(tx_file,m)
 	tx_data = get_lines_from_file(tx_file,m)
 
 
@@ -169,11 +174,8 @@ for tx_file in tx_files:
 		check_mmgen_to_btc_addr_mappings(
 		check_mmgen_to_btc_addr_mappings(
 				mmgen_inputs,b2m_map,seed_files,saved_seeds,opts)
 				mmgen_inputs,b2m_map,seed_files,saved_seeds,opts)
 
 
-	if len(tx_files) > 1:
-		msg("\nTransaction %s/%s:" % (tx_files.index(tx_file)+1,len(tx_files)))
-
-	prompt = "View transaction data? (y)es, (N)o, (v)iew in pager"
-	reply = prompt_and_get_char(prompt,"YyNnVv",enter_ok=True)
+	p = "View data for transaction{}? (y)es, (N)o, (v)iew in pager"
+	reply = prompt_and_get_char(p.format(tx_num_str),"YyNnVv",enter_ok=True)
 	if reply and reply in "YyVv":
 	if reply and reply in "YyVv":
 		p = True if reply in "Vv" else False
 		p = True if reply in "Vv" else False
 		view_tx_data(c,inputs_data,tx_hex,b2m_map,metadata,pager=p)
 		view_tx_data(c,inputs_data,tx_hex,b2m_map,metadata,pager=p)
@@ -187,27 +189,27 @@ for tx_file in tx_files:
 		keys += get_keys_for_mmgen_addrs(ml,seed_files,saved_seeds,opts)
 		keys += get_keys_for_mmgen_addrs(ml,seed_files,saved_seeds,opts)
 
 
 		if 'use_wallet_dat' in opts:
 		if 'use_wallet_dat' in opts:
-			sig_tx = sign_tx_with_bitcoind_wallet(c,tx_hex,sig_data,keys,opts)
+			sig_tx = sign_tx_with_bitcoind_wallet(c,tx_hex,tx_num_str,sig_data,keys,opts)
 		else:
 		else:
-			sig_tx = sign_transaction(c,tx_hex,sig_data,keys)
+			sig_tx = sign_transaction(c,tx_hex,tx_num_str,sig_data,keys)
 	elif other_inputs:
 	elif other_inputs:
 		if keys:
 		if keys:
-			sig_tx = sign_transaction(c,tx_hex,sig_data,keys)
+			sig_tx = sign_transaction(c,tx_hex,tx_num_str,sig_data,keys)
 		else:
 		else:
-			sig_tx = sign_tx_with_bitcoind_wallet(c,tx_hex,sig_data,keys,opts)
+			sig_tx = sign_tx_with_bitcoind_wallet(c,tx_hex,tx_num_str,sig_data,keys,opts)
 
 
 	if sig_tx['complete']:
 	if sig_tx['complete']:
-		prompt = "OK\nSave signed transaction?"
-		if user_confirm(prompt,default_yes=True):
-			outfile = "tx_%s[%s].%s" % (metadata[0],metadata[1],g.sigtx_ext)
-			data = "{}\n{}\n{}\n{}\n".format(
-					" ".join(metadata[:2] + [make_timestamp()]),
-					sig_tx['hex'],
-					repr(inputs_data),
-					repr(b2m_map)
-				)
-			confirm = False if g.quiet else True
-			write_to_file(outfile,data,opts,"signed transaction",confirm,True)
+		msg("OK")
+		outfile = "tx_%s[%s].%s" % (metadata[0],metadata[1],g.sigtx_ext)
+		data = "{}\n{}\n{}\n{}\n".format(
+				" ".join(metadata[:2] + [make_timestamp()]),
+				sig_tx['hex'],
+				repr(inputs_data),
+				repr(b2m_map)
+			)
+		w = "signed transaction{}".format(tx_num_str)
+		write_to_file(outfile,data,opts,w,(not g.quiet),True,False)
 	else:
 	else:
-		msg("failed\nSome keys were missing.  Transaction could not be signed.")
+		msg_r("failed\nSome keys were missing.  ")
+		msg("Transaction %scould not be signed." % tx_num_str)
 		sys.exit(3)
 		sys.exit(3)

+ 7 - 7
mmgen/main_walletchk.py

@@ -25,7 +25,7 @@ import sys
 import mmgen.config as g
 import mmgen.config as g
 from mmgen.Opts import *
 from mmgen.Opts import *
 from mmgen.util import *
 from mmgen.util import *
-from mmgen.crypto import get_seed_from_wallet,wallet_to_incog_data
+from mmgen.crypto import get_seed_retry,wallet_to_incog_data
 
 
 help_data = {
 help_data = {
 	'prog_name': g.prog_name,
 	'prog_name': g.prog_name,
@@ -37,7 +37,7 @@ help_data = {
 -h, --help             Print this help message
 -h, --help             Print this help message
 -d, --outdir=       d  Specify an alternate directory 'd' for output
 -d, --outdir=       d  Specify an alternate directory 'd' for output
 -e, --echo-passphrase  Print passphrase to screen when typing it
 -e, --echo-passphrase  Print passphrase to screen when typing it
--P, --passwd-file=  f  Get passphrase from file 'f'
+-P, --passwd-file=  f  Get MMGen wallet passphrase from file 'f'
 -q, --quiet            Suppress warnings; overwrite files without prompting
 -q, --quiet            Suppress warnings; overwrite files without prompting
 -r, --usr-randchars= n Get 'n' characters of additional randomness from
 -r, --usr-randchars= n Get 'n' characters of additional randomness from
                        user (min={g.min_urandchars}, max={g.max_urandchars})
                        user (min={g.min_urandchars}, max={g.max_urandchars})
@@ -89,12 +89,12 @@ elif 'export_incog' in opts:
 		)
 		)
 		data = pretty_hexdump(incog_enc,2,8,line_nums=False) \
 		data = pretty_hexdump(incog_enc,2,8,line_nums=False) \
 					if "export_incog_hex" in opts else incog_enc
 					if "export_incog_hex" in opts else incog_enc
-		export_to_file(fn, data, opts, "incognito wallet data")
+		write_to_file_or_stdout(fn, data, opts, "incognito wallet data")
 
 
 	sys.exit()
 	sys.exit()
 
 
-seed = get_seed_from_wallet(cmd_args[0], opts)
-if seed: qmsg("Wallet is OK")
+seed = get_seed_retry(cmd_args[0], opts)
+if seed: msg("Wallet is OK")
 else:
 else:
 	msg("Error opening wallet")
 	msg("Error opening wallet")
 	sys.exit(2)
 	sys.exit(2)
@@ -105,11 +105,11 @@ if 'export_mnemonic' in opts:
 	p = True if g.debug else False
 	p = True if g.debug else False
 	mn = get_mnemonic_from_seed(seed, wl, g.default_wl, print_info=p)
 	mn = get_mnemonic_from_seed(seed, wl, g.default_wl, print_info=p)
 	fn = "%s.%s" % (make_chksum_8(seed).upper(), g.mn_ext)
 	fn = "%s.%s" % (make_chksum_8(seed).upper(), g.mn_ext)
-	export_to_file(fn, " ".join(mn)+"\n", opts, "mnemonic data")
+	write_to_file_or_stdout(fn, " ".join(mn)+"\n", opts, "mnemonic data")
 
 
 elif 'export_seed' in opts:
 elif 'export_seed' in opts:
 	from mmgen.bitcoin import b58encode_pad
 	from mmgen.bitcoin import b58encode_pad
 	data = col4(b58encode_pad(seed))
 	data = col4(b58encode_pad(seed))
 	chk = make_chksum_6(b58encode_pad(seed))
 	chk = make_chksum_6(b58encode_pad(seed))
 	fn = "%s.%s" % (make_chksum_8(seed).upper(), g.seed_ext)
 	fn = "%s.%s" % (make_chksum_8(seed).upper(), g.seed_ext)
-	export_to_file(fn, "%s %s\n" % (chk,data), opts, "seed data")
+	write_to_file_or_stdout(fn, "%s %s\n" % (chk,data), opts, "seed data")

+ 1 - 1
mmgen/main_walletgen.py

@@ -44,7 +44,7 @@ help_data = {
                            Allowed symbols: A-Z, a-z, 0-9, " ", "_", ".")
                            Allowed symbols: A-Z, a-z, 0-9, " ", "_", ".")
 -p, --hash-preset=      p  Use scrypt.hash() parameters from preset 'p'
 -p, --hash-preset=      p  Use scrypt.hash() parameters from preset 'p'
                            (default: '{g.hash_preset}')
                            (default: '{g.hash_preset}')
--P, --passwd-file=      f  Get passphrase from file 'f'
+-P, --passwd-file=      f  Get MMGen wallet passphrase from file 'f'
 -q, --quiet                Produce quieter output; overwrite files without
 -q, --quiet                Produce quieter output; overwrite files without
                            prompting
                            prompting
 -r, --usr-randchars=    n  Get 'n' characters of additional randomness from
 -r, --usr-randchars=    n  Get 'n' characters of additional randomness from

+ 19 - 16
mmgen/tx.py

@@ -39,7 +39,7 @@ address was specified.
 NOTE: This transaction uses a mixture of both mmgen and non-mmgen inputs,
 NOTE: This transaction uses a mixture of both mmgen and non-mmgen inputs,
 which makes the signing process more complicated.  When signing the
 which makes the signing process more complicated.  When signing the
 transaction, keys for the non-mmgen inputs must be supplied in a separate
 transaction, keys for the non-mmgen inputs must be supplied in a separate
-file using the '-k' option to {}-txsign.
+file using either the '-k' or '-K' option to '{}-txsign'.
 
 
 Selected mmgen inputs: %s""".format(g.proj_name.lower()),
 Selected mmgen inputs: %s""".format(g.proj_name.lower()),
 'too_many_acct_addresses': """
 'too_many_acct_addresses': """
@@ -52,10 +52,9 @@ No data found for MMgen address '%s'. Please import this address into
 your tracking wallet, or supply an address file for it on the command line.
 your tracking wallet, or supply an address file for it on the command line.
 """.strip(),
 """.strip(),
 	'addrfile_warn_msg': """
 	'addrfile_warn_msg': """
-Warning: no data for address '{mmaddr}' was found in the tracking wallet, so
-this information was taken from the user-supplied address file. You're strongly
-advised to import this address into your tracking wallet before proceeding with
-this transaction.  The address will not be tracked until you do so.
+Warning: output address '{mmaddr}' is not in the tracking wallet, which means
+its balance will not be tracked.  You're strongly advised to import the address
+into your tracking wallet before broadcasting this transaction.
 """.strip(),
 """.strip(),
 	'addrfile_fail_msg': """
 	'addrfile_fail_msg': """
 No data for MMgen address '{mmaddr}' could be found in either the tracking
 No data for MMgen address '{mmaddr}' could be found in either the tracking
@@ -496,12 +495,14 @@ def mmaddr2btcaddr_addrfile(mmaddr,addr_data,silent=False):
 				if j[0] == mmidx:
 				if j[0] == mmidx:
 					if not silent:
 					if not silent:
 						msg(txmsg['addrfile_warn_msg'].format(mmaddr=mmaddr))
 						msg(txmsg['addrfile_warn_msg'].format(mmaddr=mmaddr))
-						if not user_confirm("Continue anyway?"):
+						if not keypress_confirm("Continue anyway?"):
 							sys.exit(1)
 							sys.exit(1)
 					return j[1:] if len(j) == 3 else (j[1],"")
 					return j[1:] if len(j) == 3 else (j[1],"")
 
 
 	if silent: return "",""
 	if silent: return "",""
-	else: msg(txmsg['addrfile_fail_msg'].format(mmaddr=mmaddr)); sys.exit(2)
+	else:
+		msg(txmsg['addrfile_fail_msg'].format(mmaddr=mmaddr))
+		sys.exit(2)
 
 
 
 
 def check_mmgen_to_btc_addr_mappings(mmgen_inputs,b2m_map,infiles,saved_seeds,opts):
 def check_mmgen_to_btc_addr_mappings(mmgen_inputs,b2m_map,infiles,saved_seeds,opts):
@@ -594,13 +595,13 @@ def parse_addrs_file(f):
 	sys.exit(3)
 	sys.exit(3)
 
 
 
 
-def sign_transaction(c,tx_hex,sig_data,keys=None):
+def sign_transaction(c,tx_hex,tx_num_str,sig_data,keys=None):
 
 
 	if keys:
 	if keys:
 		qmsg("%s keys total" % len(keys))
 		qmsg("%s keys total" % len(keys))
 		if g.debug: print "Keys:\n  %s" % "\n  ".join(keys)
 		if g.debug: print "Keys:\n  %s" % "\n  ".join(keys)
 
 
-	msg_r("Signing transaction...")
+	msg_r("Signing transaction{}...".format(tx_num_str))
 	from mmgen.rpc import exceptions
 	from mmgen.rpc import exceptions
 	try:
 	try:
 		sig_tx = c.signrawtransaction(tx_hex,sig_data,keys)
 		sig_tx = c.signrawtransaction(tx_hex,sig_data,keys)
@@ -646,18 +647,19 @@ def get_keys_for_mmgen_addrs(mmgen_addrs,infiles,saved_seeds,opts,gen_pairs=Fals
 		from mmgen.addr import generate_addrs
 		from mmgen.addr import generate_addrs
 		if gen_pairs:
 		if gen_pairs:
 			ret += [("{}:{}".format(seed_id,i.num),i.addr)
 			ret += [("{}:{}".format(seed_id,i.num),i.addr)
-				for i in generate_addrs(seed, addr_ids, {'gen_what':["addrs"]})]
+				for i in generate_addrs(seed,addr_ids,
+						{'gen_what':["addrs"]})]
 		else:
 		else:
-			ret += [i.wif for i in generate_addrs(
-						seed,addr_ids,{'gen_what':["keys"]})]
+			ret += [i.wif for i in generate_addrs(seed,addr_ids,
+						{'gen_what':["keys"]})]
 
 
 	return ret
 	return ret
 
 
 
 
-def sign_tx_with_bitcoind_wallet(c,tx_hex,sig_data,keys,opts):
+def sign_tx_with_bitcoind_wallet(c,tx_hex,tx_num_str,sig_data,keys,opts):
 
 
 	try:
 	try:
-		sig_tx = sign_transaction(c,tx_hex,sig_data,keys)
+		sig_tx = sign_transaction(c,tx_hex,tx_num_str,sig_data,keys)
 	except:
 	except:
 		from mmgen.rpc import exceptions
 		from mmgen.rpc import exceptions
 		msg("Using keys in wallet.dat as per user request")
 		msg("Using keys in wallet.dat as per user request")
@@ -672,7 +674,7 @@ def sign_tx_with_bitcoind_wallet(c,tx_hex,sig_data,keys,opts):
 			else:
 			else:
 				msg("Passphrase OK"); break
 				msg("Passphrase OK"); break
 
 
-		sig_tx = sign_transaction(c,tx_hex,sig_data,keys)
+		sig_tx = sign_transaction(c,tx_hex,tx_num_str,sig_data,keys)
 
 
 		msg("Locking wallet")
 		msg("Locking wallet")
 		try:
 		try:
@@ -761,5 +763,6 @@ def check_mmgen_to_btc_addr_mappings_addrfile(mmgen_inputs,b2m_map,addrfiles):
 		sys.exit(3)
 		sys.exit(3)
 
 
 	if missing:
 	if missing:
-		confirm_or_exit(txmsg['missing_mappings'] % " ".join(missing),"continue")
+		confirm_or_exit(txmsg['missing_mappings'] %
+				" ".join(missing),"continue")
 	else: qmsg("Address mappings OK")
 	else: qmsg("Address mappings OK")

+ 22 - 10
mmgen/util.py

@@ -311,6 +311,11 @@ def get_new_passphrase(what, opts, passchg=False):
 
 
 
 
 def confirm_or_exit(message, question, expect="YES"):
 def confirm_or_exit(message, question, expect="YES"):
+	if not confirm_or_false(message, question, expect):
+		msg("Exiting at user request")
+		sys.exit(2)
+
+def confirm_or_false(message, question, expect="YES"):
 
 
 	vmsg("")
 	vmsg("")
 
 
@@ -322,11 +327,11 @@ def confirm_or_exit(message, question, expect="YES"):
 	p = question+"  "+conf_msg if question[0].isupper() else \
 	p = question+"  "+conf_msg if question[0].isupper() else \
 		"Are you sure you want to %s?\n%s" % (question,conf_msg)
 		"Are you sure you want to %s?\n%s" % (question,conf_msg)
 
 
-	if my_raw_input(p).strip() != expect:
-		msg("Exiting at user request")
-		sys.exit(2)
+	ret = True if my_raw_input(p).strip() == expect else False
 
 
 	vmsg("")
 	vmsg("")
+	return ret
+
 
 
 
 
 def write_to_stdout(data, what, confirm=True):
 def write_to_stdout(data, what, confirm=True):
@@ -342,7 +347,7 @@ def write_to_stdout(data, what, confirm=True):
 	sys.stdout.write(data)
 	sys.stdout.write(data)
 
 
 
 
-def write_to_file(outfile,data,opts,what="data",confirm_overwrite=False,verbose=False):
+def write_to_file(outfile,data,opts,what="data",confirm_overwrite=False,verbose=False,exit_on_error=True):
 
 
 	if 'outdir' in opts: outfile = make_full_path(opts['outdir'],outfile)
 	if 'outdir' in opts: outfile = make_full_path(opts['outdir'],outfile)
 
 
@@ -351,7 +356,13 @@ def write_to_file(outfile,data,opts,what="data",confirm_overwrite=False,verbose=
 	except: pass
 	except: pass
 	else:
 	else:
 		if confirm_overwrite:
 		if confirm_overwrite:
-			confirm_or_exit("","File '%s' already exists\nOverwrite?" % outfile)
+			q = "File '%s' already exists\nOverwrite?" % outfile
+			if exit_on_error:
+				confirm_or_exit("",q)
+			else:
+				if not confirm_or_false("",q):
+					msg("Not overwriting file at user request")
+					return False
 		else:
 		else:
 			msg("Overwriting file '%s'" % outfile)
 			msg("Overwriting file '%s'" % outfile)
 
 
@@ -364,11 +375,12 @@ def write_to_file(outfile,data,opts,what="data",confirm_overwrite=False,verbose=
 	f.close
 	f.close
 
 
 	if verbose: msg("%s written to file '%s'" % (what.capitalize(),outfile))
 	if verbose: msg("%s written to file '%s'" % (what.capitalize(),outfile))
+	return True
 
 
 
 
-def export_to_file(outfile, data, opts, what="data"):
+def write_to_file_or_stdout(outfile, data, opts, what="data"):
 
 
-	if 'stdout' in opts:
+	if 'stdout' in opts or not sys.stdout.isatty():
 		write_to_stdout(data, what, confirm=True)
 		write_to_stdout(data, what, confirm=True)
 	else:
 	else:
 		confirm_overwrite = False if g.quiet else True
 		confirm_overwrite = False if g.quiet else True
@@ -615,9 +627,9 @@ def mark_passwd_file_as_used(opts):
 	passwd_file_used = True
 	passwd_file_used = True
 
 
 
 
-def get_mmgen_passphrase(pinfo,opts,passchg=False):
+def get_mmgen_passphrase(prompt_info,opts,passchg=False):
 	prompt = "Enter {}passphrase for {}: ".format(
 	prompt = "Enter {}passphrase for {}: ".format(
-			"old " if passchg else "",pinfo)
+			"old " if passchg else "",prompt_info)
 	if 'passwd_file' in opts:
 	if 'passwd_file' in opts:
 		mark_passwd_file_as_used(opts)
 		mark_passwd_file_as_used(opts)
 		return " ".join(_get_words_from_file(opts['passwd_file'],"passphrase"))
 		return " ".join(_get_words_from_file(opts['passwd_file'],"passphrase"))
@@ -712,7 +724,7 @@ def my_raw_input(prompt,echo=True):
 	return reply
 	return reply
 
 
 
 
-def user_confirm(prompt,default_yes=False,verbose=False):
+def keypress_confirm(prompt,default_yes=False,verbose=False):
 
 
 	q = "(Y/n)" if default_yes else "(y/N)"
 	q = "(Y/n)" if default_yes else "(y/N)"