diff --git a/mmgen-addrgen b/mmgen-addrgen
index 23ac14e0..ab4e0198 100755
--- a/mmgen-addrgen
+++ b/mmgen-addrgen
@@ -29,17 +29,19 @@ from mmgen.Opts import *
from mmgen.license import *
from mmgen.util 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"
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,
mnemonic, seed or password""".format(gen_what,g=g),
'usage':"[opts] [infile]
",
'options': """
-h, --help Print this help message{}
-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{}
-H, --show-hash-presets Show information on available hash presets
-K, --no-keyconv Use internal libraries for address generation
@@ -66,10 +68,10 @@ help_data = {
""".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 ("","","")),
seed_lens=", ".join([str(i) for i in g.seed_lens]),
@@ -148,29 +150,36 @@ if gen_what == "addresses":
else:
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)
+outfile_base = "{}[{}]".format(seed_id, fmt_addr_idxs(addr_idxs))
+
# Output data:
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)
elif not sys.stdout.isatty():
write_to_stdout(addr_data_str,gen_what,confirm=False)
else:
- write_addr_data_to_file(seed, addr_data_str, addr_idxs, opts)
+ 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)
-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())
+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")
diff --git a/mmgen-addrimport b/mmgen-addrimport
index 10b0ac23..bebd9cf0 100755
--- a/mmgen-addrimport
+++ b/mmgen-addrimport
@@ -27,7 +27,7 @@ from mmgen.util import *
from mmgen.tx import connect_to_bitcoind,parse_addrs_file
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
watching wallet""".format(pnm=g.proj_name),
'usage':"[opts] [mmgen address file]",
diff --git a/mmgen-pywallet b/mmgen-pywallet
index fff14028..1169420e 100755
--- a/mmgen-pywallet
+++ b/mmgen-pywallet
@@ -43,9 +43,6 @@ mmgen-pywallet: Dump contents of a bitcoind wallet to file
# Alex Martelli (http://www.aleax.it)
# 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 *
import sys, time
import json
@@ -61,16 +58,18 @@ import hashlib
import random
import math
+import mmgen.config as g
+from mmgen.Opts import *
+from mmgen.util import msg
+
max_version = 60000
addrtype = 0
json_db = {}
private_keys = []
password = None
-prog_name = sys.argv[0].split("/")[-1]
-
help_data = {
- 'prog_name': prog_name,
+ 'prog_name': g.prog_name,
'desc': "Dump contents of a bitcoind wallet to file",
'usage': "[opts] ",
'options': """
diff --git a/mmgen-tool b/mmgen-tool
index f902cdbe..e84a07e0 100755
--- a/mmgen-tool
+++ b/mmgen-tool
@@ -22,17 +22,17 @@ mmgen-tool: Perform various Bitcoin-related operations - part of the MMGen suite
import sys, os
from hashlib import sha256
-from mmgen.Opts import *
import mmgen.config as g
-from mmgen.util import pretty_hexdump
import mmgen.tool as tool
-prog_name = sys.argv[0].split("/")[-1]
+from mmgen.Opts import *
+from mmgen.util import pretty_hexdump
help_data = {
- 'prog_name': prog_name,
+ 'prog_name': g.prog_name,
'desc': "Perform various BTC-related operations",
'usage': "[opts] ",
'options': """
+-d, --outdir= d Specify an alternate directory 'd' for output
-h, --help Print this help message
-q, --quiet Produce quieter output
-r, --usr-randchars=n Get 'n' characters of additional randomness from
@@ -44,7 +44,7 @@ help_data = {
COMMANDS:{}
Type '{} --help for usage information on a particular
command
-""".format(tool.command_help,prog_name)
+""".format(tool.command_help,g.prog_name)
}
opts,cmd_args = parse_opts(sys.argv,help_data)
@@ -63,10 +63,10 @@ if command not in tool.commands.keys():
sys.exit(1)
if cmd_args and cmd_args[0] == '--help':
- tool.tool_usage(prog_name, command)
+ tool.tool_usage(g.prog_name, command)
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
diff --git a/mmgen-txcreate b/mmgen-txcreate
index e81bd0c7..a6590ad9 100755
--- a/mmgen-txcreate
+++ b/mmgen-txcreate
@@ -20,19 +20,16 @@ mmgen-txcreate: Create a BTC transaction, sending to specified addresses
"""
import sys
-#from hashlib import sha256
-
-from mmgen.Opts import *
-from mmgen.license import *
-import mmgen.config as g
-from mmgen.tx import *
-from mmgen.util import msg, msg_r, user_confirm
from decimal import Decimal
-prog_name = sys.argv[0].split("/")[-1]
+import mmgen.config as g
+from mmgen.Opts import *
+from mmgen.license import *
+from mmgen.tx import *
+from mmgen.util import msg, msg_r, user_confirm
help_data = {
- 'prog_name': prog_name,
+ 'prog_name': g.prog_name,
'desc': "Create a BTC transaction with outputs to specified addresses",
'usage': "[opts] ... [change addr] [addr file] ...",
'options': """
@@ -69,6 +66,7 @@ if g.debug: show_opts_and_cmd_args(opts,cmd_args)
c = connect_to_bitcoind()
if not 'info' in opts:
+ do_license_msg(immed=True)
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 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:
import mmgen.rpc
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)
-unspent = sort_and_view(us)
+unspent = sort_and_view(us,opts)
total = trim_exponent(sum([i.amount for i in unspent]))
@@ -209,6 +207,15 @@ if reply and reply in "YyVv":
prompt = "Save transaction?"
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:
msg("Transaction not saved")
diff --git a/mmgen-txsend b/mmgen-txsend
index 75c0018e..89a6ab78 100755
--- a/mmgen-txsend
+++ b/mmgen-txsend
@@ -21,17 +21,15 @@ mmgen-txsend: Broadcast a Bitcoin transaction to the network
import sys
+import mmgen.config as g
from mmgen.Opts import *
from mmgen.license import *
-import mmgen.config as g
from mmgen.tx import *
from mmgen.util import msg,check_infile,get_lines_from_file,confirm_or_exit
-prog_name = sys.argv[0].split("/")[-1]
-
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] ",
'options': """
-h, --help Print this help message
@@ -84,4 +82,5 @@ except:
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)
diff --git a/mmgen-txsign b/mmgen-txsign
index 7bd71485..a11b7242 100755
--- a/mmgen-txsign
+++ b/mmgen-txsign
@@ -21,15 +21,15 @@ mmgen-txsign: Sign a Bitcoin transaction generated by mmgen-txcreate
import sys
+import mmgen.config as g
from mmgen.Opts import *
from mmgen.license import *
-import mmgen.config as g
from mmgen.tx import *
from mmgen.util import msg,qmsg
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] .. [mmgen wallet/seed/words/brainwallet file] .. [addrfile] ..",
'options': """
-h, --help Print this help message
@@ -63,7 +63,7 @@ help_data = {
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 {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- options will be taken from a file if a second
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}'
mnemonic: '.{g.mn_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)
@@ -184,7 +184,14 @@ for tx_file in tx_files:
if sig_tx['complete']:
prompt = "OK\nSave signed transaction?"
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:
msg("failed\nSome keys were missing. Transaction could not be signed.")
sys.exit(3)
diff --git a/mmgen-walletchk b/mmgen-walletchk
index ac938d00..16b2ea31 100755
--- a/mmgen-walletchk
+++ b/mmgen-walletchk
@@ -21,12 +21,12 @@ mmgen-walletchk: Check integrity of a mmgen deterministic wallet, display
"""
import sys
+import mmgen.config as g
from mmgen.Opts import *
-
from mmgen.util import *
help_data = {
- 'prog_name': sys.argv[0].split("/")[-1],
+ 'prog_name': g.prog_name,
'desc': """Check integrity of an {} deterministic wallet, display
its information, and export seed and mnemonic data.
""".format(g.proj_name),
@@ -89,7 +89,7 @@ elif 'export_incog' in opts:
)
data = pretty_hexdump(incog_enc,2,8,line_nums=False) \
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()
@@ -105,11 +105,11 @@ if 'export_mnemonic' in opts:
p = True if g.debug else False
mn = get_mnemonic_from_seed(seed, wl, g.default_wl, print_info=p)
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:
from mmgen.bitcoin import b58encode_pad
data = col4(b58encode_pad(seed))
chk = make_chksum_6(b58encode_pad(seed))
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")
diff --git a/mmgen-walletgen b/mmgen-walletgen
index 91d0a15f..9dfce80b 100755
--- a/mmgen-walletgen
+++ b/mmgen-walletgen
@@ -22,15 +22,14 @@ mmgen-walletgen: Generate a mmgen deterministic wallet
import sys, os
from hashlib import sha256
+import mmgen.config as g
from mmgen.Opts import *
from mmgen.license import *
-import mmgen.config as g
from mmgen.walletgen import *
from mmgen.util import *
-prog_name = sys.argv[0].split("/")[-1]
help_data = {
- 'prog_name': prog_name,
+ 'prog_name': g.prog_name,
'desc': "Generate an {} deterministic wallet".format(g.proj_name),
'usage': "[opts] [infile]",
'options': """
@@ -61,7 +60,7 @@ help_data = {
'notes': """
By default (i.e. when invoked without any of the '--from-' 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- options will be taken from if
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
addresses, the same 'l' and 'p' parameters to '--from-brain' must be used
in all future invocations with that passphrase.
-""".format(prog_name=prog_name)
+""".format(g=g)
}
opts,cmd_args = parse_opts(sys.argv,help_data)
diff --git a/mmgen/addr.py b/mmgen/addr.py
index e9298507..9543fccc 100755
--- a/mmgen/addr.py
+++ b/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']
end = addr_data[-1]['num']
-
- 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)
- )
-
+ fs = " %-{}s %s".format(len(str(end)))
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")
+
+ 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.append("%s {" % seed_id.upper())
for d in addr_data:
- col1 = d['num']
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:
- 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("}")
return "\n".join(out) + "\n"
@@ -191,26 +175,3 @@ def fmt_addr_idxs(addr_idxs):
prev = i
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))
diff --git a/mmgen/config.py b/mmgen/config.py
index 5b87a31d..b6587d5a 100755
--- a/mmgen/config.py
+++ b/mmgen/config.py
@@ -19,6 +19,9 @@
config.py: Constants and configuration options for the mmgen suite
"""
+import sys, os
+prog_name = os.path.basename(sys.argv[0])
+
author = "Philemon"
email = ""
Cdates = '2013-2014'
diff --git a/mmgen/tool.py b/mmgen/tool.py
index 2e2d7bb6..181edfcd 100755
--- a/mmgen/tool.py
+++ b/mmgen/tool.py
@@ -420,7 +420,8 @@ def encrypt(infile,outfile="",hash_preset=''):
enc_d = encrypt_data(sha256(nonce+d).digest() + nonce + d, key,
int(ba.hexlify(iv),16))
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=''):
d = get_data_from_file(infile,"encrypted data")
@@ -439,6 +440,6 @@ def decrypt(infile,outfile="",hash_preset=''):
import re
of = re.sub(r'\.%s$'%g.mmenc_ext,r'',infile)
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:
msg("Incorrect passphrase or hash preset")
diff --git a/mmgen/tx.py b/mmgen/tx.py
index 2c6dd8d9..9bb09b7f 100755
--- a/mmgen/tx.py
+++ b/mmgen/tx.py
@@ -19,11 +19,12 @@
tx.py: Bitcoin transaction routines
"""
-from binascii import unhexlify
-from mmgen.util import *
import sys, os
+from binascii import unhexlify
from decimal import Decimal
+
import mmgen.config as g
+from mmgen.util import *
txmsg = {
'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,
which makes the signing process more complicated. When signing the
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': """
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}
@@ -60,8 +61,8 @@ tracking wallet, or supply an address file for it on the command line.
""".strip(),
'no_spendable_outputs': """
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': """
MMGen -> BTC address mappings differ!
In transaction: %s
@@ -82,12 +83,6 @@ The {pnm}-to-BTC mappings for these addresses cannot be verified!
""".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():
@@ -168,44 +163,6 @@ def get_bitcoind_cfg_options(cfg_keys):
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):
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_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
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"
-
options_msg = """
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
@@ -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): "
from copy import deepcopy
- write_to_file_msg = ""
- msg("")
-
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:
cols = get_terminal_size()[0]
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)
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))
+ txdots = "..." if tx_w < 64 else ""
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)
for i in unsp: i.skip = ""
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"
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)
i.amt = " "*lfill + amt
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)
if i.skip == "addr":
i.addr = "|" + "." * 33
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 ""
-
i.addr = "%s%s %s" % (
i.address[:btaddr_w-len(dots)],
dots,
@@ -305,20 +258,17 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
else:
i.addr = i.address
- dots = "..." if tx_w < 64 else ""
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.append(sort if sort else "unsorted")
if group and (sort == "address" or sort == "txid"):
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)
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 == 'q': pass
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':
do_pager("\n".join(out))
continue
@@ -572,16 +522,18 @@ Only ASCII printable characters are permitted.
""".strip() % (ch,label))
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 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
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))
msg("Check this value against your records")
diff --git a/mmgen/util.py b/mmgen/util.py
index 31446d37..303d97c0 100755
--- a/mmgen/util.py
+++ b/mmgen/util.py
@@ -24,7 +24,7 @@ from hashlib import sha256
from binascii import hexlify,unhexlify
import mmgen.config as g
-from mmgen.bitcoin import b58decode_pad
+from mmgen.bitcoin import b58decode_pad,b58encode_pad
from mmgen.term import *
def msg(s): sys.stderr.write(s + "\n")
@@ -48,7 +48,6 @@ def get_extension(f):
import os
return os.path.splitext(f)[1][1:]
-
def get_random_data_from_user(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")
+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):
s = sha256(sha256(s).digest()).hexdigest()[:8].upper()
return "{} {}".format(s[:4],s[4:]) if sep else s
@@ -427,9 +432,9 @@ def open_file_or_exit(filename,mode):
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:
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)
f = open_file_or_exit(outfile,'w')
-
try:
f.write(data)
except:
- msg("Failed to write to file '%s'" % outfile)
+ msg("Failed to write %s to file '%s'" % (what,outfile))
sys.exit(2)
-
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:
- write_to_stdout(data, label, confirm=True)
+ write_to_stdout(data, what, confirm=True)
elif not sys.stdout.isatty():
- write_to_stdout(data, label, confirm=False)
+ write_to_stdout(data, what, confirm=False)
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):
@@ -522,23 +526,13 @@ def write_wallet_to_file(seed, passwd, key_id, salt, enc_seed, opts):
seed_id = make_chksum_8(seed)
seed_len = str(len(seed)*8)
pw_status = "NE" if len(passwd) else "E"
-
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"
-
- from mmgen.bitcoin import b58encode_pad
-
+ metadata = seed_id.lower(),key_id.lower(),seed_len,\
+ pw_status,make_timestamp()
sf = b58encode_pad(salt)
esf = b58encode_pad(enc_seed)
- metadata = seed_id.lower(),key_id.lower(),\
- seed_len,pw_status,make_timestamp()
-
lines = (
label,
"{} {} {} {} {}".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))
+ 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:
_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):
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
# the filename.
- if not silent:
+ if not silent and not g.quiet:
msg("Getting {} wallet data from file '{}'".format(g.proj_name,infile))
f = open_file_or_exit(infile, 'r')
@@ -864,7 +852,7 @@ def get_seed_from_incog_wallet(
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:
p = "Enter hash preset for %s wallet (default='%s'): "
hp = my_raw_input(p % (g.proj_name, g.hash_preset))