terminal-related fixes and cleanups
This commit is contained in:
parent
d8e1d5f88c
commit
656bb69587
6 changed files with 64 additions and 45 deletions
|
|
@ -152,8 +152,8 @@ def make_key(passwd,salt,hash_preset,desc='encryption key',from_what='passphrase
|
|||
dmsg('Key: {}'.format(key.hex()))
|
||||
return key
|
||||
|
||||
def _get_random_data_from_user(uchars,desc):
|
||||
m = 'Enter {r} random symbols' if opt.quiet else crmsg['usr_rand_notice']
|
||||
def _get_random_data_from_user(uchars,desc,test_suite=False):
|
||||
m = 'Enter {r} random symbols' if opt.quiet or test_suite else crmsg['usr_rand_notice']
|
||||
msg(m.format(r=uchars,d=desc))
|
||||
prompt = 'You may begin typing. {} symbols left: '
|
||||
|
||||
|
|
@ -165,15 +165,24 @@ def _get_random_data_from_user(uchars,desc):
|
|||
key_data += get_char_raw('\r'+prompt.format(uchars-i))
|
||||
time_data.append(time.time())
|
||||
|
||||
if opt.quiet: msg_r('\r')
|
||||
else: msg_r("\rThank you. That's enough.{}\n\n".format(' '*18))
|
||||
msg_r('\r' if opt.quiet else "\rThank you. That's enough.{}\n\n".format(' '*18))
|
||||
|
||||
fmt_time_data = list(map('{:.22f}'.format,time_data))
|
||||
dmsg('\nUser input:\n{!r}\nKeystroke time values:\n{}\n'.format(key_data,'\n'.join(fmt_time_data)))
|
||||
prompt = 'User random data successfully acquired. Press ENTER to continue'
|
||||
prompt_and_get_char(prompt,'',enter_ok=True)
|
||||
time_data = ['{:.22f}'.format(t).rstrip('0') for t in time_data]
|
||||
|
||||
return key_data.encode() + ''.join(fmt_time_data).encode()
|
||||
avg_prec = sum(len(t.split('.')[1]) for t in time_data) // len(time_data)
|
||||
if avg_prec < g.min_time_precision:
|
||||
m = 'WARNING: Avg. time precision of only {} decimal points. User entropy quality is degraded!'
|
||||
ymsg(m.format(avg_prec))
|
||||
|
||||
ret = key_data + '\n' + '\n'.join(time_data)
|
||||
|
||||
if g.debug:
|
||||
msg('USER ENTROPY (user input + keystroke timings):\n{}'.format(ret))
|
||||
|
||||
if not test_suite:
|
||||
my_raw_input('User random data successfully acquired. Press ENTER to continue: ')
|
||||
|
||||
return ret.encode()
|
||||
|
||||
def get_random(length):
|
||||
return add_user_random(os.urandom(length),'OS random data')
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ class g(object):
|
|||
http_timeout = 60
|
||||
err_disp_timeout = 0.7
|
||||
short_disp_timeout = 0.3
|
||||
min_time_precision = 18
|
||||
|
||||
# Variables - these might be altered at runtime:
|
||||
|
||||
|
|
|
|||
|
|
@ -344,8 +344,10 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
|
|||
no_output,oneshot_msg = False,None
|
||||
while True:
|
||||
msg_r('' if no_output else '\n\n' if opt.no_blank else CUR_HOME+ERASE_ALL)
|
||||
reply = get_char('' if no_output else self.format_for_display()+'\n'+(oneshot_msg or '')+prompt,
|
||||
immed_chars=''.join(self.key_mappings.keys()))
|
||||
reply = get_char(
|
||||
'' if no_output else self.format_for_display()+'\n'+(oneshot_msg or '')+prompt,
|
||||
immed_chars=''.join(self.key_mappings.keys())
|
||||
)
|
||||
no_output = False
|
||||
oneshot_msg = '' if oneshot_msg else None # tristate, saves previous state
|
||||
if reply not in self.key_mappings:
|
||||
|
|
|
|||
19
mmgen/tx.py
19
mmgen/tx.py
|
|
@ -1030,11 +1030,20 @@ Selected non-{pnm} inputs: {{}}""".strip().format(pnm=g.proj_name,pnl=g.proj_nam
|
|||
ask_tty=ask_tty,
|
||||
ask_write_default_yes=ask_write_default_yes)
|
||||
|
||||
def view_with_prompt(self,prompt=''):
|
||||
prompt += ' (y)es, (N)o, pager (v)iew, (t)erse view'
|
||||
reply = prompt_and_get_char(prompt,'YyNnVvTt',enter_ok=True)
|
||||
if reply and reply in 'YyVvTt':
|
||||
self.view(pager=reply in 'Vv',terse=reply in 'Tt')
|
||||
def view_with_prompt(self,prompt='',pause=True):
|
||||
prompt += ' (y)es, (N)o, pager (v)iew, (t)erse view: '
|
||||
from mmgen.term import get_char
|
||||
ok_chars = 'YyNnVvTt'
|
||||
while True:
|
||||
reply = get_char(prompt,immed_chars=ok_chars).strip('\n\r')
|
||||
msg('')
|
||||
if reply == '' or reply in 'Nn':
|
||||
break
|
||||
elif reply in 'YyVvTt':
|
||||
self.view(pager=reply in 'Vv',terse=reply in 'Tt',pause=pause)
|
||||
break
|
||||
else:
|
||||
msg('Invalid reply')
|
||||
|
||||
def view(self,pager=False,pause=True,terse=False):
|
||||
o = self.format_view(terse=terse)
|
||||
|
|
|
|||
|
|
@ -760,7 +760,7 @@ def keypress_confirm(prompt,default_yes=False,verbose=False,no_nl=False,complete
|
|||
|
||||
from mmgen.term import get_char
|
||||
while True:
|
||||
reply = get_char(p).strip('\n\r')
|
||||
reply = get_char(p,immed_chars='yYnN').strip('\n\r')
|
||||
if not reply:
|
||||
msg_r(nl)
|
||||
return True if default_yes else False
|
||||
|
|
@ -770,16 +770,6 @@ def keypress_confirm(prompt,default_yes=False,verbose=False,no_nl=False,complete
|
|||
else:
|
||||
msg_r('\nInvalid reply\n' if verbose else '\r')
|
||||
|
||||
def prompt_and_get_char(prompt,chars,enter_ok=False,verbose=False):
|
||||
|
||||
from mmgen.term import get_char
|
||||
while True:
|
||||
reply = get_char('{}: '.format(prompt)).strip('\n\r')
|
||||
if reply in chars or (enter_ok and not reply):
|
||||
msg('')
|
||||
return reply
|
||||
msg_r('\nInvalid reply\n' if verbose else '\r')
|
||||
|
||||
def do_pager(text):
|
||||
|
||||
pagers = ['less','more']
|
||||
|
|
|
|||
|
|
@ -67,22 +67,6 @@ def tt_my_raw_input():
|
|||
reply = my_raw_input('\nEnter text: ')
|
||||
confirm('Did you enter the text {!r}?'.format(reply))
|
||||
|
||||
def tt_prompt_and_get_char():
|
||||
cmsg('Testing prompt_and_get_char():')
|
||||
m = 'Type some letters besides "x" or "z", then "x" or "z"'
|
||||
reply = prompt_and_get_char(m,'xz')
|
||||
confirm('Did you enter the letter {!r}?'.format(reply))
|
||||
|
||||
def tt_prompt_and_get_char_enter_ok():
|
||||
cmsg('Testing prompt_and_get_char() with blank choices and enter_ok=True:')
|
||||
for m in (
|
||||
'Type ENTER',
|
||||
'Type any letter followed by a pause, followed by ENTER',
|
||||
):
|
||||
reply = prompt_and_get_char(m,'',enter_ok=True)
|
||||
assert reply == ''
|
||||
msg('OK')
|
||||
|
||||
def tt_get_char(raw=False,one_char=False,sleep=0,immed_chars=''):
|
||||
fname = ('get_char','get_char_raw')[raw]
|
||||
fs = fmt("""
|
||||
|
|
@ -130,6 +114,30 @@ def tt_get_char(raw=False,one_char=False,sleep=0,immed_chars=''):
|
|||
except KeyboardInterrupt:
|
||||
msg('\nDone')
|
||||
|
||||
def tt_urand():
|
||||
cmsg('Testing _get_random_data_from_user():')
|
||||
from mmgen.crypto import _get_random_data_from_user
|
||||
ret = _get_random_data_from_user(10,desc='data',test_suite=True).decode()
|
||||
msg('USER ENTROPY (user input + keystroke timings):\n\n{}'.format(fmt(ret,' ')))
|
||||
times = ret.splitlines()[1:]
|
||||
avg_prec = sum(len(t.split('.')[1]) for t in times) // len(times)
|
||||
if avg_prec < g.min_time_precision:
|
||||
m = 'WARNING: Avg. time precision of only {} decimal points. User entropy quality is degraded!'
|
||||
ymsg(m.format(avg_prec))
|
||||
else:
|
||||
msg('Average time precision: {} decimal points - OK'.format(avg_prec))
|
||||
my_raw_input('Press ENTER to continue: ')
|
||||
|
||||
def tt_txview():
|
||||
cmsg('Testing tx.view_with_prompt() (try each viewing option)')
|
||||
from mmgen.tx import MMGenTX
|
||||
fn = 'test/ref/0B8D5A[15.31789,14,tl=1320969600].rawtx'
|
||||
tx = MMGenTX(fn,offline=True)
|
||||
while True:
|
||||
tx.view_with_prompt('View data for transaction?',pause=False)
|
||||
if not keypress_confirm('Continue testing transaction view?',default_yes=True):
|
||||
break
|
||||
|
||||
if g.platform == 'linux':
|
||||
import termios,atexit
|
||||
fd = sys.stdin.fileno()
|
||||
|
|
@ -142,8 +150,8 @@ tt_get_terminal_size()
|
|||
tt_color()
|
||||
tt_license()
|
||||
tt_my_raw_input()
|
||||
tt_prompt_and_get_char()
|
||||
tt_prompt_and_get_char_enter_ok()
|
||||
tt_urand()
|
||||
tt_txview()
|
||||
|
||||
tt_get_char(one_char=True)
|
||||
tt_get_char(one_char=True,sleep=1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue