Browse Source

mmgen-blocks-info: fixes, cleanups

The MMGen Project 4 years ago
parent
commit
078ba6dad6
1 changed files with 77 additions and 80 deletions
  1. 77 80
      mmnode-blocks-info

+ 77 - 80
mmnode-blocks-info

@@ -20,32 +20,30 @@
 mmnode-blocks-info: Display information about a block or range of blocks
 """
 
-import time,re
+import re
 from collections import namedtuple
+from time import strftime,gmtime
+
 from mmgen.common import *
+from mmgen.util import secs_to_hms
 from decimal import Decimal
 
 class local_vars: pass
 
 class BlocksInfo:
 
-	first = None
-	last = None
-	nblocks = None
 	total_bytes = 0
 	total_weight = 0
-	t_start  = None
-	t_prev   = None
-	t_cur    = None
 
 	bf = namedtuple('block_info_fields',['hdr1','hdr2','fs','bs_key','varname','deps','key'])
 	# bs=getblockstats(), bh=getblockheader()
+	# 'getblockstats' raises exception on Genesis Block!
 	# If 'bs_key' is set, it's included in self.bs_keys instead of 'key'
 	fields = {
 		'block':     bf('',     'Block',    '{:<6}',  None,                 'height',[],     None),
 		'hash':      bf('',     'Hash',     '{:<64}', None,                 'H',     [],     None),
-		'date':      bf('',     'Date',     '{:<19}', None,                 'df',    ['bs'], None),
-		'interval':  bf('Solve','Time ',    '{:>6}',  None,                 'if',    ['bs'], None),
+		'date':      bf('',     'Date',     '{:<19}', None,                 'df',    [],     None),
+		'interval':  bf('Solve','Time ',    '{:>6}',  None,                 'td',    [],     None),
 		'size':      bf('',     'Size',     '{:>7}',  None,                 'bs',    [],     'total_size'),
 		'weight':    bf('',     'Weight',   '{:>7}',  None,                 'bs',    [],     'total_weight'),
 		'utxo_inc':  bf(' UTXO',' Incr',    '{:>5}',  None,                 'bs',    [],     'utxo_increase'),
@@ -66,17 +64,15 @@ class BlocksInfo:
 	dfl_fields  = ['block','date','interval','subsidy','totalfee','size','weight','fee50','fee25','fee10','version']
 
 	funcs = {
-		'df': lambda self,loc: time.strftime('%Y-%m-%d %X',time.gmtime(self.t_cur)),
-		'if': lambda self,loc: (
-			'-{:02}:{:02}'.format(abs(loc.t_diff)//60,abs(loc.t_diff)%60) if loc.t_diff < 0 else
-			' {:02}:{:02}'.format(loc.t_diff//60,loc.t_diff%60) ),
+		'df': lambda self,loc: strftime('%Y-%m-%d %X',gmtime(self.t_cur)),
+		'td': lambda self,loc: (
+			'-{:02}:{:02}'.format(abs(self.t_diff)//60,abs(self.t_diff)%60) if self.t_diff < 0 else
+			' {:02}:{:02}'.format(self.t_diff//60,self.t_diff%60) ),
 		'tf': lambda self,loc: '{:.8f}'.format(loc.bs["totalfee"] * Decimal('0.00000001')),
-		'bh': lambda self,loc: loc.hdr,
 		'fp': lambda self,loc: loc.bs['feerate_percentiles'],
-		'su': lambda self,loc: str(loc.bs['subsidy'] * Decimal('0.00000001')).rstrip('0'),
+		'su': lambda self,loc: str(loc.bs['subsidy'] * Decimal('0.00000001')).rstrip('0').rstrip('.'),
 	}
 
-
 	def __init__(self):
 
 		self.get_block_range()
@@ -94,7 +90,7 @@ class BlocksInfo:
 		self.deps  = set(' '.join(v.varname + ' ' + ' '.join(v.deps) for v in self.fvals).split())
 
 		self.bs_keys = [(v.bs_key or v.key) for v in self.fvals if v.bs_key or v.varname == 'bs']
-		self.bs_keys.extend(['total_size','time'])
+		self.bs_keys.extend(['total_size','total_weight'])
 
 		self.ufuncs = {v.varname:self.funcs[v.varname] for v in self.fvals if v.varname in self.funcs}
 
@@ -136,7 +132,6 @@ class BlocksInfo:
 
 		self.first = first
 		self.last = last
-		self.nblocks = last - first + 1
 
 	async def run(self):
 
@@ -144,6 +139,12 @@ class BlocksInfo:
 		hashes = await c.gathered_call('getblockhash',[(height,) for height in heights])
 		hdrs   = await c.gathered_call('getblockheader',[(H,) for H in hashes])
 
+		self.t_start = hdrs[0]['time']
+		self.t_cur = (
+			self.t_start if heights[0] == 0 else
+			(await c.call('getblockheader',await c.call('getblockhash',heights[0]-1)))['time']
+		)
+
 		for height in heights:
 			await self.process_block(height,hashes.pop(0),hdrs.pop(0))
 
@@ -151,31 +152,21 @@ class BlocksInfo:
 		loc = local_vars()
 		loc.height = height
 		loc.H = H
-		loc.hdr = hdr
+		loc.bh = hdr
+		
+		self.t_diff = hdr['time'] - self.t_cur
+		self.t_cur  = hdr['time']
+
 		if 'bs' in self.deps:
 			loc.bs = await c.call('getblockstats',H,self.bs_keys)
 			self.total_bytes += loc.bs['total_size']
 			self.total_weight += loc.bs['total_weight']
-			self.t_cur = loc.bs['time']
-			if self.t_start == None:
-				if height == 0:
-					b_prev = loc.bs
-				else:
-					bH = await c.call('getblockhash',height-1)
-					b_prev = await c.call('getblockstats',bH)
-				self.t_start = loc.bs['time']
-				self.t_prev = b_prev['time']
-			loc.t_diff = self.t_cur - self.t_prev
-			self.t_prev = self.t_cur
 
 		if opt.summary:
 			return
 
 		for varname,func in self.ufuncs.items():
-			ret = func(self,loc)
-			if type(ret).__name__ == 'coroutine':
-				ret = await ret
-			setattr(loc,varname,ret)
+			setattr(loc,varname,func(self,loc))
 
 		if opt.miner_info:
 			miner_info = await self.get_miner_string(H)
@@ -212,79 +203,85 @@ class BlocksInfo:
 		if opt.miner_info:
 			hdr1.append('     ')
 			hdr2.append('Miner')
-		Msg(self.fs.format(*hdr1))
+		if ''.join(hdr1).replace(' ',''):
+			Msg(self.fs.format(*hdr1))
 		Msg(self.fs.format(*hdr2))
 
 	async def print_summary(self):
-		from mmgen.util import secs_to_hms
 		tip = c.blockcount
-		rel = tip % 2016
 
-		if rel:
-			HA,HB = await c.gathered_call('getblockhash',([tip-rel],[tip]))
-			hA,hB = await c.gathered_call('getblockheader',([HA],[HB]))
-			bdi =  (hB['time']-hA['time']) / rel
-			adj_pct = ((600 / bdi) - 1) * 100
-			Msg_r(fmt(f"""
-				Current height:    {tip}
-				Next diff adjust:  {tip-rel+2016} (in {2016-rel} blocks [{((2016-rel)*bdi)/86400:.2f} days])
-				BDI (cur period):  {bdi/60:.2f} min
-				Est. diff adjust: {adj_pct:+.2f}%
-				"""))
-		else:
-			Msg_r(fmt(f"""
-				Current height:    {tip}
-				Next diff adjust:  {tip-rel+2016} (in {2016-rel} blocks)
-				"""))
+		if self.last == tip:
+			rel = tip % 2016
+			if rel:
+				HA,HB = await c.gathered_call('getblockhash',([tip-rel],[tip]))
+				hA,hB = await c.gathered_call('getblockheader',([HA],[HB]))
+				bdi =  (hB['time']-hA['time']) / rel
+				adj_pct = ((600 / bdi) - 1) * 100
+				Msg(fmt(f"""
+					Current height:    {tip}
+					Next diff adjust:  {tip-rel+2016} (in {2016-rel} blocks [{((2016-rel)*bdi)/86400:.2f} days])
+					BDI (cur period):  {bdi/60:.2f} min
+					Est. diff adjust: {adj_pct:+.2f}%
+					"""))
+			else:
+				Msg(fmt(f"""
+					Current height:    {tip}
+					Next diff adjust:  {tip-rel+2016} (in {2016-rel} blocks)
+					"""))
 
-		Msg('\nRange:      {}-{} ({} blocks [{}])'.format(
+		nblocks = self.last - self.first + 1
+
+		Msg('Range:      {}-{} ({} blocks [{}])'.format(
 			self.first,
 			self.last,
-			self.nblocks,
+			nblocks,
 			secs_to_hms(self.t_cur - self.t_start) ))
 
-		if 'bs' in self.deps:
-			if self.nblocks > 1:
-				elapsed = self.t_cur - self.t_start
-				ac = int(elapsed / self.nblocks)
-				rate = (self.total_bytes / 10000) / (elapsed / 36)
-				Msg_r (fmt(f"""
-					Avg size:   {self.total_bytes//self.nblocks} bytes
-					Avg weight: {self.total_weight//self.nblocks} bytes
-					MB/hr:      {rate:0.4f}
-					Avg BDI:    {ac/60:.2f} min
-					"""))
+		if 'bs' in self.deps and nblocks > 1:
+			elapsed = self.t_cur - self.t_start
+			ac = int(elapsed / nblocks)
+			rate = (self.total_bytes / 10000) / (elapsed / 36)
+			Msg_r(fmt(f"""
+				Avg size:   {self.total_bytes//nblocks} bytes
+				Avg weight: {self.total_weight//nblocks} bytes
+				MB/hr:      {rate:0.4f}
+				Avg BDI:    {ac/60:.2f} min
+				"""))
 
 opts_data = {
 	'sets': [
-		('raw_miner_info',True,'miner_info',True),
-		('summary',True,'raw_miner_info',False),
-		('summary',True,'miner_info',False)
+		('raw_miner_info', True, 'miner_info',     True),
+		('summary',        True, 'raw_miner_info', False),
+		('summary',        True, 'miner_info',     False),
+		('hashes',         True, 'fields',         'block,hash'),
+		('hashes',         True, 'no_summary',     True),
 	],
 	'text': {
-		'desc':    'Display information about a range of blocks',
-		'usage':   '[opts] +<last n blocks>|<block num>|<block num range>',
+		'desc':    'Display information about a block or range of blocks',
+		'usage':   '[opts] +<last N blocks>|<block num>[-<block num>]',
 		'options': """
 -h, --help            Print this help message
 --, --longhelp        Print help message for long options (common options)
 -H, --hashes          Display only block numbers and hashes
 -m, --miner-info      Display miner info in coinbase transaction
 -M, --raw-miner-info  Display miner info in uninterpreted form
--n, --no-header       Don't print the column header
--o, --fields=         Display the specified fields
+-n, --no-header       Don’t print the column header
+-o, --fields=         Display the specified fields (comma-separated list)
+                      See AVAILABLE FIELDS below.
 -s, --summary         Print the summary only
--S, --no-summary      Don't print the summary
+-S, --no-summary      Dont print the summary
 """,
 	'notes': """
 If no block number is specified, the current block is assumed.
 
-In addition to information about the requested range of blocks, an estimate
-of the next difficulty adjustment is also displayed based on the average
-Block Discovery Interval from the beginning of the current 2016-block period
-to the chain tip.
+If the requested range ends at the current chain tip, an estimate of the next
+difficulty adjustment is also displayed. The estimate is based on the average
+Block Discovery Interval from the beginning of the current 2016-block period.
 
-Requires --txindex for correct operation.
-"""
+AVAILABLE FIELDS: {}
+
+This program requires a txindex-enabled daemon for correct operation.
+""".format(fmt_list(BlocksInfo.fields,fmt='bare'))
 	}
 }