From b43d827b50ad4fc7776b38b1c10e35b09164a82a Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Sat, 15 Jan 2022 14:00:11 +0000 Subject: [PATCH] rewrite test/gentest.py utility - support for testing all configured generators in one go has also been added (via the 'all' subparameter) --- test/gentest.py | 484 ++++++++++++++++++++++++------------------- test/test-release.sh | 2 +- 2 files changed, 268 insertions(+), 218 deletions(-) diff --git a/test/gentest.py b/test/gentest.py index 1094f6ab..27186215 100755 --- a/test/gentest.py +++ b/test/gentest.py @@ -30,68 +30,88 @@ sys.path.insert(0,overlay_setup(repo_root)) from mmgen.common import * from test.include.common import getrand +results_file = 'gentest.out.json' + rounds = 100 opts_data = { 'text': { 'desc': 'Test key/address generation of the MMGen suite in various ways', - 'usage':'[options] [spec] [rounds | dump file]', + 'usage':'[options] ', 'options': """ --h, --help Print this help message --a, --all Test all coins supported by specified external tool +-h, --help Print this help message +--, --longhelp Print help message for long options (common options) +-a, --all-coins Test all coins supported by specified external tool -k, --use-internal-keccak-module Force use of the internal keccak module ---, --longhelp Print help message for long options (common options) --q, --quiet Produce quieter output --t, --type=t Specify address type (e.g. 'compressed','segwit','zcash_z','bech32') --v, --verbose Produce more verbose output +-q, --quiet Produce quieter output +-s, --save-results Save output of external tool in Compare test to + {rf!r} +-t, --type=t Specify address type (e.g. 'compressed','segwit', + 'zcash_z','bech32') +-v, --verbose Produce more verbose output """, 'notes': """ TEST TYPES: - A/B: {prog} A:B [rounds] (compare key generators A and B) - Speed: {prog} A [rounds] (test speed of key generator A) - Compare: {prog} A (compare generator A to wallet dump) + Compare: {prog} A:B (compare address generators A and B) + Speed: {prog} A (test speed of generator A) + Dump: {prog} A (compare generator A to wallet dump) - where A and B are one of: - '1' - native Python ECDSA library (slow), or - '2' - bitcoincore.org's libsecp256k1 library (default); - or: - B is name of an external tool (see below) or 'ext'. - If B is 'ext', the external tool will be chosen automatically. + where: + + A and B are keygen backend numbers ('1' being the default); or + B is the name of an external tool (see below) or 'ext'. + + If B is 'ext', the external tool will be chosen automatically. + + For the Compare test, A may be 'all' to test all backends for the current + coin/address type combination. EXAMPLES: - Compare addresses generated by native Python ECDSA library and libsecp256k1, - 100 rounds: + Compare addresses generated by 'libsecp256k1' and 'python-ecdsa' backends, + with 100 random rounds plus private-key edge cases: $ {prog} 1:2 100 - Compare mmgen-secp256k1 Segwit address generation to pycoin library for all - supported coins, 100 rounds: - $ {prog} --all --type=segwit 2:pycoin 100 + Compare Segwit addresses from default 'libsecp256k1' backend to 'pycoin' + library for all supported coins, 100 rounds + edge cases: + $ {prog} --all-coins --type=segwit 1:pycoin 100 - Compare mmgen-secp256k1 address generation to keyconv tool for all - supported coins, 100 rounds: - $ {prog} --all --type=compressed 2:keyconv 100 + Compare addresses from 'python-ecdsa' backend to output of 'keyconv' tool + for all supported coins, 100 rounds + edge cases: + $ {prog} --all-coins --type=compressed 2:keyconv 100 - Compare mmgen-secp256k1 XMR address generation to configured external tool, - 10 rounds: - $ {prog} --coin=xmr 2:ext 10 + Compare bech32 addrs from 'libsecp256k1' backend to Bitcoin Core wallet + dump: + $ {prog} --type=bech32 1 bech32wallet.dump - Test speed of mmgen-secp256k1 address generation, 10,000 rounds: - $ {prog} 2 10000 + Compare addresses from Monero 'ed25519ll' backend to output of default + external tool, 10 rounds + edge cases: + $ {prog} --coin=xmr 3:ext 10 - Compare mmgen-secp256k1-generated bech32 addrs to coin daemon wallet dump: - $ {prog} --type=bech32 2 bech32wallet.dump + Test the speed of default Monero 'nacl' backend, 10,000 rounds: + $ test/gentest.py --coin=xmr 1 10000 -Supported external tools: + Same for Zcash: + $ test/gentest.py --coin=zec --type=zcash_z 1 10000 + + Test all configured Monero backends against 'moneropy' library, 3 rounds + + edge cases: + $ test/gentest.py --coin=xmr all:moneropy 3 + + Test 'nacl' and 'ed25519ll_djbec' backends against each other, 10,000 rounds + + edge cases: + $ test/gentest.py --coin=xmr 1:2 10000 + +SUPPORTED EXTERNAL TOOLS: + ethkey (for ETH,ETC) - https://github.com/openethereum/openethereum + https://github.com/openethereum/openethereum (build with 'cargo build -p ethkey-cli --release') - + zcash-mini (for Zcash Z-addresses) + + zcash-mini (for Zcash-Z addresses and view keys) https://github.com/FiloSottile/zcash-mini - + moneropy (for Monero addresses) + + moneropy (for Monero addresses and view keys) https://github.com/bigreddmachine/MoneroPy + pycoin (for supported coins) @@ -103,6 +123,9 @@ Supported external tools: """ }, 'code': { + 'options': lambda s: s.format( + rf=results_file, + ), 'notes': lambda s: s.format( prog='test/gentest.py', pnm=g.proj_name, @@ -110,36 +133,33 @@ Supported external tools: } } -sys.argv = [sys.argv[0]] + ['--skip-cfg-file'] + sys.argv[1:] +gtr = namedtuple('gen_tool_result',['wif','addr','vk']) -cmd_args = opts.init(opts_data,add_opts=['exact_output']) - -if not 1 <= len(cmd_args) <= 2: - opts.usage() - -from mmgen.protocol import init_proto_from_opts -proto = init_proto_from_opts() - -from subprocess import run,PIPE,DEVNULL def get_cmd_output(cmd,input=None): return run(cmd,input=input,stdout=PIPE,stderr=DEVNULL).stdout.decode().splitlines() -from collections import namedtuple -gtr = namedtuple('gen_tool_result',['wif','addr','vk']) +saved_results = {} class GenTool(object): + def __init__(self,proto,addr_type): + self.proto = proto + self.addr_type = addr_type + self.data = {} + + def __del__(self): + if opt.save_results: + key = f'{self.proto.coin}-{self.proto.network}-{self.addr_type.name}-{self.desc}'.lower() + saved_results[key] = self.data + def run_tool(self,sec): - vcoin = 'BTC' if proto.coin == 'BCH' else proto.coin - return self.run(sec,vcoin) + vcoin = 'BTC' if self.proto.coin == 'BCH' else self.proto.coin + ret = self.run(sec,vcoin) + self.data[sec] = ret._asdict() + return ret class GenToolEthkey(GenTool): desc = 'ethkey' - def __init__(self): - proto = init_proto('eth') - global addr_type - addr_type = MMGenAddrType(proto,'E') - def run(self,sec,vcoin): o = get_cmd_output(['ethkey','info',sec]) return gtr(o[0].split()[1],o[-1].split()[1],None) @@ -152,11 +172,6 @@ class GenToolKeyconv(GenTool): class GenToolZcash_mini(GenTool): desc = 'zcash-mini' - def __init__(self): - proto = init_proto('zec') - global addr_type - addr_type = MMGenAddrType(proto,'Z') - def run(self,sec,vcoin): o = get_cmd_output(['zcash-mini','-key','-simple'],input=(sec.wif+'\n').encode()) return gtr(o[1],o[0],o[-1]) @@ -166,24 +181,26 @@ class GenToolPycoin(GenTool): pycoin/networks/all.py pycoin/networks/legacy_networks.py """ desc = 'pycoin' - def __init__(self): - m = "Unable to import pycoin.networks.registry. Is pycoin installed on your system?" + def __init__(self,*args,**kwargs): + super().__init__(*args,**kwargs) try: from pycoin.networks.registry import network_for_netcode except: - raise ImportError(m) + raise ImportError('Unable to import pycoin.networks.registry. Is pycoin installed on your system?') self.nfnc = network_for_netcode def run(self,sec,vcoin): - if proto.testnet: + if self.proto.testnet: vcoin = ci.external_tests['testnet']['pycoin'][vcoin] network = self.nfnc(vcoin) - key = network.keys.private(secret_exponent=int(sec,16),is_compressed=addr_type.name != 'legacy') + key = network.keys.private( + secret_exponent = int(sec,16), + is_compressed = self.addr_type.name != 'legacy' ) if key is None: die(1,f'can’t parse {sec}') - if addr_type.name in ('segwit','bech32'): + if self.addr_type.name in ('segwit','bech32'): hash160_c = key.hash160(is_compressed=True) - if addr_type.name == 'segwit': + if self.addr_type.name == 'segwit': p2sh_script = network.contract.for_p2pkh_wit(hash160_c) addr = network.address.for_p2s(p2sh_script) else: @@ -194,44 +211,42 @@ class GenToolPycoin(GenTool): class GenToolMoneropy(GenTool): desc = 'moneropy' - def __init__(self): - m = "Unable to import moneropy. Is moneropy installed on your system?" + def __init__(self,*args,**kwargs): + super().__init__(*args,**kwargs) try: import moneropy.account except: - raise ImportError(m) - + raise ImportError('Unable to import moneropy. Is moneropy installed on your system?') self.mpa = moneropy.account - proto = init_proto('xmr') - - global addr_type - addr_type = MMGenAddrType(proto,'M') def run(self,sec,vcoin): - sk_t,vk_t,addr_t = self.mpa.account_from_spend_key(sec) # VERY slow! - return gtr(sk_t,addr_t,vk_t) + if sec in self.data: + return gtr(**self.data[sec]) + else: + sk,vk,addr = self.mpa.account_from_spend_key(sec) # VERY slow! + return gtr(sk,addr,vk) -def get_tool(arg): +def find_or_check_tool(proto,addr_type,toolname): - if arg not in ext_progs + ['ext']: - die(1,f'{arg!r}: unsupported tool for network {proto.network}') + ext_progs = list(ci.external_tests[proto.network]) - if opt.all: - if arg == 'ext': - die(1,"'--all' must be combined with a specific external testing tool") - return arg + if toolname not in ext_progs + ['ext']: + die(1,f'{toolname!r}: unsupported tool for network {proto.network}') + + if opt.all_coins and toolname == 'ext': + die(1,"'--all-coins' must be combined with a specific external testing tool") else: tool = ci.get_test_support( proto.coin, addr_type.name, proto.network, verbose = not opt.quiet, - tool = arg if arg in ext_progs else None ) - if not tool: - sys.exit(2) - if arg in ext_progs and arg != tool: + tool = toolname if toolname != 'ext' else None ) + if tool and toolname in ext_progs and toolname != tool: sys.exit(3) + if tool == None: + return None return tool def test_equal(desc,a_val,b_val,in_bytes,sec,wif,a_desc,b_desc): @@ -251,13 +266,47 @@ def test_equal(desc,a_val,b_val,in_bytes,sec,wif,a_desc,b_desc): w=max(len(e) for e in (a_desc,b_desc)) + 1 ).rstrip()) -def gentool_test(kg_a,kg_b,ag,rounds): +def do_ab_test(proto,addr_type,kg_b,rounds,backend_num): + + def run_ab_inner(n,trounds,in_bytes): + global last_t + if opt.verbose or time.time() - last_t >= 0.1: + qmsg_r(f'\rRound {i+1}/{trounds} ') + last_t = time.time() + sec = PrivKey(proto,in_bytes,compressed=addr_type.compressed,pubkey_type=addr_type.pubkey_type) + data = kg_a.to_pubhex(sec) + ag = AddrGenerator(proto,addr_type) + a_addr = ag.to_addr(data) + tinfo = (in_bytes,sec,sec.wif,type(kg_a).__name__,type(kg_b).__name__) + a_vk = None + + def do_msg(): + vmsg( fs.format( b=in_bytes.hex(), r=sec, k=sec.wif, v=a_vk, a=a_addr )) + + if isinstance(kg_b,GenTool): + def run_tool(): + b = kg_b.run_tool(sec) + test_equal('WIF keys',sec.wif,b.wif,*tinfo) + test_equal('addresses',a_addr,b.addr,*tinfo) + if b.vk: + test_equal( 'view keys', ag.to_viewkey(data), b.vk, *tinfo ) + return b.vk + a_vk = run_tool() + do_msg() + else: + test_equal( 'addresses', a_addr, ag.to_addr(kg_b.to_pubhex(sec)), *tinfo ) + do_msg() + + qmsg_r(f'\rRound {n+1}/{trounds} ') + + kg_a = KeyGenerator(proto,addr_type,backend_num) + if type(kg_a) == type(kg_b): + rdie(1,'Key generators are the same!') - m = "Comparing address generators '{A}' and '{B}' for {N} {c} ({n}), addrtype {a!r}" e = ci.get_entry(proto.coin,proto.network) - qmsg(green(m.format( - A = kg_a.desc, - B = kg_b.desc, + qmsg(green("Comparing address generators '{A}' and '{B}' for {N} {c} ({n}), addrtype {a!r}".format( + A = type(kg_a).__name__, + B = type(kg_b).__name__.replace('GenTool','').replace('_','-').lower(), N = proto.network, c = proto.coin, n = e.name if e else '---', @@ -266,61 +315,71 @@ def gentool_test(kg_a,kg_b,ag,rounds): global last_t last_t = time.time() - def do_compare_test(n,trounds,in_bytes): - global last_t - if opt.verbose or time.time() - last_t >= 0.1: - qmsg_r(f'\rRound {i+1}/{trounds} ') - last_t = time.time() - sec = PrivKey(proto,in_bytes,compressed=addr_type.compressed,pubkey_type=addr_type.pubkey_type) - a_ph = kg_a.to_pubhex(sec) - a_addr = ag.to_addr(a_ph) - a_vk = None - tinfo = (in_bytes,sec,sec.wif,kg_a.desc,kg_b.desc) - if isinstance(kg_b,GenTool): - b = kg_b.run_tool(sec) - test_equal('WIF keys',sec.wif,b.wif,*tinfo) - test_equal('addresses',a_addr,b.addr,*tinfo) - if b.vk: - a_vk = ag.to_viewkey(a_ph) - test_equal('view keys',a_vk,b.vk,*tinfo) - else: - b_addr = ag.to_addr(kg_b.to_pubhex(sec)) - test_equal('addresses',a_addr,b_addr,*tinfo) - vmsg(fs.format(b=in_bytes.hex(),k=sec.wif,v=a_vk,a=a_addr)) - qmsg_r(f'\rRound {n+1}/{trounds} ') + fs = ( + '\ninput: {b}' + + '\nreduced: {r}' + + '\n{:9} {{k}}'.format(addr_type.wif_label+':') + + ('\nviewkey: {v}' if 'viewkey' in addr_type.extra_attrs else '') + + '\naddr: {a}\n' ) - fs = ( '\ninput: {b}\n%-9s {k}\naddr: {a}\n', - '\ninput: {b}\n%-9s {k}\nviewkey: {v}\naddr: {a}\n')[ - 'viewkey' in addr_type.extra_attrs] % (addr_type.wif_label + ':') + ge = CoinProtocol.Secp256k1.secp256k1_ge # test some important private key edge cases: edgecase_sks = ( bytes([0x00]*31 + [0x01]), # min bytes([0xff]*32), # max - bytes([0x0f] + [0xff]*31), # same key as above for zcash-z + bytes([0x0f] + [0xff]*31), # produces same key as above for zcash-z + int.to_bytes(ge + 1, 32, 'big'), # bitcoin will reduce + int.to_bytes(ge - 1, 32, 'big'), # bitcoin will not reduce bytes([0x00]*31 + [0xff]), # monero will reduce bytes([0xff]*31 + [0x0f]), # monero will not reduce + bytes.fromhex('deadbeef'*8), ) qmsg(purple('edge cases:')) for i,in_bytes in enumerate(edgecase_sks): - do_compare_test(i,len(edgecase_sks),in_bytes) + run_ab_inner(i,len(edgecase_sks),in_bytes) qmsg(green('\rOK ' if opt.verbose else 'OK')) qmsg(purple('random input:')) for i in range(rounds): - do_compare_test(i,rounds,getrand(32)) + run_ab_inner(i,rounds,getrand(32)) qmsg(green('\rOK ' if opt.verbose else 'OK')) -def speed_test(kg,ag,rounds): - m = "Testing speed of address generator '{}' for coin {}" - qmsg(green(m.format(kg.desc,proto.coin))) +def init_tool(proto,addr_type,toolname): + return globals()['GenTool'+capfirst(toolname.replace('-','_'))](proto,addr_type) + +def get_backends(proto,foo): + return (1,) if isinstance(proto,CoinProtocol.Zcash) else (1,2) + +def ab_test(proto,gen_num,rounds,toolname_or_gen2_num): + + addr_type = MMGenAddrType( proto=proto, id_str=opt.type or proto.dfl_mmtype ) + + if is_int(toolname_or_gen2_num): + assert gen_num != 'all', "'all' must be used only with external tool" + tool = KeyGenerator( proto, addr_type, int(toolname_or_gen2_num) ) + else: + toolname = find_or_check_tool( proto, addr_type, toolname_or_gen2_num ) + if toolname == None: + ymsg(f'Warning: skipping tool {toolname_or_gen2_num!r} for {proto.coin} {addr_type.name}') + return + tool = init_tool( proto, addr_type, toolname ) + + if gen_num == 'all': # check all backends against external tool + for n in range(len(get_backends(proto,addr_type.pubkey_type))): + do_ab_test( proto, addr_type, tool, rounds, n+1 ) + else: # check specific backend against external tool or another backend + do_ab_test( proto, addr_type, tool, rounds, int(gen_num) ) + +def speed_test(proto,addr_type,kg,ag,rounds): + qmsg(green('Testing speed of address generator {!r} for coin {}'.format( + type(kg).__name__, + proto.coin ))) from struct import pack,unpack seed = getrand(28) qmsg('Incrementing key with each round') - qmsg('Starting key: {}'.format( - (seed + pack('I',0)).hex() - )) + qmsg('Starting key: {}'.format( (seed + pack('I',0)).hex() )) import time start = last_t = time.time() @@ -328,7 +387,7 @@ def speed_test(kg,ag,rounds): if time.time() - last_t >= 0.1: qmsg_r(f'\rRound {i+1}/{rounds} ') last_t = time.time() - sec = PrivKey(proto,seed+pack('I',i),compressed=addr_type.compressed,pubkey_type=addr_type.pubkey_type) + sec = PrivKey( proto, seed+pack('I', i), compressed=addr_type.compressed, pubkey_type=addr_type.pubkey_type ) addr = ag.to_addr(kg.to_pubhex(sec)) vmsg(f'\nkey: {sec.wif}\naddr: {addr}\n') qmsg( @@ -337,15 +396,18 @@ def speed_test(kg,ag,rounds): ('' if g.test_suite_deterministic else f' in {time.time()-start:.2f} seconds') ) -def dump_test(kg,ag,fh): +def dump_test(proto,kg,ag,filename): - dump = [[*(e.split()[0] for e in line.split('addr='))] for line in fh.readlines() if 'addr=' in line] - if not dump: - die(1,f'File {fh.name!r} appears not to be a wallet dump') - fh.close() + with open(filename) as fp: + dump = [[*(e.split()[0] for e in line.split('addr='))] for line in fp.readlines() if 'addr=' in line] + if not dump: + die(1,f'File {filename!r} appears not to be a wallet dump') - m = 'Comparing output of address generator {!r} against wallet dump {!r}' - qmsg(green(m.format(kg.desc,fh.name))) + qmsg(green( + "A: generator pair '{}:{}'\nB: wallet dump {!r}".format( + type(kg).__name__, + type(ag).__name__, + filename))) for count,(b_wif,b_addr) in enumerate(dump,1): qmsg_r(f'\rKey {count}/{len(dump)} ') @@ -355,102 +417,90 @@ def dump_test(kg,ag,fh): die(2,f'\nInvalid {proto.network} WIF address in dump file: {b_wif}') a_addr = ag.to_addr(kg.to_pubhex(b_sec)) vmsg(f'\nwif: {b_wif}\naddr: {b_addr}\n') - tinfo = (bytes.fromhex(b_sec),b_sec,b_wif,kg.desc,fh.name) + tinfo = (b_sec,b_sec,b_wif,type(kg).__name__,filename) test_equal('addresses',a_addr,b_addr,*tinfo) + qmsg(green(('\n','')[bool(opt.verbose)] + 'OK')) -def init_tool(tname): - return globals()['GenTool'+capfirst(tname.replace('-','_'))]() +def get_protos(proto,addr_type,toolname): -def parse_arg1(arg,arg_id): + init_genonly_altcoins(testnet=proto.testnet) - m1 = 'First argument must be a numeric generator ID or two colon-separated generator IDs' - m2 = 'Second part of first argument must be a numeric generator ID or one of {}' + for coin in ci.external_tests[proto.network][toolname]: + if coin.lower() not in CoinProtocol.coins: + continue + ret = init_proto(coin,testnet=proto.testnet) + if addr_type not in ret.mmtypes: + continue + yield ret - def check_gen_num(n): - if not (1 <= int(n) <= len(g.key_generators)): - die(1,f'{n}: invalid generator ID') - return int(n) +def parse_args(): - if arg_id == 'a': - if is_int(arg): - a_num = check_gen_num(arg) - return (KeyGenerator(proto,addr_type,a_num),a_num) - else: - die(1,m1) - elif arg_id == 'b': - if is_int(arg): - return KeyGenerator(proto,addr_type,check_gen_num(arg)) - elif arg in ext_progs + ['ext']: - return init_tool(get_tool(arg)) - else: - die(1,m2.format(ext_progs)) + if len(cmd_args) != 2: + opts.usage() + + arg1,arg2 = cmd_args + pa = namedtuple('parsed_args',['test','gen_num','rounds','arg']) + + if is_int(arg1) and is_int(arg2): + return pa( test='speed', gen_num=arg1, rounds=int(arg2), arg=None ) + + if is_int(arg1) and os.access(arg2,os.R_OK): + return pa( test='dump', gen_num=arg1, rounds=None, arg=arg2 ) + + if not is_int(arg2): + die(1,'Second argument must be dump filename or integer rounds specification') -def parse_arg2(): - m = 'Second argument must be dump filename or integer rounds specification' - if len(cmd_args) == 1: - return None - arg = cmd_args[1] - if is_int(arg) and int(arg) > 0: - return int(arg) try: - return open(arg) + a,b = arg1.split(':') except: - die(1,m) + die(1,'First argument must be a generator backend number or two colon-separated arguments') -# begin execution -from mmgen.protocol import init_proto + if not is_int(a) and a != 'all': + die(1,"First part of first argument must be a generator backend number or 'all'") + + if is_int(b): + if opt.all_coins: + die(1,'--all-coins must be used with external tool only') + else: + proto = init_proto_from_opts() + ext_progs = list(ci.external_tests[proto.network]) + ['ext'] + if b not in ext_progs: + die(1,f'Second part of first argument must be a generator backend number or one of {ext_progs}') + + return pa( test='ab', gen_num=a, rounds=int(arg2), arg=b ) + +def main(): + + pa = parse_args() + proto = init_proto_from_opts() + addr_type = MMGenAddrType( proto=proto, id_str=opt.type or proto.dfl_mmtype ) + + if pa.test == 'ab': + protos = get_protos(proto,addr_type,pa.arg) if opt.all_coins else [proto] + for proto in protos: + ab_test( proto, pa.gen_num, pa.rounds, toolname_or_gen2_num=pa.arg ) + else: + kg = KeyGenerator( proto, addr_type, pa.gen_num ) + ag = AddrGenerator( proto, addr_type ) + if pa.test == 'speed': + speed_test( proto, addr_type, kg, ag, pa.rounds ) + elif pa.test == 'dump': + dump_test( proto, kg, ag, filename=pa.arg ) + + if saved_results: + import json + with open(results_file,'w') as fp: + fp.write(json.dumps( saved_results, indent=4 )) + +from subprocess import run,PIPE,DEVNULL +from collections import namedtuple +from mmgen.protocol import init_proto,init_proto_from_opts,CoinProtocol,init_genonly_altcoins from mmgen.altcoin import CoinInfo as ci from mmgen.key import PrivKey from mmgen.addr import KeyGenerator,AddrGenerator,MMGenAddrType -addr_type = MMGenAddrType( - proto = proto, - id_str = opt.type or proto.dfl_mmtype ) +sys.argv = [sys.argv[0]] + ['--skip-cfg-file'] + sys.argv[1:] +cmd_args = opts.init(opts_data,add_opts=['exact_output']) -ext_progs = list(ci.external_tests[proto.network]) - -arg1 = cmd_args[0].split(':') - -if len(arg1) == 1: - a,a_num = parse_arg1(arg1[0],'a') - b = None -elif len(arg1) == 2: - a,a_num = parse_arg1(arg1[0],'a') - b = parse_arg1(arg1[1],'b') -else: - opts.usage() - -if type(a) == type(b): - rdie(1,'Address generators are the same!') - -arg2 = parse_arg2() - -if not opt.all: - ag = AddrGenerator(proto,addr_type) - -if not b and type(arg2) == int: - speed_test(a,ag,arg2) -elif not b and hasattr(arg2,'read'): - dump_test(a,ag,arg2) -elif a and b and type(arg2) == int: - if opt.all: - from mmgen.protocol import CoinProtocol,init_genonly_altcoins - init_genonly_altcoins(testnet=proto.testnet) - for coin in ci.external_tests[proto.network][b.desc]: - if coin.lower() not in CoinProtocol.coins: -# ymsg(f'Coin {coin} not configured') - continue - proto = init_proto(coin) - if addr_type not in proto.mmtypes: - continue - # proto has changed, so reinit kg and ag - a = KeyGenerator(proto,addr_type,a_num) - ag = AddrGenerator(proto,addr_type) - b_chk = ci.get_test_support(proto.coin,addr_type.name,proto.network,tool=b.desc,verbose=not opt.quiet) - if b_chk == b.desc: - gentool_test(a,b,ag,arg2) - else: - gentool_test(a,b,ag,arg2) -else: - opts.usage() +main() diff --git a/test/test-release.sh b/test/test-release.sh index 9a9dd45e..cab453ad 100755 --- a/test/test-release.sh +++ b/test/test-release.sh @@ -330,7 +330,7 @@ t_alts=" m # moneropy m $gentest_py --all --coin=xmr 2:moneropy $rounds_min # very slow, be patient! z # zcash-mini - z $gentest_py --all 2:zcash-mini $rounds_mid + z $gentest_py --all --coin=zec --type=zcash_z 1:zcash-mini $rounds_mid " [ "$MSYS2" ] && t_alts_skip='m z' # no moneropy (pysha3), zcash-mini (golang)