tw.py: new get_tw_label() function; raise exception on bad tw label
This commit is contained in:
parent
b1a30fab2e
commit
0ec3eb1a07
7 changed files with 68 additions and 21 deletions
20
mmgen/obj.py
20
mmgen/obj.py
|
|
@ -22,9 +22,11 @@ obj.py: MMGen native classes
|
|||
|
||||
import sys,os,unicodedata
|
||||
from decimal import *
|
||||
from mmgen.color import *
|
||||
from string import hexdigits,ascii_letters,digits
|
||||
|
||||
from mmgen.color import *
|
||||
from mmgen.exception import *
|
||||
|
||||
def is_mmgen_seed_id(s): return SeedID(sid=s,on_fail='silent')
|
||||
def is_mmgen_idx(s): return AddrIdx(s,on_fail='silent')
|
||||
def is_mmgen_id(s): return MMGenID(s,on_fail='silent')
|
||||
|
|
@ -169,14 +171,19 @@ class InitErrors(object):
|
|||
if m2: errmsg = '{!r}\n{}'.format(m2,errmsg)
|
||||
|
||||
from mmgen.globalvars import g
|
||||
if g.traceback: cls.on_fail == 'raise'
|
||||
from mmgen.util import die,msg
|
||||
if cls.on_fail == 'silent': return None # TODO: return False instead?
|
||||
elif cls.on_fail == 'raise': raise ValueError(errmsg)
|
||||
elif cls.on_fail == 'die': die(1,errmsg)
|
||||
if cls.on_fail == 'silent':
|
||||
return None # TODO: return False instead?
|
||||
elif cls.on_fail == 'return':
|
||||
if errmsg: msg(errmsg)
|
||||
return None # TODO: here too?
|
||||
return None # TODO: return False instead?
|
||||
elif g.traceback or cls.on_fail == 'raise':
|
||||
if hasattr(cls,'exc'):
|
||||
raise cls.exc(errmsg)
|
||||
else:
|
||||
raise
|
||||
elif cls.on_fail == 'die':
|
||||
die(1,errmsg)
|
||||
|
||||
class Hilite(object):
|
||||
|
||||
|
|
@ -860,6 +867,7 @@ class MMGenWalletLabel(MMGenLabel):
|
|||
class TwComment(MMGenLabel):
|
||||
max_screen_width = 80
|
||||
desc = 'tracking wallet comment'
|
||||
exc = BadTwComment
|
||||
|
||||
class MMGenTXLabel(MMGenLabel):
|
||||
max_len = 72
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@ rpc.py: Cryptocoin RPC library for the MMGen suite
|
|||
|
||||
import http.client,base64,json
|
||||
|
||||
from mmgen.common import *
|
||||
from decimal import Decimal
|
||||
|
||||
from mmgen.common import *
|
||||
from mmgen.obj import MMGenObject
|
||||
|
||||
def dmsg_rpc(s):
|
||||
if g.debug_rpc: msg(s)
|
||||
|
||||
|
|
@ -261,6 +263,8 @@ class EthereumRPCConnection(CoinDaemonRPCConnection):
|
|||
def rpc_error(ret):
|
||||
return type(ret) is tuple and ret and ret[0] == 'rpcfail'
|
||||
|
||||
def rpc_errmsg(ret): return ret[1][2]
|
||||
|
||||
def init_daemon_parity():
|
||||
|
||||
def resolve_token_arg(token_arg):
|
||||
|
|
@ -362,6 +366,3 @@ def init_daemon_bitcoind():
|
|||
|
||||
def init_daemon(name):
|
||||
return globals()['init_daemon_'+name]()
|
||||
|
||||
def rpc_errmsg(ret):
|
||||
return ret[1][2]
|
||||
|
|
|
|||
22
mmgen/tw.py
22
mmgen/tw.py
|
|
@ -27,6 +27,11 @@ from mmgen.tx import is_mmgen_id
|
|||
CUR_HOME,ERASE_ALL = '\033[H','\033[0J'
|
||||
def CUR_RIGHT(n): return '\033[{}C'.format(n)
|
||||
|
||||
def get_tw_label(s):
|
||||
try: return TwLabel(s,on_fail='raise')
|
||||
except BadTwComment: raise
|
||||
except: return None
|
||||
|
||||
class TwUnspentOutputs(MMGenObject):
|
||||
|
||||
def __new__(cls,*args,**kwargs):
|
||||
|
|
@ -131,8 +136,8 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
|
|||
tr_rpc = []
|
||||
lbl_id = ('account','label')['label_api' in g.rpch.caps]
|
||||
for o in us_rpc:
|
||||
if not lbl_id in o: continue # coinbase outputs have no account field
|
||||
l = TwLabel(o[lbl_id],on_fail='silent')
|
||||
if not lbl_id in o: continue # coinbase outputs have no account field
|
||||
l = get_tw_label(o[lbl_id])
|
||||
if l:
|
||||
o.update({
|
||||
'twmmid': l.mmid,
|
||||
|
|
@ -427,7 +432,7 @@ class TwAddrList(MMGenDict):
|
|||
for d in g.rpch.listunspent(0):
|
||||
if not lbl_id in d: continue # skip coinbase outputs with missing account
|
||||
if d['confirmations'] < minconf: continue
|
||||
label = TwLabel(d[lbl_id],on_fail='silent')
|
||||
label = get_tw_label(d[lbl_id])
|
||||
if label:
|
||||
if usr_addr_list and (label.mmid not in usr_addr_list): continue
|
||||
if label.mmid in self:
|
||||
|
|
@ -452,7 +457,7 @@ class TwAddrList(MMGenDict):
|
|||
else:
|
||||
acct_list = list(g.rpch.listaccounts(0,True).keys()) # raw list, no 'L'
|
||||
acct_addrs = g.rpch.getaddressesbyaccount([[a] for a in acct_list],batch=True) # use raw list here
|
||||
acct_labels = MMGenList([TwLabel(a,on_fail='silent') for a in acct_list])
|
||||
acct_labels = MMGenList([get_tw_label(a) for a in acct_list])
|
||||
check_dup_mmid(acct_labels)
|
||||
assert len(acct_list) == len(acct_addrs),(
|
||||
'listaccounts() and getaddressesbyaccount() not equal in length')
|
||||
|
|
@ -645,17 +650,16 @@ class TwGetBalance(MMGenObject):
|
|||
# 0: unconfirmed, 1: below minconf, 2: confirmed, 3: spendable (privkey in wallet)
|
||||
lbl_id = ('account','label')['label_api' in g.rpch.caps]
|
||||
for d in g.rpch.listunspent(0):
|
||||
try:
|
||||
lbl = TwLabel(d[lbl_id],on_fail='silent')
|
||||
except:
|
||||
lbl,key = None,'Non-wallet'
|
||||
else:
|
||||
lbl = get_tw_label(d[lbl_id])
|
||||
if lbl:
|
||||
if lbl.mmid.type == 'mmgen':
|
||||
key = lbl.mmid.obj.sid
|
||||
if key not in self.data:
|
||||
self.data[key] = [g.proto.coin_amt('0')] * 4
|
||||
else:
|
||||
key = 'Non-MMGen'
|
||||
else:
|
||||
lbl,key = None,'Non-wallet'
|
||||
|
||||
if not d['confirmations']:
|
||||
self.data['TOTAL'][0] += d['amount']
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ pn = os.path.dirname(sys.argv[0])
|
|||
os.chdir(os.path.join(pn,os.pardir))
|
||||
sys.path.__setitem__(0,os.path.abspath(os.curdir))
|
||||
|
||||
os.environ['MMGEN_TEST_SUITE'] = '1'
|
||||
|
||||
# Import these _after_ local path's been added to sys.path
|
||||
from mmgen.common import *
|
||||
from mmgen.obj import *
|
||||
|
|
@ -53,6 +55,7 @@ def run_test(test,arg,input_data):
|
|||
arg_copy = arg
|
||||
kwargs = {'on_fail':'silent'} if opt.silent else {}
|
||||
ret_chk = arg
|
||||
exc_type = None
|
||||
if input_data == 'good' and type(arg) == tuple: arg,ret_chk = arg
|
||||
if type(arg) == dict: # pass one arg + kwargs to constructor
|
||||
arg_copy = arg.copy()
|
||||
|
|
@ -67,6 +70,10 @@ def run_test(test,arg,input_data):
|
|||
ret_chk = arg['ret']
|
||||
del arg['ret']
|
||||
del arg_copy['ret']
|
||||
if 'ExcType' in arg:
|
||||
exc_type = arg['ExcType']
|
||||
del arg['ExcType']
|
||||
del arg_copy['ExcType']
|
||||
kwargs.update(arg)
|
||||
elif type(arg) == tuple:
|
||||
args = arg
|
||||
|
|
@ -91,7 +98,12 @@ def run_test(test,arg,input_data):
|
|||
if not opt.super_silent:
|
||||
msg('==> {}'.format(ret))
|
||||
if opt.verbose and issubclass(cls,MMGenObject):
|
||||
ret.pmsg() if hasattr(ret,'pmsg') else pmsg(ret)
|
||||
ret.ppmsg() if hasattr(ret,'ppmsg') else ppmsg(ret)
|
||||
except Exception as e:
|
||||
if not type(e).__name__ == exc_type:
|
||||
raise
|
||||
msg_r(' {}'.format(yellow(exc_type+':')))
|
||||
msg(e.args[0])
|
||||
except SystemExit as e:
|
||||
if input_data == 'good':
|
||||
raise ValueError('Error on good input data')
|
||||
|
|
|
|||
|
|
@ -100,7 +100,10 @@ tests = OrderedDict([
|
|||
}),
|
||||
('TwLabel', {
|
||||
'bad': ('x x','x я','я:я',1,'f00f00f','a:b','x:L:3','F00BAA12:0 x',
|
||||
'F00BAA12:Z:99',tw_pfx+' x',tw_pfx+'я x'),
|
||||
'F00BAA12:Z:99',tw_pfx+' x',tw_pfx+'я x',
|
||||
'F00BAA12:S:1 '+ utf8_ctrl[:40],
|
||||
{'s':'F00BAA12:S:1 '+ utf8_ctrl[:40],'on_fail':'raise','ExcType':'BadTwComment'},
|
||||
),
|
||||
'good': (
|
||||
('F00BAA12:99 a comment','F00BAA12:L:99 a comment'),
|
||||
'F00BAA12:L:99 comment (UTF-8) α',
|
||||
|
|
|
|||
8
test/ref/bad-comment-unspent.json
Normal file
8
test/ref/bad-comment-unspent.json
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[{'address': '153AwzcymCgiy7dBxHkpeSn8yzbfnRvVPx',
|
||||
'amount': BTCAmt('34.21677044'),
|
||||
'confirmations': 7528082,
|
||||
'label': '96325D83:L:99 This label has a control character (tab) here: [ ]',
|
||||
'scriptPubKey': '76a9142c49a3ad8d89af713197e55190a7c3bc47e0208e88ac',
|
||||
'spendable': False,
|
||||
'txid': '2588cbbea1f3413ee4556c0f12f825f8670771862864a44f5ad39a71e1afdb13',
|
||||
'vout': 3}]
|
||||
|
|
@ -166,6 +166,7 @@ class TestSuiteTool(TestSuiteMain,TestSuiteBase):
|
|||
('tool_rand2file', (9,"'mmgen-tool rand2file'", [])),
|
||||
('tool_encrypt', (9,"'mmgen-tool encrypt' (random data)", [])),
|
||||
('tool_decrypt', (9,"'mmgen-tool decrypt' (random data)", [[[enc_infn+'.mmenc'],9]])),
|
||||
('tool_twview_bad_comment',(9,"'mmgen-tool twview' (with bad comment)", [])),
|
||||
# ('tool_encrypt_ref', (9,"'mmgen-tool encrypt' (reference text)", [])),
|
||||
)
|
||||
|
||||
|
|
@ -215,6 +216,16 @@ class TestSuiteTool(TestSuiteMain,TestSuiteBase):
|
|||
cmp_or_die(hincog_offset,int(o))
|
||||
return t
|
||||
|
||||
def tool_twview_bad_comment(self): # test correct operation of get_tw_label()
|
||||
bw_save = os.getenv('MMGEN_BOGUS_WALLET_DATA')
|
||||
os.environ['MMGEN_BOGUS_WALLET_DATA'] = joinpath(ref_dir,'bad-comment-unspent.json')
|
||||
t = self.spawn('mmgen-tool',['twview'])
|
||||
if bw_save:
|
||||
os.environ['MMGEN_BOGUS_WALLET_DATA'] = bw_save
|
||||
t.read()
|
||||
t.req_exit_val = 2
|
||||
return t
|
||||
|
||||
class TestSuiteRefTX(TestSuiteMain,TestSuiteBase):
|
||||
'create a reference transaction file (administrative command)'
|
||||
segwit_opts_ok = False
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue