altcoin.py: add tests: verify_leading_symbols(), verify_core_coin_data()

This commit is contained in:
The MMGen Project 2019-11-06 17:34:52 +00:00
commit 3813ce33ba
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
3 changed files with 98 additions and 2 deletions

View file

@ -34,6 +34,18 @@ altcoin.py - Coin constants for Bitcoin-derived altcoins
import sys
def msg(s): sys.stderr.write(s+'\n')
def test_equal(desc,a,b,*cdata):
if type(a) == int:
a = hex(a)
b = hex(b)
(network,coin,e,b_desc,verbose) = cdata
if verbose:
m = ' {:20}: {!r}'
msg(m.format(desc,a))
if a != b:
m = '{}s for {} {} do not match:\n CoinInfo: {}\n {}: {}'
raise ValueError(m.format(desc.capitalize(),coin.upper(),network,a,b_desc,b))
from collections import namedtuple
ce = namedtuple('CoinInfoEntry',
['name','symbol','wif_ver_num','p2pkh_info','p2sh_info','has_segwit','trust_level'])
@ -123,7 +135,7 @@ class CoinInfo(object):
ce('Jumbucks', 'JBS', 0xab, (0x2b,'J'), (0x69,'j'), False, 2),
ce('Lanacoin', 'LANA', 0xb0, (0x30,'L'), None, False, 0),
ce('Latium', 'LAT', 0x80, (0x17,'A'), None, False, 0),
ce('Litecoin', 'LTC', 0xb0, (0x30,'L'), (0x05,'3'), True, 3),
ce('Litecoin', 'LTC', 0xb0, (0x30,'L'), (0x32,'M'), True, 5), # old p2sh: 0x05
ce('LiteDoge', 'LDOGE', 0xab, (0x5a,'d'), None, False, 0),
ce('LomoCoin', 'LMC', 0xb0, (0x30,'L'), None, False, 0),
ce('Marscoin', 'MARS', 0xb2, (0x32,'M'), None, False, 0),
@ -387,6 +399,63 @@ class CoinInfo(object):
'ZRC': ['lb','vg']
}
@classmethod
def verify_leading_symbols(cls,quiet=False,verbose=False):
for network in ('mainnet','testnet'):
for coin in [e.symbol for e in cls.coin_constants[network]]:
e = cls.get_entry(coin,network)
cdata = (network,coin,e,'Computed value',verbose)
if not quiet:
msg('{} {}'.format(coin,network))
vn_info = e.p2pkh_info
ret = cls.find_addr_leading_symbol(vn_info[0])
test_equal('P2PKH leading symbol',vn_info[1],ret,*cdata)
vn_info = e.p2sh_info
if vn_info:
ret = cls.find_addr_leading_symbol(vn_info[0])
test_equal('P2SH leading symbol',vn_info[1],ret,*cdata)
@classmethod
def verify_core_coin_data(cls,quiet=False,verbose=False):
from mmgen.protocol import CoinProtocol
for network in ('mainnet','testnet'):
for coin in CoinProtocol.core_coins:
e = cls.get_entry(coin,network)
if e:
proto = CoinProtocol(coin,testnet=network=='testnet')
cdata = (network,coin,e,proto.__name__,verbose)
if not quiet:
msg('Verifying {} {}'.format(coin.upper(),network))
if coin != 'bch': # TODO
test_equal('coin name',e.name,proto.name.capitalize(),*cdata)
if e.trust_level != -1:
test_equal('Trust level',e.trust_level,CoinProtocol.coins[coin].trust_level,*cdata)
test_equal(
'WIF version number',
e.wif_ver_num,
int.from_bytes(bytes.fromhex(proto.wif_ver_num['std']),'big'),
*cdata )
test_equal(
'P2PKH version number',
e.p2pkh_info[0],
int.from_bytes(proto.addr_fmt_to_ver_bytes('p2pkh'),'big'),
*cdata )
test_equal(
'P2SH version number',
e.p2sh_info[0],
int.from_bytes(proto.addr_fmt_to_ver_bytes('p2sh'),'big'),
*cdata )
@classmethod
def get_supported_coins(cls,network):
return [e for e in cls.coin_constants[network] if e.trust_level != -1]
@ -470,6 +539,9 @@ class CoinInfo(object):
@classmethod
def find_addr_leading_symbol(cls,ver_num,verbose=False):
if ver_num == 0:
return '1'
def phash2addr(ver_num,pk_hash):
from mmgen.protocol import _b58chk_encode
bl = ver_num.bit_length()
@ -618,3 +690,15 @@ class CoinInfo(object):
'segwit': { 'pycoin': ('LTC',), 'keyconv': True },
'bech32': { 'keyconv': True },
}
if __name__ == '__main__':
quiet = '--quiet' in sys.argv
verbose = '--verbose' in sys.argv
if verbose:
quiet = False
msg('Checking CoinInfo WIF/P2PKH/P2SH version numbers and trust levels against protocol.py')
CoinInfo.verify_core_coin_data(quiet=quiet,verbose=verbose)
msg('Checking CoinInfo address leading symbols')
CoinInfo.verify_leading_symbols(quiet=quiet,verbose=verbose)

View file

@ -458,6 +458,8 @@ class CoinProtocol(MMGenObject):
'zec': pi(ZcashProtocol,ZcashTestnetProtocol,2),
'xmr': pi(MoneroProtocol,MoneroTestnetProtocol,4)
}
core_coins = tuple(coins.keys())
def __new__(cls,coin,testnet):
coin = coin.lower()
assert type(testnet) == bool

View file

@ -29,13 +29,14 @@ tooltest_py='test/tooltest.py'
tooltest2_py='test/tooltest2.py --names --quiet'
gentest_py='test/gentest.py --quiet'
scrambletest_py='test/scrambletest.py'
altcoin_py='mmgen/altcoin.py --quiet'
mmgen_tool='cmds/mmgen-tool'
mmgen_keygen='cmds/mmgen-keygen'
python='python3'
rounds=100 rounds_min=20 rounds_mid=250 rounds_max=500
monero_addrs='3,99,2,22-24,101-104'
dfl_tests='obj color unit hash ref alts monero eth autosign btc btc_tn btc_rt bch bch_rt ltc ltc_tn ltc_rt tool tool2 gen'
dfl_tests='misc obj color unit hash ref alts monero eth autosign btc btc_tn btc_rt bch bch_rt ltc ltc_tn ltc_rt tool tool2 gen'
add_tests='autosign_minimal autosign_live'
PROGNAME=$(basename $0)
@ -80,6 +81,7 @@ do
echo " tool - tooltest (all supported coins)"
echo " tool2 - tooltest2 (all supported coins)"
echo " gen - gentest (all supported coins)"
echo " misc - miscellaneous tests that don't fit in the above categories"
echo " By default, all tests are run"
exit ;;
b) test_py+=" --buf-keypress" ;;
@ -110,6 +112,7 @@ do
v) EXACT_OUTPUT=1 test_py+=" --exact-output" ;&
V) VERBOSE=1 [ "$EXACT_OUTPUT" ] || test_py+=" --verbose"
unit_tests_py="${unit_tests_py/--quiet/--verbose}"
altcoin_py="${altcoin_py/--quiet/--verbose}"
tooltest2_py="${tooltest2_py/--quiet/--verbose}"
gentest_py="${gentest_py/--quiet/--verbose}"
tooltest_py+=" --verbose"
@ -196,6 +199,13 @@ do_test() {
done
}
i_misc='Miscellaneous'
s_misc='Testing various subsystems'
t_misc="
$altcoin_py
"
f_misc='Miscellaneous tests complete'
i_obj='Data object'
s_obj='Testing data objects'
t_obj="