test/test.py:
To make sure backwards compatibility is maintained, added reference files
and tests for all MMGen wallet formats, tx, address and key-address files.
This commit is contained in:
parent
4d618ac6f2
commit
4a93cdee6a
42 changed files with 561 additions and 267 deletions
|
|
@ -29,24 +29,27 @@ from mmgen.bitcoin import numtowif
|
|||
# from mmgen.util import msg,qmsg,qmsg_r,make_chksum_N,get_lines_from_file,get_data_from_file,get_extension
|
||||
from mmgen.util import *
|
||||
from mmgen.tx import *
|
||||
from mmgen.obj import *
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
|
||||
pnm = g.proj_name
|
||||
|
||||
addrmsgs = {
|
||||
'addrfile_header': """
|
||||
# MMGen address file
|
||||
# {pnm} address file
|
||||
#
|
||||
# This file is editable.
|
||||
# Everything following a hash symbol '#' is a comment and ignored by {pnm}.
|
||||
# A text label of {} characters or less may be added to the right of each
|
||||
# A text label of {n} characters or less may be added to the right of each
|
||||
# address, and it will be appended to the bitcoind wallet label upon import.
|
||||
# The label may contain any printable ASCII symbol.
|
||||
""".strip().format(g.max_addr_label_len,pnm=g.proj_name),
|
||||
""".strip().format(n=g.max_addr_label_len,pnm=pnm),
|
||||
'no_keyconv_msg': """
|
||||
Executable '{kcexe}' unavailable. Falling back on (slow) internal ECDSA library.
|
||||
Please install '{kcexe}' from the {vanityg} package on your system for much
|
||||
Executable '{kconv}' unavailable. Falling back on (slow) internal ECDSA library.
|
||||
Please install '{kconv}' from the {vgen} package on your system for much
|
||||
faster address generation.
|
||||
""".format(kcexe=g.keyconv_exec, vanityg="vanitygen")
|
||||
""".format(kconv=g.keyconv_exec, vgen="vanitygen")
|
||||
}
|
||||
|
||||
def test_for_keyconv(silent=False):
|
||||
|
|
@ -61,7 +64,7 @@ def test_for_keyconv(silent=False):
|
|||
return True
|
||||
|
||||
|
||||
def generate_addrs(seed, addrnums):
|
||||
def generate_addrs(seed, addrnums, source="addrgen"):
|
||||
|
||||
from util import make_chksum_8
|
||||
seed_id = make_chksum_8(seed) # Must do this before seed gets clobbered
|
||||
|
|
@ -116,7 +119,7 @@ def generate_addrs(seed, addrnums):
|
|||
|
||||
m = w[0] if t_addrs == 1 else w[0]+w[1]
|
||||
qmsg("\r%s: %s %s generated%s" % (seed_id,t_addrs,m," "*15))
|
||||
a = AddrInfo(has_keys='k' in opt.gen_what)
|
||||
a = AddrInfo(has_keys='k' in opt.gen_what, source=source)
|
||||
a.initialize(seed_id,out)
|
||||
return a
|
||||
|
||||
|
|
@ -182,7 +185,7 @@ def _parse_addrfile(fn,buf=[],has_keys=False,exit_on_error=True):
|
|||
elif cbrace != '}':
|
||||
errmsg = "'%s': invalid last line" % cbrace
|
||||
elif not is_mmgen_seed_id(sid):
|
||||
errmsg = "'%s': invalid Seed ID" % sid
|
||||
errmsg = "'%s': invalid seed ID" % sid
|
||||
else:
|
||||
ret = _parse_addrfile_body(lines[1:-1],has_keys)
|
||||
if type(ret) == list: return sid,ret
|
||||
|
|
@ -196,7 +199,7 @@ def _parse_addrfile(fn,buf=[],has_keys=False,exit_on_error=True):
|
|||
|
||||
|
||||
def _parse_keyaddr_file(infile):
|
||||
d = get_data_from_file(infile,"%s key-address file data" % g.proj_name)
|
||||
d = get_data_from_file(infile,"{pnm} key-address file data".format(pnm=pnm))
|
||||
enc_ext = get_extension(infile) == g.mmenc_ext
|
||||
if enc_ext or not is_utf8(d):
|
||||
m = "Decrypting" if enc_ext else "Attempting to decrypt"
|
||||
|
|
@ -206,7 +209,7 @@ def _parse_keyaddr_file(infile):
|
|||
return _parse_addrfile("",buf=d,has_keys=True,exit_on_error=False)
|
||||
|
||||
|
||||
class AddrInfoList(object):
|
||||
class AddrInfoList(MMGenObject):
|
||||
|
||||
def __init__(self,addrinfo=None,bitcoind_connection=None):
|
||||
self.data = {}
|
||||
|
|
@ -239,7 +242,8 @@ class AddrInfoList(object):
|
|||
a.idx,a.addr,a.comment = \
|
||||
int(idx),unicode(addrlist[0]),unicode(comment)
|
||||
data[seed_id].append(a)
|
||||
vmsg("%s %s addresses found, %s accounts total" % (i,g.proj_name,len(accts)))
|
||||
vmsg("{n} {pnm} addresses found, {m} accounts total".format(
|
||||
n=i,pnm=pnm,m=len(accts)))
|
||||
for sid in data:
|
||||
self.add(AddrInfo(sid=sid,adata=data[sid]))
|
||||
|
||||
|
|
@ -257,22 +261,25 @@ class AddrInfoList(object):
|
|||
d.update(self.data[k].make_reverse_dict(btcaddrs))
|
||||
return d
|
||||
|
||||
class AddrInfoEntry(object):
|
||||
class AddrInfoEntry(MMGenObject):
|
||||
|
||||
def __init__(self): pass
|
||||
|
||||
class AddrInfo(object):
|
||||
class AddrInfo(MMGenObject):
|
||||
|
||||
def __init__(self,addrfile="",has_keys=False,sid="",adata=[]):
|
||||
self.has_keys=has_keys
|
||||
def __init__(self,addrfile="",has_keys=False,sid="",adata=[], source=""):
|
||||
self.has_keys = has_keys
|
||||
do_chksum = True
|
||||
if addrfile:
|
||||
f = _parse_keyaddr_file if has_keys else _parse_addrfile
|
||||
sid,adata = f(addrfile)
|
||||
self.source = "addrfile"
|
||||
elif sid and adata: # data from wallet
|
||||
pass
|
||||
self.source = "wallet"
|
||||
elif sid or adata:
|
||||
die(3,"Must specify address file, or seed_id + adata")
|
||||
else:
|
||||
self.source = source if source else "unknown"
|
||||
return
|
||||
|
||||
self.initialize(sid,adata)
|
||||
|
|
@ -284,12 +291,21 @@ class AddrInfo(object):
|
|||
self.seed_id = seed_id
|
||||
self.addrdata = addrdata
|
||||
self.num_addrs = len(addrdata)
|
||||
self.make_addrdata_chksum()
|
||||
self.fmt_addr_idxs()
|
||||
w = "key" if self.has_keys else "addr"
|
||||
qmsg("Computed checksum for %s data %s[%s]: %s" %
|
||||
(w,self.seed_id,self.idxs_fmt,self.checksum))
|
||||
qmsg("Check this value against your records")
|
||||
if self.source in ("wallet","txsign") or \
|
||||
(self.source == "addrgen" and opt.gen_what == "k"):
|
||||
self.checksum = None
|
||||
self.idxs_fmt = None
|
||||
else: # self.source in addrfile, addrgen
|
||||
self.make_addrdata_chksum()
|
||||
self.fmt_addr_idxs()
|
||||
w = "key-address" if self.has_keys else "address"
|
||||
qmsg("Checksum for %s data %s[%s]: %s" %
|
||||
(w,self.seed_id,self.idxs_fmt,self.checksum))
|
||||
if self.source == "addrgen":
|
||||
qmsg(
|
||||
"This checksum will be used to verify the address file in the future")
|
||||
elif self.source == "addrfile":
|
||||
qmsg("Check this value against your records")
|
||||
|
||||
def idxs(self):
|
||||
return [e.idx for e in self.addrdata]
|
||||
|
|
@ -337,7 +353,7 @@ class AddrInfo(object):
|
|||
|
||||
def make_addrdata_chksum(self):
|
||||
nchars = 24
|
||||
lines = [" ".join([str(e.idx),e.addr]+([e.wif] if self.has_keys else []))
|
||||
lines=[" ".join([str(e.idx),e.addr]+([e.wif] if self.has_keys else []))
|
||||
for e in self.addrdata]
|
||||
self.checksum = make_chksum_N(" ".join(lines), nchars, sep=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ required_opts = [
|
|||
"usr_randchars","stdout","show_hash_presets"
|
||||
]
|
||||
min_screen_width = 80
|
||||
max_tx_comment_len = 72
|
||||
|
||||
wallet_ext = "mmdat"
|
||||
seed_ext = "mmseed"
|
||||
|
|
@ -84,12 +83,11 @@ default_wordlist = "electrum"
|
|||
dfl_vars = "seed_len","hash_preset","usr_randchars","debug"
|
||||
|
||||
seed_lens = 128,192,256
|
||||
|
||||
mn_lens = [i / 32 * 3 for i in seed_lens]
|
||||
|
||||
keyconv_exec = "keyconv"
|
||||
|
||||
mins_per_block = 8.5
|
||||
mins_per_block = 9
|
||||
passwd_max_tries = 5
|
||||
|
||||
max_urandchars,min_urandchars = 80,10
|
||||
|
|
@ -113,16 +111,15 @@ hash_presets = {
|
|||
|
||||
mmgen_idx_max_digits = 7
|
||||
|
||||
from string import ascii_letters, digits
|
||||
printable_nonl = [chr(i+32) for i in range(95)]
|
||||
printable = printable_nonl + ['\n','\t']
|
||||
|
||||
addr_label_symbols = wallet_label_symbols = printable_nonl
|
||||
|
||||
addr_label_symbols = tuple([chr(i) for i in range(0x20,0x7f)])
|
||||
max_addr_label_len = 32
|
||||
|
||||
wallet_label_symbols = addr_label_symbols
|
||||
max_wallet_label_len = 48
|
||||
max_tx_comment_len = 72 # Comment is b58 encoded, so can permit all UTF-8
|
||||
|
||||
printable_nospc = [chr(i+33) for i in range(94)]
|
||||
printable = printable_nospc + [' ','\n','\t']
|
||||
#addr_label_punc = ".","_",",","-"," ","(",")"
|
||||
#addr_label_symbols = tuple(ascii_letters + digits) + addr_label_punc
|
||||
#wallet_label_punc = addr_label_punc
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ def get_random(length):
|
|||
|
||||
def get_seed_from_wallet(
|
||||
infile,
|
||||
prompt_info="{} wallet".format(g.proj_name),
|
||||
prompt_info="{pnm} wallet".format(pnm=g.proj_name),
|
||||
silent=False
|
||||
):
|
||||
|
||||
|
|
@ -270,7 +270,7 @@ def confirm_old_format():
|
|||
|
||||
def get_seed_from_incog_wallet(
|
||||
infile,
|
||||
prompt_info="{} incognito wallet".format(g.proj_name),
|
||||
prompt_info="{pnm} incognito wallet".format(pnm=g.proj_name),
|
||||
silent=False,
|
||||
hex_input=False
|
||||
):
|
||||
|
|
@ -305,7 +305,7 @@ def get_seed_from_incog_wallet(
|
|||
|
||||
incog_id = make_iv_chksum(iv)
|
||||
msg("Incog ID: %s (IV ID: %s)" % (incog_id,make_chksum_8(iv)))
|
||||
qmsg("Check the applicable value against your records.")
|
||||
qmsg("Check the applicable value against your records")
|
||||
vmsg(crmsg['incog_iv_id_hidden' if opt.from_incog_hidden
|
||||
else 'incog_iv_id'])
|
||||
|
||||
|
|
@ -328,7 +328,7 @@ def get_seed_from_incog_wallet(
|
|||
old_fmt_sid = make_chksum_8(seed)
|
||||
|
||||
def confirm_correct_seed_id(sid):
|
||||
m = "Seed ID: %s. Is the Seed ID correct?" % sid
|
||||
m = "Seed ID: %s. Is the seed ID correct?" % sid
|
||||
return keypress_confirm(m, True)
|
||||
|
||||
if opt.old_incog_fmt:
|
||||
|
|
@ -344,6 +344,7 @@ def get_seed_from_incog_wallet(
|
|||
if confirm_correct_seed_id(old_fmt_sid):
|
||||
break
|
||||
|
||||
msg("Valid incog data for seed ID %s" % make_chksum_8(seed))
|
||||
return seed
|
||||
|
||||
|
||||
|
|
@ -412,7 +413,7 @@ def get_seed_retry(infile,seed_id=""):
|
|||
if seed: return seed
|
||||
|
||||
|
||||
def _get_seed_from_brain_passphrase(words):
|
||||
def _get_seed_from_brain_passphrase(words,silent=False):
|
||||
bp = " ".join(words)
|
||||
if opt.debug: Msg("Sanitized brain passphrase: %s" % bp)
|
||||
seed_len,hash_preset = get_from_brain_opt_params()
|
||||
|
|
@ -421,6 +422,10 @@ def _get_seed_from_brain_passphrase(words):
|
|||
# Use buflen arg of scrypt.hash() to get seed of desired length
|
||||
seed = scrypt_hash_passphrase(bp, "", hash_preset, buflen=seed_len/8)
|
||||
vmsg("Done")
|
||||
|
||||
if not silent:
|
||||
msg("Valid brainwallet for seed ID %s" % make_chksum_8(seed))
|
||||
|
||||
return seed
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
filename.py: Filename class and methods for the MMGen suite
|
||||
"""
|
||||
import sys,os
|
||||
from mmgen.obj import MMGenObject
|
||||
from mmgen.obj import *
|
||||
import mmgen.config as g
|
||||
from mmgen.util import msg
|
||||
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ import mmgen.config as g
|
|||
|
||||
gpl = {
|
||||
'warning': """
|
||||
MMGen Copyright (C) {g.Cdates} by {g.author} {g.email}. This
|
||||
{pnm} Copyright (C) {g.Cdates} by {g.author} {g.email}. This
|
||||
program comes with ABSOLUTELY NO WARRANTY. This is free software, and
|
||||
you are welcome to redistribute it under certain conditions.
|
||||
""".format(g=g),
|
||||
""".format(g=g,pnm=g.proj_name),
|
||||
'prompt': """
|
||||
Press 'w' for conditions and warranty info, or 'c' to continue:
|
||||
""",
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ from mmgen.addr import *
|
|||
what = "keys" if sys.argv[0].split("-")[-1] == "keygen" else "addresses"
|
||||
|
||||
opts_data = {
|
||||
'desc': """Generate a range or list of {} from an {g.proj_name} wallet,
|
||||
mnemonic, seed or password""".format(what,g=g),
|
||||
'desc': """Generate a range or list of {w} from an {pnm} wallet,
|
||||
mnemonic, seed or password""".format(w=what,pnm=g.proj_name),
|
||||
'usage':"[opts] [infile] <address range or list>",
|
||||
'options': """
|
||||
-h, --help Print this help message{}
|
||||
|
|
@ -47,7 +47,7 @@ opts_data = {
|
|||
(default: {g.seed_len})
|
||||
-p, --hash-preset= p Use scrypt.hash() parameters from preset 'p' when
|
||||
hashing password (default: '{g.hash_preset}')
|
||||
-P, --passwd-file= f Get MMGen wallet passphrase from file 'f'
|
||||
-P, --passwd-file= f Get {pnm} wallet passphrase from file 'f'
|
||||
-q, --quiet Suppress warnings; overwrite files without
|
||||
prompting
|
||||
-S, --stdout Print {what} to stdout
|
||||
|
|
@ -71,7 +71,7 @@ opts_data = {
|
|||
)
|
||||
if what == "keys" else ("","")),
|
||||
seed_lens=", ".join([str(i) for i in g.seed_lens]),
|
||||
what=what, g=g
|
||||
what=what,g=g,pnm=g.proj_name
|
||||
),
|
||||
'notes': """
|
||||
|
||||
|
|
@ -107,9 +107,9 @@ invocations with that passphrase
|
|||
|
||||
wmsg = {
|
||||
'unencrypted_secret_keys': """
|
||||
This program generates secret keys from your {} seed, outputting them in
|
||||
This program generates secret keys from your {pnm} seed, outputting them in
|
||||
UNENCRYPTED form. Generate only the key(s) you need and guard them carefully.
|
||||
""".format(g.proj_name),
|
||||
""".format(pnm=g.proj_name),
|
||||
}
|
||||
|
||||
cmd_args = opt.opts.init(opts_data,add_opts=["b16"])
|
||||
|
|
@ -136,25 +136,20 @@ if what == "keys" and not opt.quiet:
|
|||
|
||||
# Generate data:
|
||||
|
||||
seed = get_seed_retry(infile)
|
||||
seed = get_seed_retry(infile)
|
||||
|
||||
opt.gen_what = "a" if what == "addresses" else (
|
||||
"k" if opt.no_addresses else "ka")
|
||||
|
||||
ainfo = generate_addrs(seed, addr_idxs)
|
||||
ainfo = generate_addrs(seed,addr_idxs)
|
||||
|
||||
addrdata_str = ainfo.fmt_data()
|
||||
outfile_base = "{}[{}]".format(make_chksum_8(seed), ainfo.idxs_fmt)
|
||||
|
||||
if 'a' in opt.gen_what:
|
||||
if 'a' in opt.gen_what and opt.save_checksum:
|
||||
w = "key-address" if 'k' in opt.gen_what else "address"
|
||||
qmsg("Checksum for %s data %s: %s" % (w,outfile_base,ainfo.checksum))
|
||||
if opt.save_checksum:
|
||||
write_to_file(outfile_base+"."+g.addrfile_chksum_ext,
|
||||
ainfo.checksum+"\n","%s data checksum" % w,True,True,False)
|
||||
else:
|
||||
qmsg("This checksum will be used to verify the %s file in the future."%w)
|
||||
qmsg("Record it to a safe location.")
|
||||
write_to_file(outfile_base+"."+g.addrfile_chksum_ext,
|
||||
ainfo.checksum+"\n","%s data checksum" % w,True,True,False)
|
||||
|
||||
if 'k' in opt.gen_what and keypress_confirm("Encrypt key list?"):
|
||||
addrdata_str = mmgen_encrypt(addrdata_str,"new key list","")
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ if len(cmd_args) == 1:
|
|||
check_infile(infile)
|
||||
if opt.addrlist:
|
||||
lines = get_lines_from_file(
|
||||
infile,"non-{} addresses".format(g.proj_name),trim_comments=True)
|
||||
infile,"non-{pnm} addresses".format(pnm=g.proj_name),trim_comments=True)
|
||||
ai,adata = AddrInfo(),[]
|
||||
for btcaddr in lines:
|
||||
a = AddrInfoEntry()
|
||||
|
|
@ -64,9 +64,9 @@ if len(cmd_args) == 1:
|
|||
ai = AddrInfo(infile,has_keys=opt.keyaddr_file)
|
||||
else:
|
||||
msg("""
|
||||
"You must specify an mmgen address file (or a list of non-%s addresses
|
||||
"You must specify an mmgen address file (or a list of non-{pnm} addresses
|
||||
with the '--addrlist' option)
|
||||
""".strip() % g.proj_name)
|
||||
""".strip().format(pnm=g.proj_name))
|
||||
sys.exit(1)
|
||||
|
||||
from mmgen.bitcoin import verify_addr
|
||||
|
|
@ -124,7 +124,7 @@ for n,e in enumerate(ai.addrdata):
|
|||
if e.idx:
|
||||
label = "%s:%s" % (ai.seed_id,e.idx)
|
||||
if e.comment: label += " " + e.comment
|
||||
else: label = "non-%s" % g.proj_name
|
||||
else: label = "non-{pnm}".format(pnm=g.proj_name)
|
||||
|
||||
if opt.rescan:
|
||||
t = threading.Thread(target=import_address, args=(e.addr,label,True))
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ import mmgen.config as g
|
|||
import mmgen.opt as opt
|
||||
|
||||
opts_data = {
|
||||
'desc': """Change the passphrase, hash preset or label of an {}
|
||||
deterministic wallet""".format(g.proj_name),
|
||||
'desc': """Change the passphrase, hash preset or label of an {pnm}
|
||||
deterministic wallet""".format(pnm=g.proj_name),
|
||||
'usage': "[opts] [filename]",
|
||||
'options': """
|
||||
-h, --help Print this help message
|
||||
|
|
@ -40,13 +40,13 @@ opts_data = {
|
|||
-L, --label= l Change the wallet's label to 'l'
|
||||
-p, --hash-preset= p Change scrypt.hash() parameters to preset 'p'
|
||||
(default: '{g.hash_preset}')
|
||||
-P, --passwd-file= f Get new MMGen wallet passphrase from file 'f'
|
||||
-P, --passwd-file= f Get new {pnm} wallet passphrase from file 'f'
|
||||
-r, --usr-randchars= n Get 'n' characters of additional randomness from
|
||||
user (min={g.min_urandchars}, max={g.max_urandchars})
|
||||
-q, --quiet Suppress warnings; overwrite files without
|
||||
prompting
|
||||
-v, --verbose Produce more verbose output
|
||||
""".format(g=g),
|
||||
""".format(g=g,pnm=g.proj_name),
|
||||
'notes': """
|
||||
|
||||
NOTE: The key ID will change if either the passphrase or hash preset are
|
||||
|
|
@ -67,7 +67,7 @@ seed_id,key_id = metadata[:2]
|
|||
|
||||
# Repeat on incorrect pw entry
|
||||
while True:
|
||||
p = "{} wallet".format(g.proj_name)
|
||||
p = "{pnm} wallet".format(pnm=g.proj_name)
|
||||
passwd = get_mmgen_passphrase(p,not opt.keep_old_passphrase)
|
||||
key = make_key(passwd, salt, hash_preset)
|
||||
seed = decrypt_seed(enc_seed, key, seed_id, key_id)
|
||||
|
|
@ -85,7 +85,7 @@ else: opt.label = label # Copy the old label
|
|||
|
||||
if opt.hash_preset:
|
||||
if hash_preset != opt.hash_preset:
|
||||
qmsg("Hash preset has changed (%s -> %s)" %
|
||||
qmsg("Hash preset changed: '%s' -> '%s'" %
|
||||
(hash_preset, opt.hash_preset))
|
||||
changed['preset'] = True
|
||||
else:
|
||||
|
|
@ -97,7 +97,7 @@ if opt.keep_old_passphrase:
|
|||
msg("Keeping old passphrase by user request")
|
||||
else:
|
||||
new_passwd = get_new_passphrase(
|
||||
"{} wallet".format(g.proj_name), True)
|
||||
"{pnm} wallet".format(pnm=g.proj_name), True)
|
||||
|
||||
if new_passwd == passwd:
|
||||
qmsg("Passphrase is unchanged")
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import mmgen.opt as opt
|
|||
import mmgen.tool as tool
|
||||
|
||||
opts_data = {
|
||||
'desc': "Perform various MMGen- and Bitcoin-related operations",
|
||||
'desc': "Perform various {pnm}- and Bitcoin-related operations".format(pnm=g.proj_name),
|
||||
'usage': "[opts] <command> <command args>",
|
||||
'options': """
|
||||
-d, --outdir= d Specify an alternate directory 'd' for output
|
||||
|
|
@ -45,7 +45,7 @@ command
|
|||
""".format(tool.cmd_help,g.prog_name)
|
||||
}
|
||||
|
||||
cmd_args = opt.opts.init(opts_data)
|
||||
cmd_args = opt.opts.init(opts_data,add_opts=["no_keyconv"])
|
||||
|
||||
if len(cmd_args) < 1:
|
||||
opt.opts.usage()
|
||||
|
|
@ -54,6 +54,7 @@ if len(cmd_args) < 1:
|
|||
command = cmd_args.pop(0)
|
||||
|
||||
if command not in tool.cmd_data:
|
||||
from mmgen.util import msg
|
||||
msg("'%s': No such command" % command)
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
mmgen-txcreate: Create a Bitcoin transaction from MMGen- or non-MMGen inputs
|
||||
to MMGen- or non-MMGen outputs
|
||||
mmgen-txcreate: Create a Bitcoin transaction to and from MMGen- or non-MMGen
|
||||
inputs and outputs
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
|
@ -28,6 +28,8 @@ import mmgen.config as g
|
|||
import mmgen.opt as opt
|
||||
from mmgen.tx import *
|
||||
|
||||
pnm = g.proj_name
|
||||
|
||||
opts_data = {
|
||||
'desc': "Create a BTC transaction with outputs to specified addresses",
|
||||
'usage': "[opts] <addr,amt> ... [change addr] [addr file] ...",
|
||||
|
|
@ -55,7 +57,7 @@ of the form <seed ID>:<number>.
|
|||
|
||||
To send all inputs (minus TX fee) to a single output, specify one address
|
||||
with no amount on the command line.
|
||||
""".format(g=g,pnm=g.proj_name)
|
||||
""".format(g=g,pnm=pnm)
|
||||
}
|
||||
|
||||
wmsg = {
|
||||
|
|
@ -64,34 +66,34 @@ ERROR: More than one address found for account: "%s".
|
|||
Your "wallet.dat" file appears to have been altered by a non-{pnm} program.
|
||||
Please restore your tracking wallet from a backup or create a new one and
|
||||
re-import your addresses.
|
||||
""".strip().format(pnm=g.proj_name),
|
||||
""".strip().format(pnm=pnm),
|
||||
'addr_in_addrfile_only': """
|
||||
Warning: output address {mmgenaddr} is not in the tracking wallet, which means
|
||||
its balance will not be tracked. You're strongly advised to import the address
|
||||
into your tracking wallet before broadcasting this transaction.
|
||||
""".strip(),
|
||||
'addr_not_found': """
|
||||
No data for MMgen address {mmgenaddr} could be found in either the tracking
|
||||
No data for {pnm} address {mmgenaddr} could be found in either the tracking
|
||||
wallet or the supplied address file. Please import this address into your
|
||||
tracking wallet, or supply an address file for it on the command line.
|
||||
""".strip(),
|
||||
'addr_not_found_no_addrfile': """
|
||||
No data for MMgen address {mmgenaddr} could be found in the tracking wallet.
|
||||
No data for {pnm} address {mmgenaddr} could be found in the tracking wallet.
|
||||
Please import this address into your 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 '{pnm}-addrimport' and then re-run this program.
|
||||
""".strip().format(pnm=g.proj_name.lower()),
|
||||
""".strip(),
|
||||
'mixed_inputs': """
|
||||
NOTE: This transaction uses a mixture of both mmgen and non-mmgen inputs, which
|
||||
NOTE: This transaction uses a mixture of both {pnm} and non-{pnm} inputs, which
|
||||
makes the signing process more complicated. When signing the transaction, keys
|
||||
for the non-{pnm} inputs must be supplied to '{pnl}-txsign' in a file with the
|
||||
'--keys-from-file' option.
|
||||
|
||||
Selected mmgen inputs: %s
|
||||
""".strip().format(pnm=g.proj_name,pnl=g.proj_name.lower()),
|
||||
""".strip().format(pnm=pnm,pnl=pnm.lower()),
|
||||
'not_enough_btc': """
|
||||
Not enough BTC in the inputs for this transaction (%s BTC)
|
||||
""".strip(),
|
||||
|
|
@ -104,7 +106,7 @@ was specified.
|
|||
def format_unspent_outputs_for_printing(out,sort_info,total):
|
||||
|
||||
pfs = " %-4s %-67s %-34s %-12s %-13s %-8s %-10s %s"
|
||||
pout = [pfs % ("Num","TX id,Vout","Address","MMgen ID",
|
||||
pout = [pfs % ("Num","TX id,Vout","Address","{pnm} ID".format(pnm=pnm),
|
||||
"Amount (BTC)","Conf.","Age (days)", "Comment")]
|
||||
|
||||
for n,i in enumerate(out):
|
||||
|
|
@ -158,8 +160,9 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
|
|||
while True:
|
||||
cols = get_terminal_size()[0]
|
||||
if cols < g.min_screen_width:
|
||||
msg("%s-txcreate requires a screen at least %s characters wide" %
|
||||
(g.proj_name.lower(),g.min_screen_width))
|
||||
msg(
|
||||
"{pnl}-txcreate requires a screen at least {w} characters wide".format(
|
||||
pnl=pnm.lower(),w=g.min_screen_width))
|
||||
sys.exit(2)
|
||||
|
||||
addr_w = min(34+((1+max_acct_len) if show_mmaddr else 0),cols-46)
|
||||
|
|
@ -277,7 +280,7 @@ def select_outputs(unspent,prompt):
|
|||
|
||||
|
||||
def mmaddr2btcaddr_unspent(unspent,mmaddr):
|
||||
vmsg_r("Searching for {g.proj_name} address {m} in wallet...".format(g=g,m=mmaddr))
|
||||
vmsg_r("Searching for {pnm} address {m} in wallet...".format(pnm=pnm,m=mmaddr))
|
||||
m = [u for u in unspent if u.mmid == mmaddr]
|
||||
if len(m) == 0:
|
||||
vmsg("not found")
|
||||
|
|
@ -306,10 +309,10 @@ def mmaddr2btcaddr(c,mmaddr,ail_w,ail_f):
|
|||
if not keypress_confirm("Continue anyway?"):
|
||||
sys.exit(1)
|
||||
else:
|
||||
msg(wmsg['addr_not_found'].format(mmgenaddr=mmaddr))
|
||||
msg(wmsg['addr_not_found'].format(pnm=pnm,mmgenaddr=mmaddr))
|
||||
sys.exit(2)
|
||||
else:
|
||||
msg(wmsg['addr_not_found_no_addrfile'].format(mmgenaddr=mmaddr))
|
||||
msg(wmsg['addr_not_found_no_addrfile'].format(pnm=pnm,mmgenaddr=mmaddr))
|
||||
sys.exit(2)
|
||||
|
||||
return btcaddr
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ from mmgen.tx import *
|
|||
from mmgen.util import *
|
||||
|
||||
opts_data = {
|
||||
'desc': "Send a Bitcoin transaction signed by {}-txsign".format(g.proj_name.lower()),
|
||||
'desc': "Send a Bitcoin transaction signed by {pnm}-txsign".format(
|
||||
pnm=g.proj_name.lower()),
|
||||
'usage': "[opts] <signed transaction file>",
|
||||
'options': """
|
||||
-h, --help Print this help message
|
||||
|
|
|
|||
|
|
@ -27,8 +27,11 @@ import mmgen.opt as opt
|
|||
from mmgen.tx import *
|
||||
from mmgen.util import do_license_msg
|
||||
|
||||
pnm = g.proj_name
|
||||
pnl = pnm.lower()
|
||||
|
||||
opts_data = {
|
||||
'desc': "Sign Bitcoin transactions generated by {}-txcreate".format(g.proj_name.lower()),
|
||||
'desc': "Sign Bitcoin transactions generated by {pnl}-txcreate".format(pnl=pnl),
|
||||
'usage': "[opts] <transaction file> .. [mmgen wallet/seed/words/brainwallet file] ..",
|
||||
'options': """
|
||||
-h, --help Print this help message
|
||||
|
|
@ -37,16 +40,16 @@ opts_data = {
|
|||
-i, --info Display information about the transaction and exit
|
||||
-t, --terse-info Like '--info', but produce more concise output
|
||||
-I, --tx-id Display transaction ID and exit
|
||||
-k, --keys-from-file= f Provide additional keys for non-{MMG} addresses
|
||||
-k, --keys-from-file= f Provide additional keys for non-{pnm} addresses
|
||||
-K, --no-keyconv Force use of internal libraries for address gener-
|
||||
ation, even if 'keyconv' is available
|
||||
-M, --mmgen-keys-from-file=f Provide keys for {MMG} addresses in a key-
|
||||
address file (output of '{mmg}-keygen'). Permits
|
||||
online signing without an {MMG} seed source.
|
||||
-M, --mmgen-keys-from-file=f Provide keys for {pnm} addresses in a key-
|
||||
address file (output of '{pnl}-keygen'). Permits
|
||||
online signing without an {pnm} seed source.
|
||||
The key-address file is also used to verify
|
||||
{MMG}-to-BTC mappings, so its checksum should
|
||||
{pnm}-to-BTC mappings, so its checksum should
|
||||
be recorded by the user.
|
||||
-P, --passwd-file= f Get MMGen wallet or bitcoind passphrase from file 'f'
|
||||
-P, --passwd-file= f Get {pnm} wallet or bitcoind passphrase from file 'f'
|
||||
-q, --quiet Suppress warnings; overwrite files without
|
||||
prompting
|
||||
-v, --verbose Produce more verbose output
|
||||
|
|
@ -61,25 +64,25 @@ opts_data = {
|
|||
-o, --old-incog-fmt Use old (pre-0.7.8) incog format
|
||||
-m, --from-mnemonic Generate keys from an electrum-like mnemonic
|
||||
-s, --from-seed Generate keys from a seed in .{g.seed_ext} format
|
||||
""".format(g=g,MMG=g.proj_name,mmg=g.proj_name.lower()),
|
||||
""".format(g=g,pnm=pnm,pnl=pnl),
|
||||
'notes': """
|
||||
|
||||
Transactions with either {MMG} or non-{MMG} input addresses may be signed.
|
||||
For non-{MMG} inputs, the bitcoind wallet.dat is used as the key source.
|
||||
For {MMG} inputs, key data is generated from your seed as with the
|
||||
{mmg}-addrgen and {mmg}-keygen utilities.
|
||||
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
|
||||
{pnl}-addrgen and {pnl}-keygen utilities.
|
||||
|
||||
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
|
||||
prompted to enter the data.
|
||||
|
||||
In cases of transactions with mixed {MMG} and non-{MMG} inputs, non-{MMG}
|
||||
In cases of transactions with mixed {pnm} and non-{pnm} inputs, non-{pnm}
|
||||
keys must be supplied in a separate file (WIF format, one key per line)
|
||||
using the '--keys-from-file' option. Alternatively, one may get keys from
|
||||
a running bitcoind using the '--force-wallet-dat' option. First import the
|
||||
required {MMG} keys using 'bitcoind importprivkey'.
|
||||
required {pnm} keys using 'bitcoind importprivkey'.
|
||||
|
||||
For transaction outputs that are {MMG} addresses, {MMG}-to-Bitcoin address
|
||||
For transaction outputs that are {pnm} addresses, {pnm}-to-Bitcoin address
|
||||
mappings are verified. Therefore, seed material or a key-address file for
|
||||
these addresses must be supplied on the command line.
|
||||
|
||||
|
|
@ -88,18 +91,18 @@ 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,MMG=g.proj_name,mmg=g.proj_name.lower())
|
||||
""".format(g=g,pnm=pnm,pnl=pnl)
|
||||
}
|
||||
|
||||
wmsg = {
|
||||
'mm2btc_mapping_error': """
|
||||
MMGen -> BTC address mappings differ!
|
||||
{pnm} -> BTC address mappings differ!
|
||||
From %-18s %s -> %s
|
||||
From %-18s %s -> %s
|
||||
""".strip(),
|
||||
""".strip().format(pnm=pnm),
|
||||
'removed_dups': """
|
||||
Removed %s duplicate wif key%s from keylist (also in {MMG} key-address file
|
||||
""".strip().format(MMG=g.proj_name),
|
||||
Removed %s duplicate wif key%s from keylist (also in {pnm} key-address file
|
||||
""".strip().format(pnm=pnm),
|
||||
}
|
||||
|
||||
def get_seed_for_seed_id(seed_id,infiles,saved_seeds):
|
||||
|
|
@ -138,7 +141,7 @@ def get_keys_for_mmgen_addrs(mmgen_addrs,infiles,saved_seeds):
|
|||
seed = get_seed_for_seed_id(seed_id,infiles,saved_seeds)
|
||||
addr_nums = [int(i[9:]) for i in mmgen_addrs if i[:8] == seed_id]
|
||||
opt.gen_what = "ka"
|
||||
ai = generate_addrs(seed,addr_nums)
|
||||
ai = generate_addrs(seed,addr_nums,source="txsign")
|
||||
d += [("{}:{}".format(seed_id,e.idx),e.addr,e.wif) for e in ai.addrdata]
|
||||
return d
|
||||
|
||||
|
|
@ -189,10 +192,11 @@ def sign_tx_with_bitcoind_wallet(c,tx_hex,tx_num_str,sig_data,keys):
|
|||
return sig_tx
|
||||
|
||||
|
||||
def check_maps_from_seeds(maplist,label,infiles,saved_seeds,return_keys=False):
|
||||
def check_maps_from_seeds(maplist,what,infiles,saved_seeds,return_keys=False):
|
||||
|
||||
if not maplist: return []
|
||||
qmsg("Checking MMGen -> BTC address mappings for %ss (from seeds)" % label)
|
||||
qmsg("Checking {pnm} -> BTC address mappings for {w}s (from seed(s))".format(
|
||||
pnm=pnm,w=what))
|
||||
d = get_keys_for_mmgen_addrs(maplist.keys(),infiles,saved_seeds)
|
||||
# 0=mmaddr 1=addr 2=wif
|
||||
m = dict([(e[0],e[1]) for e in d])
|
||||
|
|
@ -209,8 +213,8 @@ def check_maps_from_seeds(maplist,label,infiles,saved_seeds,return_keys=False):
|
|||
def missing_keys_errormsg(addrs):
|
||||
Msg("""
|
||||
A key file must be supplied (or use the '--use-wallet-dat' option)
|
||||
for the following non-{} address{}:\n {}""".format(
|
||||
g.proj_name,suf(addrs,"a"),"\n ".join(addrs)).strip())
|
||||
for the following non-{pnm} address{suf}:\n {l}""".format(
|
||||
pnm=pnm, suf=suf(addrs,"a"), l="\n ".join(addrs)).strip())
|
||||
|
||||
|
||||
def parse_mmgen_keyaddr_file():
|
||||
|
|
@ -225,7 +229,7 @@ def parse_mmgen_keyaddr_file():
|
|||
|
||||
def parse_keylist(from_file):
|
||||
fn = opt.keys_from_file
|
||||
d = get_data_from_file(fn,"non-%s keylist" % g.proj_name)
|
||||
d = get_data_from_file(fn,"non-{pnm} keylist".format(pnm=pnm))
|
||||
enc_ext = get_extension(fn) == g.mmenc_ext
|
||||
if enc_ext or not is_utf8(d):
|
||||
if not enc_ext: qmsg("Keylist file appears to be encrypted")
|
||||
|
|
@ -250,7 +254,8 @@ def parse_keylist(from_file):
|
|||
|
||||
# Check inputs and outputs maps against key-address file, deleting entries:
|
||||
def check_maps_from_kafile(imap,what,kadata,return_keys=False):
|
||||
qmsg("Checking MMGen -> BTC address mappings for %ss (from key-address file)" % what)
|
||||
if not kadata: return []
|
||||
qmsg("Checking {pnm} -> BTC address mappings for {w}s (from key-address file)".format(pnm=pnm,w=what))
|
||||
ret = []
|
||||
for k in imap.keys():
|
||||
if k in kadata.keys():
|
||||
|
|
@ -372,7 +377,10 @@ for tx_num,tx_file in enumerate(tx_files,1):
|
|||
data = make_tx_data("{} {} {t}".format(*metadata[:2], t=make_timestamp()),
|
||||
sig_tx['hex'], inputs_data, b2m_map, comment)
|
||||
w = "signed transaction{}".format(tx_num_str)
|
||||
write_to_file(outfile,data,w,(not opt.quiet),True,False)
|
||||
if keypress_confirm("Save signed transaction?",default_yes=False):
|
||||
write_to_file(outfile,data,w,(not opt.quiet),True,False)
|
||||
else:
|
||||
msg("Signed transaction not saved")
|
||||
else:
|
||||
msg_r("failed\nSome keys were missing. ")
|
||||
msg("Transaction %scould not be signed." % tx_num_str)
|
||||
|
|
|
|||
|
|
@ -28,15 +28,15 @@ from mmgen.util import *
|
|||
from mmgen.crypto import *
|
||||
|
||||
opts_data = {
|
||||
'desc': """Check integrity of an {} deterministic wallet, display
|
||||
'desc': """Check integrity of an {pnm} deterministic wallet, display
|
||||
its information, and export seed and mnemonic data.
|
||||
""".format(g.proj_name),
|
||||
""".format(pnm=g.proj_name),
|
||||
'usage': "[opts] [filename]",
|
||||
'options': """
|
||||
-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
|
||||
-P, --passwd-file= f Get MMGen wallet passphrase from file 'f'
|
||||
-P, --passwd-file= f Get {pnm} wallet passphrase from file 'f'
|
||||
-q, --quiet Suppress warnings; overwrite files without prompting
|
||||
-r, --usr-randchars= n Get 'n' characters of additional randomness from
|
||||
user (min={g.min_urandchars}, max={g.max_urandchars})
|
||||
|
|
@ -49,7 +49,7 @@ opts_data = {
|
|||
-o, --old-incog-fmt Use old (pre-0.7.8) incog format
|
||||
-m, --export-mnemonic Export the wallet's mnemonic to file
|
||||
-s, --export-seed Export the wallet's seed to file
|
||||
""".format(g=g),
|
||||
""".format(g=g,pnm=g.proj_name),
|
||||
'notes': """
|
||||
|
||||
Since good randomness is particularly important for incognito wallets,
|
||||
|
|
@ -67,7 +67,7 @@ def wallet_to_incog_data(infile):
|
|||
d[1][0], d[1][1], d[2].split(":")[0], d[3], d[4]
|
||||
|
||||
while True:
|
||||
passwd = get_mmgen_passphrase("{} wallet".format(g.proj_name))
|
||||
passwd = get_mmgen_passphrase("{pnm} wallet".format(pnm=g.proj_name))
|
||||
key = make_key(passwd, salt, preset, "main key")
|
||||
seed = decrypt_seed(enc_seed, key, seed_id, key_id)
|
||||
if seed: break
|
||||
|
|
|
|||
|
|
@ -28,8 +28,10 @@ import mmgen.opt as opt
|
|||
from mmgen.util import *
|
||||
from mmgen.crypto import *
|
||||
|
||||
pnm = g.proj_name
|
||||
|
||||
opts_data = {
|
||||
'desc': "Generate an {} deterministic wallet".format(g.proj_name),
|
||||
'desc': "Generate an {pnm} deterministic wallet".format(pnm=pnm),
|
||||
'usage': "[opts] [infile]",
|
||||
'options': """
|
||||
-h, --help Print this help message
|
||||
|
|
@ -42,7 +44,7 @@ opts_data = {
|
|||
Allowed symbols: A-Z, a-z, 0-9, " ", "_", ".")
|
||||
-p, --hash-preset= p Use scrypt.hash() parameters from preset 'p'
|
||||
(default: '{g.hash_preset}')
|
||||
-P, --passwd-file= f Get MMGen wallet passphrase from file 'f'
|
||||
-P, --passwd-file= f Get {pnm} wallet passphrase from file 'f'
|
||||
-q, --quiet Produce quieter output; overwrite files without
|
||||
prompting
|
||||
-r, --usr-randchars= n Get 'n' characters of additional randomness from
|
||||
|
|
@ -58,7 +60,7 @@ opts_data = {
|
|||
-o, --old-incog-fmt Use old (pre-0.7.8) incog format
|
||||
-m, --from-mnemonic Generate wallet from an Electrum-like mnemonic
|
||||
-s, --from-seed Generate wallet from a seed in .{g.seed_ext} format
|
||||
""".format(seed_lens=",".join([str(i) for i in g.seed_lens]), g=g),
|
||||
""".format(seed_lens=",".join([str(i) for i in g.seed_lens]),g=g,pnm=pnm),
|
||||
'notes': """
|
||||
|
||||
By default (i.e. when invoked without any of the '--from-<what>' options),
|
||||
|
|
@ -106,16 +108,17 @@ just hit ENTER twice.
|
|||
############################## EXPERTS ONLY! ##############################
|
||||
|
||||
A brainwallet will be secure only if you really know what you're doing and
|
||||
have put much care into its creation. {} assumes no responsibility for
|
||||
coins stolen as a result of a poorly crafted brainwallet passphrase.
|
||||
have put much care into its creation. The creators of {pnm} assume no
|
||||
responsibility for coins stolen as a result of a poorly crafted brainwallet
|
||||
passphrase.
|
||||
|
||||
A key will be generated from your passphrase using the parameters requested
|
||||
by you: seed length {}, hash preset '{}'. For brainwallets it's highly
|
||||
recommended to use one of the higher-numbered presets
|
||||
recommended to use one of the higher-numbered presets.
|
||||
|
||||
Remember the seed length and hash preset parameters you've specified. To
|
||||
generate the correct keys/addresses associated with this passphrase in the
|
||||
future, you must continue using these same parameters
|
||||
future, you must continue using these same parameters.
|
||||
""",
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +148,7 @@ do_license_msg()
|
|||
|
||||
if opt.from_brain and not opt.quiet:
|
||||
confirm_or_exit(wmsg['brain_warning'].format(
|
||||
g.proj_name, *get_from_brain_opt_params()),
|
||||
pnm=pnm, *get_from_brain_opt_params()),
|
||||
"continue")
|
||||
|
||||
if infile or any([
|
||||
|
|
@ -160,7 +163,7 @@ salt = sha256(get_random(128)).digest()[:g.salt_len]
|
|||
|
||||
qmsg(wmsg['choose_wallet_passphrase'] % opt.hash_preset)
|
||||
|
||||
passwd = get_new_passphrase("new {} wallet".format(g.proj_name))
|
||||
passwd = get_new_passphrase("new {pnm} wallet".format(pnm=pnm))
|
||||
|
||||
key = make_key(passwd, salt, opt.hash_preset)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ------------------------------------------------------------------------------
|
||||
# MMgen note: this is a sorted version of the wordlist. The original
|
||||
# MMGen note: this is a sorted version of the wordlist. The original
|
||||
# can be found at:
|
||||
# https://github.com/spesmilo/electrum/blob/master/lib/mnemonic.py
|
||||
# and in the file 'wordlists/mnemonic.py' of the mmgen distribution.
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ def usage():
|
|||
|
||||
def print_version_info():
|
||||
Msg("""
|
||||
{progname_uc} version {g.version}. Part of the {g.proj_name} suite, a Bitcoin
|
||||
cold-storage solution for the command line. Copyright (C) {g.Cdates}
|
||||
by {g.author} {g.email}
|
||||
""".format(g=g,progname_uc=g.prog_name.upper()).strip())
|
||||
{progname_uc} version {g.version}
|
||||
Part of the {pnm} suite, a Bitcoin cold-storage solution for the com-
|
||||
mand line. Copyright (C) {g.Cdates} {g.author} {g.email}
|
||||
""".format(pnm=g.proj_name,g=g,progname_uc=g.prog_name.upper()).strip())
|
||||
|
||||
def warn_incompatible_opts(incompat_list):
|
||||
bad = [k for k in opt.__dict__ if opt.__dict__[k] and k in incompat_list]
|
||||
|
|
@ -61,7 +61,6 @@ def typeconvert_from_dfl(key):
|
|||
'bool': 'a boolean value',
|
||||
}
|
||||
m = [d[k] for k in d if __builtins__[k] == vtype]
|
||||
msgrepr_exit(key,vtype)
|
||||
fs = "'%s': invalid parameter for '--%s' option (not %s)"
|
||||
msg(fs % (opt.__dict__[key],opt.replace("_","-"),m))
|
||||
sys.exit(1)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ from mmgen.util import *
|
|||
from mmgen.bitcoin import b58encode_pad,b58decode_pad
|
||||
from mmgen.crypto import *
|
||||
|
||||
pnm = g.proj_name
|
||||
|
||||
class Seed(MMGenObject):
|
||||
def __init__(self,seed_bin=None):
|
||||
if not seed_bin:
|
||||
|
|
@ -293,7 +295,7 @@ class SeedFile (SeedSourceUnenc):
|
|||
|
||||
class Wallet (SeedSourceEnc):
|
||||
|
||||
desc = "%s wallet" % g.proj_name
|
||||
desc = "{pnm} wallet".format(pnm=pnm)
|
||||
|
||||
def _encode(self):
|
||||
d = self.ssdata
|
||||
|
|
@ -341,8 +343,8 @@ class Wallet (SeedSourceEnc):
|
|||
|
||||
def _deformat(self):
|
||||
|
||||
qmsg("Getting {} wallet data from file '{}'".format(
|
||||
g.proj_name,self.infile.name))
|
||||
qmsg("Getting {pnm} wallet data from file '{f}'".format(
|
||||
pnm=pnm,f=self.infile.name))
|
||||
|
||||
lines = self.fmt_data.rstrip().split("\n")
|
||||
|
||||
|
|
@ -518,13 +520,13 @@ to exit and re-run the program with the '--old-incog-fmt' option.
|
|||
d.incog_id = self._make_iv_chksum(d.iv)
|
||||
d.enc_incog_data = raw_d[g.aesctr_iv_len:]
|
||||
msg("Incog ID: %s" % d.incog_id)
|
||||
qmsg("Check the applicable value against your records.")
|
||||
qmsg("Check the applicable value against your records")
|
||||
k = 'incog_iv_id_hidden' if opt.from_incog_hidden else 'incog_iv_id'
|
||||
vmsg("\n%s\n" % self._icg_msg[k])
|
||||
|
||||
def _decode(self):
|
||||
d = self.ssdata
|
||||
prompt_info="{} incognito wallet".format(g.proj_name)
|
||||
prompt_info="{pnm} incognito wallet".format(pnm=pnm)
|
||||
|
||||
while True:
|
||||
passwd = get_mmgen_passphrase(prompt_info+" "+d.incog_id)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""
|
||||
addr.py: Shared routines for the test suites
|
||||
test.py: Shared routines for the test suites
|
||||
"""
|
||||
|
||||
import sys,os
|
||||
|
|
@ -86,6 +86,7 @@ def cmp_or_die(s,t,skip_ok=False):
|
|||
if s == t:
|
||||
if not skip_ok: ok()
|
||||
else:
|
||||
msg(red("Recoded data:\n%s\ndiffers from original data:\n%s\n" %
|
||||
(repr(t),repr(s))))
|
||||
sys.stderr.write(red(
|
||||
"ERROR: recoded data:\n%s\ndiffers from original data:\n%s\n" %
|
||||
(repr(t),repr(s))))
|
||||
sys.exit(3)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ from mmgen.crypto import *
|
|||
from mmgen.util import *
|
||||
from mmgen.tx import *
|
||||
|
||||
pnm = g.proj_name
|
||||
|
||||
from collections import OrderedDict
|
||||
cmd_data = OrderedDict([
|
||||
("help", []),
|
||||
|
|
@ -75,10 +77,10 @@ cmd_data = OrderedDict([
|
|||
|
||||
("listaddresses",['minconf [int=1]','showempty [bool=False]','pager [bool=False]']),
|
||||
("getbalance", ['minconf [int=1]']),
|
||||
("txview", ['<MMGen tx file> [str]','pager [bool=False]','terse [bool=False]']),
|
||||
("txview", ['<{pnm} tx file> [str]','pager [bool=False]','terse [bool=False]'.format(pnm=pnm)]),
|
||||
|
||||
("addrfile_chksum", ['<MMGen addr file> [str]']),
|
||||
("keyaddrfile_chksum", ['<MMGen addr file> [str]']),
|
||||
("addrfile_chksum", ['<{pnm} addr file> [str]'.format(pnm=pnm)]),
|
||||
("keyaddrfile_chksum", ['<{pnm} addr file> [str]'.format(pnm=pnm)]),
|
||||
("find_incog_data", ['<file or device name> [str]','<Incog ID> [str]','keep_searching [bool=False]']),
|
||||
|
||||
("encrypt", ['<infile> [str]','outfile [str=""]','hash_preset [str=""]']),
|
||||
|
|
@ -150,7 +152,7 @@ cmd_help = """
|
|||
|
||||
IMPORTANT NOTE: Though {pnm} mnemonics use the Electrum wordlist, they're
|
||||
computed using a different algorithm and are NOT Electrum-compatible!
|
||||
""".format(pnm=g.proj_name)
|
||||
""".format(pnm=pnm)
|
||||
|
||||
def tool_usage(prog_name, command):
|
||||
Msg("USAGE: '%s %s%s'" % (prog_name, command,
|
||||
|
|
@ -486,7 +488,7 @@ def decrypt(infile,outfile="",hash_preset=""):
|
|||
if dec_d: break
|
||||
msg("Trying again...")
|
||||
if outfile == '-':
|
||||
write_to_stdout(dec_d,"decrypted data",confirm=True)
|
||||
write_to_stdout(dec_d,"decrypted data",confirm=not opt.quiet)
|
||||
else:
|
||||
if not outfile:
|
||||
outfile = os.path.basename(infile)
|
||||
|
|
|
|||
27
mmgen/tx.py
27
mmgen/tx.py
|
|
@ -100,16 +100,21 @@ def wiftoaddr(s):
|
|||
if not hex_key: return False
|
||||
return privnum2addr(int(hex_key,16),compressed)
|
||||
|
||||
def is_valid_tx_comment(s, verbose=True):
|
||||
|
||||
def is_valid_tx_comment(s):
|
||||
|
||||
try: s = s.decode("utf8")
|
||||
except:
|
||||
msg("Invalid transaction comment (not UTF-8)")
|
||||
return False
|
||||
|
||||
if len(s) > g.max_tx_comment_len:
|
||||
if verbose: msg("Invalid transaction comment (longer than %s characters)" %
|
||||
msg("Invalid transaction comment (longer than %s characters)" %
|
||||
g.max_tx_comment_len)
|
||||
return False
|
||||
try: s.decode("utf8")
|
||||
except:
|
||||
if verbose: msg("Invalid transaction comment (not UTF-8)")
|
||||
return False
|
||||
else: return True
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def check_addr_label(label):
|
||||
|
||||
|
|
@ -149,7 +154,7 @@ def view_tx_data(c,inputs_data,tx_hex,b2m_map,comment,metadata,pager=False,pause
|
|||
if comment: out += "Comment: %s\n%s" % (comment,enl)
|
||||
out += "Inputs:\n" + enl
|
||||
|
||||
nonmm_str = "non-%s address" % g.proj_name
|
||||
nonmm_str = "non-{pnm} address".format(pnm=g.proj_name)
|
||||
|
||||
total_in = 0
|
||||
for n,i in enumerate(td['vin']):
|
||||
|
|
@ -241,7 +246,7 @@ def parse_tx_file(tx_data,infile):
|
|||
if comment == False:
|
||||
err_str = "encoded comment (not base58)"
|
||||
else:
|
||||
if is_valid_tx_comment(comment,True):
|
||||
if is_valid_tx_comment(comment):
|
||||
comment = comment.decode("utf8")
|
||||
else:
|
||||
err_str = "comment"
|
||||
|
|
@ -268,7 +273,7 @@ def get_wif2addr_f():
|
|||
|
||||
def get_tx_comment_from_file(infile):
|
||||
s = get_data_from_file(infile,"transaction comment")
|
||||
if is_valid_tx_comment(s, verbose=True):
|
||||
if is_valid_tx_comment(s):
|
||||
return s.decode("utf8").strip()
|
||||
else:
|
||||
sys.exit(2)
|
||||
|
|
@ -278,7 +283,7 @@ def get_tx_comment_from_user(comment=""):
|
|||
while True:
|
||||
s = my_raw_input("Comment: ",insert_txt=comment.encode("utf8"))
|
||||
if s == "": return False
|
||||
if is_valid_tx_comment(s, verbose=True):
|
||||
if is_valid_tx_comment(s):
|
||||
return s.decode("utf8")
|
||||
except KeyboardInterrupt:
|
||||
msg("User interrupt")
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ from string import hexdigits
|
|||
|
||||
import mmgen.config as g
|
||||
|
||||
pnm = g.proj_name
|
||||
|
||||
_red,_grn,_yel,_cya,_reset = (
|
||||
["\033[%sm" % c for c in "31;1","32;1","33;1","36;1","0"]
|
||||
)
|
||||
|
|
@ -493,7 +495,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 and not opt.quiet:
|
||||
msg("Getting {} wallet data from file '{}'".format(g.proj_name,infile))
|
||||
msg("Getting {pnm} wallet data from file '{f}'".format(pnm=pnm,f=infile))
|
||||
|
||||
f = open_file_or_exit(infile, 'r')
|
||||
|
||||
|
|
@ -609,7 +611,7 @@ def get_seed_from_seed_data(words):
|
|||
msg("Valid seed data for seed ID %s" % make_chksum_8(seed))
|
||||
return seed
|
||||
else:
|
||||
msg("Invalid checksum for {} seed".format(g.proj_name))
|
||||
msg("Invalid checksum for {pnm} seed".format(pnm=pnm))
|
||||
return False
|
||||
|
||||
|
||||
|
|
|
|||
6
test/ref/1378FC64-6F0F9BB4[192,1].mmdat
Normal file
6
test/ref/1378FC64-6F0F9BB4[192,1].mmdat
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
5439c5
|
||||
No Label
|
||||
1378fc64 6f0f9bb4 192 NE 20150406_105042
|
||||
1: 12 8 1
|
||||
0e8caa N7Co eyLd LbJ1 ACfm s4g4 rV
|
||||
f5fdd7 CF2X P6rr ng9z uQev Ldpv 1NeA BarC 6vUC f
|
||||
BIN
test/ref/1378FC64-B55E9958-77256FC1[192:1].incog.offset123
Normal file
BIN
test/ref/1378FC64-B55E9958-77256FC1[192:1].incog.offset123
Normal file
Binary file not shown.
BIN
test/ref/1378FC64-B55E9958-D85FF20C[192:1].incog-old.offset123
Normal file
BIN
test/ref/1378FC64-B55E9958-D85FF20C[192:1].incog-old.offset123
Normal file
Binary file not shown.
1
test/ref/1378FC64.mmseed
Normal file
1
test/ref/1378FC64.mmseed
Normal file
|
|
@ -0,0 +1 @@
|
|||
6bbc91 7L6o G2dR nAFk hncM Q7TU 8Gcc CEGP oKxx C
|
||||
1
test/ref/1378FC64.mmwords
Normal file
1
test/ref/1378FC64.mmwords
Normal file
|
|
@ -0,0 +1 @@
|
|||
duck memory screen world knee thank pray ignore physical season sanity anymore view prince fix compare mother make
|
||||
6
test/ref/98831F3A-27F2BF93[256,1].mmdat
Normal file
6
test/ref/98831F3A-27F2BF93[256,1].mmdat
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
cd828f
|
||||
"#$%&()*+,- ./0123456789:;<=>?@AIZ[\]^_`aiz{|}~'
|
||||
98831f3a 27f2bf93 256 NE 20150405_075000
|
||||
1: 12 8 1
|
||||
9440eb NBDH bKqG a23q FtYi nRo1 kk
|
||||
7a2f32 5nZf LqjP R9bj vgzc sMGr WPtu PR7S 6NpZ pgGd fc4e QCKt
|
||||
BIN
test/ref/98831F3A-F59B07A0-559CEF19[256:1].incog.offset123
Normal file
BIN
test/ref/98831F3A-F59B07A0-559CEF19[256:1].incog.offset123
Normal file
Binary file not shown.
BIN
test/ref/98831F3A-F59B07A0-848535F3[256:1].incog-old.offset123
Normal file
BIN
test/ref/98831F3A-F59B07A0-848535F3[256:1].incog-old.offset123
Normal file
Binary file not shown.
1
test/ref/98831F3A.mmseed
Normal file
1
test/ref/98831F3A.mmseed
Normal file
|
|
@ -0,0 +1 @@
|
|||
3f96a4 5g1y LZ2a wULJ mffJ BkuG 4b1j w4RX u6V5 9Q5A XQg9 tPtd
|
||||
1
test/ref/98831F3A.mmwords
Normal file
1
test/ref/98831F3A.mmwords
Normal file
|
|
@ -0,0 +1 @@
|
|||
dry satisfy pure admire around realize balance sentence husband weary dew trail desk velvet effort strange quite throw morning family drawn exactly block core
|
||||
19
test/ref/98831F3A[1,31-33,500-501,1010-1011].addrs
Normal file
19
test/ref/98831F3A[1,31-33,500-501,1010-1011].addrs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# MMGen address file
|
||||
#
|
||||
# This file is editable.
|
||||
# Everything following a hash symbol '#' is a comment and ignored by MMGen.
|
||||
# A text label of 32 characters or less may be added to the right of each
|
||||
# address, and it will be appended to the bitcoind wallet label upon import.
|
||||
# The label may contain any printable ASCII symbol.
|
||||
# Address data checksum for 98831F3A[1,31-33,500-501,1010-1011]: 6FEF 6FB9 7B13 5D91 854A 0BD3
|
||||
# Record this value to a secure location
|
||||
98831F3A {
|
||||
1 1MU7EdgqYy9JX35L25hR6CmXXcSEBDAwyv
|
||||
31 1Kb8npGGTVtm5qf6Gik4WdLgQoznwufEc "#$%&()*+,- ./09:;<=>?@AZ[]_az|'
|
||||
32 19X3wLG3m7Dg6o5bppk1eqwkLiLVSJ8t1H
|
||||
33 177t1mCffzMWihi9w2Jbb9MQ331zFTxmDJ
|
||||
500 1EZNuddPnaZFah9QVbGvzvTcP4KeRrRFt8
|
||||
501 1ET1CZJtXZanLqbGhFkd4h1hsHengakjqV
|
||||
1010 1DysuxsnRA46wd9bpFhLog2jwtpARmP6BY
|
||||
1011 1DD7mfGAPWme3p8f52AJA9rNQ2SxV1ZUe6
|
||||
}
|
||||
BIN
test/ref/98831F3A[1,31-33,500-501,1010-1011].akeys.mmenc
Normal file
BIN
test/ref/98831F3A[1,31-33,500-501,1010-1011].akeys.mmenc
Normal file
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
|||
.O¡ÎQe‚%S°)Àl[Ës!ÞÖŒ÷JÚU·zê¤]\q}²ä—Èjmçö ²Yr‚Ù¡M_/_³Q�#6„Þ·�¿Æ=˜›gzÈœEƒ<•sTíó�éL©ª#�õGóGöß="eÆ£h÷ªS†€y)–å`æúâmAI®ð¸j=tŽ91Ä„‘ŸnêYãdüȾå&FëO½ÞáèD~hE9ÃYòOyϪç»J‹iÝ}È+·8ÇtS`b&ƒÑ|� «†BR©¤yÑò`üI;=ã}§ƒ:_„]?†hÇñ#!ŸÊm÷º1� ëeïC_+u;nxÌ)˜À�ýñ¢–g
|
||||
ÍÍšð’ƒ…œ�mÁ¼a :‚¾ØÉâ±�†…~Aà÷§7ý 7ÿYî�t#Jô´ßµàÒ\_‘}¼¢ ¹^£/…;ŠÈw•Ã×XŠÕö°§À9˜
|
||||
‘%&´sVWÀ~T"Ç}°–ý¼Vp êˆ�EÍ*ÎOjÚÆÑHoY�–DG£ìÑu¹¿9[e�Œå`Õ©©¶OÎØÞCøT¶û�ôí<A~;Û�ÎØápbEöä8ü�=4�¢Ið¬$ii”&eݧOZ˜c3Gß9mð¼¹�Ôñ˜ãr9n�©7c…7¬=nß\åØÄ²®ývüà·bJô®¦zìâÕ¶YlØvTi,Ù‚@>·Ë²ÎÝ ©9‚ÆzT ž',ħašþZÝ8_´N£Q±·æ™Uø§€Þа’¡¶?ûÝM‚/ËjP_ ÚÝ�ÂXën0Ëéâü¾ÔƒÜoï‡ ÔÖ§'+Ú?ÆöL6HÑn�w>¥º¢éˆH|\ž+3ÏI,Ϋf–HL�%°PÛ¡î_`‹ë�~,2vÝö”üáhäYÁÿíAMd‚®WÌ8¬%H¶Ç�LEÒ†�©×nüÀ•ÐÈ¥v´lêj�Q_�`'‹¯<¯Fg�„WŸu: ) Æ#‡ægíWÛ“áèÃ!Wl÷‘�]�]»õÍ´&HŽ@©sÁ¡«¦=ô[\^?¦$ˆ´)ò%E, â’3�YßD$à”ÖgNo‡e0×Ïðé9¶Ô…-½<•سà¢Õáß®#¬H·[áwh¦@D3ŸãÒb@ÃYKà`—OÚª YG‡³ 8[pYf½�,ræ�_/öþ�A“^‘VŸ?l¼ó°±¬4ÿÅñCQý'Yç¨�‹œ˜‚¬¼6œ
|
||||
|
||||
È
|
||||
ŽC5z^EPmWA$þµI›Äq‘u׸§03Ê¡)I‘p¥^X†Áô²$¢<F›™ûÌ‹å�éR�½=^²ÜXE¢i]ÈõI
|
||||
BIN
test/ref/FE3C6545-161E495F-BEB7548E[128:1].incog-offset123
Normal file
BIN
test/ref/FE3C6545-161E495F-BEB7548E[128:1].incog-offset123
Normal file
Binary file not shown.
6
test/ref/FE3C6545-D782B529[128,1].mmdat
Normal file
6
test/ref/FE3C6545-D782B529[128,1].mmdat
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
09f434
|
||||
No Label
|
||||
fe3c6545 d782b529 128 NE 20150406_104849
|
||||
1: 12 8 1
|
||||
efa838 6aNb kfGu YGBy SxTe amwC q4
|
||||
3548be 8MM2 fxNv Sr7N h4NA WXv2 wL
|
||||
1
test/ref/FE3C6545.mmseed
Normal file
1
test/ref/FE3C6545.mmseed
Normal file
|
|
@ -0,0 +1 @@
|
|||
0e6d52 9aFM LL5z pLA7 DNLu vAha hT
|
||||
1
test/ref/FE3C6545.mmwords
Normal file
1
test/ref/FE3C6545.mmwords
Normal file
|
|
@ -0,0 +1 @@
|
|||
dude foot desperate tie stood themselves trip descend cease suicide apple busy
|
||||
1
test/ref/brainwallet
Normal file
1
test/ref/brainwallet
Normal file
|
|
@ -0,0 +1 @@
|
|||
A brainwallet with some non-standard spacing
|
||||
11
test/ref/brainwallet-spaced
Normal file
11
test/ref/brainwallet-spaced
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
A
|
||||
|
||||
brainwallet
|
||||
|
||||
with some
|
||||
non-standard
|
||||
|
||||
spacing
|
||||
|
||||
|
||||
5
test/ref/tx_FFB367[1.234].raw
Normal file
5
test/ref/tx_FFB367[1.234].raw
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
FFB367 1.234 20150405_102927
|
||||
01000000013364630b6d290a82c822facc2f7c1db4452cea459b2ce22371135530485a5d010600000000ffffffff0205d7d600010000001976a914bba3993079ccdf40c9bbbe495473f0b3d2dc5eec88ac40ef5a07000000001976a914abe58e1e45f6176910a4c1ac1ee62328d5cc4fd588ac00000000
|
||||
[{'comment': u'Test Wallet', 'mmid': u'98831F3A:500', 'vout': 6, 'txid': u'015d5a483055137123e22c9b45ea2c45b41d7c2fccfa22c8820a296d0b636433', 'amount': Decimal('44.32452045'), 'confirmations': 495L, 'address': u'1EZNuddPnaZFah9QVbGvzvTcP4KeRrRFt8', 'spendable': False, 'scriptPubKey': '76a91494b93bbe8a32f1db80b307482e83c25fa4e99b8c88ac'}]
|
||||
{u'1J79LtWctedRLnMfFNRgzzSFsozQqDeoKD': ('98831F3A:3', u''), u'1EZNuddPnaZFah9QVbGvzvTcP4KeRrRFt8': (u'98831F3A:500', u'Test Wallet'), u'1GfuYaKHrhdiVybXMGCcjadSgfjvpdt2x9': ('98831F3A:2', u'')}
|
||||
3SBcsGkhcKRVB2gr98BmscU8HtWJ12HTXpJa5XmvbEUateQ3bJBEgvLd5kPGAzg1rFkzjVpZJgiKGwvnq5mJpwnbJqcHpVEAopWyALDmtjrDwEvPiTY
|
||||
404
test/test.py
404
test/test.py
|
|
@ -10,7 +10,7 @@ sys.path.__setitem__(0,os.path.abspath(os.curdir))
|
|||
|
||||
import mmgen.config as g
|
||||
import mmgen.opt as opt
|
||||
from mmgen.util import msgrepr,msgrepr_exit,Msg
|
||||
from mmgen.util import msgrepr,msgrepr_exit,Msg,die
|
||||
from mmgen.test import *
|
||||
|
||||
hincog_fn = "rand_data"
|
||||
|
|
@ -21,29 +21,97 @@ hincog_seedlen = 256
|
|||
incog_id_fn = "incog_id"
|
||||
non_mmgen_fn = "btckey"
|
||||
|
||||
ref_dir = os.path.join("test","ref")
|
||||
|
||||
ref_wallet_brainpass = "abc"
|
||||
ref_wallet_hash_preset = "1"
|
||||
ref_wallet_incog_offset = 123
|
||||
|
||||
ref_bw_hash_preset = "1"
|
||||
ref_bw_file = "brainwallet"
|
||||
ref_bw_file_spc = "brainwallet-spaced"
|
||||
|
||||
ref_kafile_pass = "kafile password"
|
||||
ref_kafile_hash_preset = "1"
|
||||
|
||||
ref_enc_fn = "sample-text.mmenc"
|
||||
|
||||
cfgs = {
|
||||
'6': {
|
||||
'name': "reference wallet check",
|
||||
'wallet_label': "test.py reference wallet (password 'abc')",
|
||||
'bw_passwd': "abc",
|
||||
'bw_hashparams': "256,1",
|
||||
'key_id': "98831F3A",
|
||||
'addrfile_chk': "6FEF 6FB9 7B13 5D91 854A 0BD3",
|
||||
'keyaddrfile_chk': "9F2D D781 1812 8BAD C396 9DEB",
|
||||
'name': "reference wallet check (128-bit)",
|
||||
'seed_len': 128,
|
||||
'seed_id': "FE3C6545",
|
||||
'ref_bw_seed_id': "33F10310",
|
||||
'addrfile_chk': "B230 7526 638F 38CB 8FDC 8B76",
|
||||
'keyaddrfile_chk': "CF83 32FB 8A8B 08E2 0F00 D601",
|
||||
'wpasswd': "reference password",
|
||||
'ref_wallet': "FE3C6545-D782B529[128,1].mmdat",
|
||||
'ic_wallet': "FE3C6545-161E495F-BEB7548E[128:1].incog-offset123",
|
||||
'ic_wallet_old': "FE3C6545-161E495F-9860A85B[128:1].incog-old.offset123",
|
||||
|
||||
'wpasswd': "reference password",
|
||||
'tmpdir': "test/tmp6",
|
||||
'tmpdir': os.path.join("test","tmp6"),
|
||||
'kapasswd': "",
|
||||
'addr_idx_list': "1010,500-501,31-33,1,33,500,1011", # 8 addresses
|
||||
'dep_generators': {
|
||||
'mmdat': "refwalletgen",
|
||||
'addrs': "refaddrgen",
|
||||
'akeys.mmenc': "refkeyaddrgen"
|
||||
'mmdat': "refwalletgen1",
|
||||
'addrs': "refaddrgen1",
|
||||
'akeys.mmenc': "refkeyaddrgen1"
|
||||
},
|
||||
|
||||
},
|
||||
'7': {
|
||||
'name': "reference wallet check (192-bit)",
|
||||
'seed_len': 192,
|
||||
'seed_id': "1378FC64",
|
||||
'ref_bw_seed_id': "CE918388",
|
||||
'addrfile_chk': "8C17 A5FA 0470 6E89 3A87 8182",
|
||||
'keyaddrfile_chk': "9648 5132 B98E 3AD9 6FC3 C5AD",
|
||||
'wpasswd': "reference password",
|
||||
'ref_wallet': "1378FC64-6F0F9BB4[192,1].mmdat",
|
||||
'ic_wallet': "1378FC64-B55E9958-77256FC1[192:1].incog.offset123",
|
||||
'ic_wallet_old': "1378FC64-B55E9958-D85FF20C[192:1].incog-old.offset123",
|
||||
|
||||
'tmpdir': os.path.join("test","tmp7"),
|
||||
'kapasswd': "",
|
||||
'addr_idx_list': "1010,500-501,31-33,1,33,500,1011", # 8 addresses
|
||||
'dep_generators': {
|
||||
'mmdat': "refwalletgen2",
|
||||
'addrs': "refaddrgen2",
|
||||
'akeys.mmenc': "refkeyaddrgen2"
|
||||
},
|
||||
|
||||
},
|
||||
'8': {
|
||||
'name': "reference wallet check (256-bit)",
|
||||
'seed_len': 256,
|
||||
'seed_id': "98831F3A",
|
||||
'ref_bw_seed_id': "B48CD7FC",
|
||||
'addrfile_chk': "6FEF 6FB9 7B13 5D91 854A 0BD3",
|
||||
'keyaddrfile_chk': "9F2D D781 1812 8BAD C396 9DEB",
|
||||
'wpasswd': "reference password",
|
||||
'ref_wallet': "98831F3A-27F2BF93[256,1].mmdat",
|
||||
'ref_addrfile': "98831F3A[1,31-33,500-501,1010-1011].addrs",
|
||||
'ref_keyaddrfile': "98831F3A[1,31-33,500-501,1010-1011].akeys.mmenc",
|
||||
'ref_addrfile_chksum': "6FEF 6FB9 7B13 5D91 854A 0BD3",
|
||||
'ref_keyaddrfile_chksum': "9F2D D781 1812 8BAD C396 9DEB",
|
||||
|
||||
# 'ref_fake_unspent_data':"98831F3A_unspent.json",
|
||||
'ref_tx_file': "tx_FFB367[1.234].raw",
|
||||
'ic_wallet': "98831F3A-F59B07A0-559CEF19[256:1].incog.offset123",
|
||||
'ic_wallet_old': "98831F3A-F59B07A0-848535F3[256:1].incog-old.offset123",
|
||||
|
||||
'tmpdir': os.path.join("test","tmp8"),
|
||||
'kapasswd': "",
|
||||
'addr_idx_list': "1010,500-501,31-33,1,33,500,1011", # 8 addresses
|
||||
'dep_generators': {
|
||||
'mmdat': "refwalletgen3",
|
||||
'addrs': "refaddrgen3",
|
||||
'akeys.mmenc': "refkeyaddrgen3"
|
||||
},
|
||||
|
||||
},
|
||||
'1': {
|
||||
'tmpdir': "test/tmp1",
|
||||
'tmpdir': os.path.join("test","tmp1"),
|
||||
'wpasswd': "Dorian",
|
||||
'kapasswd': "Grok the blockchain",
|
||||
'addr_idx_list': "12,99,5-10,5,12", # 8 addresses
|
||||
|
|
@ -62,7 +130,7 @@ cfgs = {
|
|||
},
|
||||
},
|
||||
'2': {
|
||||
'tmpdir': "test/tmp2",
|
||||
'tmpdir': os.path.join("test","tmp2"),
|
||||
'wpasswd': "Hodling away",
|
||||
'addr_idx_list': "37,45,3-6,22-23", # 8 addresses
|
||||
'seed_len': 128,
|
||||
|
|
@ -75,7 +143,7 @@ cfgs = {
|
|||
},
|
||||
},
|
||||
'3': {
|
||||
'tmpdir': "test/tmp3",
|
||||
'tmpdir': os.path.join("test","tmp3"),
|
||||
'wpasswd': "Major miner",
|
||||
'addr_idx_list': "73,54,1022-1023,2-5", # 8 addresses
|
||||
'dep_generators': {
|
||||
|
|
@ -86,7 +154,7 @@ cfgs = {
|
|||
},
|
||||
},
|
||||
'4': {
|
||||
'tmpdir': "test/tmp4",
|
||||
'tmpdir': os.path.join("test","tmp4"),
|
||||
'wpasswd': "Hashrate rising",
|
||||
'addr_idx_list': "63,1004,542-544,7-9", # 8 addresses
|
||||
'seed_len': 192,
|
||||
|
|
@ -101,24 +169,24 @@ cfgs = {
|
|||
'bw_params': "192,1",
|
||||
},
|
||||
'5': {
|
||||
'tmpdir': "test/tmp5",
|
||||
'tmpdir': os.path.join("test","tmp5"),
|
||||
'wpasswd': "My changed password",
|
||||
'dep_generators': {
|
||||
'mmdat': "passchg",
|
||||
},
|
||||
},
|
||||
'9': {
|
||||
'tmpdir': "test/tmp9",
|
||||
'tmpdir': os.path.join("test","tmp9"),
|
||||
'tool_enc_passwd': "Scrypt it, don't hash it!",
|
||||
'tool_enc_reftext':
|
||||
'sample_text':
|
||||
"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks\n",
|
||||
'tool_enc_infn': "tool_encrypt.in",
|
||||
'tool_enc_ref_infn': "tool_encrypt_ref.in",
|
||||
# 'tool_enc_ref_infn': "tool_encrypt_ref.in",
|
||||
'dep_generators': {
|
||||
'tool_encrypt.in': "tool_encrypt",
|
||||
'tool_encrypt.in.mmenc': "tool_encrypt",
|
||||
'tool_encrypt_ref.in': "tool_encrypt_ref",
|
||||
'tool_encrypt_ref.in.mmenc': "tool_encrypt_ref",
|
||||
# 'tool_encrypt_ref.in': "tool_encrypt_ref",
|
||||
# 'tool_encrypt_ref.in.mmenc': "tool_encrypt_ref",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -126,12 +194,45 @@ cfgs = {
|
|||
from collections import OrderedDict
|
||||
cmd_data = OrderedDict([
|
||||
# test description depends
|
||||
['refwalletgen', (6,'reference wallet seed ID', [[[],6]])],
|
||||
['refaddrgen', (6,'reference wallet address checksum', [[["mmdat"],6]])],
|
||||
['refkeyaddrgen', (6,'reference wallet key-address checksum', [[["mmdat"],6]])],
|
||||
# Check saved reference files:
|
||||
['ref_wallet_chk1', (6,'saved reference wallet (128-bit)', [[[],6]])],
|
||||
['ref_wallet_chk2', (7,'saved reference wallet (192-bit)', [[[],7]])],
|
||||
['ref_wallet_chk3', (8,'saved reference wallet (256-bit)', [[[],8]])],
|
||||
['ref_seed_chk1', (6,'saved seed file (128-bit)', [[[],6]])],
|
||||
['ref_seed_chk2', (7,'saved seed file (192-bit)', [[[],7]])],
|
||||
['ref_seed_chk3', (8,'saved seed file (256-bit)', [[[],8]])],
|
||||
['ref_mn_chk1', (6,'saved mnemonic file (128-bit)', [[[],6]])],
|
||||
['ref_mn_chk2', (7,'saved mnemonic file (192-bit)', [[[],7]])],
|
||||
['ref_mn_chk3', (8,'saved mnemonic file (256-bit)', [[[],8]])],
|
||||
['ref_incog_chk1', (6,'saved incog reference wallet (128-bit)', [[[],6]])],
|
||||
['ref_incog_chk2', (7,'saved incog reference wallet (192-bit)', [[[],7]])],
|
||||
['ref_incog_chk3', (8,'saved incog reference wallet (256-bit)', [[[],8]])],
|
||||
['ref_brain_chk1', (6,'saved brainwallet (128-bit)', [[[],6]])],
|
||||
['ref_brain_chk2', (7,'saved brainwallet (192-bit)', [[[],7]])],
|
||||
['ref_brain_chk3', (8,'saved brainwallet (256-bit)', [[[],8]])],
|
||||
['ref_brain_chk3_spc', (8,'saved brainwallet (256-bit, non-standard spacing)', [[[],8]])],
|
||||
|
||||
['ref_addrfile_chk', (8,'saved reference address file', [[[],8]])],
|
||||
['ref_keyaddrfile_chk', (8,'saved reference key-address file', [[[],8]])],
|
||||
# Create the fake inputs:
|
||||
# ['txcreate8', (8,'transaction creation (8)', [[["addrs"],8]])],
|
||||
['ref_tx_chk', (8,'saved reference tx file', [[[],8]])],
|
||||
|
||||
['ref_tool_decrypt', (9,'decryption of saved MMGen-encrypted file', [[[],9]])],
|
||||
|
||||
# Generate new reference ('abc' brainwallet) files:
|
||||
['refwalletgen1', (6,'gen new refwallet (128-bit)', [[[],6]])],
|
||||
['refwalletgen2', (7,'gen new refwallet (192-bit)', [[[],7]])],
|
||||
['refwalletgen3', (8,'gen new refwallet (256-bit)', [[[],8]])],
|
||||
['refaddrgen1', (6,'new refwallet addr chksum (128-bit)', [[["mmdat"],6]])],
|
||||
['refaddrgen2', (7,'new refwallet addr chksum (192-bit)', [[["mmdat"],7]])],
|
||||
['refaddrgen3', (8,'new refwallet addr chksum (256-bit)', [[["mmdat"],8]])],
|
||||
['refkeyaddrgen1', (6,'new refwallet key-addr chksum (128-bit)', [[["mmdat"],6]])],
|
||||
['refkeyaddrgen2', (7,'new refwallet key-addr chksum (192-bit)', [[["mmdat"],7]])],
|
||||
['refkeyaddrgen3', (8,'new refwallet key-addr chksum (256-bit)', [[["mmdat"],8]])],
|
||||
|
||||
['walletgen', (1,'wallet generation', [[[],1]])],
|
||||
['walletchk', (1,'wallet check', [[["mmdat"],1]])],
|
||||
# ['walletchk', (1,'wallet check', [[["mmdat"],1]])],
|
||||
['passchg', (5,'password, label and hash preset change',[[["mmdat"],1]])],
|
||||
['walletchk_newpass',(5,'wallet check with new pw, label and hash preset',[[["mmdat"],5]])],
|
||||
['addrgen', (1,'address generation', [[["mmdat"],1]])],
|
||||
|
|
@ -177,10 +278,7 @@ cmd_data = OrderedDict([
|
|||
['tool_decrypt', (9,"'mmgen-tool decrypt' (random data)",
|
||||
[[[cfgs['9']['tool_enc_infn'],
|
||||
cfgs['9']['tool_enc_infn']+".mmenc"],9]])],
|
||||
['tool_encrypt_ref', (9,"'mmgen-tool encrypt' (reference text)", [])],
|
||||
['tool_decrypt_ref', (9,"'mmgen-tool decrypt' (reference text)",
|
||||
[[[cfgs['9']['tool_enc_ref_infn'],
|
||||
cfgs['9']['tool_enc_ref_infn']+".mmenc"],9]])],
|
||||
# ['tool_encrypt_ref', (9,"'mmgen-tool encrypt' (reference text)", [])],
|
||||
['tool_find_incog_data', (9,"'mmgen-tool find_incog_data'", [[[hincog_fn],1],[[incog_id_fn],1]])],
|
||||
])
|
||||
|
||||
|
|
@ -198,22 +296,28 @@ for k in cfgs.keys():
|
|||
cfgs[k]['amts'][idx] = "%s.%s" % ((getrandnum(2) % mod), str(getrandnum(4))[:5])
|
||||
|
||||
meta_cmds = OrderedDict([
|
||||
['ref', (6,("refwalletgen","refaddrgen","refkeyaddrgen"))],
|
||||
['gen', (1,("walletgen","walletchk","addrgen"))],
|
||||
['pass', (5,("passchg","walletchk_newpass"))],
|
||||
['tx', (1,("txcreate","txsign","txsend"))],
|
||||
['saved_ref1', (6,("ref_wallet_chk1","ref_seed_chk1","ref_mn_chk1","ref_brain_chk1","ref_incog_chk1"))],
|
||||
['saved_ref2', (7,("ref_wallet_chk2","ref_seed_chk2","ref_mn_chk2","ref_brain_chk2","ref_incog_chk2"))],
|
||||
['saved_ref3', (8,("ref_wallet_chk3","ref_seed_chk3","ref_mn_chk3","ref_brain_chk3","ref_incog_chk3","ref_brain_chk3_spc"))],
|
||||
['saved_ref_other', (8,("ref_addrfile_chk","ref_tx_chk","ref_tool_decrypt"))],
|
||||
['ref1', (6,("refwalletgen1","refaddrgen1","refkeyaddrgen1"))],
|
||||
['ref2', (7,("refwalletgen2","refaddrgen2","refkeyaddrgen2"))],
|
||||
['ref3', (8,("refwalletgen3","refaddrgen3","refkeyaddrgen3"))],
|
||||
['gen', (1,("walletgen","addrgen"))],
|
||||
['pass', (5,("passchg","walletchk_newpass"))],
|
||||
['tx', (1,("txcreate","txsign","txsend"))],
|
||||
['export', (1,[k for k in cmd_data if k[:7] == "export_" and cmd_data[k][0] == 1])],
|
||||
['gen_sp', (1,[k for k in cmd_data if k[:8] == "addrgen_" and cmd_data[k][0] == 1])],
|
||||
['online', (1,("keyaddrgen","txsign_keyaddr"))],
|
||||
['2', (2,[k for k in cmd_data if cmd_data[k][0] == 2])],
|
||||
['3', (3,[k for k in cmd_data if cmd_data[k][0] == 3])],
|
||||
['4', (4,[k for k in cmd_data if cmd_data[k][0] == 4])],
|
||||
['tool', (9,("tool_encrypt","tool_decrypt","tool_encrypt_ref","tool_decrypt_ref","tool_find_incog_data"))],
|
||||
['tool', (9,("tool_encrypt","tool_decrypt","tool_find_incog_data"))],
|
||||
])
|
||||
|
||||
opts_data = {
|
||||
'desc': "Test suite for the MMGen suite",
|
||||
'usage':"[options] [command or metacommand]",
|
||||
'usage':"[options] [command(s) or metacommand(s)]",
|
||||
'options': """
|
||||
-h, --help Print this help message
|
||||
-b, --buf-keypress Use buffered keypresses as with real human input
|
||||
|
|
@ -361,10 +465,11 @@ def verify_checksum_or_exit(checksum,chk):
|
|||
|
||||
class MMGenExpect(object):
|
||||
|
||||
def __init__(self,name,mmgen_cmd,cmd_args=[]):
|
||||
def __init__(self,name,mmgen_cmd,cmd_args=[],extra_desc=""):
|
||||
if not opt.system:
|
||||
mmgen_cmd = os.path.join(os.curdir,mmgen_cmd)
|
||||
desc = cmd_data[name][1]
|
||||
if extra_desc: desc += " " + extra_desc
|
||||
if opt.verbose or opt.exact_output:
|
||||
sys.stderr.write(
|
||||
green("Testing %s\nExecuting " % desc) +
|
||||
|
|
@ -449,6 +554,9 @@ class MMGenExpect(object):
|
|||
def readline(self):
|
||||
return self.p.readline()
|
||||
|
||||
def close(self):
|
||||
return self.p.close()
|
||||
|
||||
def readlines(self):
|
||||
return [l.rstrip()+"\n" for l in self.p.readlines()]
|
||||
|
||||
|
|
@ -681,17 +789,21 @@ class MMGenTestSuite(object):
|
|||
ok()
|
||||
|
||||
def refwalletgen(self,name):
|
||||
label = cfg['wallet_label']
|
||||
args = ["-d",cfg['tmpdir'],"-p1","-r10",
|
||||
"-b"+cfg['bw_hashparams'],"-L",label]
|
||||
label = "test.py ref. wallet (pw '%s', seed len %s)" \
|
||||
% (ref_wallet_brainpass,cfg['seed_len'])
|
||||
bw_arg = "-b%s,%s" % (cfg['seed_len'], ref_wallet_hash_preset)
|
||||
args = ["-d",cfg['tmpdir'],"-p1","-r10",bw_arg,"-L",label]
|
||||
d = " (%s-bit seed)" % cfg['seed_len']
|
||||
t = MMGenExpect(name,"mmgen-walletgen", args)
|
||||
t.license()
|
||||
t.expect("Type uppercase 'YES' to confirm: ","YES\n")
|
||||
t.expect("passphrase: ",cfg['bw_passwd']+"\n")
|
||||
t.expect("passphrase: ",ref_wallet_brainpass+"\n")
|
||||
t.usr_rand(10)
|
||||
t.passphrase_new("new MMGen wallet",cfg['wpasswd'])
|
||||
key_id = t.written_to_file("Wallet").split("-")[0].split("/")[-1]
|
||||
refcheck("key id",key_id,cfg['key_id'])
|
||||
seed_id = t.written_to_file("Wallet").split("-")[0].split("/")[-1]
|
||||
refcheck("seed id",seed_id,cfg['seed_id'])
|
||||
|
||||
refwalletgen1 = refwalletgen2 = refwalletgen3 = refwalletgen
|
||||
|
||||
def passchg(self,name,walletfile):
|
||||
|
||||
|
|
@ -699,7 +811,7 @@ class MMGenTestSuite(object):
|
|||
["-d",cfg['tmpdir'],"-p","2","-L","New Label","-r","16",walletfile])
|
||||
t.passphrase("MMGen wallet",cfgs['1']['wpasswd'],pwtype="old")
|
||||
t.expect_getend("Label changed: ")
|
||||
t.expect_getend("Hash preset has changed ")
|
||||
t.expect_getend("Hash preset changed: ")
|
||||
t.passphrase("MMGen wallet",cfg['wpasswd'],pwtype="new")
|
||||
t.expect("Repeat passphrase: ",cfg['wpasswd']+"\n")
|
||||
t.usr_rand(16)
|
||||
|
|
@ -707,10 +819,6 @@ class MMGenTestSuite(object):
|
|||
t.written_to_file("Wallet")
|
||||
ok()
|
||||
|
||||
def walletchk_newpass(self,name,walletfile):
|
||||
t = self.walletchk_beg(name,[walletfile])
|
||||
ok()
|
||||
|
||||
def walletchk_beg(self,name,args):
|
||||
t = MMGenExpect(name,"mmgen-walletchk", args)
|
||||
t.expect("Getting MMGen wallet data from file '%s'" % args[-1])
|
||||
|
|
@ -720,9 +828,11 @@ class MMGenTestSuite(object):
|
|||
return t
|
||||
|
||||
def walletchk(self,name,walletfile):
|
||||
t = self.walletchk_beg(name,[walletfile])
|
||||
self.walletchk_beg(name,[walletfile])
|
||||
ok()
|
||||
|
||||
walletchk_newpass = walletchk
|
||||
|
||||
def addrgen(self,name,walletfile,check_ref=False):
|
||||
t = MMGenExpect(name,"mmgen-addrgen",["-d",cfg['tmpdir'],walletfile,cfg['addr_idx_list']])
|
||||
t.license()
|
||||
|
|
@ -737,13 +847,16 @@ class MMGenTestSuite(object):
|
|||
ok()
|
||||
|
||||
def refaddrgen(self,name,walletfile):
|
||||
d = " (%s-bit seed)" % cfg['seed_len']
|
||||
self.addrgen(name,walletfile,check_ref=True)
|
||||
|
||||
refaddrgen1 = refaddrgen2 = refaddrgen3 = refaddrgen
|
||||
|
||||
def addrimport(self,name,addrfile):
|
||||
outfile = os.path.join(cfg['tmpdir'],"addrfile_w_comments")
|
||||
add_comments_to_addr_file(addrfile,outfile)
|
||||
t = MMGenExpect(name,"mmgen-addrimport",[outfile])
|
||||
t.expect_getend(r"checksum for addr data .*\[.*\]: ",regex=True)
|
||||
t.expect_getend(r"Checksum for address data .*\[.*\]: ",regex=True)
|
||||
t.expect_getend("Validating addresses...OK. ")
|
||||
t.expect("Type uppercase 'YES' to confirm: ","\n")
|
||||
vmsg("This is a simulation, so no addresses were actually imported into the tracking\nwallet")
|
||||
|
|
@ -765,7 +878,7 @@ class MMGenTestSuite(object):
|
|||
ail.add(ai)
|
||||
aix = parse_addr_idxs(cfgs[s]['addr_idx_list'])
|
||||
if len(aix) != addrs_per_wallet:
|
||||
errmsg(red("Addr index list length != %s: %s" %
|
||||
errmsg(red("Address index list length != %s: %s" %
|
||||
(addrs_per_wallet,repr(aix))))
|
||||
sys.exit()
|
||||
tx_data[s] = {
|
||||
|
|
@ -804,7 +917,7 @@ class MMGenTestSuite(object):
|
|||
t.license()
|
||||
for num in tx_data.keys():
|
||||
t.expect_getend("Getting address data from file ")
|
||||
chk=t.expect_getend(r"Computed checksum for addr data .*?: ",regex=True)
|
||||
chk=t.expect_getend(r"Checksum for address data .*?: ",regex=True)
|
||||
verify_checksum_or_exit(tx_data[num]['chk'],chk)
|
||||
|
||||
# not in tracking wallet warning, (1 + num sources) times
|
||||
|
|
@ -831,13 +944,25 @@ class MMGenTestSuite(object):
|
|||
t.written_to_file("Transaction")
|
||||
ok()
|
||||
|
||||
def txsign(self,name,txfile,walletfile):
|
||||
t = MMGenExpect(name,"mmgen-txsign", ["-d",cfg['tmpdir'],txfile,walletfile])
|
||||
def txsign_end(self,t,tnum=None):
|
||||
t.expect("Signing transaction")
|
||||
t.expect("Edit transaction comment? (y/N): ","\n")
|
||||
t.expect("Save signed transaction? (y/N): ","y")
|
||||
add = " #" + tnum if tnum else ""
|
||||
t.written_to_file("Signed transaction" + add)
|
||||
|
||||
def txsign(self,name,txfile,walletfile,save=True):
|
||||
t = MMGenExpect(name,"mmgen-txsign",
|
||||
["-d",cfg['tmpdir'],txfile,walletfile])
|
||||
t.license()
|
||||
t.tx_view()
|
||||
t.passphrase("MMGen wallet",cfg['wpasswd'])
|
||||
t.expect("Edit transaction comment? (y/N): ","\n")
|
||||
t.written_to_file("Signed transaction")
|
||||
if save:
|
||||
self.txsign_end(t)
|
||||
else:
|
||||
t.expect("Edit transaction comment? (y/N): ","\n")
|
||||
t.expect("Save signed transaction? (y/N): ","\n")
|
||||
t.expect("Signed transaction not saved")
|
||||
ok()
|
||||
|
||||
def txsend(self,name,sigfile):
|
||||
|
|
@ -845,10 +970,10 @@ class MMGenTestSuite(object):
|
|||
t.license()
|
||||
t.tx_view()
|
||||
t.expect("Edit transaction comment? (y/N): ","\n")
|
||||
t.expect("Are you sure you want to broadcast this transaction to the network?")
|
||||
t.expect("Type uppercase 'YES, I REALLY WANT TO DO THIS' to confirm: ","\n")
|
||||
t.expect("broadcast this transaction to the network?")
|
||||
t.expect("'YES, I REALLY WANT TO DO THIS' to confirm: ","\n")
|
||||
t.expect("Exiting at user request")
|
||||
vmsg("This is a simulation, so no transaction was sent")
|
||||
vmsg("This is a simulation; no transaction was sent")
|
||||
ok()
|
||||
|
||||
def export_seed(self,name,walletfile):
|
||||
|
|
@ -943,6 +1068,8 @@ class MMGenTestSuite(object):
|
|||
def refkeyaddrgen(self,name,walletfile):
|
||||
self.keyaddrgen(name,walletfile,check_ref=True)
|
||||
|
||||
refkeyaddrgen1 = refkeyaddrgen2 = refkeyaddrgen3 = refkeyaddrgen
|
||||
|
||||
def txsign_keyaddr(self,name,keyaddr_file,txfile):
|
||||
t = MMGenExpect(name,"mmgen-txsign", ["-d",cfg['tmpdir'],"-M",keyaddr_file,txfile])
|
||||
t.license()
|
||||
|
|
@ -950,9 +1077,7 @@ class MMGenTestSuite(object):
|
|||
t.passphrase("key-address file",cfg['kapasswd'])
|
||||
t.expect("Check key-to-address validity? (y/N): ","y")
|
||||
t.tx_view()
|
||||
t.expect("Signing transaction...OK")
|
||||
t.expect("Edit transaction comment? (y/N): ","\n")
|
||||
t.written_to_file("Signed transaction")
|
||||
self.txsign_end(t)
|
||||
ok()
|
||||
|
||||
def walletgen2(self,name):
|
||||
|
|
@ -967,14 +1092,10 @@ class MMGenTestSuite(object):
|
|||
def txsign2(self,name,txf1,wf1,txf2,wf2):
|
||||
t = MMGenExpect(name,"mmgen-txsign", ["-d",cfg['tmpdir'],txf1,wf1,txf2,wf2])
|
||||
t.license()
|
||||
|
||||
for cnum in ['1','2']:
|
||||
for cnum in ('1','2'):
|
||||
t.tx_view()
|
||||
t.passphrase("MMGen wallet",cfgs[cnum]['wpasswd'])
|
||||
t.expect_getend("Signing transaction ")
|
||||
t.expect("Edit transaction comment? (y/N): ","\n")
|
||||
t.written_to_file("Signed transaction #%s" % cnum)
|
||||
|
||||
self.txsign_end(t,cnum)
|
||||
ok()
|
||||
|
||||
def export_mnemonic2(self,name,walletfile):
|
||||
|
|
@ -993,14 +1114,10 @@ class MMGenTestSuite(object):
|
|||
t = MMGenExpect(name,"mmgen-txsign", ["-d",cfg['tmpdir'],wf1,wf2,txf2])
|
||||
t.license()
|
||||
t.tx_view()
|
||||
|
||||
for s in ['1','3']:
|
||||
for cnum in ('1','3'):
|
||||
t.expect_getend("Getting MMGen wallet data from file ")
|
||||
t.passphrase("MMGen wallet",cfgs[s]['wpasswd'])
|
||||
|
||||
t.expect_getend("Signing transaction")
|
||||
t.expect("Edit transaction comment? (y/N): ","\n")
|
||||
t.written_to_file("Signed transaction")
|
||||
t.passphrase("MMGen wallet",cfgs[cnum]['wpasswd'])
|
||||
self.txsign_end(t)
|
||||
ok()
|
||||
|
||||
def walletgen4(self,name):
|
||||
|
|
@ -1019,15 +1136,13 @@ class MMGenTestSuite(object):
|
|||
t.license()
|
||||
t.tx_view()
|
||||
|
||||
for cfgnum,what,app in ('1',"incognito"," incognito"),('3',"MMGen",""):
|
||||
for cnum,what,app in ('1',"incognito"," incognito"),('3',"MMGen",""):
|
||||
t.expect_getend("Getting %s wallet data from file " % what)
|
||||
t.passphrase("MMGen%s wallet"%app,cfgs[cfgnum]['wpasswd'])
|
||||
if cfgnum == '1':
|
||||
t.passphrase("MMGen%s wallet"%app,cfgs[cnum]['wpasswd'])
|
||||
if cnum == '1':
|
||||
t.hash_preset("incog wallet",'1')
|
||||
|
||||
t.expect_getend("Signing transaction")
|
||||
t.expect("Edit transaction comment? (y/N): ","\n")
|
||||
t.written_to_file("Signed transaction")
|
||||
self.txsign_end(t)
|
||||
ok()
|
||||
|
||||
def tool_encrypt(self,name,infile=""):
|
||||
|
|
@ -1043,11 +1158,11 @@ class MMGenTestSuite(object):
|
|||
t.passphrase_new("user data",cfg['tool_enc_passwd'])
|
||||
t.written_to_file("Encrypted data")
|
||||
ok()
|
||||
|
||||
def tool_encrypt_ref(self,name):
|
||||
infn = get_tmpfile_fn(cfg,cfg['tool_enc_ref_infn'])
|
||||
write_to_file(infn,cfg['tool_enc_reftext'],silent=True)
|
||||
self.tool_encrypt(name,infn)
|
||||
# Generate the reference mmenc file
|
||||
# def tool_encrypt_ref(self,name):
|
||||
# infn = get_tmpfile_fn(cfg,cfg['tool_enc_ref_infn'])
|
||||
# write_to_file(infn,cfg['tool_enc_reftext'],silent=True)
|
||||
# self.tool_encrypt(name,infn)
|
||||
|
||||
def tool_decrypt(self,name,f1,f2):
|
||||
of = name + ".out"
|
||||
|
|
@ -1059,9 +1174,6 @@ class MMGenTestSuite(object):
|
|||
d2 = read_from_file(get_tmpfile_fn(cfg,of))
|
||||
cmp_or_die(d1,d2)
|
||||
|
||||
def tool_decrypt_ref(self,name,f1,f2):
|
||||
self.tool_decrypt(name,f1,f2)
|
||||
|
||||
def tool_find_incog_data(self,name,f1,f2):
|
||||
i_id = read_from_file(f2).rstrip()
|
||||
vmsg("Incog ID: %s" % cyan(i_id))
|
||||
|
|
@ -1070,6 +1182,91 @@ class MMGenTestSuite(object):
|
|||
o = t.expect_getend("Incog data for ID \w{8} found at offset ",regex=True)
|
||||
cmp_or_die(hincog_offset,int(o))
|
||||
|
||||
# Saved reference file tests
|
||||
def ref_wallet_chk(self,name):
|
||||
wf = os.path.join(ref_dir,cfg['ref_wallet'])
|
||||
self.walletchk(name,wf)
|
||||
|
||||
ref_wallet_chk1 = ref_wallet_chk2 = ref_wallet_chk3 = ref_wallet_chk
|
||||
|
||||
def ref_seed_chk(self,name,ext=g.seed_ext):
|
||||
wf = os.path.join(ref_dir,"%s.%s" % (cfg['seed_id'],ext))
|
||||
what = "seed data" if ext == g.seed_ext else "mnemonic"
|
||||
self.keygen_chksum_chk(name,wf,cfg['seed_id'],what)
|
||||
|
||||
ref_seed_chk1 = ref_seed_chk2 = ref_seed_chk3 = ref_seed_chk
|
||||
|
||||
def ref_mn_chk(self,name): self.ref_seed_chk(name,ext=g.mn_ext)
|
||||
|
||||
ref_mn_chk1 = ref_mn_chk2 = ref_mn_chk3 = ref_mn_chk
|
||||
|
||||
def ref_brain_chk(self,name,bw_file=ref_bw_file):
|
||||
wf = os.path.join(ref_dir,bw_file)
|
||||
arg = "-b%s,%s" % (cfg['seed_len'],ref_bw_hash_preset)
|
||||
self.keygen_chksum_chk(name,wf,cfg['ref_bw_seed_id'],"brainwallet",[arg])
|
||||
|
||||
def keygen_chksum_chk(self,name,wf,seed_id,what,args=[]):
|
||||
t = MMGenExpect(name,"mmgen-keygen", ["-q","-A"]+args+[wf,"1"])
|
||||
chk = t.expect_getend("Valid %s for seed ID " % what)
|
||||
t.close()
|
||||
cmp_or_die(seed_id,chk)
|
||||
|
||||
ref_brain_chk1 = ref_brain_chk2 = ref_brain_chk3 = ref_brain_chk
|
||||
|
||||
def ref_brain_chk3_spc(self,name):
|
||||
self.ref_brain_chk(name,bw_file=ref_bw_file_spc)
|
||||
|
||||
def ref_incog_chk(self,name):
|
||||
for wtype,desc,earg in ('ic_wallet','',[]), \
|
||||
('ic_wallet_old','(old format)',["-o"]):
|
||||
ic_arg = "%s,%s,%s" % (
|
||||
os.path.join(ref_dir,cfg[wtype]),
|
||||
ref_wallet_incog_offset,cfg['seed_len']
|
||||
)
|
||||
t = MMGenExpect(name,"mmgen-keygen",
|
||||
["-q","-A"]+earg+["-G"]+[ic_arg]+['1'],extra_desc=desc)
|
||||
t.passphrase("MMGen incognito wallet",cfg['wpasswd'])
|
||||
t.hash_preset("incog wallet","1")
|
||||
if wtype == 'ic_wallet_old':
|
||||
t.expect("Is the seed ID correct? (Y/n): ","\n")
|
||||
chk = t.expect_getend("Valid incog data for seed ID ")
|
||||
t.close()
|
||||
cmp_or_die(cfg['seed_id'],chk)
|
||||
|
||||
ref_incog_chk1 = ref_incog_chk2 = ref_incog_chk3 = ref_incog_chk
|
||||
|
||||
def ref_addrfile_chk(self,name,ftype="addr"):
|
||||
wf = os.path.join(ref_dir,cfg['ref_'+ftype+'file'])
|
||||
t = MMGenExpect(name,"mmgen-tool",[ftype+"file_chksum",wf])
|
||||
if ftype == "keyaddr":
|
||||
w = "key-address file"
|
||||
t.hash_preset(w,ref_kafile_hash_preset)
|
||||
t.passphrase(w,ref_kafile_pass)
|
||||
t.expect("Check key-to-address validity? (y/N): ","y")
|
||||
o = t.expect_getend("Checksum for .*address data .*: ",regex=True)
|
||||
cmp_or_die(cfg['ref_'+ftype+'file_chksum'],o)
|
||||
|
||||
def ref_keyaddrfile_chk(self,name):
|
||||
self.ref_addrfile_chk(name,ftype="keyaddr")
|
||||
|
||||
# def txcreate8(self,name,addrfile):
|
||||
# self.txcreate_common(name,sources=['8'])
|
||||
|
||||
def ref_tx_chk(self,name):
|
||||
tf = os.path.join(ref_dir,cfg['ref_tx_file'])
|
||||
wf = os.path.join(ref_dir,cfg['ref_wallet'])
|
||||
self.txsign(name,tf,wf,save=False)
|
||||
|
||||
def ref_tool_decrypt(self,name):
|
||||
f = os.path.join(ref_dir,ref_enc_fn)
|
||||
t = MMGenExpect(name,"mmgen-tool",
|
||||
["-q","decrypt",f,"outfile=-","hash_preset=1"])
|
||||
t.passphrase("user data",cfg['tool_enc_passwd'])
|
||||
t.readline()
|
||||
import re
|
||||
o = re.sub('\r\n','\n',t.read())
|
||||
cmp_or_die(cfg['sample_text'],o)
|
||||
|
||||
# main()
|
||||
if opt.pause:
|
||||
import termios,atexit
|
||||
|
|
@ -1086,26 +1283,17 @@ for cfg in sorted(cfgs): mk_tmpdir(cfgs[cfg])
|
|||
|
||||
try:
|
||||
if cmd_args:
|
||||
arg1 = cmd_args[0]
|
||||
if arg1 in utils:
|
||||
globals()[arg1](cmd_args[1:])
|
||||
sys.exit()
|
||||
elif arg1 in meta_cmds:
|
||||
if len(cmd_args) == 1:
|
||||
for cmd in meta_cmds[arg1][1]:
|
||||
for arg in cmd_args:
|
||||
if arg in utils:
|
||||
globals()[arg](cmd_args[cmd_args.index(arg)+1:])
|
||||
sys.exit()
|
||||
elif arg in meta_cmds:
|
||||
for cmd in meta_cmds[arg][1]:
|
||||
check_needs_rerun(ts,cmd,build=True,force_delete=True)
|
||||
elif arg in cmd_data:
|
||||
check_needs_rerun(ts,arg,build=True)
|
||||
else:
|
||||
msg("Only one meta command may be specified")
|
||||
sys.exit(1)
|
||||
elif arg1 in cmd_data.keys():
|
||||
if len(cmd_args) == 1:
|
||||
check_needs_rerun(ts,arg1,build=True)
|
||||
else:
|
||||
msg("Only one command may be specified")
|
||||
sys.exit(1)
|
||||
else:
|
||||
errmsg("%s: unrecognized command" % arg1)
|
||||
sys.exit(1)
|
||||
die(1,"%s: unrecognized command" % arg)
|
||||
else:
|
||||
clean()
|
||||
for cmd in cmd_data:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue