Browse Source

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

The MMGen Project 5 years ago
parent
commit
3813ce33ba
3 changed files with 98 additions and 2 deletions
  1. 85 1
      mmgen/altcoin.py
  2. 2 0
      mmgen/protocol.py
  3. 11 1
      test/test-release.sh

+ 85 - 1
mmgen/altcoin.py

@@ -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)

+ 2 - 0
mmgen/protocol.py

@@ -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

+ 11 - 1
test/test-release.sh

@@ -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="