Adds Settings option to enable CompactSeedQR; more test scenarios

Also misc cleanup, simplifications (f-strings in `settings_tools_view.py`.
This commit is contained in:
kdmukai
2022-01-21 17:20:38 -06:00
parent fede7f6f3c
commit e26ce3a0e6
10 changed files with 93 additions and 26 deletions
+2 -1
View File
@@ -12,4 +12,5 @@ camera_rotation = 0
network = main
software = Prompt
qr_density = 2
custom_derivation = m/0/0
custom_derivation = m/0/0
compact_seedqr_enabled = False
+10
View File
@@ -159,6 +159,8 @@ class Controller(Singleton):
ret_val = self.show_persistent_settings_tool()
elif ret_val == Path.CAMERA_ROTATION:
ret_val = self.show_camera_rotation_tool()
elif ret_val == Path.COMPACT_SEEDQR_ENABLED:
ret_val = self.show_compact_seedqr_enabled()
elif ret_val == Path.DONATE:
ret_val = self.show_donate_tool()
elif ret_val == Path.RESET:
@@ -1111,6 +1113,14 @@ class Controller(Singleton):
return Path.SETTINGS_SUB_MENU ### Show Donate Screen and QR
def show_compact_seedqr_enabled(self):
r = self.settings_tools_view.display_compact_seedqr_enabled()
if r is not None:
self.settings.compact_seedqr_enabled = r
return Path.SETTINGS_SUB_MENU ### Show Donate Screen and QR
def show_donate_tool(self):
self.settings_tools_view.display_donate_info_screen()
+1
View File
@@ -29,6 +29,7 @@ class Path:
QR_DENSITY_SETTING = 65
PERSISTENT_SETTINGS = 67
CAMERA_ROTATION = 69
COMPACT_SEEDQR_ENABLED = 70
RESET = 68
# Seed Slots
-3
View File
@@ -248,9 +248,6 @@ class CompactSeedQR(SeedQR):
for i in range(0, math.ceil(len(binary_str) / 8)):
# int conversion reads byte data as a string prefixed with '0b'
as_bytes.append(int('0b' + binary_str[i*8:(i+1)*8], 2))
print(f"num bytes: {len(as_bytes)}")
print(as_bytes)
# Must return data as `bytes` for `qrcode` to properly recognize it as byte data
return bytes(as_bytes)
+15 -3
View File
@@ -34,7 +34,8 @@ class Settings(Singleton):
'network': "main",
'software': "Specter Desktop",
'qr_density': EncodeQRDensity.MEDIUM,
'custom_derivation': 'm/0/0'
'custom_derivation': 'm/0/0',
'compact_seedqr_enabled': False,
}
}
@@ -51,12 +52,13 @@ class Settings(Singleton):
self._data["system"]["debug"] = config.getboolean("system", "debug")
self._data["system"]["default_language"] = config["system"]["default_language"]
self._data["display"]["text_color"] = config["display"]["text_color"]
self.qr_background_color = config["display"]["qr_background_color"]
self._data["display"]["camera_rotation"] = int(config["display"]["camera_rotation"])
self.network = config["wallet"]["network"]
self.software = config["wallet"]["software"]
self.qr_density = int(config["wallet"]["qr_density"])
self.custom_derivation = config["wallet"]["custom_derivation"]
self.qr_background_color = config["display"]["qr_background_color"]
self.compact_seedqr_enabled = config.getboolean("wallet", "compact_seedqr_enabled")
### persistent settings handling
@@ -225,7 +227,17 @@ class Settings(Singleton):
def custom_derivation(self, value):
# TODO: parse and validate custom derivation path
self._data["wallet"]["custom_derivation"] = value
self.__writeConfig()
@property
def compact_seedqr_enabled(self):
return self._data["wallet"]["compact_seedqr_enabled"]
@compact_seedqr_enabled.setter
def compact_seedqr_enabled(self, value):
self._data["wallet"]["compact_seedqr_enabled"] = value
self.__writeConfig()
@staticmethod
def calc_derivation(network, wallet_type, script_type):
if network == "main":
+17 -8
View File
@@ -124,13 +124,20 @@ class MenuView(View):
### Settings Menu
def display_settings_menu(self) -> int:
lines = ["... [ Return to Main ]", "Wallet: <wallet>", "Network: <network>", "QR Density: <density>", "Input / Output Tests", "Persistent Settings: <persistent>", "Camera Rotation", "Version Info", "Donate to SeedSigner", "Reset SeedSigner"]
lines = [
"... [ Return to Main ]",
f"Wallet: {Settings.get_instance().software}",
f"Network: {Settings.get_instance().network}",
f"QR Density: {Settings.get_instance().qr_density_name}",
"Input / Output Tests",
f"Persistent Settings: {Settings.get_instance().persistent_display}",
f"Camera Rotation: {Settings.get_instance().camera_rotation}°",
f"Compact SeedQR: {'Enabled' if Settings.get_instance().compact_seedqr_enabled else 'Disabled'}",
"Version Info",
"Donate to SeedSigner",
"Reset SeedSigner"
]
input = 0
lines[1] = lines[1].replace("<wallet>", Settings.get_instance().software)
lines[2] = lines[2].replace("<network>", Settings.get_instance().network)
lines[3] = lines[3].replace("<density>", Settings.get_instance().qr_density_name)
lines[5] = lines[5].replace("<persistent>", Settings.get_instance().persistent_display)
# Draw Menu
self.selected_menu_num = 1
@@ -159,10 +166,12 @@ class MenuView(View):
elif self.selected_menu_num == 7:
return Path.CAMERA_ROTATION
elif self.selected_menu_num == 8:
return Path.VERSION_INFO
return Path.COMPACT_SEEDQR_ENABLED
elif self.selected_menu_num == 9:
return Path.DONATE
return Path.VERSION_INFO
elif self.selected_menu_num == 10:
return Path.DONATE
elif self.selected_menu_num == 11:
return Path.RESET
raise Exception("Unhandled case")
+9 -3
View File
@@ -967,7 +967,10 @@ class SeedToolsView(View):
elif show_qr_option and ret_val == B.KEY_RIGHT:
# Show the resulting seed as a transcribable QR code
self.display_seed_qr_options(seed_phrase)
if self.controller.settings.compact_seedqr_enabled:
self.display_seed_qr_options(seed_phrase)
else:
self.seed_phrase_as_qr(seed_phrase)
# Signal success to move forward
return True
@@ -994,7 +997,10 @@ class SeedToolsView(View):
elif show_qr_option and ret_val == B.KEY_RIGHT:
# Show the resulting seed as a transcribable QR code
self.display_seed_qr_options(seed_phrase)
if self.controller.settings.compact_seedqr_enabled:
self.display_seed_qr_options(seed_phrase)
else:
self.seed_phrase_as_qr(seed_phrase)
# Signal success to move forward
return True
@@ -1025,7 +1031,7 @@ class SeedToolsView(View):
return None
def seed_phrase_as_qr(self, seed_phrase, is_compact_seedqr=True):
def seed_phrase_as_qr(self, seed_phrase, is_compact_seedqr=False):
if is_compact_seedqr:
e = EncodeQR(seed_phrase=seed_phrase, qr_type=QRType.COMPACTSEEDQR, wordlist=self.controller.settings.wordlist)
else:
+21 -7
View File
@@ -64,7 +64,6 @@ class SettingsToolsView(View):
return None
def display_persistent_settings(self) -> bool:
lines = ["... [ Return to Settings ]"]
lines.append("Yes")
lines.append("No")
@@ -82,10 +81,10 @@ class SettingsToolsView(View):
def display_camera_rotation(self) -> int:
lines = ["... [ Return to Settings ]"]
lines.append("0 (default)")
lines.append("90")
lines.append("180")
lines.append("270")
lines.append("0° (default)")
lines.append("90°")
lines.append("180°")
lines.append("270°")
r = self.controller.menu_view.display_generic_selection_menu(lines, "Camera Rotation")
if r == 1:
@@ -123,7 +122,6 @@ class SettingsToolsView(View):
###
### Custom Derivation Path
###
def draw_derivation_keyboard_entry(self, existing_derivation = "m/"):
def render_right_panel():
row_height = 28
@@ -273,4 +271,20 @@ class SettingsToolsView(View):
# Render the text entry display and cursor block
text_entry_display.render(self.derivation)
View.DispShowImage()
View.DispShowImage()
def display_compact_seedqr_enabled(self) -> bool:
lines = ["... [ Return to Settings ]"]
lines.append("Enable")
lines.append("Disable")
r = self.controller.menu_view.display_generic_selection_menu(lines, "Compact SeedQR")
if r == 1:
return None
elif r == 2:
return True
elif r == 3:
return False
else:
return None
+2 -1
View File
@@ -12,4 +12,5 @@ camera_rotation = 0
network = main
software = Prompt
qr_density = 2
custom_derivation = m/0/0
custom_derivation = m/0/0
compact_seedqr_enabled = False
+16
View File
@@ -77,6 +77,14 @@ def test_compact_seedqr_handles_null_bytes():
entropy = os.urandom(31) + b'\x00'
run_encode_decode_test(entropy, mnemonic_length=24, qr_type=QRType.COMPACTSEEDQR)
# 24-word seed, multiple null bytes
entropy = os.urandom(5) + b'\x00' + os.urandom(5) + b'\x00' + os.urandom(20)
run_encode_decode_test(entropy, mnemonic_length=24, qr_type=QRType.COMPACTSEEDQR)
# 24-word seed, multiple null bytes in a row
entropy = os.urandom(10) + b'\x00\x00' + os.urandom(20)
run_encode_decode_test(entropy, mnemonic_length=24, qr_type=QRType.COMPACTSEEDQR)
# 12-word seed, null bytes at the beginning
entropy = b'\x00' + os.urandom(15)
run_encode_decode_test(entropy, mnemonic_length=12, qr_type=QRType.COMPACTSEEDQR)
@@ -88,3 +96,11 @@ def test_compact_seedqr_handles_null_bytes():
# 12-word seed, null bytes at the end
entropy = os.urandom(15) + b'\x00'
run_encode_decode_test(entropy, mnemonic_length=12, qr_type=QRType.COMPACTSEEDQR)
# 12-word seed, multiple null bytes
entropy = os.urandom(5) + b'\x00' + os.urandom(5) + b'\x00' + os.urandom(4)
run_encode_decode_test(entropy, mnemonic_length=12, qr_type=QRType.COMPACTSEEDQR)
# 12-word seed, multiple null bytes in a row
entropy = os.urandom(10) + b'\x00\x00' + os.urandom(4)
run_encode_decode_test(entropy, mnemonic_length=12, qr_type=QRType.COMPACTSEEDQR)