mmgen-tool txview: add 'sort' option, rename old sort option to 'filesort'

- filesort: sort tx files by time ('mtime', 'ctime', 'atime')
- sort: view transaction inputs and outputs either sorted by MMGen ID/address
        ('addr') or in their actual order in the transaction ('raw')
This commit is contained in:
The MMGen Project 2019-03-27 18:45:36 +00:00
commit 105f6c3033
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
3 changed files with 40 additions and 14 deletions

View file

@ -239,7 +239,7 @@ class EthereumMMGenTX(MMGenTX):
if self.outputs:
self.send_amt = self.outputs[0].amt
def format_view_body(self,blockcount,nonmm_str,max_mmwid,enl,terse):
def format_view_body(self,blockcount,nonmm_str,max_mmwid,enl,terse,sort):
m = {}
for k in ('in','out'):
if len(getattr(self,k+'puts')):

View file

@ -519,20 +519,32 @@ class MMGenToolCmdFile(MMGenToolCmdBase):
return PasswordList(infile=mmgen_passwdfile).chksum
def txview( varargs_call_sig = { # hack to allow for multiple filenames
'args': ( 'mmgen_tx_file(s)', 'pager', 'terse', 'sort' ),
'dfls': ( False, False, 'mtime' ),
'annots': { 'mmgen_tx_file(s)': str, 'sort': '(valid options: mtime,ctime,atime)' } },
'args': (
'mmgen_tx_file(s)',
'pager',
'terse',
'sort',
'filesort' ),
'dfls': ( False, False, 'addr', 'mtime' ),
'annots': {
'mmgen_tx_file(s)': str,
'sort': '(valid options: addr,raw)',
'filesort': '(valid options: mtime,ctime,atime)'
} },
*infiles,**kwargs):
"show raw/signed MMGen transaction in human-readable form"
self = varargs_call_sig
terse = bool(kwargs.get('terse'))
tx_sort = kwargs.get('sort') or 'addr'
file_sort = kwargs.get('filesort') or 'mtime'
from mmgen.filename import MMGenFileList
terse = 'terse' in kwargs and kwargs['terse']
sort_key = kwargs['sort'] if 'sort' in kwargs else 'mtime'
from mmgen.tx import MMGenTX
flist = MMGenFileList(infiles,ftype=MMGenTX)
flist.sort_by_age(key=sort_key) # in-place sort
flist.sort_by_age(key=file_sort) # in-place sort
sep = ''*77+'\n'
return sep.join([MMGenTX(fn).format_view(terse=terse) for fn in flist.names()]).rstrip()
return sep.join([MMGenTX(fn).format_view(terse=terse,sort=tx_sort) for fn in flist.names()]).rstrip()
class MMGenToolCmdFileCrypt(MMGenToolCmdBase):
"""

View file

@ -293,6 +293,8 @@ class MMGenTX(MMGenObject):
usr_fee_prompt = 'Enter transaction fee: '
fee_is_approximate = False
fn_fee_unit = 'satoshi'
view_sort_orders = ('addr','raw')
dfl_view_sort_order = 'addr'
msg_low_coin = 'Selected outputs insufficient to fund this transaction ({} {} needed)'
msg_no_change_output = """
@ -1035,7 +1037,11 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
def is_replaceable(self):
return self.inputs[0].sequence == g.max_int - 2
def format_view_body(self,blockcount,nonmm_str,max_mmwid,enl,terse):
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)))
def format_io(desc):
io = getattr(self,desc)
@ -1043,7 +1049,12 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
out = 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
for n,e in enumerate(sorted(io,key=lambda o: o.mmid.sort_key if o.mmid else o.addr)):
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:
confs = e.confs + blockcount - self.blockcount
days = int(confs // confs_per_day)
@ -1072,7 +1083,10 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
out += '\n'.join([('{:>3} {:<8} {}'.format(*d)) for d in items if d[2]]) + '\n\n'
return out
return format_io('inputs') + format_io('outputs')
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 format_view_rel_fee(self,terse):
return ' ({} {})\n'.format(
@ -1090,7 +1104,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
out += ', Base {}, Witness {}'.format(ts-ws,ws)
return out + '\n'
def format_view(self,terse=False):
def format_view(self,terse=False,sort=dfl_view_sort_order):
blockcount = None
if g.proto.base_coin != 'ETH':
try:
@ -1127,7 +1141,7 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
if self.label:
out += 'Comment: {}\n{}'.format(self.label.hl(),enl)
out += self.format_view_body(blockcount,nonmm_str,max_mmwid,enl,terse=terse)
out += self.format_view_body(blockcount,nonmm_str,max_mmwid,enl,terse=terse,sort=sort)
out += (self.txview_ftr_fs,self.txview_ftr_fs_short)[bool(terse)].format(
i=self.sum_inputs().hl(),