Browse Source

fixes and cleanups throughout

The MMGen Project 3 years ago
parent
commit
fc87dcf0ba

+ 7 - 0
mmgen/baseconv.py

@@ -30,6 +30,13 @@ def is_b58_str(s):
 def is_b32_str(s):
 	return set(list(s)) <= set(baseconv('b32').digits)
 
+def is_mmgen_mnemonic(s):
+	try:
+		baseconv('mmgen').tobytes(s.split(),pad='seed')
+		return True
+	except:
+		return False
+
 class baseconv(object):
 	mn_base = 1626
 	dt = namedtuple('desc_tuple',['short','long'])

+ 1 - 1
mmgen/bip39.py

@@ -25,7 +25,7 @@ from hashlib import sha256
 from .baseconv import baseconv
 from .util import is_hex_str,die
 
-def is_bip39_str(s):
+def is_bip39_mnemonic(s):
 	return bool( bip39().tohex(s.split()) )
 
 # implements a subset of the baseconv API

+ 10 - 9
mmgen/main_wallet.py

@@ -231,15 +231,16 @@ if invoked_as == 'passchg' and ss_in.infile.dirname == g.data_dir:
 	shred_file(
 		ss_in.infile.name,
 		verbose = opt.verbose )
-elif (
-	invoked_as == 'gen'
-	and not opt.outdir
-	and not opt.stdout
-	and not find_file_in_dir( MMGenWallet, g.data_dir )
-	and keypress_confirm(
-		'Make this wallet your default and move it to the data directory?',
-		default_yes = True ) ):
-	ss_out.write_to_file(outdir=g.data_dir)
+elif invoked_as == 'gen' and not opt.outdir and not opt.stdout:
+	from .filename import find_file_in_dir
+	if (
+		not find_file_in_dir( MMGenWallet, g.data_dir )
+		and keypress_confirm(
+			'Make this wallet your default and move it to the data directory?',
+			default_yes = True ) ):
+		ss_out.write_to_file(outdir=g.data_dir)
+	else:
+		ss_out.write_to_file()
 else:
 	ss_out.write_to_file()
 

+ 2 - 0
mmgen/opts.py

@@ -475,10 +475,12 @@ def check_usr_opts(usr_opts): # Raises an exception if any check fails
 			opt_unrecognized(key,val)
 		if key == 'out_fmt':
 			p = 'hidden_incog_output_params'
+
 			if sstype == IncogWalletHidden and not getattr(opt,p):
 				die( 'UserOptError',
 					'Hidden incog format output requested.  ' +
 					f'You must supply a file and offset with the {fmt_opt(p)!r} option' )
+
 			if issubclass(sstype,IncogWallet) and opt.old_incog_fmt:
 				opt_display(key,val,beg='Selected',end=' ')
 				opt_display('old_incog_fmt',beg='conflicts with',end=':\n')

+ 1 - 1
mmgen/passwdlist.py

@@ -55,7 +55,7 @@ class PasswordList(AddrList):
 	pw_info     = {
 		'b32':     pwinfo(10, 42 ,24, None,      'base32 password',          'baseconv.is_b32_str'), # 32**24 < 2**128
 		'b58':     pwinfo(8,  36 ,20, None,      'base58 password',          'baseconv.is_b58_str'), # 58**20 < 2**128
-		'bip39':   pwinfo(12, 24 ,24, [12,18,24],'BIP39 mnemonic',           'bip39.is_bip39_str'),
+		'bip39':   pwinfo(12, 24 ,24, [12,18,24],'BIP39 mnemonic',           'bip39.is_bip39_mnemonic'),
 		'xmrseed': pwinfo(25, 25, 25, [25],      'Monero new-style mnemonic','xmrseed.is_xmrseed'),
 		'hex':     pwinfo(32, 64 ,64, [32,48,64],'hexadecimal password',     'util.is_hex_str'),
 	}

+ 6 - 5
mmgen/txsign.py

@@ -105,12 +105,12 @@ def add_keys(tx,src,infiles=None,saved_seeds=None,keyaddr_list=None):
 		vmsg(f'Added {len(new_keys)} wif key{suf(new_keys)} from {desc}')
 	return new_keys
 
-def _pop_and_return(args,cmplist): # strips found args
+def _pop_matching_fns(args,cmplist): # strips found args
 	return list(reversed([args.pop(args.index(a)) for a in reversed(args) if get_extension(a) in cmplist]))
 
 def get_tx_files(opt,args):
 	from .tx.unsigned import Unsigned
-	ret = _pop_and_return(args,[Unsigned.ext])
+	ret = _pop_matching_fns(args,[Unsigned.ext])
 	if not ret:
 		die(1,'You must specify a raw transaction file!')
 	return ret
@@ -118,11 +118,12 @@ def get_tx_files(opt,args):
 def get_seed_files(opt,args):
 	# favor unencrypted seed sources first, as they don't require passwords
 	u,e = WalletUnenc,WalletEnc
-	ret = _pop_and_return(args,u.get_extensions())
+	ret = _pop_matching_fns(args,u.get_extensions())
 	from .filename import find_file_in_dir
 	wf = find_file_in_dir(MMGenWallet,g.data_dir) # Make this the first encrypted ss in the list
-	if wf: ret.append(wf)
-	ret += _pop_and_return(args,e.get_extensions())
+	if wf:
+		ret.append(wf)
+	ret += _pop_matching_fns(args,e.get_extensions())
 	if not (ret or opt.mmgen_keys_from_file or opt.keys_from_file): # or opt.use_wallet_dat
 		die(1,'You must specify a seed or key source!')
 	return ret

+ 0 - 21
mmgen/util.py

@@ -332,16 +332,6 @@ def make_iv_chksum(s):
 	from hashlib import sha256
 	return sha256(s).hexdigest()[:8].upper()
 
-def splitN(s,n,sep=None): # always return an n-element list
-	ret = s.split(sep,n-1)
-	return ret + ['' for i in range(n-len(ret))]
-
-def split2(s,sep=None):
-	return splitN(s,2,sep) # always return a 2-element list
-
-def split3(s,sep=None):
-	return splitN(s,3,sep) # always return a 3-element list
-
 def split_into_cols(col_wid,s):
 	return ' '.join([s[col_wid*i:col_wid*(i+1)] for i in range(len(s)//col_wid+1)]).rstrip()
 
@@ -646,17 +636,6 @@ def do_license_msg(immed=False):
 			msg_r('\r')
 	msg('')
 
-def format_par(s,indent=0,width=80,as_list=False):
-	words,lines = s.split(),[]
-	assert width >= indent + 4,'width must be >= indent + 4'
-	while words:
-		line = ''
-		while len(line) <= (width-indent) and words:
-			if line and len(line) + len(words[0]) + 1 > width-indent: break
-			line += ('',' ')[bool(line)] + words.pop(0)
-		lines.append(' '*indent + line)
-	return lines if as_list else '\n'.join(lines) + '\n'
-
 def get_subclasses(cls,names=False):
 	def gen(cls):
 		for i in cls.__subclasses__():

+ 1 - 16
mmgen/wallet.py

@@ -32,21 +32,6 @@ def check_usr_seed_len(seed_len):
 	if opt.seed_len and opt.seed_len != seed_len:
 		die(1,f'ERROR: requested seed length ({opt.seed_len}) doesn’t match seed length of source ({seed_len})')
 
-def _is_mnemonic(s,fmt):
-	oq_save = bool(opt.quiet)
-	opt.quiet = True
-	try:
-		Wallet(in_data=s,in_fmt=fmt)
-		ret = True
-	except:
-		ret = False
-	finally:
-		opt.quiet = oq_save
-	return ret
-
-def is_bip39_mnemonic(s): return _is_mnemonic(s,fmt='bip39')
-def is_mmgen_mnemonic(s): return _is_mnemonic(s,fmt='words')
-
 class WalletMeta(type):
 	wallet_classes = set() # one-instance class, so store data in class attr
 	def __init__(cls,name,bases,namespace):
@@ -841,7 +826,7 @@ class MMGenWallet(WalletEnc):
 class Brainwallet(WalletEnc):
 
 	stdin_ok = True
-	fmt_codes = ('mmbrain','brainwallet','brain','bw','b')
+	fmt_codes = ('mmbrain','brainwallet','brain','bw')
 	desc = 'brainwallet'
 	ext = 'mmbrain'
 	# brainwallet warning message? TODO

+ 6 - 4
scripts/exec_wrapper.py

@@ -28,7 +28,7 @@ def exec_wrapper_init(): # don't change: name is used to test if script is runni
 
 	if not os.getenv('EXEC_WRAPPER_NO_TRACEBACK'):
 		try:
-			os.unlink('my.err')
+			os.unlink('test.py.err')
 		except:
 			pass
 
@@ -55,8 +55,9 @@ def exec_wrapper_write_traceback(e):
 		c.red(message) )
 	+ '\n' )
 
-	with open('my.err','w') as fp:
-		fp.write(''.join(lines+[exc]))
+	if not os.getenv('EXEC_WRAPPER_NO_TRACEBACK'):
+		with open('test.py.err','w') as fp:
+			fp.write(''.join(lines+[exc]))
 
 def exec_wrapper_end_msg():
 	if os.getenv('EXEC_WRAPPER_SPAWN') and not os.getenv('MMGEN_TEST_SUITE_DETERMINISTIC'):
@@ -110,7 +111,8 @@ except SystemExit as e:
 		exec_wrapper_end_msg()
 	sys.exit(e.code)
 except Exception as e:
-	exec_wrapper_write_traceback(e)
+	if not os.getenv('EXEC_WRAPPER_NO_TRACEBACK'):
+		exec_wrapper_write_traceback(e)
 	retval = e.mmcode if hasattr(e,'mmcode') else e.code if hasattr(e,'code') else 1
 	sys.exit(retval)
 

+ 4 - 2
test/test.py

@@ -84,8 +84,10 @@ if not (len(sys.argv) == 2 and sys.argv[1] == 'clean'):
 
 from mmgen.common import *
 
-try: os.unlink(os.path.join(repo_root,'my.err'))
-except: pass
+try:
+	os.unlink(os.path.join(repo_root,'test.py.err'))
+except:
+	pass
 
 g.quiet = False # if 'quiet' was set in config file, disable here
 os.environ['MMGEN_QUIET'] = '0' # for this script and spawned scripts

+ 12 - 10
test/test_py_d/ts_main.py

@@ -583,8 +583,8 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 			t.passphrase(icls.desc,self.wpasswd)
 
 		ocls = Wallet.fmt_code_to_type(out_fmt)
-		out_pw = issubclass(ocls,WalletEnc) and ocls != Brainwallet
-		if out_pw:
+
+		if issubclass(ocls,WalletEnc) and ocls != Brainwallet:
 			t.passphrase_new('new '+ocls.desc,self.wpasswd)
 			t.usr_rand(self.usr_rand_chars)
 
@@ -594,6 +594,7 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 			t.expect(m)
 			incog_id = t.expect_getend('New Incog Wallet ID: ')
 			t.expect(m)
+
 		if ocls == IncogWalletHidden:
 			self.write_to_tmpfile(incog_id_fn,incog_id)
 			t.hincog_create(hincog_bytes)
@@ -637,17 +638,18 @@ class TestSuiteMain(TestSuiteBase,TestSuiteShared):
 	def addrgen_seed(self,wf,foo,in_fmt='seed'):
 		wcls = Wallet.fmt_code_to_type(in_fmt)
 		stdout = wcls == MMGenSeedFile # capture output to screen once
-		add_args = ([],['-S'])[bool(stdout)] + self.segwit_arg
-		t = self.spawn('mmgen-addrgen', add_args +
-				['-i'+in_fmt,'-d',self.tmpdir,wf,self.addr_idx_list])
+		t = self.spawn(
+			'mmgen-addrgen',
+			(['-S'] if stdout else []) +
+			self.segwit_arg +
+			[ '-i' + in_fmt, '-d', self.tmpdir, wf, self.addr_idx_list ] )
 		t.license()
 		t.expect_getend(f'Valid {wcls.desc} for Seed ID ')
 		vmsg('Comparing generated checksum with checksum from previous address file')
-		chk = t.expect_getend(r'Checksum for address data .*?: ',regex=True)
-		if stdout:
-			t.read()
-		verify_checksum_or_exit(self._get_addrfile_checksum(),chk)
-		if in_fmt != 'seed':
+		verify_checksum_or_exit(
+			self._get_addrfile_checksum(),
+			t.expect_getend(r'Checksum for address data .*?: ',regex=True) )
+		if not stdout:
 			t.no_overwrite()
 			t.req_exit_val = 1
 		return t

+ 3 - 3
test/test_py_d/ts_ref_3seed.py

@@ -67,7 +67,7 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared):
 		('ref_walletconv_plainhexseed',([],'wallet filename (plain hex seed)')),
 		('ref_walletconv_dieroll',     ([],'wallet filename (dieroll (b6d) seed)')),
 		('ref_walletconv_incog',       ([],'wallet filename (incog)')),
-		('ref_walletconv_xincog',      ([],'wallet filename (hex incog)')),
+		('ref_walletconv_hexincog',    ([],'wallet filename (hex incog)')),
 	)
 
 	def __init__(self,trunner,cfgs,spawn):
@@ -135,7 +135,7 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared):
 		hp_arg = f'-p{ref_wallet_hash_preset}'
 		label = f'test.py ref. wallet (pw {ref_wallet_brainpass!r}, seed len {self.seed_len}) α'
 		bf = 'ref.mmbrain'
-		args = ['-d',self.tmpdir,hp_arg,sl_arg,'-ib','-L',label]
+		args = ['-d',self.tmpdir,hp_arg,sl_arg,'-ibw','-L',label]
 		self.write_to_tmpfile(bf,ref_wallet_brainpass)
 		self.write_to_tmpfile(pwfile,self.wpasswd)
 		t = self.spawn('mmgen-walletconv', args + [self.usr_rand_arg])
@@ -190,7 +190,7 @@ class TestSuiteRef3Seed(TestSuiteBase,TestSuiteShared):
 		pat = r'{}-[0-9A-F]{{8}}-[0-9A-F]{{8}}\[{},1\]' + ('-α' if g.debug_utf8 else '') + '.' + ext
 		return self.ref_walletconv(ofmt=ofmt,extra_args=args,re_pat=pat)
 
-	def ref_walletconv_xincog(self):
+	def ref_walletconv_hexincog(self):
 		return self.ref_walletconv_incog(ofmt='incog_hex',ext='mmincox')
 
 class TestSuiteRef3Addr(TestSuiteRef3Seed):

+ 1 - 2
test/test_py_d/ts_seedsplit.py

@@ -112,8 +112,7 @@ class TestSuiteSeedSplit(TestSuiteBase):
 			pat = f'master share #{master}'
 		t.expect(pat,regex=True)
 		ocls = Wallet.fmt_code_to_type(ofmt)
-		pw = issubclass(ocls,WalletEnc)
-		if pw:
+		if issubclass(ocls,WalletEnc):
 			t.hash_preset('new '+ocls.desc,'1')
 			t.passphrase_new('new '+ocls.desc,sh1_passwd)
 			if ocls == IncogWalletHidden:

+ 4 - 5
test/test_py_d/ts_shared.py

@@ -168,8 +168,7 @@ class TestSuiteShared(object):
 		t.license()
 		t.view_tx(view)
 		wcls = MMGenWallet if dfl_wallet else Wallet.ext_to_type(get_extension(wf))
-		pw = issubclass(wcls,WalletEnc) and wcls != Brainwallet
-		if pw:
+		if issubclass(wcls,WalletEnc) and wcls != Brainwallet:
 			t.passphrase(wcls.desc,self.wpasswd)
 		if save:
 			self.txsign_end(t,has_label=has_label)
@@ -194,12 +193,12 @@ class TestSuiteShared(object):
 				extra_desc=extra_desc)
 		if wcls != IncogWalletHidden:
 			t.expect(f"Getting {wcls.desc} from file '")
-		pw = issubclass(wcls,WalletEnc) and wcls != Brainwallet
-		if pw:
+		if issubclass(wcls,WalletEnc) and wcls != Brainwallet:
 			t.passphrase(wcls.desc,self.wpasswd)
 			t.expect(['Passphrase is OK', 'Passphrase.* are correct'],regex=True)
 		chk = t.expect_getend(f'Valid {wcls.desc} for Seed ID ')[:8]
-		if sid: cmp_or_die(chk,sid)
+		if sid:
+			cmp_or_die(chk,sid)
 		return t
 
 	def addrgen(self,wf,

+ 8 - 6
test/test_py_d/ts_wallet.py

@@ -106,7 +106,7 @@ class TestSuiteWalletConv(TestSuiteBase,TestSuiteShared):
 	def ref_dieroll_conv(self):  return self.ref_mn_conv(ext='b6d')
 
 	def ref_brain_conv(self):
-		uopts = ['-i','b','-p','1','-l',str(self.seed_len)]
+		uopts = ['-i','bw','-p','1','-l',str(self.seed_len)]
 		return self.walletconv_in(None,uopts,oo=True,icls=Brainwallet)
 
 	def ref_incog_conv(self,wfk='ic_wallet',in_fmt='i'):
@@ -121,7 +121,11 @@ class TestSuiteWalletConv(TestSuiteBase,TestSuiteShared):
 		ic_f = joinpath(ref_dir,self.sources[str(self.seed_len)][wfk])
 		uopts = ['-i','hi','-p','1','-l',str(self.seed_len)] + add_uopts
 		hi_opt = ['-H',f'{ic_f},{ref_wallet_incog_offset}']
-		return self.walletconv_in(None,uopts+hi_opt,oo=True,icls=IncogWalletHidden)
+		return self.walletconv_in(
+			None,
+			uopts + hi_opt,
+			oo = True,
+			icls = IncogWalletHidden )
 
 	def ref_hincog_conv_old(self):
 		return self.ref_hincog_conv(wfk='hic_wallet_old',add_uopts=['-O'])
@@ -178,8 +182,7 @@ class TestSuiteWalletConv(TestSuiteBase,TestSuiteShared):
 		icls = icls or Wallet.ext_to_type(get_extension(infile))
 		if icls == Brainwallet:
 			t.expect('Enter brainwallet: ',ref_wallet_brainpass+'\n')
-		pw = issubclass(icls,WalletEnc) and icls != Brainwallet
-		if pw:
+		if issubclass(icls,WalletEnc) and icls != Brainwallet:
 			t.passphrase(icls.desc,self.wpasswd)
 			if self.test_name[:19] == 'ref_hincog_conv_old':
 				t.expect('Is the Seed ID correct? (Y/n): ','\n')
@@ -202,8 +205,7 @@ class TestSuiteWalletConv(TestSuiteBase,TestSuiteShared):
 
 		add_args = [f'-l{self.seed_len}']
 		t.license()
-		pw = issubclass(wcls,WalletEnc) and wcls != Brainwallet
-		if pw:
+		if issubclass(wcls,WalletEnc) and wcls != Brainwallet:
 			t.passphrase_new('new '+wcls.desc,self.wpasswd)
 			t.usr_rand(self.usr_rand_chars)
 		if wcls in (IncogWallet,IncogWalletHex,IncogWalletHidden):

+ 2 - 1
test/tooltest2.py

@@ -33,7 +33,8 @@ sys.path.insert(0,overlay_setup(repo_root))
 
 from mmgen.common import *
 from test.include.common import *
-from mmgen.wallet import is_bip39_mnemonic,is_mmgen_mnemonic
+from mmgen.bip39 import is_bip39_mnemonic
+from mmgen.baseconv import is_mmgen_mnemonic
 from mmgen.xmrseed import is_xmrseed
 from mmgen.baseconv import *
 

+ 1 - 0
test/unit_tests_d/ut_dep.py

@@ -7,6 +7,7 @@ test.unit_tests_d.ut_dep: dependency unit tests for the MMGen suite
 """
 
 from mmgen.common import *
+from mmgen.exception import NoLEDSupport
 
 class unit_tests:
 

+ 1 - 0
test/unit_tests_d/ut_testdep.py

@@ -4,6 +4,7 @@ test.unit_tests_d.ut_testdep: test dependency unit tests for the MMGen suite
 """
 
 from mmgen.common import *
+from subprocess import run,PIPE
 
 sec = 'deadbeef' * 8
 

+ 3 - 3
test/unit_tests_d/ut_tx_deserialize.py

@@ -41,12 +41,12 @@ async def test_tx(tx_proto,tx_hex,desc,n):
 	dt = DeserializeTX(tx_proto,tx_hex)
 
 	if opt.verbose:
-		Msg('\n====================================================')
+		Msg('\n\n================================ Core vector: ==================================')
 	Msg_r('.' if opt.quiet else f'{n:>3}) {desc}\n')
 	if opt.verbose:
 		Pmsg(d)
-		Msg('----------------------------------------------------')
-		Pmsg(dt)
+		Msg('\n------------------------------ MMGen deserialized: -----------------------------')
+		Pmsg(dt._asdict())
 
 	# metadata
 	assert dt.txid == d['txid'],'TXID does not match'