Browse Source

Longer checksum for addrfile, bugfixes, code cleanups

philemon 10 years ago
parent
commit
791fc1910f
14 changed files with 170 additions and 245 deletions
  1. 31 22
      mmgen-addrgen
  2. 1 1
      mmgen-addrimport
  3. 5 6
      mmgen-pywallet
  4. 7 7
      mmgen-tool
  5. 17 10
      mmgen-txcreate
  6. 5 6
      mmgen-txsend
  7. 13 6
      mmgen-txsign
  8. 5 5
      mmgen-walletchk
  9. 4 5
      mmgen-walletgen
  10. 13 52
      mmgen/addr.py
  11. 3 0
      mmgen/config.py
  12. 3 2
      mmgen/tool.py
  13. 36 84
      mmgen/tx.py
  14. 27 39
      mmgen/util.py

+ 31 - 22
mmgen-addrgen

@@ -29,17 +29,19 @@ from mmgen.Opts import *
 from mmgen.license import *
 from mmgen.license import *
 from mmgen.util import *
 from mmgen.util import *
 from mmgen.addr import *
 from mmgen.addr import *
+from mmgen.tx import make_addr_data_chksum
 
 
 gen_what = "addresses" if sys.argv[0].split("-")[-1] == "addrgen" else "keys"
 gen_what = "addresses" if sys.argv[0].split("-")[-1] == "addrgen" else "keys"
 
 
 help_data = {
 help_data = {
-	'prog_name': sys.argv[0].split("/")[-1],
+	'prog_name': g.prog_name,
 	'desc': """Generate a list or range of {} from an {g.proj_name} wallet,
 	'desc': """Generate a list or range of {} from an {g.proj_name} wallet,
                   mnemonic, seed or password""".format(gen_what,g=g),
                   mnemonic, seed or password""".format(gen_what,g=g),
 	'usage':"[opts] [infile] <address list>",
 	'usage':"[opts] [infile] <address 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
+-c, --save-checksum     Save address list checksum to file
 -e, --echo-passphrase   Echo passphrase or mnemonic to screen upon entry{}
 -e, --echo-passphrase   Echo passphrase or mnemonic to screen upon entry{}
 -H, --show-hash-presets Show information on available hash presets
 -H, --show-hash-presets Show information on available hash presets
 -K, --no-keyconv        Use internal libraries for address generation
 -K, --no-keyconv        Use internal libraries for address generation
@@ -66,10 +68,10 @@ help_data = {
 """.format(
 """.format(
 		*(
 		*(
 		   (
 		   (
-"\n-A, --no-addresses       Print only secret keys, no addresses",
-"\n-f, --flat-list          Produce a flat list of keys suitable for use with" +
-"\n                         'mmgen-txsign'",
-"\n-x, --b16                Print secret keys in hexadecimal too"
+"\n-A, --no-addresses      Print only secret keys, no addresses",
+"\n-f, --flat-list         Produce a flat list of keys suitable for use with" +
+"\n                        '{}-txsign'".format(g.proj_name.lower()),
+"\n-x, --b16               Print secret keys in hexadecimal too"
 			)
 			)
 		if gen_what == "keys" else ("","","")),
 		if gen_what == "keys" else ("","","")),
 		seed_lens=", ".join([str(i) for i in g.seed_lens]),
 		seed_lens=", ".join([str(i) for i in g.seed_lens]),
@@ -148,29 +150,36 @@ if gen_what == "addresses":
 else:
 else:
 	if not 'no_addresses' in opts: opts['print_secret'] = True
 	if not 'no_addresses' in opts: opts['print_secret'] = True
 
 
-seed          = get_seed_retry(infile,opts)
-seed_id       = make_chksum_8(seed)
+seed    = get_seed_retry(infile,opts)
+seed_id = make_chksum_8(seed)
 
 
-addr_data     = generate_addrs(seed, addr_idxs, opts)
-addr_data_chksum = make_chksum_8(
-	" ".join(["{} {}".format(a['num'],a['addr']) for a in addr_data]),
-	sep=True
-)
-addr_data_str = format_addr_data(
+addr_data        = generate_addrs(seed, addr_idxs, opts)
+addr_data_chksum = make_addr_data_chksum([(a['num'],a['addr'])
+		for a in addr_data]) if not 'no_addresses' in opts else ""
+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))
+
 # Output data:
 # Output data:
 if 'stdout' in opts:
 if 'stdout' in opts:
-	if gen_what == "keys" and not g.quiet:
-		confirm = True
-	else: confirm = False
+	confirm = True if (gen_what == "keys" and not g.quiet) else False
 	write_to_stdout(addr_data_str,gen_what,confirm)
 	write_to_stdout(addr_data_str,gen_what,confirm)
 elif not sys.stdout.isatty():
 elif not sys.stdout.isatty():
 	write_to_stdout(addr_data_str,gen_what,confirm=False)
 	write_to_stdout(addr_data_str,gen_what,confirm=False)
 else:
 else:
-	write_addr_data_to_file(seed, addr_data_str, addr_idxs, opts)
-
-msg("""
-Checksum for address data {}[{}]: {}
-Remember this checksum or save it to a secure location
-""".format(seed_id, fmt_addr_idxs(addr_idxs), addr_data_chksum).strip())
+	confirm = False if g.quiet else True
+	outfile = outfile_base + "." + (
+		g.addrfile_ext if 'print_addresses_only' in opts else (
+		g.keyfile_ext if 'no_addresses' in opts else (
+		g.keylist_ext if 'flat_list' in opts else "akeys"))
+	)
+	write_to_file(outfile,addr_data_str,opts,gen_what,confirm,True)
+
+if not 'no_addresses' in opts:
+	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,confirm,True)
+	else:
+		qmsg("Save this information to a secure location")

+ 1 - 1
mmgen-addrimport

@@ -27,7 +27,7 @@ from mmgen.util import *
 from mmgen.tx import connect_to_bitcoind,parse_addrs_file
 from mmgen.tx import connect_to_bitcoind,parse_addrs_file
 
 
 help_data = {
 help_data = {
-	'prog_name': sys.argv[0].split("/")[-1],
+	'prog_name': g.prog_name,
 	'desc': """Import addresses (both {pnm} and non-{pnm}) into a bitcoind
 	'desc': """Import addresses (both {pnm} and non-{pnm}) into a bitcoind
                      watching wallet""".format(pnm=g.proj_name),
                      watching wallet""".format(pnm=g.proj_name),
 	'usage':"[opts] [mmgen address file]",
 	'usage':"[opts] [mmgen address file]",

+ 5 - 6
mmgen-pywallet

@@ -43,9 +43,6 @@ mmgen-pywallet: Dump contents of a bitcoind wallet to file
 # Alex Martelli (http://www.aleax.it)
 # Alex Martelli (http://www.aleax.it)
 # Ported from C code written by Laurent Haan (http://www.progressive-coding.com)
 # Ported from C code written by Laurent Haan (http://www.progressive-coding.com)
 
 
-from mmgen.Opts import *
-from mmgen.util import msg
-import mmgen.config as g
 from bsddb.db import *
 from bsddb.db import *
 import sys, time
 import sys, time
 import json
 import json
@@ -61,16 +58,18 @@ import hashlib
 import random
 import random
 import math
 import math
 
 
+import mmgen.config as g
+from mmgen.Opts import *
+from mmgen.util import msg
+
 max_version = 60000
 max_version = 60000
 addrtype = 0
 addrtype = 0
 json_db = {}
 json_db = {}
 private_keys = []
 private_keys = []
 password = None
 password = None
 
 
-prog_name = sys.argv[0].split("/")[-1]
-
 help_data = {
 help_data = {
-	'prog_name': prog_name,
+	'prog_name': g.prog_name,
 	'desc':    "Dump contents of a bitcoind wallet to file",
 	'desc':    "Dump contents of a bitcoind wallet to file",
 	'usage':   "[opts] <bitcoind wallet file>",
 	'usage':   "[opts] <bitcoind wallet file>",
 	'options': """
 	'options': """

+ 7 - 7
mmgen-tool

@@ -22,17 +22,17 @@ mmgen-tool: Perform various Bitcoin-related operations - part of the MMGen suite
 import sys, os
 import sys, os
 from hashlib import sha256
 from hashlib import sha256
 
 
-from mmgen.Opts import *
 import mmgen.config as g
 import mmgen.config as g
-from mmgen.util import pretty_hexdump
 import mmgen.tool as tool
 import mmgen.tool as tool
-prog_name = sys.argv[0].split("/")[-1]
+from mmgen.Opts import *
+from mmgen.util import pretty_hexdump
 
 
 help_data = {
 help_data = {
-	'prog_name': prog_name,
+	'prog_name': g.prog_name,
 	'desc':    "Perform various BTC-related operations",
 	'desc':    "Perform various BTC-related operations",
 	'usage':   "[opts] <command> <args>",
 	'usage':   "[opts] <command> <args>",
 	'options': """
 	'options': """
+-d, --outdir=       d Specify an alternate directory 'd' for output
 -h, --help            Print this help message
 -h, --help            Print this help message
 -q, --quiet           Produce quieter output
 -q, --quiet           Produce quieter output
 -r, --usr-randchars=n Get 'n' characters of additional randomness from
 -r, --usr-randchars=n Get 'n' characters of additional randomness from
@@ -44,7 +44,7 @@ help_data = {
 COMMANDS:{}
 COMMANDS:{}
 Type '{} <command> --help for usage information on a particular
 Type '{} <command> --help for usage information on a particular
 command
 command
-""".format(tool.command_help,prog_name)
+""".format(tool.command_help,g.prog_name)
 }
 }
 
 
 opts,cmd_args = parse_opts(sys.argv,help_data)
 opts,cmd_args = parse_opts(sys.argv,help_data)
@@ -63,10 +63,10 @@ if command not in tool.commands.keys():
 	sys.exit(1)
 	sys.exit(1)
 
 
 if cmd_args and cmd_args[0] == '--help':
 if cmd_args and cmd_args[0] == '--help':
-	tool.tool_usage(prog_name, command)
+	tool.tool_usage(g.prog_name, command)
 	sys.exit(0)
 	sys.exit(0)
 
 
-args = tool.process_args(prog_name, command, cmd_args)
+args = tool.process_args(g.prog_name, command, cmd_args)
 
 
 tool.opts = opts
 tool.opts = opts
 
 

+ 17 - 10
mmgen-txcreate

@@ -20,19 +20,16 @@ mmgen-txcreate: Create a BTC transaction, sending to specified addresses
 """
 """
 
 
 import sys
 import sys
-#from hashlib import sha256
+from decimal import Decimal
 
 
+import mmgen.config as g
 from mmgen.Opts import *
 from mmgen.Opts import *
 from mmgen.license import *
 from mmgen.license import *
-import mmgen.config as g
 from mmgen.tx import *
 from mmgen.tx import *
 from mmgen.util import msg, msg_r, user_confirm
 from mmgen.util import msg, msg_r, user_confirm
-from decimal import Decimal
-
-prog_name = sys.argv[0].split("/")[-1]
 
 
 help_data = {
 help_data = {
-	'prog_name': prog_name,
+	'prog_name': g.prog_name,
 	'desc':    "Create a BTC transaction with outputs to specified addresses",
 	'desc':    "Create a BTC transaction with outputs to specified addresses",
 	'usage':   "[opts]  <addr,amt> ... [change addr] [addr file] ...",
 	'usage':   "[opts]  <addr,amt> ... [change addr] [addr file] ...",
 	'options': """
 	'options': """
@@ -69,6 +66,7 @@ if g.debug: show_opts_and_cmd_args(opts,cmd_args)
 c = connect_to_bitcoind()
 c = connect_to_bitcoind()
 
 
 if not 'info' in opts:
 if not 'info' in opts:
+	do_license_msg(immed=True)
 
 
 	tx_out,addr_data,b2m_map,acct_data,change_addr = {},[],{},[],""
 	tx_out,addr_data,b2m_map,acct_data,change_addr = {},[],{},[],""
 
 
@@ -132,9 +130,9 @@ if not 'info' in opts:
 
 
 if g.debug: show_opts_and_cmd_args(opts,cmd_args)
 if g.debug: show_opts_and_cmd_args(opts,cmd_args)
 
 
-if not 'info' in opts: do_license_msg(immed=True)
+#write_to_file("bogus_unspent.json", repr(us), opts); sys.exit()
 
 
-#write_to_file("bogus_unspent.json", repr(us)); sys.exit()
+#if False:
 if g.bogus_wallet_data:
 if g.bogus_wallet_data:
 	import mmgen.rpc
 	import mmgen.rpc
 	us = eval(get_data_from_file(g.bogus_wallet_data))
 	us = eval(get_data_from_file(g.bogus_wallet_data))
@@ -143,7 +141,7 @@ else:
 
 
 if not us: msg(txmsg['no_spendable_outputs']); sys.exit(2)
 if not us: msg(txmsg['no_spendable_outputs']); sys.exit(2)
 
 
-unspent = sort_and_view(us)
+unspent = sort_and_view(us,opts)
 
 
 total = trim_exponent(sum([i.amount for i in unspent]))
 total = trim_exponent(sum([i.amount for i in unspent]))
 
 
@@ -209,6 +207,15 @@ if reply and reply in "YyVv":
 
 
 prompt = "Save transaction?"
 prompt = "Save transaction?"
 if user_confirm(prompt,default_yes=True):
 if user_confirm(prompt,default_yes=True):
-	write_tx_to_file(tx_hex,sel_unspent,send_amt or change,b2m_map,opts)
+	amt = send_amt or change
+	tx_id = make_chksum_6(unhexlify(tx_hex)).upper()
+	outfile = "tx_%s[%s].%s" % (tx_id,amt,g.rawtx_ext)
+	data = "{} {} {}\n{}\n{}\n{}\n".format(
+			tx_id, amt, make_timestamp(),
+			tx_hex,
+			repr([i.__dict__ for i in sel_unspent]),
+			repr(b2m_map)
+		)
+	write_to_file(outfile,data,opts,"transaction",False,True)
 else:
 else:
 	msg("Transaction not saved")
 	msg("Transaction not saved")

+ 5 - 6
mmgen-txsend

@@ -21,17 +21,15 @@ mmgen-txsend: Broadcast a Bitcoin transaction to the network
 
 
 import sys
 import sys
 
 
+import mmgen.config as g
 from mmgen.Opts import *
 from mmgen.Opts import *
 from mmgen.license import *
 from mmgen.license import *
-import mmgen.config as g
 from mmgen.tx import *
 from mmgen.tx import *
 from mmgen.util import msg,check_infile,get_lines_from_file,confirm_or_exit
 from mmgen.util import msg,check_infile,get_lines_from_file,confirm_or_exit
 
 
-prog_name = sys.argv[0].split("/")[-1]
-
 help_data = {
 help_data = {
-	'prog_name': prog_name,
-	'desc':    "Send a Bitcoin transaction signed by mmgen-txsign",
+	'prog_name': g.prog_name,
+	'desc':    "Send a Bitcoin transaction signed by {}-txsign".format(g.proj_name.lower()),
 	'usage':   "[opts] <signed transaction file>",
 	'usage':   "[opts] <signed transaction file>",
 	'options': """
 	'options': """
 -h, --help      Print this help message
 -h, --help      Print this help message
@@ -84,4 +82,5 @@ except:
 
 
 msg("Transaction sent: %s" % tx_id)
 msg("Transaction sent: %s" % tx_id)
 
 
-write_sent_tx_num_to_file(tx_id,metadata,opts)
+of = "tx_{}[{}].out".format(*metadata[:2])
+write_to_file(of, tx_id+"\n",opts,"transaction ID",True,True)

+ 13 - 6
mmgen-txsign

@@ -21,15 +21,15 @@ mmgen-txsign: Sign a Bitcoin transaction generated by mmgen-txcreate
 
 
 import sys
 import sys
 
 
+import mmgen.config as g
 from mmgen.Opts import *
 from mmgen.Opts import *
 from mmgen.license import *
 from mmgen.license import *
-import mmgen.config as g
 from mmgen.tx import *
 from mmgen.tx import *
 from mmgen.util import msg,qmsg
 from mmgen.util import msg,qmsg
 
 
 help_data = {
 help_data = {
-	'prog_name': sys.argv[0].split("/")[-1],
-	'desc':    "Sign Bitcoin transactions generated by mmgen-txcreate",
+	'prog_name': g.prog_name,
+	'desc':    "Sign Bitcoin transactions generated by {}-txcreate".format(g.proj_name.lower()),
 	'usage':   "[opts] <transaction file> .. [mmgen wallet/seed/words/brainwallet file] .. [addrfile] ..",
 	'usage':   "[opts] <transaction file> .. [mmgen wallet/seed/words/brainwallet file] .. [addrfile] ..",
 	'options': """
 	'options': """
 -h, --help               Print this help message
 -h, --help               Print this help message
@@ -63,7 +63,7 @@ help_data = {
 Transactions with either {pnm} or non-{pnm} input addresses may be signed.
 Transactions with either {pnm} or non-{pnm} input addresses may be signed.
 For non-{pnm} inputs, the bitcoind wallet.dat is used as the key source.
 For non-{pnm} inputs, the bitcoind wallet.dat is used as the key source.
 For {pnm} inputs, key data is generated from your seed as with the
 For {pnm} inputs, key data is generated from your seed as with the
-mmgen-addrgen and mmgen-keygen utilities.
+{pnl}-addrgen and {pnl}-keygen utilities.
 
 
 Data for the --from-<what> options will be taken from a file if a second
 Data for the --from-<what> options will be taken from a file if a second
 file is specified on the command line.  Otherwise, the user will be
 file is specified on the command line.  Otherwise, the user will be
@@ -84,7 +84,7 @@ Seed data supplied in files must have the following extensions:
    seed:        '.{g.seed_ext}'
    seed:        '.{g.seed_ext}'
    mnemonic:    '.{g.mn_ext}'
    mnemonic:    '.{g.mn_ext}'
    brainwallet: '.{g.brain_ext}'
    brainwallet: '.{g.brain_ext}'
-""".format(g=g,pnm=g.proj_name)
+""".format(g=g,pnm=g.proj_name,pnl=g.proj_name.lower())
 }
 }
 
 
 opts,infiles = parse_opts(sys.argv,help_data)
 opts,infiles = parse_opts(sys.argv,help_data)
@@ -184,7 +184,14 @@ for tx_file in tx_files:
 	if sig_tx['complete']:
 	if sig_tx['complete']:
 		prompt = "OK\nSave signed transaction?"
 		prompt = "OK\nSave signed transaction?"
 		if user_confirm(prompt,default_yes=True):
 		if user_confirm(prompt,default_yes=True):
-			write_signed_tx_to_file(tx_hex,sig_tx['hex'],metadata,inputs_data,b2m_map,opts)
+			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)
+				)
+			write_to_file(outfile,data,opts,"signed transaction",True,True)
 	else:
 	else:
 		msg("failed\nSome keys were missing.  Transaction could not be signed.")
 		msg("failed\nSome keys were missing.  Transaction could not be signed.")
 		sys.exit(3)
 		sys.exit(3)

+ 5 - 5
mmgen-walletchk

@@ -21,12 +21,12 @@ mmgen-walletchk: Check integrity of a mmgen deterministic wallet, display
 """
 """
 
 
 import sys
 import sys
+import mmgen.config as g
 from mmgen.Opts import *
 from mmgen.Opts import *
-
 from mmgen.util import *
 from mmgen.util import *
 
 
 help_data = {
 help_data = {
-	'prog_name': sys.argv[0].split("/")[-1],
+	'prog_name': g.prog_name,
 	'desc':  """Check integrity of an {} deterministic wallet, display
 	'desc':  """Check integrity of an {} deterministic wallet, display
                     its information, and export seed and mnemonic data.
                     its information, and export seed and mnemonic data.
              """.format(g.proj_name),
              """.format(g.proj_name),
@@ -89,7 +89,7 @@ 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, "incognito wallet data", opts)
+		export_to_file(fn, data, opts, "incognito wallet data")
 
 
 	sys.exit()
 	sys.exit()
 
 
@@ -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", "mnemonic data", opts)
+	export_to_file(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), "seed data", opts)
+	export_to_file(fn, "%s %s\n" % (chk,data), opts, "seed data")

+ 4 - 5
mmgen-walletgen

@@ -22,15 +22,14 @@ mmgen-walletgen: Generate a mmgen deterministic wallet
 import sys, os
 import sys, os
 from hashlib import sha256
 from hashlib import sha256
 
 
+import mmgen.config as g
 from mmgen.Opts import *
 from mmgen.Opts import *
 from mmgen.license import *
 from mmgen.license import *
-import mmgen.config as g
 from mmgen.walletgen import *
 from mmgen.walletgen import *
 from mmgen.util import *
 from mmgen.util import *
-prog_name = sys.argv[0].split("/")[-1]
 
 
 help_data = {
 help_data = {
-	'prog_name': prog_name,
+	'prog_name': g.prog_name,
 	'desc':    "Generate an {} deterministic wallet".format(g.proj_name),
 	'desc':    "Generate an {} deterministic wallet".format(g.proj_name),
 	'usage':   "[opts] [infile]",
 	'usage':   "[opts] [infile]",
 	'options': """
 	'options': """
@@ -61,7 +60,7 @@ help_data = {
 	'notes': """
 	'notes': """
 
 
 By default (i.e. when invoked without any of the '--from-<what>' options),
 By default (i.e. when invoked without any of the '--from-<what>' options),
-{prog_name} generates a wallet based on a random seed.
+{g.prog_name} generates a wallet based on a random seed.
 
 
 Data for the --from-<what> options will be taken from <infile> if <infile>
 Data for the --from-<what> options will be taken from <infile> if <infile>
 is specified.  Otherwise, the user will be prompted to enter the data.
 is specified.  Otherwise, the user will be prompted to enter the data.
@@ -91,7 +90,7 @@ the '--seed-len' option.
 For a brainwallet passphrase to always generate the same keys and
 For a brainwallet passphrase to always generate the same keys and
 addresses, the same 'l' and 'p' parameters to '--from-brain' must be used
 addresses, the same 'l' and 'p' parameters to '--from-brain' must be used
 in all future invocations with that passphrase.
 in all future invocations with that passphrase.
-""".format(prog_name=prog_name)
+""".format(g=g)
 }
 }
 
 
 opts,cmd_args = parse_opts(sys.argv,help_data)
 opts,cmd_args = parse_opts(sys.argv,help_data)

+ 13 - 52
mmgen/addr.py

@@ -133,43 +133,27 @@ def format_addr_data(addr_data, addr_data_chksum, seed_id, addr_idxs, opts):
 
 
 	start = addr_data[0]['num']
 	start = addr_data[0]['num']
 	end   = addr_data[-1]['num']
 	end   = addr_data[-1]['num']
+	fs = "  %-{}s  %s".format(len(str(end)))
+	out = []
 
 
-	wif_msg = ""
-	if ('b16' in opts and 'print_secret' in opts) \
-		or 'no_addresses' in opts:
-			wif_msg = " (wif)"
-
-	fa = "%s%%-%ss %%-%ss %%s" % (
-			" "*2, len(str(end)) + (0 if 'no_addresses' in opts else 1),
-			(5 if 'print_secret' in opts else 1) + len(wif_msg)
-		)
+	if not 'no_addresses' in opts:
+		if not 'stdout' in opts: out.append(addrmsgs['addrfile_header'] + "\n")
+		out.append("# Address data checksum for {}[{}]: {}".format(
+					seed_id, fmt_addr_idxs(addr_idxs), addr_data_chksum))
+		out.append("# Record this value to a secure location\n")
 
 
-	out = []
-	if not 'stdout' in opts: out.append(addrmsgs['addrfile_header'] + "\n")
-	out.append("# Address data checksum for {}[{}]: {}".format(
-				seed_id, fmt_addr_idxs(addr_idxs), addr_data_chksum))
-	out.append("# Record this value to a secure location\n")
 	out.append("%s {" % seed_id.upper())
 	out.append("%s {" % seed_id.upper())
 
 
 	for d in addr_data:
 	for d in addr_data:
-		col1 = d['num']
 		if 'no_addresses' in opts:
 		if 'no_addresses' in opts:
-			if 'b16' in opts:
-				out.append(fa % (col1, " (hex):", d['sec']))
-				col1 = ""
-			out.append(fa % (col1, " (wif):", d['wif']))
-			if 'b16' in opts: out.append("")
-		elif 'print_secret' in opts:
-			if 'b16' in opts:
-				out.append(fa % (col1, "sec (hex):", d['sec']))
-				col1 = ""
-			out.append(fa % (col1, "sec"+wif_msg+":", d['wif']))
-			out.append(fa % ("",   "addr:", d['addr']))
-			out.append("")
+			out.append(fs % (d['num'], "wif: " + d['wif']))
 		else:
 		else:
-			out.append(fa % (col1, "", d['addr']))
+			out.append(fs % (d['num'], d['addr']))
+		if 'b16' in opts:
+			out.append(fs % ("", "hex: " + d['sec']))
+		if 'print_secret' in opts and not 'no_addresses' in opts:
+			out.append(fs % ("", "wif: " + d['wif']))
 
 
-	if not out[-1]: out.pop()
 	out.append("}")
 	out.append("}")
 
 
 	return "\n".join(out) + "\n"
 	return "\n".join(out) + "\n"
@@ -191,26 +175,3 @@ def fmt_addr_idxs(addr_idxs):
 		prev = i
 		prev = i
 
 
 	return "".join([str(i) for i in ret])
 	return "".join([str(i) for i in ret])
-
-
-def write_addr_data_to_file(seed, addr_data_str, addr_idxs, opts):
-
-	if 'print_addresses_only' in opts: ext = g.addrfile_ext
-	elif 'no_addresses' in opts:       ext = g.keyfile_ext
-	elif 'flat_list' in opts:          ext = g.keylist_ext
-	else:                              ext = "akeys"
-
-	if 'b16' in opts: ext = ext.replace("keys","xkeys")
-	from mmgen.util import write_to_file, make_chksum_8
-	outfile = "{}[{}].{}".format(
-			make_chksum_8(seed),
-			fmt_addr_idxs(addr_idxs),
-			ext
-		)
-	if 'outdir' in opts:
-		outfile = "%s/%s" % (opts['outdir'], outfile)
-
-	write_to_file(outfile,addr_data_str)
-
-	dtype = "Address" if 'print_addresses_only' in opts else "Key"
-	msg("%s data saved to file '%s'" % (dtype,outfile))

+ 3 - 0
mmgen/config.py

@@ -19,6 +19,9 @@
 config.py:  Constants and configuration options for the mmgen suite
 config.py:  Constants and configuration options for the mmgen suite
 """
 """
 
 
+import sys, os
+prog_name = os.path.basename(sys.argv[0])
+
 author = "Philemon"
 author = "Philemon"
 email = "<mmgen-py@yandex.com>"
 email = "<mmgen-py@yandex.com>"
 Cdates = '2013-2014'
 Cdates = '2013-2014'

+ 3 - 2
mmgen/tool.py

@@ -420,7 +420,8 @@ def encrypt(infile,outfile="",hash_preset=''):
 	enc_d = encrypt_data(sha256(nonce+d).digest() + nonce + d, key,
 	enc_d = encrypt_data(sha256(nonce+d).digest() + nonce + d, key,
 				int(ba.hexlify(iv),16))
 				int(ba.hexlify(iv),16))
 	if outfile == '-':  sys.stdout.write(salt+iv+enc_d)
 	if outfile == '-':  sys.stdout.write(salt+iv+enc_d)
-	else: write_to_file((outfile or infile+"."+g.mmenc_ext),salt+iv+enc_d,True,True)
+	else: write_to_file((outfile or infile+"."+g.mmenc_ext),
+			salt+iv+enc_d,opts,"encrypted data",True,True)
 
 
 def decrypt(infile,outfile="",hash_preset=''):
 def decrypt(infile,outfile="",hash_preset=''):
 	d = get_data_from_file(infile,"encrypted data")
 	d = get_data_from_file(infile,"encrypted data")
@@ -439,6 +440,6 @@ def decrypt(infile,outfile="",hash_preset=''):
 			import re
 			import re
 			of = re.sub(r'\.%s$'%g.mmenc_ext,r'',infile)
 			of = re.sub(r'\.%s$'%g.mmenc_ext,r'',infile)
 			if of == infile: of = infile+".dec"
 			if of == infile: of = infile+".dec"
-			write_to_file((outfile or of), out, True,True)
+			write_to_file((outfile or of),out,opts,"decrypted data",True,True)
 	else:
 	else:
 		msg("Incorrect passphrase or hash preset")
 		msg("Incorrect passphrase or hash preset")

+ 36 - 84
mmgen/tx.py

@@ -19,11 +19,12 @@
 tx.py:  Bitcoin transaction routines
 tx.py:  Bitcoin transaction routines
 """
 """
 
 
-from binascii import unhexlify
-from mmgen.util import *
 import sys, os
 import sys, os
+from binascii import unhexlify
 from decimal import Decimal
 from decimal import Decimal
+
 import mmgen.config as g
 import mmgen.config as g
+from mmgen.util import *
 
 
 txmsg = {
 txmsg = {
 'not_enough_btc': "Not enough BTC in the inputs for this transaction (%s BTC)",
 'not_enough_btc': "Not enough BTC in the inputs for this transaction (%s BTC)",
@@ -35,9 +36,9 @@ 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 mmgen-txsign.
+file using the '-k' option to {}-txsign.
 
 
-Selected mmgen inputs: %s""",
+Selected mmgen inputs: %s""".format(g.proj_name.lower()),
 'too_many_acct_addresses': """
 'too_many_acct_addresses': """
 ERROR: More than one address found for account: "%s".
 ERROR: More than one address found for account: "%s".
 The tracking "wallet.dat" file appears to have been altered by a non-{g.proj_name}
 The tracking "wallet.dat" file appears to have been altered by a non-{g.proj_name}
@@ -60,8 +61,8 @@ tracking wallet, or supply an address file for it on the command line.
 """.strip(),
 """.strip(),
 	'no_spendable_outputs': """
 	'no_spendable_outputs': """
 No spendable outputs found!  Import addresses with balances into your
 No spendable outputs found!  Import addresses with balances into your
-watch-only wallet using 'mmgen-addrimport' and then re-run this program.
-""".strip(),
+watch-only wallet using '{}-addrimport' and then re-run this program.
+""".strip().format(g.proj_name.lower()),
 	'mapping_error': """
 	'mapping_error': """
 MMGen -> BTC address mappings differ!
 MMGen -> BTC address mappings differ!
 In transaction:      %s
 In transaction:      %s
@@ -82,12 +83,6 @@ The {pnm}-to-BTC mappings for these addresses cannot be verified!
 """.strip().format(pnm=g.proj_name),
 """.strip().format(pnm=g.proj_name),
 }
 }
 
 
-# Deleted text:
-# Alternatively, you may import the mmgen keys into the wallet.dat of your
-# offline bitcoind, first generating the required keys with mmgen-keygen and
-# then running mmgen-txsign with the '-f' option to force the use of
-# wallet.dat as the key source.
-
 
 
 def connect_to_bitcoind():
 def connect_to_bitcoind():
 
 
@@ -168,44 +163,6 @@ def get_bitcoind_cfg_options(cfg_keys):
 	return cfg
 	return cfg
 
 
 
 
-def write_tx_to_file(tx,sel_unspent,send_amt,b2m_map,opts):
-	tx_id = make_chksum_6(unhexlify(tx)).upper()
-	outfile = "tx_%s[%s].%s" % (tx_id,send_amt,g.rawtx_ext)
-	if 'outdir' in opts:
-		outfile = "%s/%s" % (opts['outdir'], outfile)
-	data = "{} {} {}\n{}\n{}\n{}\n".format(
-			tx_id, send_amt, make_timestamp(),
-			tx,
-			repr([i.__dict__ for i in sel_unspent]),
-			repr(b2m_map)
-		)
-	write_to_file(outfile,data,confirm=False)
-	msg("Transaction data saved to file '%s'" % outfile)
-
-
-def write_signed_tx_to_file(tx,sig_tx,metadata,inputs_data,b2m_map,opts):
-	tx_id = make_chksum_6(unhexlify(tx)).upper()
-	outfile = "tx_%s[%s].%s" % (metadata[0],metadata[1],g.sigtx_ext)
-	if 'outdir' in opts:
-		outfile = "%s/%s" % (opts['outdir'], outfile)
-	data = "{}\n{}\n{}\n{}\n".format(
-			" ".join(metadata[:2] + [make_timestamp()]),
-			sig_tx,
-			repr(inputs_data),
-			repr(b2m_map)
-		)
-	write_to_file(outfile,data,confirm=False)
-	msg("Signed transaction saved to file '%s'" % outfile)
-
-
-def write_sent_tx_num_to_file(tx,metadata,opts):
-	outfile = "tx_{}[{}].out".format(*metadata[:2])
-	if 'outdir' in opts:
-		outfile = "%s/%s" % (opts['outdir'], outfile)
-	write_to_file(outfile,tx+"\n",confirm=False)
-	msg("Transaction ID saved to file '%s'" % outfile)
-
-
 def format_unspent_outputs_for_printing(out,sort_info,total):
 def format_unspent_outputs_for_printing(out,sort_info,total):
 
 
 	pfs  = " %-4s %-67s %-34s %-12s %-13s %-8s %-10s %s"
 	pfs  = " %-4s %-67s %-34s %-12s %-13s %-8s %-10s %s"
@@ -227,7 +184,7 @@ def format_unspent_outputs_for_printing(out,sort_info,total):
 	)
 	)
 
 
 
 
-def sort_and_view(unspent):
+def sort_and_view(unspent,opts):
 
 
 	def s_amt(i):   return i.amount
 	def s_amt(i):   return i.amount
 	def s_txid(i):  return "%s %03s" % (i.txid,i.vout)
 	def s_txid(i):  return "%s %03s" % (i.txid,i.vout)
@@ -242,9 +199,9 @@ def sort_and_view(unspent):
 	unspent.sort(key=s_age,reverse=reverse) # Reverse age sort by default
 	unspent.sort(key=s_age,reverse=reverse) # Reverse age sort by default
 
 
 	total = trim_exponent(sum([i.amount for i in unspent]))
 	total = trim_exponent(sum([i.amount for i in unspent]))
+	max_acct_len = max([len(i.account) for i in unspent])
 
 
 	hdr_fmt   = "UNSPENT OUTPUTS (sort order: %s)  Total BTC: %s"
 	hdr_fmt   = "UNSPENT OUTPUTS (sort order: %s)  Total BTC: %s"
-
 	options_msg = """
 	options_msg = """
 Sort options: [t]xid, [a]mount, a[d]dress, [A]ge, [r]everse, [M]mgen addr
 Sort options: [t]xid, [a]mount, a[d]dress, [A]ge, [r]everse, [M]mgen addr
 Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
 Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
@@ -253,31 +210,31 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
 "('q' = quit sorting, 'p' = print to file, 'v' = pager view, 'w' = wide view): "
 "('q' = quit sorting, 'p' = print to file, 'v' = pager view, 'w' = wide view): "
 
 
 	from copy import deepcopy
 	from copy import deepcopy
-	write_to_file_msg = ""
-	msg("")
-
 	from mmgen.term import get_terminal_size
 	from mmgen.term import get_terminal_size
 
 
-	max_acct_len = max([len(i.account) for i in unspent])
+	write_to_file_msg = ""
+	msg("")
 
 
 	while True:
 	while True:
 		cols = get_terminal_size()[0]
 		cols = get_terminal_size()[0]
 		if cols < g.min_screen_width:
 		if cols < g.min_screen_width:
-			msg("mmgen-txcreate requires a screen at least %s characters wide" %
-					g.min_screen_width)
+			msg("%s-txcreate requires a screen at least %s characters wide" %
+					(g.proj_name.lower(),g.min_screen_width))
 			sys.exit(2)
 			sys.exit(2)
 
 
 		addr_w = min(34+((1+max_acct_len) if show_mmaddr else 0),cols-46)
 		addr_w = min(34+((1+max_acct_len) if show_mmaddr else 0),cols-46)
+		acct_w   = min(max_acct_len, max(24,int(addr_w-10)))
+		btaddr_w = addr_w - acct_w - 1
 		tx_w = max(11,min(64, cols-addr_w-32))
 		tx_w = max(11,min(64, cols-addr_w-32))
+		txdots = "..." if tx_w < 64 else ""
 		fs = " %-4s %-" + str(tx_w) + "s %-2s %-" + str(addr_w) + "s %-13s %-s"
 		fs = " %-4s %-" + str(tx_w) + "s %-2s %-" + str(addr_w) + "s %-13s %-s"
-		a = "Age(d)" if show_days else "Conf."
-		table_hdr = fs % ("Num","TX id  Vout","","Address", "Amount (BTC)",a)
+		table_hdr = fs % ("Num","TX id  Vout","","Address","Amount (BTC)",
+							"Age(d)" if show_days else "Conf.")
 
 
 		unsp = deepcopy(unspent)
 		unsp = deepcopy(unspent)
 		for i in unsp: i.skip = ""
 		for i in unsp: i.skip = ""
 		if group and (sort == "address" or sort == "txid"):
 		if group and (sort == "address" or sort == "txid"):
-			for n in range(len(unsp)-1):
-				a,b = unsp[n],unsp[n+1]
+			for a,b in [(unsp[i],unsp[i+1]) for i in range(len(unsp)-1)]:
 				if sort == "address" and a.address == b.address: b.skip = "addr"
 				if sort == "address" and a.address == b.address: b.skip = "addr"
 				elif sort == "txid" and a.txid == b.txid:        b.skip = "txid"
 				elif sort == "txid" and a.txid == b.txid:        b.skip = "txid"
 
 
@@ -286,18 +243,14 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
 			lfill = 3 - len(amt.split(".")[0]) if "." in amt else 3 - len(amt)
 			lfill = 3 - len(amt.split(".")[0]) if "." in amt else 3 - len(amt)
 			i.amt = " "*lfill + amt
 			i.amt = " "*lfill + amt
 			i.days = int(i.confirmations * g.mins_per_block / (60*24))
 			i.days = int(i.confirmations * g.mins_per_block / (60*24))
-
+			i.age = i.days if show_days else i.confirmations
 			i.mmid,i.label = parse_mmgen_label(i.account)
 			i.mmid,i.label = parse_mmgen_label(i.account)
 
 
 			if i.skip == "addr":
 			if i.skip == "addr":
 				i.addr = "|" + "." * 33
 				i.addr = "|" + "." * 33
 			else:
 			else:
-				if show_mmaddr and i.mmid:
-					acct_w   = min(max_acct_len, max(24,int(addr_w-10)))
-					btaddr_w = addr_w - acct_w - 1
-
+				if show_mmaddr:
 					dots = ".." if btaddr_w < len(i.address) else ""
 					dots = ".." if btaddr_w < len(i.address) else ""
-
 					i.addr = "%s%s %s" % (
 					i.addr = "%s%s %s" % (
 						i.address[:btaddr_w-len(dots)],
 						i.address[:btaddr_w-len(dots)],
 						dots,
 						dots,
@@ -305,20 +258,17 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
 				else:
 				else:
 					i.addr = i.address
 					i.addr = i.address
 
 
-			dots = "..." if tx_w < 64 else ""
 			i.tx = " " * (tx_w-4) + "|..." if i.skip == "txid" \
 			i.tx = " " * (tx_w-4) + "|..." if i.skip == "txid" \
-					else i.txid[:tx_w-len(dots)]+dots
+					else i.txid[:tx_w-len(txdots)]+txdots
 
 
 		sort_info = ["reverse"] if reverse else []
 		sort_info = ["reverse"] if reverse else []
 		sort_info.append(sort if sort else "unsorted")
 		sort_info.append(sort if sort else "unsorted")
 		if group and (sort == "address" or sort == "txid"):
 		if group and (sort == "address" or sort == "txid"):
 			sort_info.append("grouped")
 			sort_info.append("grouped")
 
 
-		out = [hdr_fmt % (" ".join(sort_info), total), table_hdr]
-
-		for n,i in enumerate(unsp):
-			d = i.days if show_days else i.confirmations
-			out.append(fs % (str(n+1)+")",i.tx,i.vout,i.addr,i.amt,d))
+		out  = [hdr_fmt % (" ".join(sort_info), total), table_hdr]
+		out += [fs % (str(n+1)+")",i.tx,i.vout,i.addr,i.amt,i.age)
+					for n,i in enumerate(unsp)]
 
 
 		msg("\n".join(out) +"\n\n" + write_to_file_msg + options_msg)
 		msg("\n".join(out) +"\n\n" + write_to_file_msg + options_msg)
 		write_to_file_msg = ""
 		write_to_file_msg = ""
@@ -344,10 +294,10 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
 			elif reply == 'e': pass
 			elif reply == 'e': pass
 			elif reply == 'q': pass
 			elif reply == 'q': pass
 			elif reply == 'p':
 			elif reply == 'p':
-				data = format_unspent_outputs_for_printing(unsp,sort_info,total)
-				outfile = "listunspent[%s].out" % ",".join(sort_info)
-				write_to_file(outfile, data)
-				write_to_file_msg = "Data written to '%s'\n\n" % outfile
+				d = format_unspent_outputs_for_printing(unsp,sort_info,total)
+				of = "listunspent[%s].out" % ",".join(sort_info)
+				write_to_file(of, d, opts,"",False,False)
+				write_to_file_msg = "Data written to '%s'\n\n" % of
 			elif reply == 'v':
 			elif reply == 'v':
 				do_pager("\n".join(out))
 				do_pager("\n".join(out))
 				continue
 				continue
@@ -572,16 +522,18 @@ Only ASCII printable characters are permitted.
 """.strip() % (ch,label))
 """.strip() % (ch,label))
 			sys.exit(3)
 			sys.exit(3)
 
 
+def make_addr_data_chksum(addr_data):
+	nchars = 24
+	return make_chksum_N(
+		" ".join(["{} {}".format(*d[:2]) for d in addr_data]), nchars, sep=True
+	)
 
 
 def check_addr_data_hash(seed_id,addr_data):
 def check_addr_data_hash(seed_id,addr_data):
 	def s_addrdata(a): return int(a[0])
 	def s_addrdata(a): return int(a[0])
-	addr_data.sort(key=s_addrdata)
-	addr_data_chksum = make_chksum_8(
-		" ".join(["{} {}".format(*d[:2]) for d in addr_data]), sep=True
-	)
+	addr_data_chksum = make_addr_data_chksum(sorted(addr_data,key=s_addrdata))
 	from mmgen.addr import fmt_addr_idxs
 	from mmgen.addr import fmt_addr_idxs
 	fl = fmt_addr_idxs([int(a[0]) for a in addr_data])
 	fl = fmt_addr_idxs([int(a[0]) for a in addr_data])
-	msg("Computed address data checksum for '{}[{}]': {}".format(
+	msg("Computed checksum for addr data {}[{}]: {}".format(
 				seed_id,fl,addr_data_chksum))
 				seed_id,fl,addr_data_chksum))
 	msg("Check this value against your records")
 	msg("Check this value against your records")
 
 

+ 27 - 39
mmgen/util.py

@@ -24,7 +24,7 @@ from hashlib import sha256
 from binascii import hexlify,unhexlify
 from binascii import hexlify,unhexlify
 
 
 import mmgen.config as g
 import mmgen.config as g
-from mmgen.bitcoin import b58decode_pad
+from mmgen.bitcoin import b58decode_pad,b58encode_pad
 from mmgen.term import *
 from mmgen.term import *
 
 
 def msg(s):    sys.stderr.write(s + "\n")
 def msg(s):    sys.stderr.write(s + "\n")
@@ -48,7 +48,6 @@ def get_extension(f):
 	import os
 	import os
 	return os.path.splitext(f)[1][1:]
 	return os.path.splitext(f)[1][1:]
 
 
-
 def get_random_data_from_user(uchars):
 def get_random_data_from_user(uchars):
 
 
 	if g.quiet: msg("Enter %s random symbols" % uchars)
 	if g.quiet: msg("Enter %s random symbols" % uchars)
@@ -241,6 +240,12 @@ def prompt_and_get_char(prompt,chars,enter_ok=False,verbose=False):
 		else: msg_r("\r")
 		else: msg_r("\r")
 
 
 
 
+def make_chksum_N(s,n,sep=False):
+	if n%4 or not (4 <= n <= 64): return False
+	s = sha256(sha256(s).digest()).hexdigest().upper()
+	sep = " " if sep else ""
+	return sep.join([s[i*4:i*4+4] for i in range(n/4)])
+
 def make_chksum_8(s,sep=False):
 def make_chksum_8(s,sep=False):
 	s = sha256(sha256(s).digest()).hexdigest()[:8].upper()
 	s = sha256(sha256(s).digest()).hexdigest()[:8].upper()
 	return "{} {}".format(s[:4],s[4:]) if sep else s
 	return "{} {}".format(s[:4],s[4:]) if sep else s
@@ -427,9 +432,9 @@ def open_file_or_exit(filename,mode):
 	return f
 	return f
 
 
 
 
-def write_to_file(outfile,data,confirm=False,verbose=False):
+def write_to_file(outfile,data,opts,what="data",confirm=False,verbose=False):
 
 
-	if verbose: qmsg("Writing data to file '%s'" % outfile)
+	if 'outdir' in opts: outfile = "%s/%s" % (opts['outdir'], outfile)
 
 
 	if confirm:
 	if confirm:
 		from os import stat
 		from os import stat
@@ -441,27 +446,26 @@ def write_to_file(outfile,data,confirm=False,verbose=False):
 			confirm_or_exit("","File '%s' already exists\nOverwrite?" % outfile)
 			confirm_or_exit("","File '%s' already exists\nOverwrite?" % outfile)
 
 
 	f = open_file_or_exit(outfile,'w')
 	f = open_file_or_exit(outfile,'w')
-
 	try:
 	try:
 		f.write(data)
 		f.write(data)
 	except:
 	except:
-		msg("Failed to write to file '%s'" % outfile)
+		msg("Failed to write %s to file '%s'" % (what,outfile))
 		sys.exit(2)
 		sys.exit(2)
-
 	f.close
 	f.close
 
 
+	if verbose: msg("%s written to file '%s'" % (what.capitalize(),outfile))
 
 
-def export_to_file(outfile, data, label, opts):
+
+
+def export_to_file(outfile, data, opts, what="data"):
 
 
 	if 'stdout' in opts:
 	if 'stdout' in opts:
-		write_to_stdout(data, label, confirm=True)
+		write_to_stdout(data, what, confirm=True)
 	elif not sys.stdout.isatty():
 	elif not sys.stdout.isatty():
-		write_to_stdout(data, label, confirm=False)
+		write_to_stdout(data, what, confirm=False)
 	else:
 	else:
-		if 'outdir' in opts:
-			outfile = "%s/%s" % (opts['outdir'], outfile)
-		write_to_file(outfile, data, confirm=False if g.quiet else True)
-		msg("%s saved to file '%s'" % (label.capitalize(), outfile))
+		c = False if g.quiet else True
+		write_to_file(outfile,data,opts,what,c,True)
 
 
 
 
 def _display_control_data(label,metadata,hash_preset,salt,enc_seed):
 def _display_control_data(label,metadata,hash_preset,salt,enc_seed):
@@ -522,23 +526,13 @@ def write_wallet_to_file(seed, passwd, key_id, salt, enc_seed, opts):
 	seed_id = make_chksum_8(seed)
 	seed_id = make_chksum_8(seed)
 	seed_len = str(len(seed)*8)
 	seed_len = str(len(seed)*8)
 	pw_status = "NE" if len(passwd) else "E"
 	pw_status = "NE" if len(passwd) else "E"
-
 	hash_preset = opts['hash_preset']
 	hash_preset = opts['hash_preset']
-
-	outfile="{}-{}[{},{}].{}".format(seed_id,key_id,seed_len,hash_preset,g.wallet_ext)
-	if 'outdir' in opts:
-		outfile = "%s/%s" % (opts['outdir'], outfile)
-
 	label = opts['label'] if 'label' in opts else "No Label"
 	label = opts['label'] if 'label' in opts else "No Label"
-
-	from mmgen.bitcoin import b58encode_pad
-
+	metadata = seed_id.lower(),key_id.lower(),seed_len,\
+		pw_status,make_timestamp()
 	sf  = b58encode_pad(salt)
 	sf  = b58encode_pad(salt)
 	esf = b58encode_pad(enc_seed)
 	esf = b58encode_pad(enc_seed)
 
 
-	metadata = seed_id.lower(),key_id.lower(),\
-		seed_len,pw_status,make_timestamp()
-
 	lines = (
 	lines = (
 		label,
 		label,
 		"{} {} {} {} {}".format(*metadata),
 		"{} {} {} {} {}".format(*metadata),
@@ -548,23 +542,17 @@ def write_wallet_to_file(seed, passwd, key_id, salt, enc_seed, opts):
 	)
 	)
 
 
 	chk = make_chksum_6(" ".join(lines))
 	chk = make_chksum_6(" ".join(lines))
+	outfile="{}-{}[{},{}].{}".format(
+		seed_id,key_id,seed_len,hash_preset,g.wallet_ext)
 
 
-	confirm = False if g.quiet else True
-	write_to_file(outfile, "\n".join((chk,)+lines)+"\n", confirm)
+	c = False if g.quiet else True
+	d = "\n".join((chk,)+lines)+"\n"
+	write_to_file(outfile,d,opts,"wallet",c,True)
 
 
-	msg("Wallet saved to file '%s'" % outfile)
 	if g.verbose:
 	if g.verbose:
 		_display_control_data(label,metadata,hash_preset,salt,enc_seed)
 		_display_control_data(label,metadata,hash_preset,salt,enc_seed)
 
 
 
 
-def write_walletdat_dump_to_file(wallet_id,data,num_keys,ext,what,opts):
-	outfile = "wd_{}[{}].{}".format(wallet_id,num_keys,ext)
-	if 'outdir' in opts:
-		outfile = "%s/%s" % (opts['outdir'], outfile)
-	write_to_file(outfile,data,confirm=False)
-	msg("wallet.dat %s saved to file '%s'" % (what,outfile))
-
-
 def _compare_checksums(chksum1, desc1, chksum2, desc2):
 def _compare_checksums(chksum1, desc1, chksum2, desc2):
 
 
 	if chksum1.lower() == chksum2.lower():
 	if chksum1.lower() == chksum2.lower():
@@ -637,7 +625,7 @@ def get_data_from_wallet(infile,silent=False):
 
 
 	# Don't make this a qmsg: User will be prompted for passphrase and must see
 	# Don't make this a qmsg: User will be prompted for passphrase and must see
 	# the filename.
 	# the filename.
-	if not silent:
+	if not silent and not g.quiet:
 		msg("Getting {} wallet data from file '{}'".format(g.proj_name,infile))
 		msg("Getting {} wallet data from file '{}'".format(g.proj_name,infile))
 
 
 	f = open_file_or_exit(infile, 'r')
 	f = open_file_or_exit(infile, 'r')
@@ -864,7 +852,7 @@ def get_seed_from_incog_wallet(
 
 
 	passwd = get_mmgen_passphrase(prompt,opts)
 	passwd = get_mmgen_passphrase(prompt,opts)
 
 
-	msg("Configured hash presets: %s" % " ".join(sorted(g.hash_presets)))
+	qmsg("Configured hash presets: %s" % " ".join(sorted(g.hash_presets)))
 	while True:
 	while True:
 		p = "Enter hash preset for %s wallet (default='%s'): "
 		p = "Enter hash preset for %s wallet (default='%s'): "
 		hp = my_raw_input(p % (g.proj_name, g.hash_preset))
 		hp = my_raw_input(p % (g.proj_name, g.hash_preset))