New test 'test/gentest.py' checks MMGen's internally generated addresses

against output of 'keyconv'

New test in 'test/test.py': 'tool_find_incog_data'
This commit is contained in:
philemon 2015-01-12 00:07:21 +03:00
commit d966956ffd
4 changed files with 110 additions and 18 deletions

View file

@ -49,13 +49,13 @@ faster address generation.
""".format(kcexe=g.keyconv_exec, vanityg="vanitygen")
}
def test_for_keyconv():
def test_for_keyconv(silent=False):
from subprocess import check_output,STDOUT
try:
check_output([g.keyconv_exec, '-G'],stderr=STDOUT)
except:
msg(addrmsgs['no_keyconv_msg'])
if not silent: msg(addrmsgs['no_keyconv_msg'])
return False
return True

77
test/gentest.py Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/python
# Chdir to repo root.
# Since script is not in repo root, fix sys.path so that modules are
# imported from repo, not system.
import sys,os
pn = os.path.dirname(sys.argv[0])
os.chdir(os.path.join(pn,os.pardir))
sys.path.__setitem__(0,os.path.abspath(os.curdir))
from binascii import hexlify
import mmgen.opt as opt
import mmgen.config as g
from mmgen.util import msg,msg_r,msgrepr,msgrepr_exit,red,green
from mmgen.bitcoin import hextowif,privnum2addr
rounds = 100
opts_data = {
'desc': "Test addresses generated by {} against output of 'keyconv'".format(g.proj_name),
'usage':"[options] [rounds]",
'options': """
-h, --help Print this help message
-s, --system Test scripts and modules installed on system rather than
those in the repo root
""",
'notes': """
'keyconv' is the address generation utility from the well-known vanitygen
package. If it's installed on your system, {pnm} will use it by default to
generate Bitcoin addresses. Otherwise, it falls back on its own internal
routines, which use the Python ecdsa library.
rounds is {} by default.
""".format(rounds,pnm=g.proj_name)
}
cmd_args = opt.opts.init(opts_data,add_opts=["exact_output"])
if len(cmd_args) == 1:
try:
rounds = int(cmd_args[0])
assert rounds > 0
except:
msg("'rounds' must be a positive integer")
sys.exit(1)
elif len(cmd_args) > 1:
opt.opts.usage(opts_data)
if opt.system: sys.path.pop(0)
from mmgen.addr import test_for_keyconv
if not test_for_keyconv(silent=True):
msg(
"To run this test, you must install 'keyconv' from the vanitygen package.")
sys.exit(1)
msg(green("Comparing {}'s internally generated addresses against output of 'keyconv'").format(g.proj_name))
from subprocess import check_output
for i in range(1,rounds+1):
msg_r("\rRound %s/%s " % (i,rounds))
sec = hexlify(os.urandom(32))
wif = hextowif(sec)
a = privnum2addr(int(sec,16))
b = check_output(["keyconv", wif]).split()[1]
if a != b:
msg_r(red("\nERROR: Addresses do not match!"))
msg("""
sec key: {}
WIF key: {}
{pnm}: {}
keyconv: {}
""".format(sec,wif,a,b,pnm=g.proj_name).rstrip())
sys.exit(3)
msg(green("\nOK"))

View file

@ -13,7 +13,12 @@ import mmgen.opt as opt
from mmgen.util import msgrepr,msgrepr_exit,Msg
from mmgen.test import *
hincog_fn = "rand_data"
hincog_fn = "rand_data"
hincog_bytes = 1024*1024
hincog_offset = 98765
hincog_seedlen = 256
incog_id_fn = "incog_id"
non_mmgen_fn = "btckey"
cfgs = {
@ -51,7 +56,8 @@ cfgs = {
'mmseed': "export_seed",
'mmincog': "export_incog",
'mmincox': "export_incog_hex",
hincog_fn: "export_incog_hidden",
hincog_fn: "export_incog_hidden",
incog_id_fn: "export_incog_hidden",
'akeys.mmenc': "keyaddrgen"
},
},
@ -175,6 +181,7 @@ cmd_data = OrderedDict([
['tool_decrypt_ref', (9,"'mmgen-tool decrypt' (reference text)",
[[[cfgs['9']['tool_enc_ref_infn'],
cfgs['9']['tool_enc_ref_infn']+".mmenc"],9]])],
['tool_find_incog_data', (9,"'mmgen-tool find_incog_data'", [[[hincog_fn],1],[[incog_id_fn],1]])],
])
utils = {
@ -201,7 +208,7 @@ meta_cmds = OrderedDict([
['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', (9,("tool_encrypt","tool_decrypt","tool_encrypt_ref","tool_decrypt_ref","tool_find_incog_data"))],
])
opts_data = {
@ -211,12 +218,14 @@ opts_data = {
-h, --help Print this help message
-b, --buf-keypress Use buffered keypresses as with real human input
-d, --debug Produce debugging output
-D, --direct-exec Bypass pexpect and execute a command directly (for debugging only)
-D, --direct-exec Bypass pexpect and execute a command directly (for
debugging only)
-e, --exact-output Show the exact output of the MMGen script(s) being run
-l, --list-cmds List and describe the tests and commands in the test suite
-p, --pause Pause between tests, resuming on keypress
-q, --quiet Produce minimal output. Suppress dependency info
-s, --system Test scripts and modules installed on system rather than those in the repo root
-s, --system Test scripts and modules installed on system rather than
those in the repo root
-v, --verbose Produce more verbose output
""",
'notes': """
@ -517,10 +526,6 @@ def do_between():
sys.stderr.write("\n")
hincog_bytes = 1024*1024
hincog_offset = 98765
hincog_seedlen = 256
rebuild_list = OrderedDict()
def check_needs_rerun(ts,cmd,build=False,root=True,force_delete=False,dpy=False):
@ -529,7 +534,8 @@ def check_needs_rerun(ts,cmd,build=False,root=True,force_delete=False,dpy=False)
fns = []
if force_delete or not root:
ret = ts.get_num_exts_for_cmd(cmd,dpy) #does cmd produce a needed dependency?
# does cmd produce a needed dependency(ies)?
ret = ts.get_num_exts_for_cmd(cmd,dpy)
if ret:
for ext in ret[1]:
fn = get_file_with_ext(ext,cfgs[ret[0]]['tmpdir'],delete=build)
@ -574,7 +580,7 @@ Fatal error - %s '%s' does not match reference value '%s'. Aborting test
""".strip() % (what,chk,refchk)))
sys.exit(3)
def check_deps(ts,name,cmds):
def check_deps(cmds):
if len(cmds) != 1:
msg("Usage: %s check_deps <command>" % g.prog_name)
sys.exit(1)
@ -624,8 +630,8 @@ class MMGenTestSuite(object):
dgl = cfgs[num]['dep_generators']
# msgrepr(num,cmd,dgl)
if cmd in dgl.values():
ext = [k for k in dgl if dgl[k] == cmd][0]
return (num,[ext])
exts = [k for k in dgl if dgl[k] == cmd]
return (num,exts)
else:
return None
@ -860,7 +866,8 @@ class MMGenTestSuite(object):
t = MMGenExpect(name,"mmgen-walletchk",args+["-d",cfg['tmpdir'],"-r","10",walletfile])
t.passphrase("MMGen wallet",cfg['wpasswd'])
t.usr_rand(10)
t.expect_getend("Incog ID: ")
incog_id = t.expect_getend("Incog ID: ")
write_to_tmpfile(cfg,incog_id_fn,incog_id+"\n")
if args[0] == "-G": return t
t.written_to_file("Incognito wallet data",overwrite_unlikely=True)
ok()
@ -1037,7 +1044,6 @@ class MMGenTestSuite(object):
write_to_file(infn,cfg['tool_enc_reftext'],silent=True)
self.tool_encrypt(name,infn)
# Two deps produced by one prog is broken - TODO
def tool_decrypt(self,name,f1,f2):
of = name + ".out"
t = MMGenExpect(name,"mmgen-tool",
@ -1051,6 +1057,14 @@ class MMGenTestSuite(object):
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))
t = MMGenExpect(name,"mmgen-tool",
["-d",cfg['tmpdir'],"find_incog_data",f1,i_id])
o = t.expect_getend("Incog data for ID \w{8} found at offset ",regex=True)
cmp_or_die(hincog_offset,int(o))
# main()
if opt.pause:
import termios,atexit

View file

@ -81,7 +81,8 @@ opts_data = {
-h, --help Print this help message
-d, --debug Produce debugging output
-l, --list-cmds List and describe the tests and commands in the test suite
-s, --system Test scripts and modules installed on system rather than those in the repo root
-s, --system Test scripts and modules installed on system rather than
those in the repo root
-v, --verbose Produce more verbose output
""",
'notes': """