Browse Source

Minor changes and fixes

- eth/tw.py,main_txsign.py,protocol.py,rpc.py,tx.py: changes
- test.py,addr.py: fixes
MMGen 6 years ago
parent
commit
26210569f8
7 changed files with 45 additions and 34 deletions
  1. 1 1
      mmgen/addr.py
  2. 1 1
      mmgen/altcoins/eth/tw.py
  3. 3 2
      mmgen/main_txsign.py
  4. 4 1
      mmgen/protocol.py
  5. 1 0
      mmgen/rpc.py
  6. 30 26
      mmgen/tx.py
  7. 5 3
      test/test.py

+ 1 - 1
mmgen/addr.py

@@ -572,7 +572,7 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
 		else:
 		else:
 			bc,mt = g.proto.base_coin,self.al_id.mmtype
 			bc,mt = g.proto.base_coin,self.al_id.mmtype
 			l_coin = [] if bc == 'BTC' else [g.coin] if bc == 'ETH' else [bc]
 			l_coin = [] if bc == 'BTC' else [g.coin] if bc == 'ETH' else [bc]
-			l_type = [] if mt in ('L','E') else [mt.name.upper()]
+			l_type = [] if mt == 'E' or (mt == 'L' and not g.proto.is_testnet()) else [mt.name.upper()]
 			l_tn   = [] if not g.proto.is_testnet() else ['TESTNET']
 			l_tn   = [] if not g.proto.is_testnet() else ['TESTNET']
 			lbl_p2 = ':'.join(l_coin+l_type+l_tn)
 			lbl_p2 = ':'.join(l_coin+l_type+l_tn)
 			lbl = self.al_id.sid + ('',' ')[bool(lbl_p2)] + lbl_p2
 			lbl = self.al_id.sid + ('',' ')[bool(lbl_p2)] + lbl_p2

+ 1 - 1
mmgen/altcoins/eth/tw.py

@@ -29,7 +29,7 @@ from mmgen.addr import AddrData
 # No file locking - 2 processes accessing the wallet at the same time will corrupt it
 # No file locking - 2 processes accessing the wallet at the same time will corrupt it
 class EthereumTrackingWallet(TrackingWallet):
 class EthereumTrackingWallet(TrackingWallet):
 
 
-	data_dir = os.path.join(g.altcoin_data_dir,'eth')
+	data_dir = os.path.join(g.altcoin_data_dir,'eth',g.proto.data_subdir)
 	tw_file = os.path.join(data_dir,'tracking-wallet.json')
 	tw_file = os.path.join(data_dir,'tracking-wallet.json')
 
 
 	def __init__(self):
 	def __init__(self):

+ 3 - 2
mmgen/main_txsign.py

@@ -60,13 +60,14 @@ opts_data = lambda: {
 -v, --verbose         Produce more verbose output
 -v, --verbose         Produce more verbose output
 -V, --vsize-adj=   f  Adjust transaction's estimated vsize by factor 'f'
 -V, --vsize-adj=   f  Adjust transaction's estimated vsize by factor 'f'
 -y, --yes             Answer 'yes' to prompts, suppress non-essential output
 -y, --yes             Answer 'yes' to prompts, suppress non-essential output
-""".format(
+""",
+	'options_fmt_args': lambda: dict(
 		g=g,pnm=g.proj_name,pnl=g.proj_name.lower(),dn=g.proto.daemon_name,
 		g=g,pnm=g.proj_name,pnl=g.proj_name.lower(),dn=g.proto.daemon_name,
 		kgs=' '.join(['{}:{}'.format(n,k) for n,k in enumerate(g.key_generators,1)]),
 		kgs=' '.join(['{}:{}'.format(n,k) for n,k in enumerate(g.key_generators,1)]),
 		kg=g.key_generator,
 		kg=g.key_generator,
 		cu=g.coin
 		cu=g.coin
 		),
 		),
-	'notes': '\n' + help_notes('txsign')
+	'notes': lambda: '\n' + help_notes('txsign')
 }
 }
 
 
 infiles = opts.init(opts_data,add_opts=['b16'])
 infiles = opts.init(opts_data,add_opts=['b16'])

+ 4 - 1
mmgen/protocol.py

@@ -298,11 +298,13 @@ class EthereumProtocol(DummyWIF,BitcoinProtocolAddrgen):
 	base_coin = 'ETH'
 	base_coin = 'ETH'
 	pubkey_type = 'std' # required by DummyWIF
 	pubkey_type = 'std' # required by DummyWIF
 
 
+	data_subdir = ''
 	daemon_name = 'parity'
 	daemon_name = 'parity'
 	rpc_port    = 8545
 	rpc_port    = 8545
 	mmcaps      = ('key','addr','rpc')
 	mmcaps      = ('key','addr','rpc')
 	coin_amt    = ETHAmt
 	coin_amt    = ETHAmt
 
 
+
 	@classmethod
 	@classmethod
 	def verify_addr(cls,addr,hex_width,return_dict=False):
 	def verify_addr(cls,addr,hex_width,return_dict=False):
 		from mmgen.util import is_hex_str_lc
 		from mmgen.util import is_hex_str_lc
@@ -317,7 +319,8 @@ class EthereumProtocol(DummyWIF,BitcoinProtocolAddrgen):
 		assert not p2sh,'Ethereum has no P2SH address format'
 		assert not p2sh,'Ethereum has no P2SH address format'
 		return pubkey_hash
 		return pubkey_hash
 
 
-class EthereumTestnetProtocol(EthereumProtocol): pass
+class EthereumTestnetProtocol(EthereumProtocol):
+	data_subdir = 'testnet'
 class EthereumClassicProtocol(EthereumProtocol):
 class EthereumClassicProtocol(EthereumProtocol):
 	name   = 'ethereum_classic'
 	name   = 'ethereum_classic'
 	mmcaps = ('key','addr')
 	mmcaps = ('key','addr')

+ 1 - 0
mmgen/rpc.py

@@ -235,6 +235,7 @@ class EthereumRPCConnection(CoinDaemonRPCConnection):
 		'parity_minGasPrice',
 		'parity_minGasPrice',
 		'parity_mode',
 		'parity_mode',
 		'parity_netPeers',
 		'parity_netPeers',
+		'parity_nextNonce',
 		'parity_nodeKind',
 		'parity_nodeKind',
 		'parity_nodeName',
 		'parity_nodeName',
 		'parity_pendingTransactions',
 		'parity_pendingTransactions',

+ 30 - 26
mmgen/tx.py

@@ -479,7 +479,7 @@ class MMGenTX(MMGenObject):
 	def fee_abs2rel(self,abs_fee):
 	def fee_abs2rel(self,abs_fee):
 		return int(abs_fee/g.proto.coin_amt.min_coin_unit/self.estimate_size())
 		return int(abs_fee/g.proto.coin_amt.min_coin_unit/self.estimate_size())
 
 
-	def get_rel_fee_from_network(self): # rel_fee is BTC/kB
+	def get_rel_fee_from_network(self): # rel_fee is in BTC/kB
 		try:
 		try:
 			ret = g.rpch.estimatesmartfee(opt.tx_confs,on_fail='raise')
 			ret = g.rpch.estimatesmartfee(opt.tx_confs,on_fail='raise')
 			rel_fee = ret['feerate'] if 'feerate' in ret else -2
 			rel_fee = ret['feerate'] if 'feerate' in ret else -2
@@ -496,24 +496,8 @@ class MMGenTX(MMGenObject):
 		return g.proto.coin_amt(int(amt)*tx_size*getattr(g.proto.coin_amt,units[unit])) \
 		return g.proto.coin_amt(int(amt)*tx_size*getattr(g.proto.coin_amt,units[unit])) \
 			if tx_size else None
 			if tx_size else None
 
 
-	# given tx size and absolute fee or fee spec, return absolute fee
-	# relative fee is N+<first letter of unit name>
-	def process_fee_spec(self,tx_fee,tx_size,on_fail='throw'):
-		import re
-		units = dict((u[0],u) for u in g.proto.coin_amt.units)
-		pat = r'([1-9][0-9]*)({})'.format('|'.join(units.keys()))
-		if g.proto.coin_amt(tx_fee,on_fail='silent'):
-			return g.proto.coin_amt(tx_fee)
-		elif re.match(pat,tx_fee):
-			return self.convert_fee_spec(tx_size,units,*re.match(pat,tx_fee).groups())
-		else:
-			if on_fail == 'return':
-				return False
-			elif on_fail == 'throw':
-				assert False, "'{}': invalid tx-fee argument".format(tx_fee)
-
 	# given network fee estimate in BTC/kB, return absolute fee using estimated tx size
 	# given network fee estimate in BTC/kB, return absolute fee using estimated tx size
-	def calculate_fee(self,rel_fee,fe_type=None):
+	def fee_est2abs(self,rel_fee,fe_type=None):
 		tx_size = self.estimate_size()
 		tx_size = self.estimate_size()
 		ret = g.proto.coin_amt(rel_fee) * opt.tx_fee_adj * tx_size / 1024
 		ret = g.proto.coin_amt(rel_fee) * opt.tx_fee_adj * tx_size / 1024
 		if opt.verbose:
 		if opt.verbose:
@@ -543,6 +527,23 @@ class MMGenTX(MMGenObject):
 			return abs_fee
 			return abs_fee
 
 
 	# non-coin-specific fee routines
 	# non-coin-specific fee routines
+
+	# given tx size and absolute fee or fee spec, return absolute fee
+	# relative fee is N+<first letter of unit name>
+	def process_fee_spec(self,tx_fee,tx_size,on_fail='throw'):
+		import re
+		units = dict((u[0],u) for u in g.proto.coin_amt.units)
+		pat = r'([1-9][0-9]*)({})'.format('|'.join(units.keys()))
+		if g.proto.coin_amt(tx_fee,on_fail='silent'):
+			return g.proto.coin_amt(tx_fee)
+		elif re.match(pat,tx_fee):
+			return self.convert_fee_spec(tx_size,units,*re.match(pat,tx_fee).groups())
+		else:
+			if on_fail == 'return':
+				return False
+			elif on_fail == 'throw':
+				assert False, "'{}': invalid tx-fee argument".format(tx_fee)
+
 	def get_usr_fee_interactive(self,tx_fee=None,desc='Starting'):
 	def get_usr_fee_interactive(self,tx_fee=None,desc='Starting'):
 		abs_fee = None
 		abs_fee = None
 		while True:
 		while True:
@@ -578,7 +579,7 @@ class MMGenTX(MMGenObject):
 					have_estimate_fail.append(True)
 					have_estimate_fail.append(True)
 				start_fee = None
 				start_fee = None
 			else:
 			else:
-				start_fee = self.calculate_fee(rel_fee,fe_type)
+				start_fee = self.fee_est2abs(rel_fee,fe_type)
 
 
 		return self.get_usr_fee_interactive(start_fee,desc=desc)
 		return self.get_usr_fee_interactive(start_fee,desc=desc)
 
 
@@ -852,6 +853,13 @@ class MMGenTX(MMGenObject):
 						msg('  {}{}'.format(t,('',' in mempool')[s]))
 						msg('  {}{}'.format(t,('',' in mempool')[s]))
 				die(0,'')
 				die(0,'')
 
 
+	def confirm_send(self):
+		m1 = ("Once this transaction is sent, there's no taking it back!",'')[bool(opt.quiet)]
+		m2 = 'broadcast this transaction to the {} network'.format(g.chain.upper())
+		m3 = ('YES, I REALLY WANT TO DO THIS','YES')[bool(opt.quiet or opt.yes)]
+		confirm_or_exit(m1,m2,m3)
+		msg('Sending transaction')
+
 	def send(self,prompt_user=True,exit_on_fail=False):
 	def send(self,prompt_user=True,exit_on_fail=False):
 
 
 		if not self.marked_signed():
 		if not self.marked_signed():
@@ -869,17 +877,12 @@ class MMGenTX(MMGenObject):
 
 
 		if self.get_fee_from_tx() > g.proto.max_tx_fee:
 		if self.get_fee_from_tx() > g.proto.max_tx_fee:
 			die(2,'Transaction fee ({}) greater than {} max_tx_fee ({} {})!'.format(
 			die(2,'Transaction fee ({}) greater than {} max_tx_fee ({} {})!'.format(
-				self.get_fee_from_tx(),g.proto.name.capitalize(),g.proto.max_tx_fee,g.coin.upper()))
+				self.get_fee_from_tx(),g.proto.name.capitalize(),g.proto.max_tx_fee,g.coin))
 
 
 		self.get_status()
 		self.get_status()
 
 
-		if prompt_user:
-			m1 = ("Once this transaction is sent, there's no taking it back!",'')[bool(opt.quiet)]
-			m2 = 'broadcast this transaction to the {} network'.format(g.chain.upper())
-			m3 = ('YES, I REALLY WANT TO DO THIS','YES')[bool(opt.quiet or opt.yes)]
-			confirm_or_exit(m1,m2,m3)
+		if prompt_user: self.confirm_send()
 
 
-		msg('Sending transaction')
 		ret = None if bogus_send else g.rpch.sendrawtransaction(self.hex,on_fail='return')
 		ret = None if bogus_send else g.rpch.sendrawtransaction(self.hex,on_fail='return')
 
 
 		from mmgen.rpc import rpc_error,rpc_errmsg
 		from mmgen.rpc import rpc_error,rpc_errmsg
@@ -1162,6 +1165,7 @@ class MMGenTX(MMGenObject):
 		except Exception as e:
 		except Exception as e:
 			die(2,'Invalid {} in transaction file: {}'.format(desc,e[0]))
 			die(2,'Invalid {} in transaction file: {}'.format(desc,e[0]))
 
 
+		# test doesn't work for Ethereum
 		if not self.chain and not self.inputs[0].addr.is_for_chain('testnet'):
 		if not self.chain and not self.inputs[0].addr.is_for_chain('testnet'):
 			self.chain = 'mainnet'
 			self.chain = 'mainnet'
 
 

+ 5 - 3
test/test.py

@@ -2525,8 +2525,9 @@ class MMGenTestSuite(object):
 		for mmtype in g.proto.mmtypes:
 		for mmtype in g.proto.mmtypes:
 			desc = MMGenAddrType.mmtypes[mmtype]['name']
 			desc = MMGenAddrType.mmtypes[mmtype]['name']
 			fn = os.path.join(self.regtest_user_dir(user),
 			fn = os.path.join(self.regtest_user_dir(user),
-				u'{}{}{}[{}]{x}.addrs'.format(sid,altcoin_pfx,id_strs[desc],addr_range,
-												x=u'-α' if g.debug_utf8 else ''))
+				u'{}{}{}[{}]{x}.testnet.addrs'.format(
+					sid,altcoin_pfx,id_strs[desc],addr_range,
+					x=u'-α' if g.debug_utf8 else ''))
 			if mmtype == g.proto.mmtypes[0] and user == 'bob':
 			if mmtype == g.proto.mmtypes[0] and user == 'bob':
 				psave = g.proto
 				psave = g.proto
 				g.proto = CoinProtocol(g.coin,True)
 				g.proto = CoinProtocol(g.coin,True)
@@ -2634,7 +2635,8 @@ class MMGenTestSuite(object):
 
 
 	def get_addr_from_regtest_addrlist(self,user,sid,mmtype,idx,addr_range='1-5'):
 	def get_addr_from_regtest_addrlist(self,user,sid,mmtype,idx,addr_range='1-5'):
 		id_str = { 'L':'', 'S':'-S', 'C':'-C' }[mmtype]
 		id_str = { 'L':'', 'S':'-S', 'C':'-C' }[mmtype]
-		ext = u'{}{}{}[{}]{x}.addrs'.format(sid,altcoin_pfx,id_str,addr_range,x=u'-α' if g.debug_utf8 else '')
+		ext = u'{}{}{}[{}]{x}.testnet.addrs'.format(
+			sid,altcoin_pfx,id_str,addr_range,x=u'-α' if g.debug_utf8 else '')
 		fn = get_file_with_ext(ext,self.regtest_user_dir(user),no_dot=True)
 		fn = get_file_with_ext(ext,self.regtest_user_dir(user),no_dot=True)
 		silence()
 		silence()
 		psave = g.proto
 		psave = g.proto