Browse Source

protocol-specific cfg_file vars: fix chain_name parsing regression, add test

The MMGen Project 4 years ago
parent
commit
e10f5d19ac
4 changed files with 102 additions and 9 deletions
  1. 4 1
      mmgen/opts.py
  2. 8 1
      mmgen/protocol.py
  3. 11 5
      test/misc/cfg.py
  4. 79 2
      test/test_py_d/ts_cfg.py

+ 4 - 1
mmgen/opts.py

@@ -129,7 +129,10 @@ def override_globals_from_cfg_file(ucfg):
 		if d.name in g.cfg_file_opts:
 			ns = d.name.split('_')
 			if ns[0] in CoinProtocol.coins:
-				nse,tn = (ns[2:],True) if len(ns) > 2 and ns[1] == 'testnet' else (ns[1:],False)
+				nse,tn = (
+					(ns[2:],ns[1]=='testnet') if len(ns) > 2 and ns[1] in ('mainnet','testnet') else
+					(ns[1:],False)
+				)
 				cls = type(init_proto(ns[0],tn)) # no instance yet, so override _class_ attr
 				attr = '_'.join(nse)
 			else:

+ 8 - 1
mmgen/protocol.py

@@ -87,7 +87,6 @@ class CoinProtocol(MMGenObject):
 		base_proto = None
 		is_fork_of = None
 		networks   = ('mainnet','testnet','regtest')
-		ignore_daemon_version = False
 
 		def __init__(self,coin,name,network,tokensym=None):
 			self.coin       = coin.upper()
@@ -230,6 +229,7 @@ class CoinProtocol(MMGenObject):
 		halving_interval = 210000
 		max_halvings    = 64
 		start_subsidy   = 50
+		ignore_daemon_version = False
 
 		def hex2wif(self,hexpriv,pubkey_type,compressed): # input is preprocessed hex
 			sec = bytes.fromhex(hexpriv)
@@ -314,6 +314,7 @@ class CoinProtocol(MMGenObject):
 		caps = ()
 		coin_amt        = BCHAmt
 		max_tx_fee      = BCHAmt('0.1')
+		ignore_daemon_version = False
 
 		def pubhex2redeem_script(self,pubhex): raise NotImplementedError
 		def pubhex2segwitaddr(self,pubhex):    raise NotImplementedError
@@ -332,6 +333,7 @@ class CoinProtocol(MMGenObject):
 		forks = [
 			finfo(None,'','BTC',True) # activation: 494784
 		]
+		ignore_daemon_version = False
 
 	class B2XTestnet(B2X):
 		addr_ver_bytes     = { '6f': 'p2pkh', 'c4': 'p2sh' }
@@ -349,6 +351,7 @@ class CoinProtocol(MMGenObject):
 		bech32_hrp      = 'ltc'
 		avg_bdi         = 150
 		halving_interval = 840000
+		ignore_daemon_version = False
 
 	class LitecoinTestnet(Litecoin):
 		# addr ver nums same as Bitcoin testnet, except for 'p2sh'
@@ -387,6 +390,7 @@ class CoinProtocol(MMGenObject):
 		mmcaps        = ('key','addr','rpc','tx')
 		base_proto    = 'Ethereum'
 		avg_bdi       = 15
+		ignore_daemon_version = False
 
 		@property
 		def dcoin(self):
@@ -413,6 +417,8 @@ class CoinProtocol(MMGenObject):
 
 	class EthereumClassic(Ethereum):
 		chain_name = 'ethereum_classic' # chain_id 0x3d (61)
+		max_tx_fee = ETHAmt('0.005')
+		ignore_daemon_version = False
 
 	class EthereumClassicTestnet(EthereumClassic):
 		chain_name = 'classic-testnet' # aka Morden, chain_id 0x3e (62) (UNTESTED)
@@ -463,6 +469,7 @@ class CoinProtocol(MMGenObject):
 		avg_bdi        = 120
 		privkey_len    = 32
 		mmcaps         = ('key','addr')
+		ignore_daemon_version = False
 
 		def preprocess_key(self,sec,pubkey_type): # reduce key
 			from .ed25519 import l

+ 11 - 5
test/misc/cfg.py

@@ -13,8 +13,14 @@ msg('usr cfg: {}'.format(cu.fn))
 msg('sys cfg: {}'.format(cS.fn))
 msg('sample cfg: {}'.format(cs.fn))
 
-if cmd_args == ['parse_test']:
-	ps = cs.parse(parse_vars=True)
-	msg('parsed chunks: {}'.format(len(ps)))
-	pu = cu.parse()
-	msg('usr cfg: {}'.format(' '.join(['{}={}'.format(i.name,i.value) for i in pu])))
+if cmd_args:
+	if cmd_args[0] == 'parse_test':
+		ps = cs.parse(parse_vars=True)
+		msg('parsed chunks: {}'.format(len(ps)))
+		pu = cu.parse()
+		msg('usr cfg: {}'.format(' '.join(['{}={}'.format(i.name,i.value) for i in pu])))
+	elif cmd_args[0] == 'coin_specific_vars':
+		from mmgen.protocol import init_proto_from_opts
+		proto = init_proto_from_opts()
+		for varname in cmd_args[1:]:
+			print(f'{type(proto).__name__}.{varname}:',getattr(proto,varname))

+ 79 - 2
test/test_py_d/ts_cfg.py

@@ -29,14 +29,20 @@ class TestSuiteCfg(TestSuiteBase):
 		('altered_sample',     (40,'init with user-modified cfg sample file', [])),
 		('old_sample',         (40,'init with old v2 cfg sample file', [])),
 		('old_sample_bad_var', (40,'init with old v2 cfg sample file and bad variable in mmgen.cfg', [])),
+		('coin_specific_vars', (40,'test setting of coin-specific vars', [])),
+		('chain_names',        (40,'test setting of chain names', [])),
 	)
 
 	def __init__(self,trunner,cfgs,spawn):
 		os.environ['MMGEN_TEST_SUITE_CFGTEST'] = '1'
 		TestSuiteBase.__init__(self,trunner,cfgs,spawn)
 
-	def spawn_test(self,args=[]):
-		return self.spawn('test/misc/cfg.py',['--data-dir={}'.format(self.path('data_dir'))]+args,cmd_dir='.')
+	def spawn_test(self,args=[],extra_desc=''):
+		return self.spawn(
+			'test/misc/cfg.py',
+			[f'--data-dir={self.path("data_dir")}'] + args,
+			cmd_dir = '.',
+			extra_desc = extra_desc )
 
 	def path(self,id_str):
 		return {
@@ -148,3 +154,74 @@ class TestSuiteCfg(TestSuiteBase):
 		d = ['foo true','bar false']
 		write_to_file(self.path('usr'),'\n'.join(d) + '\n')
 		return self.old_sample_common(old_set=True)
+
+	def coin_specific_vars(self):
+		"""
+		ensure that derived classes explicitly set these variables
+		"""
+		d = [
+			'btc_max_tx_fee 1.2345',
+			'eth_max_tx_fee 5.4321',
+			'btc_ignore_daemon_version true',
+			'eth_ignore_daemon_version true'
+		]
+		write_to_file(self.path('usr'),'\n'.join(d) + '\n')
+		imsg(yellow('Wrote cfg file:\n  {}'.format('\n  '.join(d))))
+
+		for coin,res1_chk,res2_chk,res2_chk_eq in (
+			('BTC','True', '1.2345',True),
+			('LTC','False','1.2345',False),
+			('BCH','False','1.2345',False),
+			('ETH','True', '5.4321',True),
+			('ETC','False','5.4321',False)
+		):
+			t = self.spawn_test(
+				args = [
+					f'--coin={coin}',
+					'coin_specific_vars',
+					'ignore_daemon_version',
+					'max_tx_fee'
+				],
+				extra_desc=f'({coin})' )
+			res1 = t.expect_getend('ignore_daemon_version: ')
+			res2 = t.expect_getend('max_tx_fee: ')
+			assert res1 == res1_chk, f'{res1} != {res1_chk}'
+			if res2_chk_eq:
+				assert res2 == res2_chk, f'{res2} != {res2_chk}'
+			else:
+				assert res2 != res2_chk, f'{res2} == {res2_chk}'
+			t.read()
+			t.ok()
+
+		t.skip_ok = True
+		return t
+
+	def chain_names(self):
+
+		def run(chk,testnet):
+			for coin,chain_chk in (('ETH',chk),('ETC',None)):
+				t = self.spawn_test(
+					args       = [f'--coin={coin}',f'--testnet={(0,1)[testnet]}','coin_specific_vars','chain_name'],
+					extra_desc = f'({coin} testnet={testnet} chain={chain_chk})' )
+				chain = t.expect_getend('chain_name: ')
+				if chain_chk:
+					assert chain == chain_chk, f'{chain} != {chain_chk}'
+				else:
+					assert chain != chain_chk, f'{chain} == {chain_chk}'
+				t.read()
+				t.ok()
+			return t
+
+		write_to_file(self.path('usr'),'eth_mainnet_chain_name foobar\n')
+		imsg(yellow('Wrote cfg file: "eth_mainnet_chain_name foobar"'))
+		t = run('foobar',False)
+		t = run(None,True)
+
+		write_to_file(self.path('usr'),'eth_testnet_chain_name foobar\n')
+		imsg(yellow('Wrote cfg file: "eth_testnet_chain_name foobar"'))
+		t = run(None,False)
+		t = run('foobar',True)
+
+		t.skip_ok = True
+		return t
+