minor changes and fixes
This commit is contained in:
parent
94e02995de
commit
c82c9c5bd7
11 changed files with 54 additions and 42 deletions
|
|
@ -473,7 +473,8 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
|
|||
dmsg('Key {:>03}: {}'.format(pos,e.passwd))
|
||||
|
||||
out.append(e)
|
||||
if g.debug_addrlist: Msg('generate():\n{}'.format(e.pformat()))
|
||||
if g.debug_addrlist:
|
||||
Msg('generate():\n{}'.format(e.ppformat()))
|
||||
|
||||
qmsg('\r{}: {} {}{} generated{}'.format(
|
||||
self.al_id.hl(),t_addrs,self.gen_desc,suf(t_addrs,self.gen_desc_pl),' '*15))
|
||||
|
|
@ -577,7 +578,8 @@ Removed {{}} duplicate WIF key{{}} from keylist (also in {pnm} key-address file
|
|||
for n,e in enumerate(d,1):
|
||||
qmsg_r('\rGenerating addresses from keylist: {}/{}'.format(n,len(d)))
|
||||
e.addr = ag.to_addr(kg.to_pubhex(e.sec))
|
||||
if g.debug_addrlist: Msg('generate_addrs_from_keys():\n{}'.format(e.pformat()))
|
||||
if g.debug_addrlist:
|
||||
Msg('generate_addrs_from_keys():\n{}'.format(e.ppformat()))
|
||||
qmsg('\rGenerated addresses from keylist: {}/{} '.format(n,len(d)))
|
||||
|
||||
def format(self,enable_comments=False):
|
||||
|
|
|
|||
|
|
@ -303,7 +303,6 @@ class EthereumTokenTwUnspentOutputs(EthereumTwUnspentOutputs):
|
|||
|
||||
def get_display_precision(self): return 10 # truncate precision for narrow display
|
||||
|
||||
# NB: two wallet instances open simultaneously on the same data:
|
||||
def get_unspent_data(self):
|
||||
super().get_unspent_data()
|
||||
for e in self.unspent:
|
||||
|
|
|
|||
|
|
@ -118,14 +118,18 @@ def scrypt_hash_passphrase(passwd,salt,hash_preset,buflen=32):
|
|||
import scrypt
|
||||
return scrypt.hash(passwd,salt,2**N,r,p,buflen=buflen)
|
||||
|
||||
msg_r('Hashing passphrase...')
|
||||
if int(hash_preset) > 3:
|
||||
msg_r('Hashing passphrase, please wait...')
|
||||
|
||||
# hashlib.scrypt doesn't support N > 14 (hash preset 3)
|
||||
if N > 14 or g.force_standalone_scrypt_module:
|
||||
ret = do_standalone_scrypt()
|
||||
else:
|
||||
try: ret = do_hashlib_scrypt()
|
||||
except: ret = do_standalone_scrypt()
|
||||
msg('done')
|
||||
|
||||
if int(hash_preset) > 3:
|
||||
msg_r('\b'*34 + ' '*34 + '\b'*34)
|
||||
|
||||
return ret
|
||||
|
||||
|
|
|
|||
|
|
@ -765,28 +765,27 @@ class Mnemonic (SeedSourceUnenc):
|
|||
while True:
|
||||
r = get_char('\r'+prompt).decode()
|
||||
if r in urange: break
|
||||
msg_r('\r' + ' '*len(prompt) + '\r')
|
||||
msg_r(('\r','\n')[g.test_suite] + ' '*len(prompt) + '\r')
|
||||
return self.mn_lens[int(r)-1]
|
||||
|
||||
while True:
|
||||
mn_len = choose_mn_len()
|
||||
prompt = 'Mnemonic length of {} words chosen. OK?'.format(mn_len)
|
||||
if keypress_confirm(prompt,default_yes=True,no_nl=True): break
|
||||
|
||||
if keypress_confirm(prompt,default_yes=True,no_nl=not g.test_suite):
|
||||
break
|
||||
wl = baseconv.digits[self.wl_id]
|
||||
longest_word = max(len(w) for w in wl)
|
||||
from string import ascii_lowercase
|
||||
|
||||
m = 'Enter your {ml}-word mnemonic, hitting ENTER or SPACE after each word.\n'
|
||||
m = 'Enter your {ml}-word seed phrase, hitting ENTER or SPACE after each word.\n'
|
||||
m += "Optionally, you may use pad characters. Anything you type that's not a\n"
|
||||
m += 'lowercase letter will be treated as a {lq}pad character{rq}, i.e. it will simply\n'
|
||||
m += 'be discarded. Pad characters may be typed before, after, or in the middle\n'
|
||||
m += "of words. For each word, once you've typed {lw} characters total (including\n"
|
||||
m += 'pad characters) a pad character will enter the word.'
|
||||
m += 'pad characters) any pad character will enter the word.'
|
||||
|
||||
# pexpect chokes on these utf8 chars under MSYS2
|
||||
lq,rq = (('“','”'),('"','"'))[g.test_suite and g.platform=='win']
|
||||
|
||||
msg(m.format(ml=mn_len,lw=longest_word,lq=lq,rq=rq))
|
||||
|
||||
def get_word():
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ def _kb_hold_protect_unix():
|
|||
# as well as UTF8 chars (4 bytes max).
|
||||
def _get_keypress_unix(prompt='',immed_chars='',prehold_protect=True,num_chars=5):
|
||||
msg_r(prompt)
|
||||
sys.stderr.flush()
|
||||
timeout = float(0.3)
|
||||
fd = sys.stdin.fileno()
|
||||
old = termios.tcgetattr(fd)
|
||||
|
|
@ -81,7 +80,6 @@ def _get_keypress_unix(prompt='',immed_chars='',prehold_protect=True,num_chars=5
|
|||
|
||||
def _get_keypress_unix_raw(prompt='',immed_chars='',prehold_protect=None,num_chars=5):
|
||||
msg_r(prompt)
|
||||
sys.stderr.flush()
|
||||
fd = sys.stdin.fileno()
|
||||
old = termios.tcgetattr(fd)
|
||||
tty.setcbreak(fd)
|
||||
|
|
@ -91,7 +89,6 @@ def _get_keypress_unix_raw(prompt='',immed_chars='',prehold_protect=None,num_cha
|
|||
|
||||
def _get_keypress_unix_stub(prompt='',immed_chars='',prehold_protect=None,num_chars=None):
|
||||
msg_r(prompt)
|
||||
sys.stderr.flush()
|
||||
return sys.stdin.read(1).encode()
|
||||
|
||||
#_get_keypress_unix_stub = _get_keypress_unix
|
||||
|
|
@ -112,7 +109,6 @@ def _kb_hold_protect_mswin():
|
|||
def _get_keypress_mswin(prompt='',immed_chars='',prehold_protect=True,num_chars=None):
|
||||
|
||||
msg_r(prompt)
|
||||
sys.stderr.flush()
|
||||
timeout = float(0.5)
|
||||
|
||||
while True:
|
||||
|
|
@ -135,14 +131,12 @@ def _get_keypress_mswin(prompt='',immed_chars='',prehold_protect=True,num_chars=
|
|||
|
||||
def _get_keypress_mswin_raw(prompt='',immed_chars='',prehold_protect=None,num_chars=None):
|
||||
msg_r(prompt)
|
||||
sys.stderr.flush()
|
||||
ch = msvcrt.getch()
|
||||
if ch == b'\x03': raise KeyboardInterrupt
|
||||
return ch
|
||||
|
||||
def _get_keypress_mswin_stub(prompt='',immed_chars='',prehold_protect=None,num_chars=None):
|
||||
msg_r(prompt)
|
||||
sys.stderr.flush()
|
||||
return os.read(0,1)
|
||||
|
||||
def _get_terminal_size_linux():
|
||||
|
|
|
|||
|
|
@ -31,11 +31,13 @@ if g.platform == 'win':
|
|||
def msg_r(s):
|
||||
try:
|
||||
g.stderr.write(s)
|
||||
g.stderr.flush()
|
||||
except:
|
||||
os.write(2,s.encode())
|
||||
def Msg_r(s):
|
||||
try:
|
||||
g.stdout.write(s)
|
||||
g.stdout.flush()
|
||||
except:
|
||||
os.write(1,s.encode())
|
||||
def msg(s): msg_r(s + '\n')
|
||||
|
|
@ -300,16 +302,16 @@ class baseconv(object):
|
|||
|
||||
@classmethod
|
||||
def b58encode(cls,s,pad=None):
|
||||
pad = cls.get_pad(s,pad,'b58encode',cls.b58pad_lens,(bytes,))
|
||||
pad = cls._get_pad(s,pad,'b58encode',cls.b58pad_lens,(bytes,))
|
||||
return cls.fromhex(s.hex(),'b58',pad=pad,tostr=True)
|
||||
|
||||
@classmethod
|
||||
def b58decode(cls,s,pad=None):
|
||||
pad = cls.get_pad(s,pad,'b58decode',cls.b58pad_lens_rev,(bytes,str))
|
||||
pad = cls._get_pad(s,pad,'b58decode',cls.b58pad_lens_rev,(bytes,str))
|
||||
return bytes.fromhex(cls.tohex(s,'b58',pad=pad*2 if pad else None))
|
||||
|
||||
@staticmethod
|
||||
def get_pad(s,pad,op_desc,pad_map,ok_types):
|
||||
def _get_pad(s,pad,op_desc,pad_map,ok_types):
|
||||
if not isinstance(s,ok_types):
|
||||
m = "{}() input must be one of {}, not '{}'"
|
||||
raise ValueError(m.format(op_desc,repr([t.__name__ for t in ok_types]),type(s).__name__))
|
||||
|
|
@ -329,21 +331,21 @@ class baseconv(object):
|
|||
|
||||
@classmethod
|
||||
def check_wordlists(cls):
|
||||
for k,v in list(cls.wl_chksums.items()): assert cls.get_wordlist_chksum(k) == v
|
||||
for k,v in list(cls.wl_chksums.items()):
|
||||
res = cls.get_wordlist_chksum(k)
|
||||
assert res == v,'{}: checksum mismatch for {} (should be {})'.format(res,k,v)
|
||||
|
||||
@classmethod
|
||||
def check_wordlist(cls,wl_id):
|
||||
|
||||
wl = baseconv.digits[wl_id]
|
||||
Msg('Wordlist: {}\nLength: {} words'.format(capfirst(wl_id),len(wl)))
|
||||
wl = cls.digits[wl_id]
|
||||
qmsg('Wordlist: {}\nLength: {} words'.format(wl_id,len(wl)))
|
||||
new_chksum = cls.get_wordlist_chksum(wl_id)
|
||||
|
||||
a,b = 'generated checksum','saved checksum'
|
||||
a,b = 'generated','saved'
|
||||
compare_chksums(new_chksum,a,cls.wl_chksums[wl_id],b,die_on_fail=True)
|
||||
|
||||
Msg('Checksum {} matches'.format(new_chksum))
|
||||
Msg('List is sorted') if tuple(sorted(wl)) == wl else die(3,'ERROR: List is not sorted!')
|
||||
|
||||
qmsg('List is sorted') if tuple(sorted(wl)) == wl else die(3,'ERROR: List is not sorted!')
|
||||
|
||||
@classmethod
|
||||
def tohex(cls,words_arg,wl_id,pad=None):
|
||||
|
|
@ -362,6 +364,8 @@ class baseconv(object):
|
|||
|
||||
@classmethod
|
||||
def fromhex(cls,hexnum,wl_id,pad=None,tostr=False):
|
||||
if wl_id in ('electrum','tirosh'):
|
||||
assert tostr == False,"'tostr' must be False for '{}'".format(wl_id)
|
||||
|
||||
if not is_hex_str(hexnum):
|
||||
die(2,"{!r}: not a hexadecimal number".format(hexnum))
|
||||
|
|
|
|||
|
|
@ -94,7 +94,11 @@ def run_tests():
|
|||
msg_r('Testing: --coin {:4} {:22}'.format(coin.upper(),type_arg))
|
||||
p = subprocess.Popen(cmd.split(),stdout=subprocess.PIPE,stderr=subprocess.PIPE)
|
||||
o = p.stdout.read().decode()
|
||||
vmsg(o)
|
||||
err = p.stderr.read().decode()
|
||||
exit_val = p.wait()
|
||||
if exit_val != 0:
|
||||
ydie(2,'\nSpawned program exited with error code {}:\n{}'.format(exit_val,err))
|
||||
vmsg('\nCOMMAND OUTPUT:\n[{}]'.format(o))
|
||||
o = o.splitlines()
|
||||
d = [e for e in o if len(e) > 4 and e[:9] == 'sc_debug_']
|
||||
d.append('sc_debug_addr: ' + o[-2].split()[-1])
|
||||
|
|
@ -103,7 +107,7 @@ def run_tests():
|
|||
a = test_data[test][n]
|
||||
b = [e for e in d if e[:len(kk)] == kk][0][len(kk)+2:]
|
||||
if b == a:
|
||||
vmsg('sc_{}: {}'.format(k,a))
|
||||
vmsg('sc_debug_{}: {}'.format(k,a))
|
||||
else:
|
||||
rdie(1,'\nError: sc_{} value {} does not match reference value {}'.format(k,b,a))
|
||||
msg('OK')
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ non_mmgen_fn = 'coinkey'
|
|||
|
||||
ref_dir = os.path.join('test','ref')
|
||||
dfl_words_file = os.path.join(ref_dir,'98831F3A.mmwords')
|
||||
mn_words_mmgen = os.path.join(ref_dir,'FE3C6545.mmwords')
|
||||
|
||||
from mmgen.obj import MMGenTXLabel,TwComment
|
||||
|
||||
|
|
@ -146,23 +147,26 @@ def get_label(do_shuffle=False):
|
|||
label_iter = iter(labels)
|
||||
return next(label_iter)
|
||||
|
||||
def stealth_mnemonic_entry(t,mn):
|
||||
def stealth_mnemonic_entry(t,mn,fmt):
|
||||
wnum = 1
|
||||
max_wordlen = 12
|
||||
max_wordlen = { 'words': 12 }[fmt]
|
||||
|
||||
def get_pad_chars(n):
|
||||
ret = ''
|
||||
for i in range(n):
|
||||
m = int(os.urandom(1).hex(),16) % 32
|
||||
m = int.from_bytes(os.urandom(1),'big') % 32
|
||||
ret += r'123579!@#$%^&*()_+-=[]{}"?/,.<>|'[m]
|
||||
return ret
|
||||
|
||||
for i in range(len(mn)):
|
||||
w = mn[i]
|
||||
if len(w) > 5:
|
||||
if len(w) > (3,5)[max_wordlen==12]:
|
||||
w = w + '\n'
|
||||
else:
|
||||
w = get_pad_chars(3 if randbool() else 0) + w[0] + get_pad_chars(3) + w[1:] + get_pad_chars(7)
|
||||
w = (
|
||||
get_pad_chars(2 if randbool() else 0)
|
||||
+ w[0] + get_pad_chars(2) + w[1:]
|
||||
+ get_pad_chars(9) )
|
||||
w = w[:max_wordlen+1]
|
||||
em,rm = 'Enter word #{}: ','Repeat word #{}: '
|
||||
ret = t.expect((em.format(wnum),rm.format(wnum-1)))
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class TestSuiteAutosign(TestSuiteBase):
|
|||
mn_file = dfl_words_file
|
||||
mn = read_from_file(mn_file).strip().split()
|
||||
mn = ['foo'] + mn[:5] + ['realiz','realized'] + mn[5:]
|
||||
stealth_mnemonic_entry(t,mn)
|
||||
stealth_mnemonic_entry(t,mn,fmt='words')
|
||||
wf = t.written_to_file('Autosign wallet')
|
||||
t.ok()
|
||||
|
||||
|
|
|
|||
|
|
@ -141,20 +141,22 @@ class TestSuiteInput(TestSuiteBase):
|
|||
return 'skip' # pexpect double-escapes utf8, so skip
|
||||
return self.password_entry('Enter passphrase (echoed): ',['--echo-passphrase'])
|
||||
|
||||
def mnemonic_entry(self):
|
||||
mn = read_from_file(dfl_words_file).strip().split()[:12]
|
||||
mn = ['foo'] + mn[:5] + ['realiz','realized'] + mn[5:]
|
||||
t = self.spawn('mmgen-walletconv',['-S','-i','words','-o','words'])
|
||||
def _mnemonic_entry(self,fmt,wf):
|
||||
mn = read_from_file(wf).strip().split()
|
||||
mn = ['foo'] + mn[:5] + ['grac','graceful'] + mn[5:]
|
||||
t = self.spawn('mmgen-walletconv',['-S','-i',fmt,'-o',fmt])
|
||||
t.expect('words: ','1')
|
||||
t.expect('(Y/n): ','y')
|
||||
stealth_mnemonic_entry(t,mn)
|
||||
sid_chk = '5F9BC42F'
|
||||
stealth_mnemonic_entry(t,mn,fmt=fmt)
|
||||
sid_chk = 'FE3C6545'
|
||||
sid = t.expect_getend('Valid mnemonic data for Seed ID ')[:8]
|
||||
assert sid == sid_chk,'Seed ID mismatch! {} != {}'.format(sid,sid_chk)
|
||||
t.expect('to confirm: ','YES\n')
|
||||
t.read()
|
||||
return t
|
||||
|
||||
def mnemonic_entry(self): return self._mnemonic_entry('words',mn_words_mmgen)
|
||||
|
||||
class TestSuiteTool(TestSuiteMain,TestSuiteBase):
|
||||
"tests for interactive 'mmgen-tool' commands"
|
||||
networks = ('btc',)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class unit_test(object):
|
|||
seed2.subseeds._generate(10)
|
||||
assert len(ss2_list) == 10, len(ss2_list)
|
||||
|
||||
assert seed.pformat() == seed2.pformat()
|
||||
assert seed.ppformat() == seed2.ppformat()
|
||||
|
||||
s = seed.subseeds.format(1,g.subseeds)
|
||||
s_lines = s.strip().split('\n')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue