minor fixes and cleanups

This commit is contained in:
The MMGen Project 2024-03-13 12:16:09 +00:00
commit ede7353ea2
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
6 changed files with 76 additions and 34 deletions

View file

@ -44,7 +44,7 @@ def launch(*, mod=None, func=None, fqmod=None, package='mmgen'):
try:
errmsg = str(e.args[0])
except:
errmsg = repr(e.args[0])
errmsg = repr(e.args[0]) if e.args else repr(e)
from collections import namedtuple
from .color import nocolor,yellow,red

View file

@ -347,6 +347,7 @@ class MMGenLabel(HiliteStr,InitErrors):
color = 'pink'
allowed = []
forbidden = []
first_char = []
max_len = 0
min_len = 0
max_screen_width = 0 # if != 0, overrides max_len
@ -354,21 +355,18 @@ class MMGenLabel(HiliteStr,InitErrors):
def __new__(cls,s):
if isinstance(s,cls):
return s
for k in ( cls.forbidden, cls.allowed ):
assert isinstance(k,list)
for ch in k:
assert isinstance(ch,str) and len(ch) == 1
try:
s = s.strip()
for ch in s:
# Allow: (L)etter,(N)umber,(P)unctuation,(S)ymbol,(Z)space
# Disallow: (C)ontrol,(M)combining
# Combining characters create width formatting issues, so disallow them for now
if unicodedata.category(ch)[0] in ('C','M'):
raise ValueError(
'{!a}: {} characters not allowed'.format(
ch,
{ 'C':'control', 'M':'combining' }[unicodedata.category(ch)[0]] ))
if not cls.allowed:
for ch in s:
# Allow: (L)etter,(N)umber,(P)unctuation,(S)ymbol,(Z)space
# Disallow: (C)ontrol,(M)combining
# Combining characters create width formatting issues, so disallow them for now
if unicodedata.category(ch)[0] in ('C','M'):
raise ValueError(
'{!a}: {} characters not allowed'.format(
ch,
{ 'C':'control', 'M':'combining' }[unicodedata.category(ch)[0]] ))
me = str.__new__(cls,s)
@ -380,11 +378,14 @@ class MMGenLabel(HiliteStr,InitErrors):
assert len(s) >= cls.min_len, f'too short (<{cls.min_len} symbols)'
if cls.first_char and s and not s[0] in cls.first_char:
raise ValueError('first character not in set ' + ' '.join(cls.first_char))
if cls.allowed and not set(list(s)).issubset(set(cls.allowed)):
raise ValueError('contains non-allowed symbols: ' + ' '.join(set(list(s)) - set(cls.allowed)) )
raise ValueError('contains symbols not in set: ' + ' '.join(cls.allowed))
if cls.forbidden and any(ch in s for ch in cls.forbidden):
raise ValueError('contains one of these forbidden symbols: ' + ' '.join(cls.forbidden) )
raise ValueError('contains one of these forbidden symbols: ' + ' '.join(cls.forbidden))
return me
except Exception as e:

View file

@ -79,14 +79,16 @@ class New(Base,TxBase.New):
self.txid = MMGenTxID(make_chksum_6(self.serialized).upper())
async def process_cmd_args(self,cmd_args,ad_f,ad_w):
lc = len(cmd_args)
if lc == 0 and self.usr_contract_data and 'Token' not in self.name:
return
if lc != 1:
die(1,f'{lc} output{suf(lc)} specified, but Ethereum transactions must have exactly one')
for a in cmd_args:
await self.process_cmd_arg(a,ad_f,ad_w)
if lc != 1:
die(1, f'{lc} output{suf(lc)} specified, but Ethereum transactions must have exactly one')
await self.process_cmd_arg(cmd_args[0],ad_f,ad_w)
def select_unspent(self,unspent):
from ....ui import line_input

View file

@ -323,7 +323,10 @@ class TwAddresses(TwView):
if start is not None:
for d in data[start:]:
if d.al_id == al_id:
if not d.recvd and (self.cfg.autochg_ignore_labels or not d.comment):
if (
not d.recvd
and (self.cfg.autochg_ignore_labels or not d.comment)
):
if d.comment:
msg('{} {} {} {}{}'.format(
yellow('WARNING: address'),
@ -369,7 +372,8 @@ class TwAddresses(TwView):
assert isinstance(mmtype,MMGenAddrType)
res = [self.get_change_address( f'{sid}:{mmtype}', r.bot, r.top ) for sid,r in self.sid_ranges.items()]
res = [self.get_change_address(f'{sid}:{mmtype}', r.bot, r.top)
for sid,r in self.sid_ranges.items()]
if any(res):
res = list(filter(None,res))

View file

@ -221,17 +221,18 @@ class New(Base):
await self.process_cmd_arg(a,ad_f,ad_w)
if self.chg_idx is None:
die(2,(
fmt( self.msg_no_change_output.format(self.dcoin) ).strip()
die(2,
fmt(self.msg_no_change_output.format(self.dcoin)).strip()
if len(self.outputs) == 1 else
'ERROR: No change output specified' ))
'ERROR: No change output specified')
if self.has_segwit_outputs() and not self.rpc.info('segwit_is_active'):
die(2,f'{gc.proj_name} Segwit address requested on the command line, '
+ 'but Segwit is not active on this chain')
die(2,
f'{gc.proj_name} Segwit address requested on the command line, '
'but Segwit is not active on this chain')
if not self.outputs:
die(2,'At least one output must be specified on the command line')
die(2, 'At least one output must be specified on the command line')
async def get_outputs_from_cmdline(self,cmd_args):
from ..addrdata import AddrData,TwAddrData

View file

@ -438,6 +438,11 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
('bob_auto_chg_bad3', 'error handling for auto change address transaction (no unused addresses)'),
('bob_auto_chg_bad4', 'error handling for auto change address transaction by addrtype '
'(no unused addresses)'),
('bob_auto_chg_bad5', 'error handling (more than one chg address listed)'),
('bob_auto_chg_bad6', 'error handling for auto change address transaction '
'(more than one chg address, mixed)'),
('bob_auto_chg_bad7', 'error handling for auto change address transaction '
'(more than one chg address requested)'),
('carol_twimport2', 'recreating Carol’s tracking wallet from JSON dump'),
('carol_rescan_blockchain', 'rescanning the blockchain (full rescan)'),
('carol_auto_chg1', 'creating an automatic change address transaction (C)'),
@ -1882,16 +1887,19 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
idx,
by_mmtype = False,
include_dest = True,
ignore_labels = False):
ignore_labels = False,
add_args = []):
if mmtype in ('S','B') and not self.proto.cap('segwit'):
return 'skip'
sid = self._user_sid('bob')
t = self.spawn(
'mmgen-txcreate',
[f'--outdir={self.tr.trash_dir}', '--no-blank', f'--{user}'] +
(['--autochg-ignore-labels'] if ignore_labels else []) +
[mmtype if by_mmtype else f'{sid}:{mmtype}'] +
([self.burn_addr+',0.01'] if include_dest else [])
[f'--outdir={self.tr.trash_dir}', '--no-blank', f'--{user}']
+ (['--autochg-ignore-labels'] if ignore_labels else [])
+ [mmtype if by_mmtype else f'{sid}:{mmtype}']
+ ([self.burn_addr+',0.01'] if include_dest else [])
+ add_args
)
return self.txcreate_ui_common(t,
menu = [],
@ -1949,10 +1957,13 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
def bob_remove_comment_uua1(self):
return self._bob_remove_comment_uua(':C:3')
def _usr_auto_chg_bad(self,user,al_id,expect):
def _usr_auto_chg_bad(self, user, al_id, expect, add_args=[]):
t = self.spawn(
'mmgen-txcreate',
['-d', self.tr.trash_dir, '-B', f'--{user}', self.burn_addr+', 0.01', al_id],
['-d', self.tr.trash_dir, '-B', f'--{user}']
+ [f'{self.burn_addr},0.01']
+ ([al_id] if al_id else [])
+ add_args,
exit_val = 2)
t.expect(expect)
return t
@ -1981,6 +1992,29 @@ class CmdTestRegtest(CmdTestBase,CmdTestShared):
'L',
'contains no unused addresses of address type' )
def bob_auto_chg_bad5(self):
sid = self._user_sid('bob')
return self._usr_auto_chg_bad(
'bob',
None,
'More than one change address listed',
add_args = [f'{sid}:C:4', f'{sid}:C:5'])
def bob_auto_chg_bad6(self):
sid = self._user_sid('bob')
return self._usr_auto_chg_bad(
'bob',
'L',
'More than one',
add_args = [f'{sid}:C:4'])
def bob_auto_chg_bad7(self):
return self._usr_auto_chg_bad(
'bob',
'L',
'More than one change address requested',
add_args = ['B'])
def carol_twimport2(self):
u,b = (4,3) if self.proto.cap('segwit') else (3,2)
return self.carol_twimport(