fixes and cleanups throughout
This commit is contained in:
parent
f1844789d7
commit
fc87dcf0ba
19 changed files with 73 additions and 89 deletions
|
|
@ -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'])
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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'),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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__():
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue