protocol.py: add Regtest coin protocols, related changes

This commit is contained in:
The MMGen Project 2020-05-15 15:54:02 +00:00
commit 534f58994b
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
6 changed files with 65 additions and 53 deletions

View file

@ -698,8 +698,7 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
mmtype = MMGenAddrType(al_mmtype,on_fail='raise')
from .protocol import init_proto
base_coin = init_proto(al_coin or 'BTC',testnet=False).base_coin
return base_coin,mmtype,tn
return (init_proto(al_coin or 'BTC').base_coin, mmtype, tn)
def check_coin_mismatch(base_coin): # die if addrfile coin doesn't match g.coin
m = '{} address file format, but base coin is {}!'
@ -960,8 +959,8 @@ Record this checksum: it will be used to verify the password file in the future
pw_len_hex = baseconv.seedlen_map_rev['xmrseed'][self.pw_len] * 2
# take most significant part
bytes_trunc = bytes.fromhex(hex_sec[:pw_len_hex])
from .protocol import CoinProtocol
bytes_preproc = CoinProtocol.Monero().preprocess_key(bytes_trunc,None)
from .protocol import init_proto
bytes_preproc = init_proto('xmr').preprocess_key(bytes_trunc,None)
return ' '.join(baseconv.frombytes(bytes_preproc,wl_id='xmrseed'))
else:
# take least significant part

View file

@ -541,8 +541,8 @@ class CoinAddr(str,Hilite,InitErrors,MMGenObject):
if type(g.proto).__name__.startswith('Ethereum'):
return True
from mmgen.protocol import CoinProtocol
proto = CoinProtocol.get_protocol_by_chain(chain)
from mmgen.protocol import init_proto
proto = init_proto(g.coin,network=chain)
if self.addr_fmt == 'bech32':
return self[:len(proto.bech32_hrp)] == proto.bech32_hrp

View file

@ -273,7 +273,7 @@ def init(opts_data=None,add_opts=[],opt_filter=None,parse_only=False):
if g.regtest: # These are equivalent for now
g.testnet = True
g.network = 'testnet' if g.testnet else 'mainnet'
g.network = 'regtest' if g.regtest else 'testnet' if g.testnet else 'mainnet'
from .protocol import init_genonly_altcoins,init_proto
altcoin_trust_level = init_genonly_altcoins(g.coin)
@ -309,7 +309,7 @@ def init(opts_data=None,add_opts=[],opt_filter=None,parse_only=False):
if g.bob or g.alice:
g.testnet = True
g.regtest = True
g.proto = init_proto(g.coin,g.testnet)
g.proto = init_proto(g.coin,regtest=True)
g.rpc_host = 'localhost'
g.data_dir = os.path.join(g.data_dir_root,'regtest',g.coin.lower(),('alice','bob')[g.bob])
from .regtest import MMGenRegtest

View file

@ -71,32 +71,33 @@ finfo = namedtuple('fork_info',['height','hash','name','replayable'])
class CoinProtocol(MMGenObject):
proto_info = namedtuple('proto_info',['mainnet','testnet','trust_level']) # trust levels: see altcoin.py
proto_info = namedtuple('proto_info',['base_name','trust_level']) # trust levels: see altcoin.py
coins = {
'btc': proto_info('Bitcoin', 'BitcoinTestnet', 5),
'bch': proto_info('BitcoinCash', 'BitcoinCashTestnet', 5),
'ltc': proto_info('Litecoin', 'LitecoinTestnet', 5),
'eth': proto_info('Ethereum', 'EthereumTestnet', 4),
'etc': proto_info('EthereumClassic', 'EthereumClassicTestnet', 4),
'zec': proto_info('Zcash', 'ZcashTestnet', 2),
'xmr': proto_info('Monero', 'MoneroTestnet', 4)
'btc': proto_info('Bitcoin', 5),
'bch': proto_info('BitcoinCash', 5),
'ltc': proto_info('Litecoin', 5),
'eth': proto_info('Ethereum', 4),
'etc': proto_info('EthereumClassic', 4),
'zec': proto_info('Zcash', 2),
'xmr': proto_info('Monero', 4)
}
core_coins = tuple(coins.keys()) # coins may be added by init_genonly_altcoins(), so save
@staticmethod
def get_protocol_by_chain(chain):
return init_proto(g.coin,{'mainnet':False,'testnet':True,'regtest':True}[chain])
class Common(MMGenObject):
networks = ('mainnet','testnet','regtest')
def __init__(self,coin,base_name,network):
self.coin = coin.upper()
self.name = base_name[0].lower() + base_name[1:]
self.network = network
def is_testnet(self):
return type(self).__name__.endswith('Testnet')
return self.network in ('testnet','regtest')
def cap(self,s):
return s in self.caps
class Bitcoin(Common): # chainparams.cpp
name = 'bitcoin'
mod_clsname = 'bitcoin'
daemon_name = 'bitcoind'
daemon_family = 'bitcoind'
@ -236,7 +237,10 @@ class CoinProtocol(MMGenObject):
data_subdir = 'testnet'
daemon_data_subdir = 'testnet3'
rpc_port = 18332
bech32_hrps = {'testnet':'tb','regtest':'bcrt'}
bech32_hrp = 'tb'
class BitcoinRegtest(BitcoinTestnet):
bech32_hrp = 'bcrt'
class BitcoinCash(Bitcoin):
# TODO: assumes MSWin user installs in custom dir 'Bitcoin_ABC'
@ -263,6 +267,9 @@ class CoinProtocol(MMGenObject):
data_subdir = 'testnet'
daemon_data_subdir = 'testnet3'
class BitcoinCashRegtest(BitcoinCashTestnet):
pass
class B2X(Bitcoin):
daemon_name = 'bitcoind-2x'
daemon_data_dir = os.path.join(os.getenv('APPDATA'),'Bitcoin_2X') if g.platform == 'win' \
@ -283,7 +290,6 @@ class CoinProtocol(MMGenObject):
class Litecoin(Bitcoin):
block0 = '12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2'
name = 'litecoin'
daemon_name = 'litecoind'
daemon_data_dir = os.path.join(os.getenv('APPDATA'),'Litecoin') if g.platform == 'win' \
else os.path.join(g.home_dir,'.litecoin')
@ -306,7 +312,10 @@ class CoinProtocol(MMGenObject):
data_subdir = 'testnet'
daemon_data_subdir = 'testnet4'
rpc_port = 19332
bech32_hrps = {'testnet':'tltc','regtest':'rltc'}
bech32_hrp = 'tltc'
class LitecoinRegtest(LitecoinTestnet):
bech32_hrp = 'rltc'
class BitcoinAddrgen(Bitcoin):
mmcaps = ('key','addr')
@ -330,7 +339,6 @@ class CoinProtocol(MMGenObject):
addr_len = 20
mmtypes = ('E',)
dfl_mmtype = 'E'
name = 'ethereum'
mod_clsname = 'ethereum'
base_coin = 'ETH'
pubkey_type = 'std' # required by DummyWIF
@ -365,7 +373,6 @@ class CoinProtocol(MMGenObject):
chain_name = 'kovan'
class EthereumClassic(Ethereum):
name = 'ethereumClassic' # TODO
rpc_port = 8555 # start Parity with --jsonrpc-port=8555 or --ports-shift=10
chain_name = 'ethereum_classic' # chain_id 0x3d (61)
@ -374,7 +381,6 @@ class CoinProtocol(MMGenObject):
chain_name = 'classic-testnet' # aka Morden, chain_id 0x3e (62) (UNTESTED)
class Zcash(BitcoinAddrgen):
name = 'zcash'
base_coin = 'ZEC'
addr_ver_bytes = { '1cb8': 'p2pkh', '1cbd': 'p2sh', '169a': 'zcash_z', 'a8abd3': 'viewkey' }
wif_ver_num = { 'std': '80', 'zcash_z': 'ab36' }
@ -405,7 +411,6 @@ class CoinProtocol(MMGenObject):
# https://github.com/monero-project/monero/blob/master/src/cryptonote_config.h
class Monero(DummyWIF,BitcoinAddrgen):
name = 'monero'
base_coin = 'XMR'
addr_ver_bytes = { '12': 'monero', '2a': 'monero_sub' }
addr_len = 68
@ -445,18 +450,32 @@ class CoinProtocol(MMGenObject):
class MoneroTestnet(Monero):
addr_ver_bytes = { '35': 'monero', '3f': 'monero_sub' }
def init_proto(coin,testnet):
def init_proto(coin,testnet=False,regtest=False,network=None):
assert type(testnet) == bool
assert type(regtest) == bool
if network is None:
network = 'regtest' if regtest else 'testnet' if testnet else 'mainnet'
else:
assert network in CoinProtocol.Common.networks
assert testnet == False
assert regtest == False
coin = coin.lower()
assert type(testnet) == bool, type(testnet)
if coin not in CoinProtocol.coins:
raise ValueError(
'{}: not a valid coin for network {}\nSupported coins: {}'.format(
coin.upper(),g.network.upper(),
' '.join(c.upper() for c in CoinProtocol.coins) ))
proto = getattr(CoinProtocol,CoinProtocol.coins[coin][testnet])
if hasattr(proto,'bech32_hrps'):
proto.bech32_hrp = proto.bech32_hrps[('testnet','regtest')[g.regtest]]
return proto()
base_name = CoinProtocol.coins[coin].base_name
proto_name = base_name + ('' if network == 'mainnet' else network.capitalize())
return getattr(CoinProtocol,proto_name)(
coin = coin,
base_name = base_name,
network = network )
def init_genonly_altcoins(usr_coin=None):
"""
@ -513,8 +532,6 @@ def make_init_genonly_altcoins_str(data):
return f"""
class {proto}(CoinProtocol.BitcoinAddrgen{tn_str}):
base_coin = {coin!r}
name = {e.name.lower()!r}
nameCaps = {e.name!r}
addr_ver_bytes = {{ {num2hexstr(e.p2pkh_info[0])}: 'p2pkh'{p2sh_info} }}
wif_ver_num = {{ 'std': {num2hexstr(e.wif_ver_num)} }}
mmtypes = ('L','C'{sw_mmtype})
@ -535,10 +552,9 @@ def make_init_genonly_altcoins_str(data):
proto = 'X_'+proto
if hasattr(CoinProtocol,proto) or coin.lower() in CoinProtocol.coins:
continue
yield 'CoinProtocol.coins[{!r}] = CoinProtocol.proto_info({!r},{},{})'.format(
yield 'CoinProtocol.coins[{!r}] = CoinProtocol.proto_info({!r},{})'.format(
coin.lower(),
proto,
('None',f"'{proto}Testnet'")[coin in [e.symbol for e in data['testnet']]],
e.trust_level )
return '\n'.join(gen_text()) + '\n'
@ -546,7 +562,7 @@ def make_init_genonly_altcoins_str(data):
def init_coin(coin,testnet=None):
if testnet is not None:
g.testnet = testnet
g.network = ('mainnet','testnet')[g.testnet]
g.network = 'regtest' if g.regtest else 'testnet' if g.testnet else 'mainnet'
g.coin = coin.upper()
g.proto = init_proto(g.coin,g.testnet)
g.proto = init_proto(g.coin,testnet=g.testnet,regtest=g.regtest)
return g.proto

View file

@ -526,12 +526,12 @@ class MMGenToolCmdMnemonic(MMGenToolCmds):
@staticmethod
def _xmr_reduce(bytestr):
from .protocol import CoinProtocol
p = CoinProtocol.Monero()
if len(bytestr) != p.privkey_len:
from .protocol import init_proto
proto = init_proto('xmr')
if len(bytestr) != proto.privkey_len:
m = '{!r}: invalid bit length for Monero private key (must be {})'
die(1,m.format(len(bytestr*8),p.privkey_len*8))
return p.preprocess_key(bytestr,None)
die(1,m.format(len(bytestr*8),proto.privkey_len*8))
return proto.preprocess_key(bytestr,None)
def _do_random_mn(self,nbytes:int,fmt:str):
assert nbytes in (16,24,32), 'nbytes must be 16, 24 or 32'
@ -1208,10 +1208,7 @@ class tool_api(
@property
def network(self):
"""The currently configured network"""
if g.network == 'testnet':
return ('testnet','regtest')[g.regtest]
else:
return g.network
return g.network
@property
def addrtypes(self):

View file

@ -344,7 +344,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
x='' if g.debug_utf8 else ''))
if mmtype == g.proto.mmtypes[0] and user == 'bob':
psave = g.proto
g.proto = init_proto(g.coin,True)
g.proto = init_proto(g.coin,regtest=True)
self._add_comments_to_addr_file(addrfile,addrfile,use_labels=True)
g.proto = psave
t = self.spawn( 'mmgen-addrimport',
@ -568,7 +568,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
sid,self.altcoin_pfx,id_str,addr_range,x='' if g.debug_utf8 else '')
addrfile = get_file_with_ext(self._user_dir(user),ext,no_dot=True)
psave = g.proto
g.proto = init_proto(g.coin,True)
g.proto = init_proto(g.coin,regtest=True)
silence()
addr = AddrList(addrfile).data[idx].addr
end_silence()
@ -810,7 +810,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
"MMGen address '{}' not found in tracking wallet".format(addr))
def alice_add_label_badaddr4(self):
addr = init_proto(g.coin,True).pubhash2addr('00'*20,False) # testnet zero address
addr = init_proto(g.coin,regtest=True).pubhash2addr('00'*20,False) # testnet zero address
return self.alice_add_label_badaddr(addr,
"Address '{}' not found in tracking wallet".format(addr))