Browse Source

mn_entry.py: select default entry mode with ENTER at prompt

The MMGen Project 4 years ago
parent
commit
685cbbc360
3 changed files with 34 additions and 16 deletions
  1. 25 10
      mmgen/mn_entry.py
  2. 1 1
      test/test_py_d/ts_autosign.py
  3. 8 5
      test/test_py_d/ts_input.py

+ 25 - 10
mmgen/mn_entry.py

@@ -241,7 +241,7 @@ class MnemonicEntry(object):
 		""",
 		""",
 	}
 	}
 	word_prompt = ('Enter word #{}: ','Incorrect entry. Repeat word #{}: ')
 	word_prompt = ('Enter word #{}: ','Incorrect entry. Repeat word #{}: ')
-	dfl_entry_mode = None
+	usr_dfl_entry_mode = None
 	_lw = None
 	_lw = None
 	_sw = None
 	_sw = None
 	_usl = None
 	_usl = None
@@ -319,21 +319,27 @@ class MnemonicEntry(object):
 				mode.name + ':',
 				mode.name + ':',
 				fmt(mode.choose_info,' '*14).lstrip().format(usl=self.uniq_ss_len),
 				fmt(mode.choose_info,' '*14).lstrip().format(usl=self.uniq_ss_len),
 			))
 			))
+		prompt = f'Type a number, or hit ENTER for the default ({capfirst(self.dfl_entry_mode)}): '
+		erase = '\r' + ' ' * (len(prompt)+19) + '\r'
 		while True:
 		while True:
-			uret = get_char('Entry mode: ')
-			if uret in [str(i) for i in range(1,len(em_objs)+1)]:
+			uret = get_char(prompt).strip()
+			if uret == '':
+				msg_r(erase)
+				return self.get_cls_by_entry_mode(self.dfl_entry_mode)(self)
+			elif uret in [str(i) for i in range(1,len(em_objs)+1)]:
+				msg_r(erase)
 				return em_objs[int(uret)-1]
 				return em_objs[int(uret)-1]
 			else:
 			else:
-				msg_r('\b {!r}: invalid choice '.format(uret))
+				msg_r(f'\b {uret!r}: invalid choice ')
 				time.sleep(g.err_disp_timeout)
 				time.sleep(g.err_disp_timeout)
-				msg_r('\r'+' '*38+'\r')
+				msg_r(erase)
 
 
 	def get_mnemonic_from_user(self,mn_len,validate=True):
 	def get_mnemonic_from_user(self,mn_len,validate=True):
 		mll = list(self.conv_cls.seedlen_map_rev[self.wl_id])
 		mll = list(self.conv_cls.seedlen_map_rev[self.wl_id])
 		assert mn_len in mll, '{}: invalid mnemonic length (must be one of {})'.format(mn_len,mll)
 		assert mn_len in mll, '{}: invalid mnemonic length (must be one of {})'.format(mn_len,mll)
 
 
-		if self.dfl_entry_mode:
-			em = self.get_cls_by_entry_mode(self.dfl_entry_mode)(self)
+		if self.usr_dfl_entry_mode:
+			em = self.get_cls_by_entry_mode(self.usr_dfl_entry_mode)(self)
 			i_add = ' (user-configured)'
 			i_add = ' (user-configured)'
 		else:
 		else:
 			em = self.choose_entry_mode()
 			em = self.choose_entry_mode()
@@ -342,7 +348,7 @@ class MnemonicEntry(object):
 		msg('\r' + 'Using {} entry mode{}'.format(cyan(em.name.upper()),i_add))
 		msg('\r' + 'Using {} entry mode{}'.format(cyan(em.name.upper()),i_add))
 		self.em = em
 		self.em = em
 
 
-		if not self.dfl_entry_mode:
+		if not self.usr_dfl_entry_mode:
 			m = (
 			m = (
 				fmt(self.prompt_info['intro'])
 				fmt(self.prompt_info['intro'])
 				+ '\n'
 				+ '\n'
@@ -371,7 +377,10 @@ class MnemonicEntry(object):
 
 
 		if validate:
 		if validate:
 			self.conv_cls.tohex(words,self.wl_id)
 			self.conv_cls.tohex(words,self.wl_id)
-			qmsg('Mnemonic is valid')
+			if self.has_chksum:
+				qmsg('Mnemonic is valid')
+			else:
+				qmsg('Mnemonic is well-formed (mnemonic format has no checksum to validate)')
 
 
 		return ' '.join(words)
 		return ' '.join(words)
 
 
@@ -395,22 +404,28 @@ class MnemonicEntry(object):
 			if v not in tcls.entry_modes:
 			if v not in tcls.entry_modes:
 				m = 'entry mode {!r} not recognized for wordlist {!r}:\n    (valid options: {})'
 				m = 'entry mode {!r} not recognized for wordlist {!r}:\n    (valid options: {})'
 				raise ValueError(m.format(v,k,fmt_list(tcls.entry_modes)))
 				raise ValueError(m.format(v,k,fmt_list(tcls.entry_modes)))
-			tcls.dfl_entry_mode = v
+			tcls.usr_dfl_entry_mode = v
 
 
 class MnemonicEntryMMGen(MnemonicEntry):
 class MnemonicEntryMMGen(MnemonicEntry):
 	wl_id = 'mmgen'
 	wl_id = 'mmgen'
 	modname = 'baseconv'
 	modname = 'baseconv'
 	entry_modes = ('full','minimal','fixed')
 	entry_modes = ('full','minimal','fixed')
+	dfl_entry_mode = 'minimal'
+	has_chksum = False
 
 
 class MnemonicEntryBIP39(MnemonicEntry):
 class MnemonicEntryBIP39(MnemonicEntry):
 	wl_id = 'bip39'
 	wl_id = 'bip39'
 	modname = 'bip39'
 	modname = 'bip39'
 	entry_modes = ('full','short','fixed')
 	entry_modes = ('full','short','fixed')
+	dfl_entry_mode = 'fixed'
+	has_chksum = True
 
 
 class MnemonicEntryMonero(MnemonicEntry):
 class MnemonicEntryMonero(MnemonicEntry):
 	wl_id = 'xmrseed'
 	wl_id = 'xmrseed'
 	modname = 'baseconv'
 	modname = 'baseconv'
 	entry_modes = ('full','short')
 	entry_modes = ('full','short')
+	dfl_entry_mode = 'short'
+	has_chksum = True
 
 
 try:
 try:
 	MnemonicEntry.get_cfg_vars()
 	MnemonicEntry.get_cfg_vars()

+ 1 - 1
test/test_py_d/ts_autosign.py

@@ -80,7 +80,7 @@ class TestSuiteAutosign(TestSuiteBase):
 			from mmgen.mn_entry import mn_entry
 			from mmgen.mn_entry import mn_entry
 			entry_mode = 'full'
 			entry_mode = 'full'
 			mne = mn_entry('mmgen',entry_mode)
 			mne = mn_entry('mmgen',entry_mode)
-			t.expect('Entry mode: ',str(mne.entry_modes.index(entry_mode)+1))
+			t.expect('Type a number.*: ',str(mne.entry_modes.index(entry_mode)+1),regex=True)
 			stealth_mnemonic_entry(t,mne,mn,entry_mode)
 			stealth_mnemonic_entry(t,mne,mn,entry_mode)
 			wf = t.written_to_file('Autosign wallet')
 			wf = t.written_to_file('Autosign wallet')
 			t.ok()
 			t.ok()

+ 8 - 5
test/test_py_d/ts_input.py

@@ -179,12 +179,15 @@ class TestSuiteInput(TestSuiteBase):
 			return ('skip_warn',m)
 			return ('skip_warn',m)
 		return self.password_entry('Enter passphrase (echoed): ',['--echo-passphrase'])
 		return self.password_entry('Enter passphrase (echoed): ',['--echo-passphrase'])
 
 
-	def _mn2hex(self,fmt,entry_mode='full',mn=None,pad_entry=False):
+	def _mn2hex(self,fmt,entry_mode='full',mn=None,pad_entry=False,enter_for_dfl=False):
 		mn = mn or sample_mn[fmt]['mn'].split()
 		mn = mn or sample_mn[fmt]['mn'].split()
 		t = self.spawn('mmgen-tool',['mn2hex_interactive','fmt='+fmt,'mn_len=12','print_mn=1'])
 		t = self.spawn('mmgen-tool',['mn2hex_interactive','fmt='+fmt,'mn_len=12','print_mn=1'])
 		from mmgen.mn_entry import mn_entry
 		from mmgen.mn_entry import mn_entry
 		mne = mn_entry(fmt,entry_mode)
 		mne = mn_entry(fmt,entry_mode)
-		t.expect('Entry mode: ',str(mne.entry_modes.index(entry_mode)+1))
+		t.expect(
+			'Type a number.*: ',
+			('\n' if enter_for_dfl else str(mne.entry_modes.index(entry_mode)+1)),
+			regex = True )
 		t.expect('Using (.+) entry mode',regex=True)
 		t.expect('Using (.+) entry mode',regex=True)
 		mode = strip_ansi_escapes(t.p.match.group(1)).lower()
 		mode = strip_ansi_escapes(t.p.match.group(1)).lower()
 		assert mode == mne.em.name.lower(), '{} != {}'.format(mode,mne.em.name.lower())
 		assert mode == mne.em.name.lower(), '{} != {}'.format(mode,mne.em.name.lower())
@@ -207,11 +210,11 @@ class TestSuiteInput(TestSuiteBase):
 		t.expect(wcls.choose_seedlen_prompt,'1')
 		t.expect(wcls.choose_seedlen_prompt,'1')
 		t.expect('(Y/n): ','y')
 		t.expect('(Y/n): ','y')
 		if wcls.wclass == 'mnemonic':
 		if wcls.wclass == 'mnemonic':
-			t.expect('Entry mode: ','6')
+			t.expect('Type a number.*: ','6',regex=True)
 			t.expect('invalid')
 			t.expect('invalid')
 			from mmgen.mn_entry import mn_entry
 			from mmgen.mn_entry import mn_entry
 			mne = mn_entry(fmt,entry_mode)
 			mne = mn_entry(fmt,entry_mode)
-			t.expect('Entry mode: ',str(mne.entry_modes.index(entry_mode)+1))
+			t.expect('Type a number.*: ',str(mne.entry_modes.index(entry_mode)+1),regex=True)
 			t.expect('Using (.+) entry mode',regex=True)
 			t.expect('Using (.+) entry mode',regex=True)
 			mode = strip_ansi_escapes(t.p.match.group(1)).lower()
 			mode = strip_ansi_escapes(t.p.match.group(1)).lower()
 			assert mode == mne.em.name.lower(), '{} != {}'.format(mode,mne.em.name.lower())
 			assert mode == mne.em.name.lower(), '{} != {}'.format(mode,mne.em.name.lower())
@@ -262,7 +265,7 @@ class TestSuiteInput(TestSuiteBase):
 	def mn2hex_interactive_mmgen_fixed(self): return self._mn2hex('mmgen',entry_mode='fixed')
 	def mn2hex_interactive_mmgen_fixed(self): return self._mn2hex('mmgen',entry_mode='fixed')
 	def mn2hex_interactive_bip39(self):       return self._mn2hex('bip39',entry_mode='full')
 	def mn2hex_interactive_bip39(self):       return self._mn2hex('bip39',entry_mode='full')
 	def mn2hex_interactive_bip39_short(self): return self._mn2hex('bip39',entry_mode='short',pad_entry=True)
 	def mn2hex_interactive_bip39_short(self): return self._mn2hex('bip39',entry_mode='short',pad_entry=True)
-	def mn2hex_interactive_bip39_fixed(self): return self._mn2hex('bip39',entry_mode='fixed')
+	def mn2hex_interactive_bip39_fixed(self): return self._mn2hex('bip39',entry_mode='fixed',enter_for_dfl=True)
 	def mn2hex_interactive_xmr(self):         return self._mn2hex('xmrseed',entry_mode='full')
 	def mn2hex_interactive_xmr(self):         return self._mn2hex('xmrseed',entry_mode='full')
 	def mn2hex_interactive_xmr_short(self):   return self._mn2hex('xmrseed',entry_mode='short')
 	def mn2hex_interactive_xmr_short(self):   return self._mn2hex('xmrseed',entry_mode='short')