async def add_dice_rolls(count, seed, judge_them): from main import dis from display import FontTiny, FontLarge md = tcc.sha256(seed) pr = PressRelease() # fixed parts of screen dis.clear() y = 38 dis.text(0, y, "Press 1-6 for each dice") y += 13 dis.text(0, y, "roll to mix in.") dis.save() while 1: # Note: cannot scroll this msg because 5=up arrow dis.restore() dis.text(None, 0, '%d rolls' % count, FontLarge) hx = str(b2a_hex(md.digest()), 'ascii') dis.text(0, 20, hx[0:32], FontTiny) dis.text(0, 20 + 7, hx[32:], FontTiny) dis.show() ch = await pr.wait() if ch in '123456': count += 1 dis.restore() dis.text(None, 0, '%d rolls' % count, FontLarge) dis.show() # this is slow enough to see md.update(ch) elif ch == 'x': # Because the change (roll) has already been applied, # only let them abort if it's early still if count < 10 and judge_them: return 0, seed elif ch == 'y': if count < 99 and judge_them: if not count: return 0, seed ok = await ux_confirm('''\ You only provided %d dice rolls, and each roll adds only 2.585 bits of entropy. \ For 128-bit security, which is considered the minimum, you need 50 rolls, and \ for 256-bits of security, 99 rolls.''' % count) if not ok: continue break if count: seed = md.digest() return count, seed
async def add_numbers(self, *a): # collect a series of digits from main import dis from display import FontTiny, FontSmall global pp_sofar # allow key repeat on X only press = PressRelease('1234567890y') footer = "X to DELETE, or OK when DONE." lx = 6 y = 16 here = '' dis.clear() dis.text(None, -1, footer, FontTiny) dis.save() while 1: dis.restore() # text centered msg = here by = y bx = dis.text(lx, y, msg[0:16]) dis.text(lx, y - 9, str(pp_sofar, 'ascii').replace(' ', '_'), FontTiny) if len(msg) > 16: # second line when needed (left just) by += 15 bx = dis.text(lx, by, msg[16:]) if len(here) < 32: dis.icon(bx, by - 2, 'sm_box') dis.show() ch = await press.wait() if ch == 'y': pp_sofar += here self.check_length() return elif ch == 'x': if here: here = here[0:-1] else: # quit if they press X on empty screen return else: if len(here) < 32: here += ch
def show_pin(self, show_hint=False): filled = len(self.pin) if show_hint: filled -= 1 hint = self.pin[-1] if not version.has_membrane else None dis.clear() if not self.pin_prefix: prompt="Enter PIN Prefix" else: prompt="Enter rest of PIN" if self.subtitle: dis.text(None, 0, self.subtitle) dis.text(None, 16, prompt, FontTiny) else: dis.text(None, 4, prompt) y = 27 w = 18 x = 12 for idx in range(filled): dis.icon(x, y, 'xbox') x += w if show_hint: if not version.has_membrane: dis.text(x+1, y+1, hint, FontLarge) dis.icon(x, y, 'box') else: dis.icon(x, y, 'tbox') else: if len(self.pin) != MAX_PIN_PART_LEN: dis.icon(x, y, 'box') # BTW: √ also works here, but looks like square root, not a checkmark if self.footer: footer = self.footer elif self.is_repeat: footer = "CONFIRM PIN VALUE" elif not self.pin_prefix: footer = "X to CANCEL, or OK when DONE" else: footer = "X to CANCEL, or OK to CONTINUE" dis.text(None, -1, footer, FontTiny) dis.show()
def redraw(self): # Redraw screen. from main import dis from display import FontSmall, FontTiny # what we are showing inside the QR msg = self.addrs[self.idx] # make the QR, if needed. if not self.qr_data: dis.busy_bar(True) self.render_qr(msg) # draw display dis.clear() w = 29 # because version=3 XO, YO = 7, 3 # offsets if not self.invert: dis.dis.fill_rect(XO - YO, 0, 64, 64, 1) data = self.qr_data inv = self.invert for x in range(w): for y in range(w): px = data[x][y] X = (x * 2) + XO Y = (y * 2) + YO dis.dis.fill_rect(X, Y, 2, 2, px if inv else (not px)) x, y = 73, 0 if self.is_alnum else 2 sidebar, ll = self.sidebar or (msg, 7) for i in range(0, len(sidebar), ll): dis.text(x, y, sidebar[i:i + ll], FontSmall) y += 10 if self.is_alnum else 12 if not inv and len(self.addrs) > 1: # show path number, very tiny ai = str(self.start_n + self.idx) if len(ai) == 1: dis.text(0, 30, ai[0], FontTiny) else: dis.text(0, 27, ai[0], FontTiny) dis.text(0, 27 + 7, ai[1], FontTiny) dis.busy_bar(False) # includes show
async def do_delay(self, pa): # show # of failures and implement the delay, which could be # very long. dis.clear() dis.text(None, 0, "Please Wait", FontLarge) dis.text(None, 24, pretty_delay(pa.delay_required * pa.seconds_per_tick)) dis.text(None, 40, "# of failures: %d" % pa.num_fails) while pa.is_delay_needed(): dis.progress_bar(pa.delay_achieved / pa.delay_required) dis.show() pa.delay() ch = ux_poll_once('x') if ch == 'x': return False return True