altcoin trust level changes

- make trust level system consistent, include all coins
- rewrite init_genonly_altcoins():
  + with coin argument, create only requested protocol
  + with no arguments, create all protocols
This commit is contained in:
The MMGen Project 2019-11-04 16:48:05 +00:00
commit 1295fdb6e0
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
4 changed files with 60 additions and 38 deletions

View file

@ -41,8 +41,9 @@ ce = namedtuple('CoinInfoEntry',
class CoinInfo(object):
coin_constants = {}
coin_constants['mainnet'] = (
# Trust levels: 0=untested 1=low 2=med 3=high -1=disable
# Fork coins must be disabled here to prevent generation from incorrect sub-seed
# Trust levels: -1=disabled 0=untested 1=low 2=med 3=high 4=very high (no warn) 5=unconditional
# Trust levels apply to key/address generation only.
# Fork coins must be disabled here to prevent generation from incorrect sub-seed.
ce('Bitcoin', 'BTC', 0x80, (0x00,'1'), (0x05,'3'), True, -1),
ce('BitcoinSegwit2X', 'B2X', 0x80, (0x00,'1'), (0x05,'3'), True, -1),
ce('BitcoinGold', 'BCG', 0x80, (0x00,'1'), (0x05,'3'), True, -1),
@ -385,6 +386,18 @@ class CoinInfo(object):
'ZRC': ['lb','vg']
}
@classmethod
def get_supported_coins(cls,network):
return [e for e in cls.coin_constants[network] if e.trust_level != -1]
@classmethod
def get_entry(cls,coin,network):
try:
idx = [e.symbol for e in cls.coin_constants[network]].index(coin.upper())
except:
return None
return cls.coin_constants[network][idx]
# Data is one of the coin_constants lists above. Normalize ints to hex of correct width, add
# missing leading letters, set trust level from external_tests.
# Insert a coin entry from outside source, set version info leading letters to '?' and trust level

View file

@ -169,7 +169,8 @@ def override_from_env():
setattr(g,gname,set_for_type(val,getattr(g,gname),name,disable))
def warn_altcoins(trust_level):
if trust_level == None: return
if trust_level > 3:
return
tl = (red('COMPLETELY UNTESTED'),red('LOW'),yellow('MEDIUM'),green('HIGH'))
m = """
Support for coin '{}' is EXPERIMENTAL. The {pn} project assumes no
@ -270,7 +271,7 @@ def init(opts_data,add_opts=[],opt_filter=None,parse_only=False):
g.network = 'testnet' if g.testnet else 'mainnet'
from mmgen.protocol import init_genonly_altcoins,CoinProtocol
altcoin_trust_level = init_genonly_altcoins(opt.coin)
altcoin_trust_level = init_genonly_altcoins(opt.coin or 'btc')
# g.testnet is set, so we can set g.proto
g.proto = CoinProtocol(g.coin,g.testnet)

View file

@ -449,30 +449,26 @@ class MoneroTestnetProtocol(MoneroProtocol):
addr_ver_num = { 'monero': ('35','4'), 'monero_sub': ('3f','8') } # 53,63
class CoinProtocol(MMGenObject):
pi = namedtuple('proto_info',['main_cls','test_cls','trust_level']) # trust levels: see altcoin.py
coins = {
# mainnet testnet trustlevel (None == skip)
'btc': (BitcoinProtocol,BitcoinTestnetProtocol,None),
'bch': (BitcoinCashProtocol,BitcoinCashTestnetProtocol,None),
'ltc': (LitecoinProtocol,LitecoinTestnetProtocol,None),
'eth': (EthereumProtocol,EthereumTestnetProtocol,None),
'etc': (EthereumClassicProtocol,EthereumClassicTestnetProtocol,None),
'zec': (ZcashProtocol,ZcashTestnetProtocol,2),
'xmr': (MoneroProtocol,MoneroTestnetProtocol,None)
'btc': pi(BitcoinProtocol,BitcoinTestnetProtocol,5),
'bch': pi(BitcoinCashProtocol,BitcoinCashTestnetProtocol,5),
'ltc': pi(LitecoinProtocol,LitecoinTestnetProtocol,5),
'eth': pi(EthereumProtocol,EthereumTestnetProtocol,4),
'etc': pi(EthereumClassicProtocol,EthereumClassicTestnetProtocol,4),
'zec': pi(ZcashProtocol,ZcashTestnetProtocol,2),
'xmr': pi(MoneroProtocol,MoneroTestnetProtocol,4)
}
def __new__(cls,coin,testnet):
coin = coin.lower()
assert type(testnet) == bool
m = "'{}': not a valid coin. Valid choices are {}"
assert coin in cls.coins,m.format(coin,','.join(cls.get_valid_coins()))
m = "{}: not a valid coin for network {}\nSupported coins: {}"
assert coin in cls.coins, m.format(coin.upper(),g.network.upper(),cls.list_coins())
return cls.coins[coin][testnet]
@classmethod
def get_valid_coins(cls,upcase=False):
from mmgen.altcoin import CoinInfo as ci
ret = sorted(set(
[e.symbol for e in ci.coin_constants['mainnet'] if e.trust_level != -1]
+ list(cls.coins.keys())))
return [getattr(e,('lower','upper')[upcase])() for e in ret]
def list_coins(cls):
return ' '.join(c.upper() for c in cls.coins)
@classmethod
def get_base_coin_from_name(cls,name):
@ -481,23 +477,36 @@ class CoinProtocol(MMGenObject):
return proto.base_coin
return False
def init_genonly_altcoins(usr_coin,trust_level=None):
def init_genonly_altcoins(usr_coin=None):
"""
Initialize altcoin protocol class or classes for current network.
If usr_coin is None, initializes all supported altcoins for current network.
Returns trust_level of usr_coin, or 0 (untrusted) if usr_coin is None.
"""
from mmgen.altcoin import CoinInfo as ci
if trust_level is None:
if not usr_coin: return None # BTC
data = { 'mainnet': (), 'testnet': () }
networks = ['mainnet'] + (['testnet'] if g.testnet else [])
if usr_coin == None:
for network in networks:
data[network] = ci.get_supported_coins(network)
trust_level = 0
else:
if usr_coin.lower() in CoinProtocol.coins:
return CoinProtocol.coins[usr_coin.lower()][2]
usr_coin = usr_coin.upper()
usr_entry = [e for e in ci.coin_constants['mainnet'] if e.symbol == usr_coin]
if not usr_entry:
raise ValueError('Coin {} not recognized'.format(usr_coin))
usr_entry = usr_entry[0]
if usr_entry.trust_level == -1:
raise ValueError('Coin {} ({}) not supported'.format(usr_coin,usr_entry.name))
trust_level = usr_entry.trust_level
data = {}
for k in ('mainnet','testnet'):
data[k] = [e for e in ci.coin_constants[k] if e.trust_level >= trust_level]
return CoinProtocol.coins[usr_coin.lower()].trust_level
for network in networks:
data[network] = (ci.get_entry(usr_coin,network),)
cinfo = data[g.network][0]
if not cinfo:
m = '{!r}: unrecognized coin for network {}'
raise ValueError(m.format(usr_coin.upper(),g.network.upper()))
if cinfo.trust_level == -1:
m = '{!r}: unsupported (disabled) coin for network {}'
raise ValueError(m.format(usr_coin.upper(),g.network.upper()))
trust_level = cinfo.trust_level
exec(make_init_genonly_altcoins_str(data),globals(),globals())
return trust_level

View file

@ -351,10 +351,9 @@ ag = AddrGenerator(addr_type)
if a and b:
if opt.all:
from mmgen.protocol import init_genonly_altcoins,CoinProtocol
init_genonly_altcoins('btc',trust_level=0)
mmgen_supported = CoinProtocol.get_valid_coins(upcase=True)
init_genonly_altcoins()
for coin in ci.external_tests[('mainnet','testnet')[g.testnet]][ext_prog]:
if coin not in mmgen_supported: continue
if coin not in CoinProtocol.coins: continue
init_coin(coin)
if addr_type not in g.proto.mmtypes:
addr_type = MMGenAddrType(g.proto.dfl_mmtype)