Browse Source

coin protocol, txview: minor cleanups

The MMGen Project 4 years ago
parent
commit
28b4f56919
3 changed files with 53 additions and 46 deletions
  1. 1 1
      mmgen/common.py
  2. 20 21
      mmgen/protocol.py
  3. 32 24
      mmgen/tx.py

+ 1 - 1
mmgen/common.py

@@ -193,7 +193,7 @@ Network-estimated fees will be multiplied by the value of '--tx-fee-adj',
 if specified.
 
 Ages of transactions are approximate based on an average block discovery
-interval of one per {g.proto.secs_per_block} seconds.
+interval of one per {g.proto.avg_bdi} seconds.
 
 All addresses on the command line can be either {pnu} addresses or {pnm}
 addresses of the form <seed ID>:<index>.

+ 20 - 21
mmgen/protocol.py

@@ -110,11 +110,10 @@ class CoinProtocol(MMGenObject):
 		dfl_mmtype      = 'L'
 		data_subdir     = ''
 		rpc_port        = 8332
-		secs_per_block  = 600
 		coin_amt        = BTCAmt
 		max_tx_fee      = BTCAmt('0.003')
-		daemon_data_dir = os.path.join(os.getenv('APPDATA'),'Bitcoin') if g.platform == 'win' \
-							else os.path.join(g.home_dir,'.bitcoin')
+		daemon_data_dir = ( os.path.join(os.getenv('APPDATA'),'Bitcoin') if g.platform == 'win' else
+							os.path.join(g.home_dir,'.bitcoin') )
 		daemon_data_subdir = ''
 		sighash_type    = 'ALL'
 		block0          = '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'
@@ -248,8 +247,8 @@ class CoinProtocol(MMGenObject):
 		is_fork_of      = 'Bitcoin'
 		# TODO: assumes MSWin user installs in custom dir 'Bitcoin_ABC'
 		daemon_name     = 'bitcoind-abc'
-		daemon_data_dir = os.path.join(os.getenv('APPDATA'),'Bitcoin_ABC') if g.platform == 'win' \
-							else os.path.join(g.home_dir,'.bitcoin-abc')
+		daemon_data_dir = ( os.path.join(os.getenv('APPDATA'),'Bitcoin_ABC') if g.platform == 'win' else
+							os.path.join(g.home_dir,'.bitcoin-abc') )
 		rpc_port        = 8442
 		mmtypes         = ('L','C')
 		sighash_type    = 'ALL|FORKID'
@@ -276,8 +275,8 @@ class CoinProtocol(MMGenObject):
 	class B2X(Bitcoin):
 		is_fork_of      = 'Bitcoin'
 		daemon_name     = 'bitcoind-2x'
-		daemon_data_dir = os.path.join(os.getenv('APPDATA'),'Bitcoin_2X') if g.platform == 'win' \
-							else os.path.join(g.home_dir,'.bitcoin-2x')
+		daemon_data_dir = ( os.path.join(os.getenv('APPDATA'),'Bitcoin_2X') if g.platform == 'win' else
+							os.path.join(g.home_dir,'.bitcoin-2x') )
 		rpc_port        = 8338
 		coin_amt        = B2XAmt
 		max_tx_fee      = B2XAmt('0.1')
@@ -295,19 +294,18 @@ class CoinProtocol(MMGenObject):
 	class Litecoin(Bitcoin):
 		block0          = '12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2'
 		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')
+		daemon_data_dir = ( os.path.join(os.getenv('APPDATA'),'Litecoin') if g.platform == 'win' else
+							os.path.join(g.home_dir,'.litecoin') )
 		addr_ver_bytes  = { '30': 'p2pkh', '32': 'p2sh', '05': 'p2sh' } # new p2sh ver 0x32 must come first
 		wif_ver_num     = { 'std': 'b0' }
 		mmtypes         = ('L','C','S','B')
-		secs_per_block  = 150
 		rpc_port        = 9332
 		coin_amt        = LTCAmt
 		max_tx_fee      = LTCAmt('0.3')
 		base_coin       = 'LTC'
 		forks           = []
 		bech32_hrp      = 'ltc'
-		avg_bdi         = 2 * 60
+		avg_bdi         = 150
 
 	class LitecoinTestnet(Litecoin):
 		# addr ver nums same as Bitcoin testnet, except for 'p2sh'
@@ -327,7 +325,7 @@ class CoinProtocol(MMGenObject):
 	class BitcoinAddrgenTestnet(BitcoinTestnet):
 		mmcaps = ('key','addr')
 
-	class DummyWIF(object):
+	class DummyWIF:
 
 		def hex2wif(self,hexpriv,pubkey_type,compressed):
 			n = self.name.capitalize()
@@ -358,16 +356,18 @@ class CoinProtocol(MMGenObject):
 		sign_mode     = 'standalone'
 		caps          = ('token',)
 		base_proto    = 'Ethereum'
+		avg_bdi       = 15
 
 		def parse_addr(self,addr):
 			from .util import is_hex_str_lc
 			if is_hex_str_lc(addr) and len(addr) == self.addr_len * 2:
 				return parsed_addr( bytes.fromhex(addr), 'ethereum' )
-			if g.debug: Msg("Invalid address '{}'".format(addr))
+			if g.debug:
+				Msg(f'Invalid address: {addr}')
 			return False
 
 		def pubhash2addr(self,pubkey_hash,p2sh):
-			assert len(pubkey_hash) == 40,'{}: invalid length for pubkey hash'.format(len(pubkey_hash))
+			assert len(pubkey_hash) == 40, f'{len(pubkey_hash)}: invalid length for pubkey hash'
 			assert not p2sh,'Ethereum has no P2SH address format'
 			return pubkey_hash
 
@@ -390,6 +390,7 @@ class CoinProtocol(MMGenObject):
 		wif_ver_num    = { 'std': '80', 'zcash_z': 'ab36' }
 		mmtypes        = ('L','C','Z')
 		dfl_mmtype     = 'L'
+		avg_bdi        = 75
 
 		def get_addr_len(self,addr_fmt):
 			return (20,64)[addr_fmt in ('zcash_z','viewkey')]
@@ -413,7 +414,7 @@ class CoinProtocol(MMGenObject):
 		wif_ver_num  = { 'std': 'ef', 'zcash_z': 'ac08' }
 		addr_ver_bytes = { '1d25': 'p2pkh', '1cba': 'p2sh', '16b6': 'zcash_z', 'a8ac0c': 'viewkey' }
 
-# https://github.com/monero-project/monero/blob/master/src/cryptonote_config.h
+	# https://github.com/monero-project/monero/blob/master/src/cryptonote_config.h
 	class Monero(DummyWIF,BitcoinAddrgen):
 		base_coin      = 'XMR'
 		addr_ver_bytes = { '12': 'monero', '2a': 'monero_sub' }
@@ -422,6 +423,7 @@ class CoinProtocol(MMGenObject):
 		mmtypes        = ('M',)
 		dfl_mmtype     = 'M'
 		pubkey_type    = 'monero' # required by DummyWIF
+		avg_bdi        = 120
 
 		def preprocess_key(self,sec,pubkey_type): # reduce key
 			from .ed25519 import l
@@ -447,7 +449,7 @@ class CoinProtocol(MMGenObject):
 				from .keccak import keccak_256
 
 			chk = keccak_256(ret[:-4]).digest()[:4]
-			assert ret[-4:] == chk,'{}: incorrect checksum.  Correct value: {}'.format(ret[-4:].hex(),chk.hex())
+			assert ret[-4:] == chk, f'{ret[-4:].hex()}: incorrect checksum.  Correct value: {chk.hex()}'
 
 			return self.parse_addr_bytes(ret)
 
@@ -506,11 +508,9 @@ def init_genonly_altcoins(usr_coin=None,testnet=False):
 
 		cinfo = data[network][0]
 		if not cinfo:
-			m = '{!r}: unrecognized coin for network {}'
-			raise ValueError(m.format(usr_coin.upper(),network.upper()))
+			raise ValueError(f'{usr_coin.upper()!r}: unrecognized coin for network {network.upper()}')
 		if cinfo.trust_level == -1:
-			m = '{!r}: unsupported (disabled) coin for network {}'
-			raise ValueError(m.format(usr_coin.upper(),network.upper()))
+			raise ValueError(f'{usr_coin.upper()!r}: unsupported (disabled) coin for network {network.upper()}')
 
 		trust_level = cinfo.trust_level
 
@@ -549,7 +549,6 @@ def make_init_genonly_altcoins_str(data):
 			yield make_proto(e)
 		for e in data['testnet']:
 			yield make_proto(e,testnet=True)
-		yield ''
 
 		for e in data['mainnet']:
 			proto,coin = e.name,e.symbol

+ 32 - 24
mmgen/tx.py

@@ -1020,22 +1020,22 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 	def format_view_body(self,blockcount,nonmm_str,max_mmwid,enl,terse,sort):
 
 		if sort not in self.view_sort_orders:
-			m = '{!r}: invalid transaction view sort order.  Valid options: {}'
-			die(1,m.format(sort,','.join(self.view_sort_orders)))
+			die(1,f'{sort!r}: invalid transaction view sort order. Valid options: {{}}'.format(
+					','.join(self.view_sort_orders) ))
 
 		def format_io(desc):
 			io = getattr(self,desc)
-			ip = desc == 'inputs'
-			out = desc.capitalize() + ':\n' + enl
+			is_input = desc == 'inputs'
+			yield desc.capitalize() + ':\n' + enl
 			addr_w = max(len(e.addr) for e in io)
-			confs_per_day = 60*60*24 // g.proto.secs_per_block
+			confs_per_day = 60*60*24 // g.proto.avg_bdi
 			io_sorted = {
 				# prepend '/' (sorts before '0') to ensure non-MMGen addrs are displayed first
 				'addr': lambda: sorted(io,key=lambda o: o.mmid.sort_key if o.mmid else '/'+o.addr),
 				'raw':  lambda: io
 			}[sort]
 			for n,e in enumerate(io_sorted()):
-				if ip and blockcount:
+				if is_input and blockcount:
 					confs = e.confs + blockcount - self.blockcount
 					days = int(confs // confs_per_day)
 				if e.mmid:
@@ -1043,30 +1043,38 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
 						width=max_mmwid,
 						encl='()',
 						color=True,
-						append_chars=('',' (chg)')[bool(not ip and e.is_chg and terse)],
+						append_chars=('',' (chg)')[bool(not is_input and e.is_chg and terse)],
 						append_color='green')
 				else:
 					mmid_fmt = MMGenID.fmtc(nonmm_str,width=max_mmwid,color=True)
 				if terse:
-					out += '{:3} {} {} {} {}\n'.format(n+1,
+					yield '{:3} {} {} {} {}\n'.format(
+						n+1,
 						e.addr.fmt(color=True,width=addr_w),
-						mmid_fmt,e.amt.hl(),g.dcoin)
+						mmid_fmt,
+						e.amt.hl(),
+						g.dcoin )
 				else:
-					icommon = [
-						((n+1,'')[ip],'address:',e.addr.fmt(color=True,width=addr_w) + ' '+mmid_fmt),
-						('','comment:',e.label.hl() if e.label else ''),
-						('','amount:','{} {}'.format(e.amt.hl(),g.dcoin))]
-					items = [(n+1, 'tx,vout:','{},{}'.format(e.txid,e.vout))] + icommon + [
-						('','confirmations:','{} (around {} days)'.format(confs,days) if blockcount else '')
-					] if ip else icommon + [
-						('','change:',green('True') if e.is_chg else '')]
-					out += '\n'.join([('{:>3} {:<8} {}'.format(*d)) for d in items if d[2]]) + '\n\n'
-			return out
-
-		md = {'raw':'raw','addr':'address'}
-		m = 'Displaying inputs and outputs in {} sort order'.format(md[sort])
-
-		return m + ('\n\n','\n')[terse] + format_io('inputs') + format_io('outputs')
+					def gen():
+						if is_input:
+							yield (n+1,      'tx,vout:', e.txid + ',' + str(e.vout))
+							yield ('',       'address:', e.addr.fmt(color=True,width=addr_w) + ' ' + mmid_fmt)
+						else:
+							yield (n+1,      'address:', e.addr.fmt(color=True,width=addr_w) + ' ' + mmid_fmt)
+						if e.label:
+							yield ('',       'comment:', e.label.hl())
+						yield     ('',       'amount:',  e.amt.hl() + ' ' + g.dcoin)
+						if is_input and blockcount:
+							yield ('',       'confirmations:', f'{confs} (around {days} days)')
+						if not is_input and e.is_chg:
+							yield ('',       'change:',  green('True'))
+					yield '\n'.join('{:>3} {:<8} {}'.format(*d) for d in gen()) + '\n\n'
+
+		return (
+			'Displaying inputs and outputs in {} sort order'.format({'raw':'raw','addr':'address'}[sort])
+			+ ('\n\n','\n')[terse]
+			+ ''.join(format_io('inputs'))
+			+ ''.join(format_io('outputs')) )
 
 	def format_view_rel_fee(self,terse):
 		return ' ({} {})\n'.format(