Browse Source

Conflicts:
mmgen-txcreate
mmgen-txsend
mmgen-txsign
mmgen/config.py
mmgen/license.py
mmgen/tx.py
mmgen/utils.py

philemon 11 years ago
parent
commit
9f852f2d86
13 changed files with 390 additions and 26 deletions
  1. 5 6
      mmgen-keygen
  2. 1 1
      mmgen-passchg
  3. 60 0
      mmgen-txcreate
  4. 66 0
      mmgen-txsend
  5. 50 0
      mmgen-txsign
  6. 1 1
      mmgen-walletchk
  7. 1 1
      mmgen-walletgen
  8. 5 5
      mmgen/addr.py
  9. 2 2
      mmgen/bitcoin.py
  10. 4 0
      mmgen/config.py
  11. 15 0
      mmgen/license.py
  12. 123 0
      mmgen/tx.py
  13. 57 10
      mmgen/utils.py

+ 5 - 6
mmgen-keygen

@@ -19,8 +19,8 @@
 """
 mmgen-keygen: Generate addresses/secret keys from a mmgen deterministic 
               wallet for a range of addresses.
-			  Call as 'btc-addrgen' for safe, reduced functionality
-			  with no output of secret keys.
+              Call as 'btc-addrgen' for safe, reduced functionality
+              with no output of secret keys.
 """
 
 import sys
@@ -103,8 +103,8 @@ invocations with that passphrase
 
 so = "h","A","d:","e","K","l:","p:","P","q","S","v","x","b:","m","s"
 lo = "help","no_addresses","outdir=","echo_passphrase","no_keyconv",\
-	  "seed_len=","hash_preset=","show_hash_presets","quiet","stdout",\
-	  "verbose","b16","from_brain=","from_mnemonic","from_seed"
+		"seed_len=","hash_preset=","show_hash_presets","quiet","stdout",\
+		"verbose","b16","from_brain=","from_mnemonic","from_seed"
 
 if invoked_as == "addrgen":
 	short_opts = so[0:1] + so[2:10] + so[11:]
@@ -144,10 +144,9 @@ else: usage(help_data)
 
 start,end = parse_address_range(addr_range)
 
-if not 'quiet' in opts: do_license_msg(); msg("\n")
+if not 'quiet' in opts: do_license_msg()
 
 # Interact with user:
-
 if invoked_as == "keygen" and not 'quiet' in opts:
 	confirm_or_exit(cmessages['unencrypted_secret_keys'], 'continue')
 

+ 1 - 1
mmgen-passchg

@@ -48,7 +48,7 @@ NOTE: The key ID will change if either the passphrase or hash preset
 
 short_opts = "hd:kL:p:Pv"
 long_opts  = "help","outdir=","keep_old_passphrase","label=","hash_preset=",\
-			   "show_hash_presets","verbose"
+				"show_hash_presets","verbose"
 
 opts,cmd_args = Opts.process_opts(sys.argv,help_data,short_opts,long_opts)
 

+ 60 - 0
mmgen-txcreate

@@ -36,6 +36,7 @@ help_data = {
 	'desc':    "Send BTC from specified outputs to specified addresses",
 	'usage':   "[opts] <recipient address> <amount> <transaction fee> <change address>",
 	'options': """
+<<<<<<< HEAD
 -h, --help                 Print this help message
 -d, --outdir            d  Specify an alternate directory 'd' for output
 -e, --echo-passphrase      Print passphrase to screen when typing it
@@ -45,6 +46,21 @@ help_data = {
 
 short_opts = "hd:eq"
 long_opts  = "help","outdir=","echo_passphrase","quiet"
+=======
+-h, --help                Print this help message
+-d, --outdir           d  Specify an alternate directory 'd' for output
+-e, --echo-passphrase     Print passphrase to screen when typing it
+-i, --info                Display unspent outputs and exit
+-q, --quiet               Suppress warnings; overwrite files without asking
+
+Ages of transactions are approximate based on an estimated block discovery
+time of %s minutes.
+""" % mins_per_block
+}
+
+short_opts = "hd:eiq"
+long_opts  = "help","outdir=","echo_passphrase","info","quiet"
+>>>>>>> my
 
 opts,cmd_args = process_opts(sys.argv,help_data,short_opts,long_opts)
 
@@ -61,15 +77,27 @@ if len(cmd_args) == 4:
 elif len(cmd_args) == 3:
 	rcpt_addr,send_amt,tx_fee = cmd_args	
 	change_addr = ""
+<<<<<<< HEAD
 else: usage(help_data)
 
 check_address(rcpt_addr)
 send_amt = check_btc_amt(send_amt)
 tx_fee   = check_btc_amt(tx_fee)
+=======
+elif len(cmd_args) == 0 and 'info' in opts:
+	pass
+else: usage(help_data)
+
+if not 'info' in opts:
+	check_address(rcpt_addr)
+	send_amt = check_btc_amt(send_amt)
+	tx_fee   = check_btc_amt(tx_fee)
+>>>>>>> my
 
 # Begin execution
 c = connect_to_bitcoind()
 
+<<<<<<< HEAD
 if not 'quiet' in opts: do_license_msg()
 
 unspent = sort_and_view(c.listunspent())
@@ -89,6 +117,34 @@ if change < 0:
 	msg(txmsg['not_enough_btc'] % change)
 	sys.exit(2)
 elif change > 0 and not change_addr:
+=======
+if not 'quiet' in opts and not 'info' in opts: do_license_msg()
+
+unspent = sort_and_view(c.listunspent())
+
+total = trim_exponent(sum([i.amount for i in unspent]))
+
+msg("Total unspent:   %s BTC" % total)
+if 'info' in opts: sys.exit(0)
+
+msg("Amount to spend: %s BTC" % send_amt)
+msg("%s unspent outputs total" % len(unspent))
+
+
+while True:
+	sel_unspent = select_outputs(unspent,"Choose the outputs to spend: ")
+	total_in = trim_exponent(sum([o.amount for o in sel_unspent]))
+	change   = trim_exponent(total_in - (send_amt + tx_fee))
+
+	if change >= 0:
+		prompt = "Transaction produces %s BTC in change.  OK?" % change
+		if user_confirm(prompt,default_yes=True):
+			break
+
+	msg(txmsg['not_enough_btc'] % change)
+
+if change > 0 and not change_addr:
+>>>>>>> my
 	msg(txmsg['throwaway_change'] % (change, total_in-tx_fee))
 	sys.exit(2)
 
@@ -96,7 +152,11 @@ tx_in = [{"txid":i.txid, "vout":i.vout} for i in sel_unspent]
 tx_out = {rcpt_addr:float(send_amt), change_addr:float(change)}
 tx_hex = c.createrawtransaction(tx_in,tx_out)
 
+<<<<<<< HEAD
 msg("Transaction successfully created\n")
+=======
+msg("Transaction successfully created")
+>>>>>>> my
 prompt = "View decoded transaction?"
 if user_confirm(prompt,default_yes=False):
 	view_tx_data(c,[i.__dict__ for i in sel_unspent],tx_hex)

+ 66 - 0
mmgen-txsend

@@ -20,18 +20,26 @@ mmgen-txsend: Broadcast a Bitcoin transaction to the network
 """
 
 import sys
+<<<<<<< HEAD
 #from hashlib import sha256
+=======
+>>>>>>> my
 
 from mmgen.Opts import *
 from mmgen.license import *
 from mmgen.config import *
 from mmgen.tx import *
+<<<<<<< HEAD
 from mmgen.utils import msg,check_infile,get_lines_from_file,confirm_or_exit
+=======
+from mmgen.utils import msg,check_opts,check_infile,get_lines_from_file,confirm_or_exit
+>>>>>>> my
 
 prog_name = sys.argv[0].split("/")[-1]
 
 help_data = {
 	'prog_name': prog_name,
+<<<<<<< HEAD
 	'desc':    "Sign a Bitcoin transaction generated by mmgen-txcreate",
 	'usage':   "[opts] <transaction file>",
 	'options': """
@@ -45,6 +53,25 @@ long_opts  = "help","quiet"
 
 opts,cmd_args = process_opts(sys.argv,help_data,short_opts,long_opts)
 
+=======
+	'desc':    "Send a Bitcoin transaction signed by mmgen-txsign",
+	'usage':   "[opts] <signed transaction file>",
+	'options': """
+-h, --help          Print this help message
+-d, --outdir     d  Specify an alternate directory 'd' for output
+-q, --quiet         Suppress warnings; overwrite files without asking
+"""
+}
+
+short_opts = "hd:q"
+long_opts  = "help","outdir=","quiet"
+
+opts,cmd_args = process_opts(sys.argv,help_data,short_opts,long_opts)
+
+# Exits on invalid input
+check_opts(opts, ('outdir',))
+
+>>>>>>> my
 if len(cmd_args) == 1:
 	infile = cmd_args[0]
 	check_infile(infile)
@@ -52,13 +79,27 @@ else: usage(help_data)
 
 # Begin execution
 
+<<<<<<< HEAD
 c = connect_to_bitcoind()
 
 tx_sig = get_lines_from_file(infile,"signed transaction")[0]
+=======
+try:
+	metadata,tx_sig = get_lines_from_file(infile,"signed transaction")
+except:
+	msg("Invalid signed transaction file")
+	sys.exit(3)
+
+metadata = metadata.split()
+if len(metadata) != 3:
+	msg("Invalid file header")
+	sys.exit(3)
+>>>>>>> my
 
 from binascii import unhexlify
 try: unhexlify(tx_sig)
 except:
+<<<<<<< HEAD
 	msg("Invalid transaction data")
 	sys.exit(3)
 
@@ -70,10 +111,35 @@ msg("Sending transaction")
 
 try:
 	tx = c.sendrawtransaction(tx_sig)
+=======
+	msg("Invalid signed transaction data")
+	sys.exit(3)
+
+if not 'quiet' in opts: do_license_msg()
+
+msg("Signed transaction file '%s' appears valid" % infile)
+
+warn   = "Once this transaction is sent, there's no taking it back!"
+what   = "broadcast this transaction to the network"
+expect = "yes, i really want to do this".upper()
+confirm_or_exit(warn, what, expect)
+
+msg("Sending transaction")
+
+c = connect_to_bitcoind()
+
+try:
+	tx = c.sendrawtransaction(tx_sig)
+#	tx = "deadbeef"
+>>>>>>> my
 except:
 	msg("Unable to send transaction")
 	sys.exit(3)
 
 msg("Transaction sent: %s" % tx)
 
+<<<<<<< HEAD
 print_sent_tx_to_file(tx)
+=======
+print_sent_tx_to_file(tx,metadata,opts)
+>>>>>>> my

+ 50 - 0
mmgen-txsign

@@ -35,11 +35,19 @@ help_data = {
 	'desc':    "Sign a Bitcoin transaction generated by mmgen-txcreate",
 	'usage':   "[opts] <transaction file>",
 	'options': """
+<<<<<<< HEAD
 -h, --help                 Print this help message
 -d, --outdir            d  Specify an alternate directory 'd' for output
 -e, --echo-passphrase      Print passphrase to screen when typing it
 -i, --info                 Just show info about the transaction and exit
 -q, --quiet                Suppress warnings; overwrite files without asking
+=======
+-h, --help               Print this help message
+-d, --outdir          d  Specify an alternate directory 'd' for output
+-e, --echo-passphrase    Print passphrase to screen when typing it
+-i, --info               Display information about the transaction and exit
+-q, --quiet              Suppress warnings; overwrite files without asking
+>>>>>>> my
 """
 }
 
@@ -66,10 +74,17 @@ c = connect_to_bitcoind()
 
 tx_data = get_lines_from_file(infile,"transaction data")
 
+<<<<<<< HEAD
 timestamp,tx_hex,sig_data,inputs_data = parse_tx_data(tx_data)
 
 if 'info' in opts:
 	view_tx_data(c,inputs_data,tx_hex,timestamp)
+=======
+metadata,tx_hex,sig_data,inputs_data =  parse_tx_data(tx_data)
+
+if 'info' in opts:
+	view_tx_data(c,inputs_data,tx_hex,metadata)
+>>>>>>> my
 	sys.exit(0)
 
 if not 'quiet' in opts and not 'info' in opts: do_license_msg()
@@ -77,9 +92,15 @@ if not 'quiet' in opts and not 'info' in opts: do_license_msg()
 msg("Successfully opened transaction file '%s'" % infile)
 
 if user_confirm("View transaction data? ",default_yes=False):
+<<<<<<< HEAD
 	view_tx_data(c,inputs_data,tx_hex,timestamp)
 
 prompt = "Enter bitcoind passphrase: "
+=======
+	view_tx_data(c,inputs_data,tx_hex,metadata)
+
+prompt = "Enter passphrase for bitcoind wallet: "
+>>>>>>> my
 if 'echo_passphrase' in opts:
 	password = my_raw_input(prompt)
 else:
@@ -98,6 +119,7 @@ except exceptions.WalletPassphraseIncorrect:
 	sys.exit(3)
 except exceptions.WalletAlreadyUnlocked:
 	msg("WARNING: Wallet already unlocked!")
+<<<<<<< HEAD
 
 # signrawtransaction <hex string> [{"txid":txid,"vout":n,"scriptPubKey":hex,"redeemScript":hex},...] [<privatekey1>,...] [sighashtype="ALL"]
 try:
@@ -116,3 +138,31 @@ if not sig_tx['complete']:
 prompt = "Save signed transaction?"
 if user_confirm(prompt,default_yes=True):
 	print_signed_tx_to_file(tx_hex,sig_tx['hex'],opts)
+=======
+else:
+	msg("Passphrase OK")
+
+try:
+	sig_tx = c.signrawtransaction(tx_hex,sig_data)
+#	sig_tx = {'hex':"deadbeef0123456789ab",'complete':True}
+except:
+	msg("Failed to sign transaction")
+	if wallet_enc:
+		c.walletlock()
+		msg("Locking wallet")
+	sys.exit(3)
+
+if wallet_enc:
+	c.walletlock()
+	msg("Locking wallet")
+
+if sig_tx['complete']:
+	msg("Signing completed")
+else:
+	msg("signrawtransaction() returned failure")
+	sys.exit(3)
+
+prompt = "Save signed transaction?"
+if user_confirm(prompt,default_yes=True):
+	print_signed_tx_to_file(tx_hex,sig_tx['hex'],metadata,opts)
+>>>>>>> my

+ 1 - 1
mmgen-walletchk

@@ -43,7 +43,7 @@ help_data = {
 
 short_opts = "hd:emsSv"
 long_opts  = "help","outdir=","echo_passphrase","export_mnemonic",\
-			  "export_seed","stdout","verbose"
+				"export_seed","stdout","verbose"
 
 opts,cmd_args = Opts.process_opts(sys.argv,help_data,short_opts,long_opts)
 

+ 1 - 1
mmgen-walletgen

@@ -90,7 +90,7 @@ invocations with that passphrase.
 short_opts = "hd:el:L:p:Pqu:b:ms"
 long_opts  = "help","outdir=","echo_passphrase","seed_len=","label=",\
 		"hash_preset=","show_hash_presets","quiet","usr_randlen=",\
-        "from_brain=","from_mnemonic","from_seed"
+		"from_brain=","from_mnemonic","from_seed"
 
 opts,cmd_args = process_opts(sys.argv,help_data,short_opts,long_opts)
 

+ 5 - 5
mmgen/addr.py

@@ -58,10 +58,10 @@ def generate_addrs(seed, start, end, opts):
 	installed.  Otherwise an internal function is used
 
 	Supported options:
-	  print_secret, no_addresses, no_keyconv, gen_what
+		print_secret, no_addresses, no_keyconv, gen_what
 	
 	Addresses are returned in a list of dictionaries with the following keys:
-	  num, sec, wif, addr
+		num, sec, wif, addr
 	"""
 
 	if not 'no_addresses' in opts:
@@ -121,9 +121,9 @@ def format_addr_data(addrlist, seed_chksum, opts):
 	By default, prints addresses only
 
 	Output can be customized with the following command line options:
-	  print_secret
-	  no_addresses
-	  b16
+		print_secret
+		no_addresses
+		b16
 	"""
 
 	start = addrlist[0]['num']

+ 2 - 2
mmgen/bitcoin.py

@@ -147,8 +147,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))
+		print "_b58_pad() accepts only %s %s bytes long "\
+			"(input was %s bytes)" % (w,",".join([str(i) for i in a]),len(s))
 		sys.exit(9)
 
 	out = f(s)

+ 4 - 0
mmgen/config.py

@@ -31,7 +31,11 @@ mnemonic_lens = [i / 32 * 3 for i in seed_lens]
 from os import getenv
 debug = True if getenv("MMGEN_DEBUG") else False
 
+<<<<<<< HEAD
 mins_per_block = 9
+=======
+mins_per_block = 8.5
+>>>>>>> my
 passwd_max_tries = 5
 max_randlen,min_randlen = 80,5
 usr_randlen = 20

+ 15 - 0
mmgen/license.py

@@ -25,10 +25,17 @@ from mmgen.utils import msg, msg_r, get_char
 
 gpl = {
 	'warning': """
+<<<<<<< HEAD
 {} Copyright (C) 2013 by Philemon <mmgen-py@yandex.com>.  This program
 comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are
 welcome to redistribute it under certain conditions.
 """.format(proj_name),
+=======
+  MMGen Copyright (C) 2013 by Philemon <mmgen-py@yandex.com>.  This
+  program comes with ABSOLUTELY NO WARRANTY.  This is free software,
+  and you are welcome to redistribute it under certain conditions.
+""",
+>>>>>>> my
 	'prompt': """
 Press 'c' for conditions, 'w' for warranty info, or ENTER to continue:
 """,
@@ -629,7 +636,11 @@ def do_pager(text):
 
 
 def do_license_msg():
+<<<<<<< HEAD
 	msg("%s\n" % gpl['warning'].strip())
+=======
+	msg(gpl['warning'])
+>>>>>>> my
 
 	while True:
 
@@ -638,4 +649,8 @@ def do_license_msg():
 
 		if   reply == 'c': do_pager(gpl['conditions'])
 		elif reply == 'w': do_pager(gpl['warranty'])
+<<<<<<< HEAD
 		else: msg("\n"); break
+=======
+		else: msg(""); break
+>>>>>>> my

+ 123 - 0
mmgen/tx.py

@@ -50,10 +50,17 @@ def connect_to_bitcoind():
 	return c
 
 
+<<<<<<< HEAD
 def remove_exponent(d):
     '''Remove exponent and trailing zeros.
     '''
     return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
+=======
+def trim_exponent(d):
+	'''Remove exponent and trailing zeros.
+	'''
+	return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
+>>>>>>> my
 
 def	check_address(rcpt_address):
 	from mmgen.bitcoin import verify_addr
@@ -73,7 +80,11 @@ def check_btc_amt(send_amt):
 		msg("%s: Too many decimal places in amount" % send_amt)
 		sys.exit(3)
 	
+<<<<<<< HEAD
 	return remove_exponent(retval)
+=======
+	return trim_exponent(retval)
+>>>>>>> my
 
 
 def get_cfg_options(cfg_keys):
@@ -109,15 +120,22 @@ def print_tx_to_file(tx,sel_unspent,send_amt,opts):
 	outfile = "%s[%s].tx" % (tx_id,send_amt)
 	if 'outdir' in opts:
 		outfile = "%s/%s" % (opts['outdir'], outfile)
+<<<<<<< HEAD
 	input_data = sel_unspent
 	data = "%s\n%s\n%s\n%s\n" % (
 			make_timestamp(), tx, repr(sig_data),
+=======
+	metadata = "%s %s %s" % (tx_id, send_amt, make_timestamp())
+	data = "%s\n%s\n%s\n%s\n" % (
+			metadata, tx, repr(sig_data),
+>>>>>>> my
 			repr([i.__dict__ for i in sel_unspent])
 		)
 	write_to_file(outfile,data,confirm=False)
 	msg("Transaction data saved to file '%s'" % outfile)
 
 
+<<<<<<< HEAD
 def print_signed_tx_to_file(tx,sig_tx,opts):
 	tx_id = make_chksum_8(unhexlify(tx))
 	outfile = "%s.txsig" % tx_id
@@ -132,6 +150,26 @@ def print_sent_tx_to_file(tx):
 	write_to_file(outfile,tx+"\n",confirm=False)
 	msg("Transaction ID saved to file '%s'" % outfile)
 
+=======
+def print_signed_tx_to_file(tx,sig_tx,metadata,opts):
+	tx_id = make_chksum_8(unhexlify(tx))
+	outfile = "{}[{}].txsig".format(*metadata[:2])
+	if 'outdir' in opts:
+		outfile = "%s/%s" % (opts['outdir'], outfile)
+	data = "%s\n%s\n" % (" ".join(metadata),sig_tx)
+	write_to_file(outfile,data,confirm=False)
+	msg("Signed transaction saved to file '%s'" % outfile)
+
+
+def print_sent_tx_to_file(tx,metadata,opts):
+	outfile = "{}[{}].txout".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)
+
+
+>>>>>>> my
 def sort_and_view(unspent):
 
 	def s_amt(a,b):  return cmp(a.amount,b.amount)
@@ -140,10 +178,19 @@ def sort_and_view(unspent):
 	def s_addr(a,b): return cmp(a.address,b.address)
 	def s_age(a,b):  return cmp(b.confirmations,a.confirmations)
 
+<<<<<<< HEAD
 	fs = "%-4s %-11s %-2s %-34s %13s"
 	sort,group,reverse = "",False,False
 
 	from copy import deepcopy
+=======
+	fs =     " %-4s %-11s %-2s %-34s %13s %-s"
+	fs_hdr = " %-4s %-11s %-4s %-35s %-9s %-s"
+	sort,group,reverse = "",False,False
+
+	from copy import deepcopy
+	msg("")
+>>>>>>> my
 	while True:
 		out = deepcopy(unspent)
 		for i in out: i.skip = ""
@@ -156,11 +203,16 @@ def sort_and_view(unspent):
 					out[n+1].skip = "t"
 
 		output = []
+<<<<<<< HEAD
 		output.append("Sort order: %s%s%s" % (
+=======
+		output.append("UNSPENT OUTPUTS (sort order: %s%s%s)" % (
+>>>>>>> my
 				"reverse " if reverse else "",
 				sort if sort else "None",
 	" (grouped)" if group and (sort == "address" or sort == "txid") else ""
 			))
+<<<<<<< HEAD
 		output.append(fs % ("Num","TX id","Vout","Address","Amount       "))
 
 		for n,i in enumerate(out):
@@ -170,6 +222,19 @@ def sort_and_view(unspent):
 			txid = "       |---" if i.skip == "t" else i.txid[:8]+"..."
 
 			output.append(fs % (str(n+1)+")", txid,i.vout,addr,amt+(" "*fill)))
+=======
+		output.append(fs_hdr % ("Num","TX id","Vout","Address","Amount",
+					"Age (days)"))
+
+		for n,i in enumerate(out):
+			amt = str(trim_exponent(i.amount))
+			fill = 8 - len(amt.split(".")[-1]) if "." in amt else 9
+			addr = " |" + "-"*32 if i.skip == "d" else i.address
+			txid = "       |---" if i.skip == "t" else i.txid[:8]+"..."
+			days = int(i.confirmations * mins_per_block / (60*24))
+
+			output.append(fs % (str(n+1)+")", txid,i.vout,addr,amt+(" "*fill),days))
+>>>>>>> my
 
 		while True:
 			reply = get_char("\n".join(output) +
@@ -194,47 +259,82 @@ Sort options: [t]xid, [a]mount, a[d]dress, [A]ge, [r]everse, [g]roup
 	return unspent
 
 
+<<<<<<< HEAD
 def view_tx_data(c,inputs_data,tx_hex,timestamp=""):
+=======
+def view_tx_data(c,inputs_data,tx_hex,metadata=[]):
+>>>>>>> my
 
 	td = c.decoderawtransaction(tx_hex)
 
 	msg("TRANSACTION DATA:\n")
 
+<<<<<<< HEAD
 	if timestamp: msg("Timestamp: %s\n" % timestamp)
+=======
+	if metadata: msg(
+		"Header: [ID: {}] [Amount: {} BTC] [Time: {}]\n".format(*metadata))
+>>>>>>> my
 
 	msg("Inputs:")
 	total_in = 0
 	for n,i in enumerate(td['vin']):
 		for j in inputs_data:
 			if j['txid'] == i['txid'] and j['vout'] == i['vout']:
+<<<<<<< HEAD
 				days = j['confirmations'] * mins_per_block / (60*24)
 				total_in += j['amount']
 				msg("""
 %-3s tx,vout: %s,%s
+=======
+				days = int(j['confirmations'] * mins_per_block / (60*24))
+				total_in += j['amount']
+				msg(" " + """
+%-2s tx,vout: %s,%s
+>>>>>>> my
     address:        %s
     amount:         %s BTC
     confirmations:  %s (around %s days)
 """.strip() %
 	(n+1,i['txid'],i['vout'],j['address'],
+<<<<<<< HEAD
 	 remove_exponent(j['amount']),j['confirmations'],days)+"\n")
 				break
 
 	msg("Total input: %s BTC\n" % remove_exponent(total_in))
+=======
+		trim_exponent(j['amount']),j['confirmations'],days)+"\n")
+				break
+
+	msg("Total input: %s BTC\n" % trim_exponent(total_in))
+>>>>>>> my
 
 	total_out = 0
 	msg("Outputs:")
 	for n,i in enumerate(td['vout']):
 		total_out += i['value']
+<<<<<<< HEAD
  		msg("""
 %-3s address: %s
+=======
+		msg(" " + """
+%-2s address: %s
+>>>>>>> my
     amount:  %s BTC
 """.strip() % (
 		n,
 		i['scriptPubKey']['addresses'][0],
+<<<<<<< HEAD
 		remove_exponent(i['value']))
 	+ "\n")
 	msg("Total output: %s BTC" % remove_exponent(total_out))
 	msg("TX fee:       %s BTC\n" % remove_exponent(total_in-total_out))
+=======
+		trim_exponent(i['value']))
+	+ "\n")
+	msg("Total output: %s BTC" % trim_exponent(total_out))
+	msg("TX fee:       %s BTC\n" % trim_exponent(total_in-total_out))
+>>>>>>> my
 
 
 def parse_tx_data(tx_data):
@@ -243,24 +343,47 @@ def parse_tx_data(tx_data):
 		msg("'%s': not a transaction file" % infile)
 		sys.exit(2)
 
+<<<<<<< HEAD
 	try: unhexlify(tx_data[1])
 	except:
 		msg("Transaction data is invalid")
+=======
+	err_fmt = "Transaction %s is invalid"
+
+	if len(tx_data[0].split()) != 3:
+		msg(err_fmt % "metadata")
+		sys.exit(2)
+
+	try: unhexlify(tx_data[1])
+	except:
+		msg(err_fmt % "hex data")
+>>>>>>> my
 		sys.exit(2)
 
 	try:
 		sig_data = eval(tx_data[2])
 	except:
+<<<<<<< HEAD
 		msg("Signature data is invalid")
+=======
+		msg(err_fmt % "signature data")
+>>>>>>> my
 		sys.exit(2)
 
 	try:
 		inputs_data = eval(tx_data[3])
 	except:
+<<<<<<< HEAD
 		msg("Inputs data is invalid")
 		sys.exit(2)
 
 	return tx_data[0],tx_data[1],sig_data,inputs_data
+=======
+		msg(err_fmt % "inputs data")
+		sys.exit(2)
+
+	return tx_data[0].split(),tx_data[1],sig_data,inputs_data
+>>>>>>> my
 
 
 def select_outputs(unspent,prompt):

+ 57 - 10
mmgen/utils.py

@@ -190,21 +190,32 @@ future, you must continue using these same parameters
 """
 }
 
-def confirm_or_exit(message, question):
+def confirm_or_exit(message, question, expect="YES"):
 
+<<<<<<< HEAD
 	m = message.strip()
 	if m: msg(m)
+=======
+>>>>>>> my
 	msg("")
 
-	conf_msg = "Type uppercase 'YES' to confirm: "
+	m = message.strip()
+	if m: msg(m)
+
+	conf_msg = "Type uppercase '%s' to confirm: " % expect
 
 	if question[0].isupper():
 		prompt = question + "  " + conf_msg
 	else:
 		prompt = "Are you sure you want to %s?\n%s" % (question,conf_msg)
 
+<<<<<<< HEAD
 	if my_raw_input(prompt).strip() != "YES":
 		msg("Program aborted by user")
+=======
+	if my_raw_input(prompt).strip() != expect:
+		msg("Exiting at user request")
+>>>>>>> my
 		sys.exit(2)
 
 	msg("")
@@ -313,7 +324,13 @@ no strength checking of passphrases is performed.  For an empty passphrase,
 just hit ENTER twice.
 """ % opts['hash_preset'])
 
+	if 'echo_passphrase' in opts:
+		ret = " ".join(_get_words_from_user(opts,"Enter %s: " % what))
+		if ret == "": msg("Empty passphrase")
+		return ret
+
 	for i in range(passwd_max_tries):
+<<<<<<< HEAD
 		if 'echo_passphrase' in opts:
 			return my_raw_input("Enter %s: " % what)
 		else:
@@ -324,8 +341,19 @@ just hit ENTER twice.
 				return ret
 			else:
 				msg("%ss do not match" % what.capitalize())
+=======
+		ret  = " ".join(_get_words_from_user(opts,"Enter %s: " % what))
+		ret2 = " ".join(_get_words_from_user(opts,"Repeat %s: " % what))
+		if debug: print "Passphrases: [%s] [%s]" % (ret,ret2)
+		if ret2 == ret:
+			s = " (empty)" if not len(ret) else ""
+			msg("%ss match%s" % (what.capitalize(),s))
+			return ret
+		else:
+			msg("%ss do not match" % what.capitalize())
+>>>>>>> my
 
-	msg("User failed to duplicate passphrase in " + str(passwd_max_tries) + " attempts")
+	msg("User failed to duplicate passphrase in %s attempts" % passwd_max_tries)
 	sys.exit(2)
 
 
@@ -333,7 +361,7 @@ def _scrypt_hash_passphrase(passwd, salt, hash_preset, buflen=32):
 
 	N,r,p = _get_hash_params(hash_preset)
 
-  	import scrypt
+	import scrypt
 	return scrypt.hash(passwd, salt, 2**N, r, p, buflen=buflen)
 
 
@@ -354,14 +382,14 @@ def encrypt_seed(seed, key, opts):
 	Encrypt a seed for a {} deterministic wallet
 	""".format(proj_name)
 
-    # 192-bit seed is 24 bytes -> not multiple of 16.  Must use MODE_CTR
+	# 192-bit seed is 24 bytes -> not multiple of 16.  Must use MODE_CTR
 	from Crypto.Cipher import AES
 	from Crypto.Util import Counter
 
 	c = AES.new(key, AES.MODE_CTR,counter=Counter.new(128))
 	enc_seed = c.encrypt(seed)
 
- 	msg_r("Performing a test decryption of the seed...")
+	msg_r("Performing a test decryption of the seed...")
 
 	c = AES.new(key, AES.MODE_CTR,counter=Counter.new(128))
 	dec_seed = c.decrypt(enc_seed)
@@ -473,7 +501,7 @@ def _display_control_data(label,metadata,hash_preset,salt,enc_seed):
 		("Key  ID:",             metadata[1]),
 		("Seed length:",         metadata[2]),
 		("Scrypt hash params:",  "Preset '%s' (%s)" % (hash_preset,
-		 " ".join([str(i) for i in _get_hash_params(hash_preset)]))),
+			" ".join([str(i) for i in _get_hash_params(hash_preset)]))),
 		("Passphrase is empty:", pw_empty),
 		("Timestamp:",           "%s UTC" % metadata[4]),
 		("Salt:",                b58encode_pad(salt)),
@@ -510,7 +538,11 @@ def write_wallet_to_file(seed, passwd, key_id, salt, enc_seed, opts):
 	esf = b58encode_pad(enc_seed)
 
 	metadata = seed_id.lower(),key_id.lower(),\
+<<<<<<< HEAD
 			   seed_len,pw_status,make_timestamp()
+=======
+		seed_len,pw_status,make_timestamp()
+>>>>>>> my
 
 	lines = (
 		label,
@@ -593,12 +625,12 @@ def _check_chksum_6(chk,val,desc,infile):
 		msg("Checksum: %s. Computed value: %s" % (chk,comp_chk))
 		sys.exit(2)
 	elif debug:
-	 	msg("%s checksum passed: %s" % (desc.capitalize(),chk))
+		msg("%s checksum passed: %s" % (desc.capitalize(),chk))
 
 
 def get_data_from_wallet(infile,opts):
 
-	msg("Getting {} wallet data from file: {}".format(proj_name,infile))
+	msg("Getting {} wallet data from file '{}'".format(proj_name,infile))
 
 	f = open_file_or_exit(infile, 'r')
 
@@ -646,9 +678,21 @@ def _get_words_from_user(opts, prompt):
 def _get_words_from_file(infile,what):
 	msg("Getting %s from file '%s'" % (what,infile))
 	f = open_file_or_exit(infile, 'r')
+<<<<<<< HEAD
 	lines = f.readlines(); f.close()
+=======
+	data = f.read(); f.close()
+>>>>>>> my
 	# split() also strips
-	return [w for l in lines for w in l.split()]
+	return data.split()
+
+
+def get_lines_from_file(infile,what):
+	msg("Getting %s from file '%s'" % (what,infile))
+	f = open_file_or_exit(infile,'r')
+	lines = f.readlines(); f.close()
+	return [i.strip("\n") for i in lines]
+
 
 
 def get_lines_from_file(infile,what):
@@ -773,3 +817,6 @@ def get_seed(infile,opts,no_wallet=False):
 		return False
 	else:
 		return get_seed_from_wallet(infile, opts)
+
+if __name__ == "__main__":
+	print get_lines_from_file("/tmp/lines","test file")