Support 40-character UTF-8 tracking wallet comments

This commit is contained in:
The MMGen Project 2018-03-09 15:16:20 +00:00
commit d49c8627aa
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
6 changed files with 31 additions and 33 deletions

View file

@ -494,7 +494,7 @@ class TwMMGenID(str,Hilite,InitErrors,MMGenObject):
return me
# contains TwMMGenID,TwComment. Not for display
class TwLabel(str,InitErrors,MMGenObject):
class TwLabel(unicode,InitErrors,MMGenObject):
def __new__(cls,s,on_fail='die'):
if type(s) == cls: return s
cls.arg_chk(cls,on_fail)
@ -502,7 +502,7 @@ class TwLabel(str,InitErrors,MMGenObject):
ss = s.split(None,1)
mmid = TwMMGenID(ss[0],on_fail='raise')
comment = TwComment(ss[1] if len(ss) == 2 else '',on_fail='raise')
me = str.__new__(cls,'{}{}'.format(mmid,' {}'.format(comment) if comment else ''))
me = unicode.__new__(cls,u'{}{}'.format(mmid,u' {}'.format(comment) if comment else ''))
me.mmid = mmid
me.comment = comment
return me
@ -671,8 +671,7 @@ class MMGenWalletLabel(MMGenLabel):
desc = 'wallet label'
class TwComment(MMGenLabel):
max_len = 32
allowed = map(unichr,range(32,127))
max_len = 40
desc = 'tracking wallet comment'
class MMGenTXLabel(MMGenLabel):

View file

@ -103,20 +103,16 @@ class CoinDaemonRPCConnection(object):
dmsg_rpc('=== request() debug ===')
dmsg_rpc(' RPC POST data ==> {}\n'.format(p))
caller = self
class MyJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj,g.proto.coin_amt):
return g.proto.get_rpc_coin_amt_type()(obj)
return json.JSONEncoder.default(self, obj)
# TODO: UTF-8 labels
# if type(p) != list and p['method'] == 'importaddress':
# dump = json.dumps(p,cls=MyJSONEncoder,ensure_ascii=False)
# print(dump)
dmsg_rpc(' RPC AUTHORIZATION data ==> raw: [{}]\n{}enc: [Basic {}]\n'.format(
self.auth_str,' '*31,base64.b64encode(self.auth_str)))
try:
hc.request('POST', '/', json.dumps(p,cls=MyJSONEncoder), {
'Host': self.host,
@ -146,15 +142,14 @@ class CoinDaemonRPCConnection(object):
e2 = str(e1)
return do_fail(r,1,e2)
r2 = r.read()
r2 = r.read().decode('utf8')
dmsg_rpc(' RPC REPLY data ==> {}\n'.format(r2))
dmsg_rpc(u' RPC REPLY data ==> {}\n'.format(r2))
if not r2:
return do_fail(r,2,'Error: empty reply')
# from decimal import Decimal
r3 = json.loads(r2.decode('utf8'), parse_float=Decimal)
r3 = json.loads(r2,parse_float=Decimal)
ret = []
for resp in r3 if cf['batch'] else [r3]:

View file

@ -725,7 +725,7 @@ def Listaddresses(addrs='',minconf=1,
out = ([],[green('Chain: {}'.format(g.chain.upper()))])[g.chain in ('testnet','regtest')]
fs = '{{mid}}{} {{cmt}} {{amt}}{}'.format(('',' {addr}')[showbtcaddrs],('',' {age}')[show_age])
fs = u'{{mid}}{} {{cmt}} {{amt}}{}'.format(('',' {addr}')[showbtcaddrs],('',' {age}')[show_age])
mmaddrs = [k for k in addrs.keys() if k.type == 'mmgen']
max_mmid_len = max(len(k) for k in mmaddrs) + 2 if mmaddrs else 10
max_cmt_len = max(max(len(v['lbl'].comment) for v in addrs.values()),7)
@ -835,6 +835,6 @@ def Twview(pager=False,reverse=False,wide=False,minconf=1,sort='age',show_days=T
def Add_label(mmaddr_or_coin_addr,label):
rpc_init()
from mmgen.tw import MMGenTrackingWallet
MMGenTrackingWallet.add_label(mmaddr_or_coin_addr,label) # dies on failure
MMGenTrackingWallet.add_label(mmaddr_or_coin_addr,label,on_fail='raise')
def Remove_label(mmaddr_or_coin_addr): Add_label(mmaddr_or_coin_addr,'')

View file

@ -162,7 +162,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
out = [hdr_fmt.format(' '.join(self.sort_info()),g.coin,self.total.hl())]
if g.chain in ('testnet','regtest'):
out += [green('Chain: {}'.format(g.chain.upper()))]
fs = ' {:%s} {:%s} {:2} {} {} {:<}' % (col1_w,tx_w)
fs = u' {:%s} {:%s} {:2} {} {} {:<}' % (col1_w,tx_w)
out += [fs.format('Num',
'TXid'.ljust(tx_w - 5) + ' Vout', '',
'Address'.ljust(addr_w),
@ -175,10 +175,10 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
else i.twmmid if i.twmmid.type=='mmgen'
else 'Non-{}'.format(g.proj_name),width=mmid_w,color=True)
if self.show_mmid:
addr_out = '{} {}'.format(
addr_out = u'{} {}'.format(
type(i.addr).fmtc(addr_dots,width=btaddr_w,color=True) if i.skip == 'addr' \
else i.addr.fmt(width=btaddr_w,color=True),
'{} {}'.format(mmid_disp,i.label.fmt(width=label_w,color=True) \
u'{} {}'.format(mmid_disp,i.label.fmt(width=label_w,color=True) \
if label_w > 0 else ''))
else:
addr_out = type(i.addr).fmtc(addr_dots,width=addr_w,color=True) \
@ -280,10 +280,10 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
idx,lbl = self.get_idx_and_label_from_user()
if idx:
e = self.unspent[idx-1]
if type(self).add_label(e.twmmid,lbl,addr=e.addr):
if type(self).add_label(e.twmmid,lbl.decode('utf8'),addr=e.addr):
self.get_unspent_data()
self.do_sort()
msg('{}\n{}\n{}'.format(self.fmt_display,prompt,p))
msg(u'{}\n{}\n{}'.format(self.fmt_display,prompt,p))
else:
msg('Label could not be added\n{}\n{}'.format(prompt,p))
elif reply == 'M': self.do_sort('twmmid'); self.show_mmid = True
@ -314,7 +314,7 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
# returns on failure
@classmethod
def add_label(cls,arg1,label='',addr=None,silent=False):
def add_label(cls,arg1,label='',addr=None,silent=False,on_fail='return'):
from mmgen.tx import is_mmgen_id,is_coin_addr
mmaddr,coinaddr = None,None
if is_coin_addr(addr or arg1):
@ -345,10 +345,10 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
mmaddr = TwMMGenID(mmaddr)
cmt = TwComment(label,on_fail='return')
cmt = TwComment(label,on_fail=on_fail)
if cmt in (False,None): return False
lbl = TwLabel(mmaddr + ('',' '+cmt)[bool(cmt)]) # label is ASCII for now
lbl = TwLabel(mmaddr + ('',' '+cmt)[bool(cmt)],on_fail=on_fail)
# NOTE: this works because importaddress() removes the old account before
# associating the new account with the address.
@ -366,8 +366,8 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
m = mmaddr.type.replace('mmg','MMG')
a = mmaddr.replace(g.proto.base_coin.lower()+':','')
s = '{} address {} in tracking wallet'.format(m,a)
if label: msg("Added label '{}' to {}".format(label,s))
else: msg('Removed label from {}'.format(s))
if label: msg(u"Added label '{}' to {}".format(label,s))
else: msg(u'Removed label from {}'.format(s))
return True
@classmethod

View file

@ -949,7 +949,7 @@ class MMGenTX(MMGenObject):
('','confirmations:','{} (around {} days)'.format(confs,days) if blockcount!=None else '')
] if ip else icommon + [
('','change:',green('True') if e.is_chg else '')]
io_out += '\n'.join([('{:>3} {:<8} {}'.format(*d)) for d in items if d[2]]) + '\n\n'
io_out += '\n'.join([(u'{:>3} {:<8} {}'.format(*d)) for d in items if d[2]]) + '\n\n'
return io_out
hdr_fs = (

View file

@ -2713,9 +2713,9 @@ class MMGenTestSuite(object):
sid = self.regtest_user_sid('alice')
return self.regtest_user_remove_label(name,'alice',sid+':C:1')
def regtest_user_chk_label(self,name,user,addr,label):
def regtest_user_chk_label(self,name,user,addr,label,label_pat=None):
t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses','all_labels=1'])
t.expect('{}\s+\S{{30}}\S+\s+{}\s+'.format(addr,label),regex=True)
t.expect(ur'{}\s+\S{{30}}\S+\s+{}\s+'.format(addr,label_pat or label),regex=True)
t.ok()
def regtest_alice_chk_label1(self,name):
@ -2726,9 +2726,16 @@ class MMGenTestSuite(object):
sid = self.regtest_user_sid('alice')
return self.regtest_user_chk_label(name,'alice',sid+':C:1','Replacement Label')
utf8_label = u'Edited label (40 characters, UTF8) α-β-γ'
utf8_label_pat = ur'Edited label \(40 characters, UTF8\) ..-..-..'
def regtest_alice_edit_label1(self,name):
return self.regtest_user_edit_label(name,'alice','1',self.utf8_label)
def regtest_alice_chk_label3(self,name):
sid = self.regtest_user_sid('alice')
return self.regtest_user_chk_label(name,'alice',sid+':C:1','Edited Label')
return self.regtest_user_chk_label(name,'alice',sid+':C:1',self.utf8_label,
label_pat=self.utf8_label_pat)
def regtest_alice_chk_label4(self,name):
sid = self.regtest_user_sid('alice')
@ -2743,9 +2750,6 @@ class MMGenTestSuite(object):
t.expect(r"'q'=quit view, .*?:.",'q',regex=True)
t.ok()
def regtest_alice_edit_label1(self,name):
return self.regtest_user_edit_label(name,'alice','1','Edited Label')
def regtest_stop(self,name):
t = MMGenExpect(name,'mmgen-regtest',['stop'])
t.ok()