From 801f507bb471b9b62e18e01a2c542a44a70eb221 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 5 Apr 2023 13:21:10 -0500 Subject: [PATCH 001/187] SFT-1618: handle errors in save_seed_task --- .../modules/flows/restore_seed_flow.py | 4 ++-- .../Passport/modules/tasks/save_seed_task.py | 22 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py index 6c7bcabba..dd8eb655d 100644 --- a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py @@ -91,7 +91,7 @@ async def invalid_seed(self): async def valid_seed(self): from foundation import bip39 - entropy = bytearray(33) # Includes and extra byte for the checksum bits + entropy = bytearray(33) # Includes an extra byte for the checksum bits len = bip39.mnemonic_to_bits(self.mnemonic, entropy) @@ -116,4 +116,4 @@ async def valid_seed(self): self.set_result(True) else: # WIP: This is not complete - offer backup? - pass + await ErrorPage('Unable to save seed.').show() diff --git a/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py b/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py index 80287b30b..66c50e598 100644 --- a/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py @@ -16,18 +16,22 @@ async def save_seed_task(on_done, seed_bits): from common import pa import stash - secret = SecretStash.encode(seed_bits=seed_bits) + try: + secret = SecretStash.encode(seed_bits=seed_bits) - pa.change(new_secret=secret) + pa.change(new_secret=secret) - # Recapture XFP, etc. for new secret - await pa.new_main_secret(secret) + # Recapture XFP, etc. for new secret + await pa.new_main_secret(secret) - # Check and reload secret - pa.reset() - pa.login() + # Check and reload secret + pa.reset() + pa.login() - with stash.SensitiveValues() as sv: - sv.capture_xpub(save=True) + with stash.SensitiveValues() as sv: + sv.capture_xpub(save=True) + except Exception as e: + await on_done(False) + return await on_done(None) From d8b34eb079cf102b4d35c655be991431276b39ad Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 5 Apr 2023 15:23:34 -0500 Subject: [PATCH 002/187] SFT-1618: fixed control flow in save_seed_task error handling --- ports/stm32/boards/Passport/modules/tasks/save_seed_task.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py b/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py index 66c50e598..6f06e815b 100644 --- a/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/save_seed_task.py @@ -30,6 +30,7 @@ async def save_seed_task(on_done, seed_bits): with stash.SensitiveValues() as sv: sv.capture_xpub(save=True) + except Exception as e: await on_done(False) return From 6b8880983a7ad9b4f69a364d9d2e9ebc25b03330 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 5 Apr 2023 16:29:12 -0500 Subject: [PATCH 003/187] SFT-1787: included SeedQR formats in ViewSeedWords flow --- .../modules/flows/initial_seed_setup_flow.py | 1 - .../modules/flows/view_seed_words_flow.py | 56 +++++++++++++++---- ports/stm32/boards/Passport/modules/menus.py | 5 +- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py index b51b860a3..f02fb032a 100644 --- a/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py @@ -3,7 +3,6 @@ # # initial_seed_setup_flow.py - Menu to let user choose seed setup method -from flows.view_seed_words_flow import ViewSeedWordsFlow import lvgl as lv from flows import Flow diff --git a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py index 91ef354d5..3f8100fd7 100644 --- a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py @@ -7,33 +7,69 @@ class ViewSeedWordsFlow(Flow): - def __init__(self, external_key=None): + def __init__(self, external_key=None, qr_option=False): self.external_key = external_key + self.qr_option = qr_option + self.mode = None + self.words = None super().__init__(initial_state=self.show_warning, name='ViewSeedWordsFlow') async def show_warning(self): from flows import SeedWarningFlow + from flows import GetSeedWordsFlow mention_passphrase = False if self.external_key else True result = await SeedWarningFlow(mention_passphrase=mention_passphrase).run() if not result: self.set_result(False) + return - self.goto(self.show_seed_words) + self.words = await GetSeedWordsFlow(self.external_key).run() - async def show_seed_words(self): - from flows import GetSeedWordsFlow - from pages import SeedWordsListPage, InfoPage - import stash + if self.words is None: + self.set_result(False) + return + + if self.qr_option: + self.goto(self.choose_mode) + else: + self.goto(self.show_seed_words) - words = await GetSeedWordsFlow(self.external_key).run() + async def choose_mode(self): + from pages import ChooserPage + from data_codecs.qr_type import QRType - if words is None: + options = [{'label': 'Seed Words', 'value': self.show_seed_words}, + {'label': 'Compact SeedQR', 'value': QRType.COMPACT_SEED_QR}, + {'label': 'SeedQr', 'value': QRType.SEED_QR}] + self.mode = await ChooserPage(card_header={'title': 'View'}, options=options).show() + if self.mode is None: self.set_result(False) return - result = await SeedWordsListPage(words=words).show() + if isinstance(self.mode, int): + self.goto(self.show_qr) + else: + self.goto(self.show_seed_words) + + async def show_qr(self): + from pages import ShowQRPage + import microns + + await ShowQRPage(qr_type=self.mode, qr_data=self.words, right_micron=microns.Checkmark).show() + self.goto(self.show_passphrase) + + async def show_seed_words(self): + from pages import SeedWordsListPage + + await SeedWordsListPage(words=self.words).show() + self.goto(self.show_passphrase) + + async def show_passphrase(self): + import stash + from pages import InfoPage + if stash.bip39_passphrase != '' and not self.external_key: await InfoPage(text='Passphrase: {}'.format(stash.bip39_passphrase)).show() - self.set_result(result) + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 0aba843db..0f9ba1190 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -227,7 +227,7 @@ def bitcoin_menu(): def security_menu(): - from flows import ChangePINFlow, SignTextFileFlow, ViewSeedWordsFlow, NewSeedFlow, RestoreSeedFlow + from flows import ChangePINFlow, SignTextFileFlow, NewSeedFlow, RestoreSeedFlow return [ {'icon': lv.ICON_SEED, 'label': 'Restore Seed', 'flow': RestoreSeedFlow, 'is_visible': lambda: not has_seed(), @@ -324,7 +324,8 @@ def advanced_menu(): return [ {'icon': lv.ICON_SETTINGS, 'label': 'Security Words', 'flow': ShowSecurityWordsSettingFlow}, {'icon': lv.ICON_SEED, 'label': 'View Seed Words', 'flow': ViewSeedWordsFlow, 'is_visible': has_seed, - 'statusbar': {'title': 'SEED WORDS', 'icon': lv.ICON_SEED}}, + 'statusbar': {'title': 'SEED WORDS', 'icon': lv.ICON_SEED}, + 'args': {'external_key': None, 'qr_option': True}}, {'icon': lv.ICON_ONE_KEY, 'label': 'Developer Pubkey', 'submenu': developer_pubkey_menu, 'statusbar': {'title': 'DEV. PUBKEY'}}, {'icon': lv.ICON_MICROSD, 'label': 'microSD', 'submenu': microsd_menu}, From fda7baa875dc23488f01291b94a5324128816a06 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 11 Apr 2023 16:32:44 -0500 Subject: [PATCH 004/187] SFT-1825: first pass read file flow --- ports/stm32/boards/Passport/manifest.py | 1 + .../boards/Passport/modules/flows/__init__.py | 1 + .../flows/casa_health_check_microsd_flow.py | 30 +++++-------- .../boards/Passport/modules/flows/flow.py | 13 ++++++ .../Passport/modules/flows/read_file_flow.py | 43 +++++++++++++++++++ .../modules/flows/save_to_microsd_flow.py | 15 +------ .../modules/flows/sign_psbt_microsd_flow.py | 10 ----- .../Passport/modules/tasks/read_file_task.py | 5 ++- 8 files changed, 73 insertions(+), 45 deletions(-) create mode 100644 ports/stm32/boards/Passport/modules/flows/read_file_flow.py diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index 88d716e5b..1348fbac5 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -126,6 +126,7 @@ 'flows/new_seed_flow.py', 'flows/connect_wallet_flow.py', 'flows/page_flow.py', + 'flows/read_file_flow.py', 'flows/remove_dev_pubkey_flow.py', 'flows/rename_account_flow.py', 'flows/rename_derived_key_flow.py', diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index b4b7d9497..791a1f8d8 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -51,6 +51,7 @@ from .new_derived_key_flow import * from .new_seed_flow import * from .connect_wallet_flow import * +from .read_file_flow import * from .remove_dev_pubkey_flow import * from .rename_account_flow import * from .rename_derived_key_flow import * diff --git a/ports/stm32/boards/Passport/modules/flows/casa_health_check_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/casa_health_check_microsd_flow.py index 4f2dad23e..4223e85ee 100644 --- a/ports/stm32/boards/Passport/modules/flows/casa_health_check_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/casa_health_check_microsd_flow.py @@ -4,8 +4,6 @@ # casa_health_check_flow.py - Scan and process a Casa health check QR code in `crypto-request` format from flows import Flow -from files import CardSlot, CardMissingError -from pages.insert_microsd_page import InsertMicroSDPage def is_health_check(filename, path=None): @@ -40,24 +38,16 @@ async def choose_file(self): self.goto(self.parse_message) async def parse_message(self): - from files import CardSlot - from pages import ErrorPage - - try: - with CardSlot() as _card: - with open(self.file_path, 'r') as fd: - try: - self.lines = fd.read().split('\n') - except Exception as e: - await ErrorPage(text='Health check format is invalid.').show() - self.set_result(False) - return - - self.goto(self.common_flow) - except CardMissingError: - result = await InsertMicroSDPage().show() - if not result: - self.back() + from flows import ReadFileFlow + + data = await ReadFileFlow(self.file_path, binary=False).run() + + if not data: + self.set_result(False) + return + + self.lines = data.split('\n') + self.goto(self.common_flow) async def common_flow(self): from flows import CasaHealthCheckCommonFlow diff --git a/ports/stm32/boards/Passport/modules/flows/flow.py b/ports/stm32/boards/Passport/modules/flows/flow.py index 88861b9ce..c01473c46 100644 --- a/ports/stm32/boards/Passport/modules/flows/flow.py +++ b/ports/stm32/boards/Passport/modules/flows/flow.py @@ -148,3 +148,16 @@ async def run(self): return self.result except Exception as e: handle_fatal_error(e) + + async def show_card_missing(self, automatic=False): + from pages import InsertMicroSDPage + + if automatic: + self.set_result(False) + return + + result = await InsertMicroSDPage().show() + if not result: + self.set_result(False) + else: + self.back() diff --git a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py new file mode 100644 index 000000000..00ab699f9 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py @@ -0,0 +1,43 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# read_file_flow.py - Read a file and handle errors + +from flows import Flow + + +class ReadFileFlow(Flow): + def __init__(self, file_path, binary=True, automatic=False): + self.file_path = file_path + self.binary = binary + self.automatic = automatic + super().__init__(initial_state=self.read_file, name='ReadFileFlow') + + async def read_file(self): + from utils import spinner_task + from tasks import read_file_task + from errors import Error + from pages import ErrorPage + + (data, error) = await spinner_task('Reading File', + read_file_task, + args=[self.file_path, self.binary]) + + if error is Error.MICROSD_CARD_MISSING: + # show_card_missing is a global flow state + self.goto(self.show_card_missing, self.automatic) + return + + if error is Error.FILE_READ_ERROR: + if not self.automatic: + await ErrorPage('Unable to read file from microSD card.').show() + self.set_result(None) + return + + if len(data) == 0: + if not self.automatic: + await ErrorPage('File is empty.').show() + self.set_result(None) + return + + self.set_result(data) diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index 7b6f0ecbc..7c01dff5f 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -62,10 +62,8 @@ async def save(self): break except CardMissingError: - if not self.automatic: - self.goto(self.show_card_missing) - else: - self.set_result(False) + # show_card_missing is a global flow state + self.goto(self.show_card_missing, self.automatic) return except Exception as e: @@ -88,12 +86,3 @@ async def success(self): right_micron=self.show_check) \ .show(auto_close_timeout=self.auto_timeout) self.set_result(True) - - async def show_card_missing(self): - from pages import InsertMicroSDPage - - result = await InsertMicroSDPage().show() - if not result: - self.set_result(False) - else: - self.goto(self.save) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py index c77075bea..e4e2cba1d 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py @@ -98,16 +98,6 @@ async def common_flow(self): self.psbt = result self.goto(self.write_signed_transaction) - async def show_card_missing(self): - - result = await InsertMicroSDPage().show() - if not result: - result = QuestionPage(text='Cancel signing this transaction?').show() - if result: - self.set_result(None) - - self.goto(self.write_signed_transaction) - async def write_signed_transaction(self): from files import securely_blank_file from pages import ErrorPage diff --git a/ports/stm32/boards/Passport/modules/tasks/read_file_task.py b/ports/stm32/boards/Passport/modules/tasks/read_file_task.py index b0b2c0f40..4d8cee447 100644 --- a/ports/stm32/boards/Passport/modules/tasks/read_file_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/read_file_task.py @@ -7,11 +7,12 @@ from files import CardSlot, CardMissingError -async def read_file_task(on_done, file_path): +async def read_file_task(on_done, file_path, binary=True): ''' NOTE: Assumes that that path above the leaf filename already exists.''' + mode = 'b' if binary else '' try: with CardSlot() as _card: - with open(file_path, 'rb') as fd: + with open(file_path, 'r' + mode) as fd: data = fd.read() await on_done(data, None) From 01084245071585ddcf0458a3972942f7a61ec8ec Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 11 Apr 2023 16:49:31 -0500 Subject: [PATCH 005/187] SFT-1825: error checked common insert SD prompt --- .../Passport/modules/flows/file_picker_flow.py | 16 ++++++---------- .../stm32/boards/Passport/modules/flows/flow.py | 4 ++-- .../modules/flows/save_to_microsd_flow.py | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py index 5a3466a76..007458a5a 100644 --- a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py @@ -47,7 +47,8 @@ def on_empty_sd_card_change(self, sd_card_present): else: self.reset_paths() self.status_page.set_result(None) - self.goto(self.show_insert_microsd_error) + # show_card_missing is a global flow state + self.goto(self.show_card_missing) return False async def on_empty_result(self, res): @@ -61,7 +62,8 @@ def on_exception(self, exception): def on_file_sd_card_change(self, sd_card_present): if not sd_card_present: self.reset_paths() - self.goto(self.show_insert_microsd_error) + # show_card_missing is a global flow state + self.goto(self.show_card_missing) return True async def on_file_result(self, res): @@ -108,7 +110,8 @@ async def show_file_picker(self): except CardMissingError: self.reset_paths() - self.goto(self.show_insert_microsd_error) + # show_card_missing is a global flow state + self.goto(self.show_card_missing) return is_root = active_path == CardSlot.get_sd_root() @@ -159,12 +162,5 @@ async def show_file_picker(self): if self.finished: return - async def show_insert_microsd_error(self): - result = await InsertMicroSDPage().show() - if not result: - self.set_result(None) - else: - self.goto(self.show_file_picker) - def reset_paths(self): self.paths = [self.initial_path] diff --git a/ports/stm32/boards/Passport/modules/flows/flow.py b/ports/stm32/boards/Passport/modules/flows/flow.py index c01473c46..379672825 100644 --- a/ports/stm32/boards/Passport/modules/flows/flow.py +++ b/ports/stm32/boards/Passport/modules/flows/flow.py @@ -149,10 +149,10 @@ async def run(self): except Exception as e: handle_fatal_error(e) - async def show_card_missing(self, automatic=False): + async def show_card_missing(self): from pages import InsertMicroSDPage - if automatic: + if hasattr(self, 'automatic') and self.automatic: self.set_result(False) return diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index 7c01dff5f..beb8cc402 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -63,7 +63,7 @@ async def save(self): except CardMissingError: # show_card_missing is a global flow state - self.goto(self.show_card_missing, self.automatic) + self.goto(self.show_card_missing) return except Exception as e: From 6d600f545d995e7483da109721b70f04d497d261 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 11 Apr 2023 16:55:35 -0500 Subject: [PATCH 006/187] SFT-1825: added note --- ports/stm32/boards/Passport/modules/flows/read_file_flow.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py index 00ab699f9..1f655cb72 100644 --- a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py @@ -19,6 +19,7 @@ async def read_file(self): from errors import Error from pages import ErrorPage + # TODO: make custom read task support for InstallDevPubkeyFLow and SignTextFileFlow (data, error) = await spinner_task('Reading File', read_file_task, args=[self.file_path, self.binary]) From 949b0f56c51520e456f6e1a5228630e2528966ab Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 11 Apr 2023 20:55:33 -0500 Subject: [PATCH 007/187] SFT-1825: added notes --- ports/stm32/boards/Passport/modules/flows/flow.py | 1 + .../stm32/boards/Passport/modules/flows/save_to_microsd_flow.py | 1 + 2 files changed, 2 insertions(+) diff --git a/ports/stm32/boards/Passport/modules/flows/flow.py b/ports/stm32/boards/Passport/modules/flows/flow.py index 379672825..a7841e607 100644 --- a/ports/stm32/boards/Passport/modules/flows/flow.py +++ b/ports/stm32/boards/Passport/modules/flows/flow.py @@ -158,6 +158,7 @@ async def show_card_missing(self): result = await InsertMicroSDPage().show() if not result: + # TODO: make result consistent with subclass return type self.set_result(False) else: self.back() diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index beb8cc402..18cbf0950 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -46,6 +46,7 @@ async def save(self): self.out_full, _ = card.pick_filename(self.filename, path) if self.data: + # TODO: turn this into the default write_fn with open(self.out_full, 'w' + self.mode) as fd: fd.write(self.data) written = True From 96a901c9d467a95d7ae9dc159c7f39a7f5608327 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 12 Apr 2023 15:40:13 -0500 Subject: [PATCH 008/187] SFT-1825: separated out read_fn from read_file_task, cleaned up excess CardSlot imports --- .../boards/Passport/modules/flows/read_file_flow.py | 5 +++-- .../Passport/modules/flows/sign_psbt_microsd_flow.py | 6 +----- .../boards/Passport/modules/tasks/read_file_task.py | 9 +++++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py index 1f655cb72..64e08cb19 100644 --- a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py @@ -7,10 +7,11 @@ class ReadFileFlow(Flow): - def __init__(self, file_path, binary=True, automatic=False): + def __init__(self, file_path, binary=True, automatic=False, read_fn=None): self.file_path = file_path self.binary = binary self.automatic = automatic + self.read_fn = read_fn super().__init__(initial_state=self.read_file, name='ReadFileFlow') async def read_file(self): @@ -22,7 +23,7 @@ async def read_file(self): # TODO: make custom read task support for InstallDevPubkeyFLow and SignTextFileFlow (data, error) = await spinner_task('Reading File', read_file_task, - args=[self.file_path, self.binary]) + args=[self.file_path, self.binary, self.read_fn]) if error is Error.MICROSD_CARD_MISSING: # show_card_missing is a global flow state diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py index e4e2cba1d..fc8483063 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py @@ -37,12 +37,8 @@ def __init__(self): async def choose_file(self): from flows import FilePickerFlow - from files import CardSlot - root_path = CardSlot.get_sd_root() - - result = await FilePickerFlow( - initial_path=root_path, show_folders=True, suffix='psbt', filter_fn=None).run() + result = await FilePickerFlow(show_folders=True, suffix='psbt', filter_fn=None).run() if result is None: self.set_result(False) return diff --git a/ports/stm32/boards/Passport/modules/tasks/read_file_task.py b/ports/stm32/boards/Passport/modules/tasks/read_file_task.py index 4d8cee447..abb1587f6 100644 --- a/ports/stm32/boards/Passport/modules/tasks/read_file_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/read_file_task.py @@ -7,13 +7,18 @@ from files import CardSlot, CardMissingError -async def read_file_task(on_done, file_path, binary=True): +def default_read_fn(fd): + return fd.read() + + +async def read_file_task(on_done, file_path, binary=True, read_fn=None): ''' NOTE: Assumes that that path above the leaf filename already exists.''' mode = 'b' if binary else '' + read_fn = read_fn or default_read_fn try: with CardSlot() as _card: with open(file_path, 'r' + mode) as fd: - data = fd.read() + data = read_fn(fd) await on_done(data, None) except CardMissingError: From a6440cc3fd985a3de5bc26320055b5723bf3bb47 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 12 Apr 2023 15:59:51 -0500 Subject: [PATCH 009/187] SFT-1825: removed unnecessary CardSlot import --- ports/stm32/boards/Passport/modules/flows/list_files_flow.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/list_files_flow.py b/ports/stm32/boards/Passport/modules/flows/list_files_flow.py index 4e670eaa2..d40b3fd05 100644 --- a/ports/stm32/boards/Passport/modules/flows/list_files_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/list_files_flow.py @@ -3,7 +3,6 @@ # # list_files_flow.py - Flow to let user view microSD card files and view the SHA256 of the chosen file -from files import CardSlot from flows import Flow, FilePickerFlow from pages import SuccessPage, ErrorPage, ProgressPage, InsertMicroSDPage from tasks import calculate_file_sha256_task @@ -24,9 +23,7 @@ async def on_done(self, digest, error=None): self.progress_page.set_result(error is None) async def choose_file(self): - root_path = CardSlot.get_sd_root() - - result = await FilePickerFlow(initial_path=root_path, show_folders=True, select_text='Info').run() + result = await FilePickerFlow(show_folders=True, select_text='Info').run() if result is None: self.set_result(False) return From f84234797aa8e0ef231eac4966d08fa6978ad0ab Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 12 Apr 2023 17:05:51 -0500 Subject: [PATCH 010/187] SFT-1825: show_card_missing returns types consistent with subclasses --- .../Passport/modules/flows/file_picker_flow.py | 2 ++ .../stm32/boards/Passport/modules/flows/flow.py | 17 ++++++++++++----- .../Passport/modules/flows/read_file_flow.py | 2 ++ .../modules/flows/save_to_microsd_flow.py | 2 ++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py index 007458a5a..d6698ae16 100644 --- a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py @@ -40,6 +40,8 @@ def __init__( self.status_page = None self.empty_result = None self.finished = False + # return_bool attribute required to use show_card_missing + self.return_bool = False def on_empty_sd_card_change(self, sd_card_present): if sd_card_present: diff --git a/ports/stm32/boards/Passport/modules/flows/flow.py b/ports/stm32/boards/Passport/modules/flows/flow.py index a7841e607..676c8a315 100644 --- a/ports/stm32/boards/Passport/modules/flows/flow.py +++ b/ports/stm32/boards/Passport/modules/flows/flow.py @@ -152,13 +152,20 @@ async def run(self): async def show_card_missing(self): from pages import InsertMicroSDPage + # This makes the return type consistent with the subclass + if hasattr(self, 'return_bool') and self.return_bool: + print("returning False") + result = False + else: + print("returning None") + result = None + if hasattr(self, 'automatic') and self.automatic: - self.set_result(False) + self.set_result(result) return - result = await InsertMicroSDPage().show() - if not result: - # TODO: make result consistent with subclass return type - self.set_result(False) + retry = await InsertMicroSDPage().show() + if not retry: + self.set_result(result) else: self.back() diff --git a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py index 64e08cb19..1a2c90fd7 100644 --- a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py @@ -12,6 +12,8 @@ def __init__(self, file_path, binary=True, automatic=False, read_fn=None): self.binary = binary self.automatic = automatic self.read_fn = read_fn + # return_bool attribute required to use show_card_missing + self.return_bool = False super().__init__(initial_state=self.read_file, name='ReadFileFlow') async def read_file(self): diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index 18cbf0950..a4575e899 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -27,6 +27,8 @@ def __init__(self, self.automatic = automatic self.auto_timeout = 1000 if automatic else None self.show_check = None if automatic else microns.Checkmark + # return_bool attribute required to use show_card_missing + self.return_bool = True super().__init__(initial_state=self.save, name='SaveToMicroSDFlow') async def save(self): From 550eda3234dd711917221c245be4be9dd78cd7fa Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 12 Apr 2023 17:09:11 -0500 Subject: [PATCH 011/187] SFT-1825: removed TODOs --- ports/stm32/boards/Passport/modules/flows/read_file_flow.py | 1 - .../stm32/boards/Passport/modules/flows/save_to_microsd_flow.py | 1 - 2 files changed, 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py index 1a2c90fd7..a68922c2c 100644 --- a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py @@ -22,7 +22,6 @@ async def read_file(self): from errors import Error from pages import ErrorPage - # TODO: make custom read task support for InstallDevPubkeyFLow and SignTextFileFlow (data, error) = await spinner_task('Reading File', read_file_task, args=[self.file_path, self.binary, self.read_fn]) diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index a4575e899..694b5183f 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -48,7 +48,6 @@ async def save(self): self.out_full, _ = card.pick_filename(self.filename, path) if self.data: - # TODO: turn this into the default write_fn with open(self.out_full, 'w' + self.mode) as fd: fd.write(self.data) written = True From bc424d43ed2dd38139c01a059908250ebec2d2ec Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Fri, 10 Mar 2023 13:55:29 +0100 Subject: [PATCH 012/187] SFT-1508: Fix FCC test flow Signed-off-by: Jean-Pierre De Jesus DIAZ --- ports/stm32/boards/Passport/manifest.py | 1 - ports/stm32/boards/Passport/manifest_dev.py | 1 + .../{flows => developer}/fcc_test_flow.py | 49 +++++++++---------- ports/stm32/boards/Passport/modules/menus.py | 3 +- .../modules/tasks/fcc_copy_files_task.py | 2 +- 5 files changed, 27 insertions(+), 29 deletions(-) rename ports/stm32/boards/Passport/modules/{flows => developer}/fcc_test_flow.py (56%) diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index 1348fbac5..c8c85881f 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -94,7 +94,6 @@ 'flows/export_multisig_microsd_flow.py', 'flows/export_multisig_qr_flow.py', 'flows/export_summary_flow.py', - # 'flows/fcc_test_flow.py', 'flows/file_picker_flow.py', 'flows/flow.py', 'flows/format_microsd_flow.py', diff --git a/ports/stm32/boards/Passport/manifest_dev.py b/ports/stm32/boards/Passport/manifest_dev.py index 665ff12f6..86b9743fc 100644 --- a/ports/stm32/boards/Passport/manifest_dev.py +++ b/ports/stm32/boards/Passport/manifest_dev.py @@ -9,6 +9,7 @@ 'developer/battery_page.py', 'developer/delete_derived_keys_flow.py', 'developer/developer_functions_flow.py', + 'developer/fcc_test_flow.py', 'developer/spin_delay_flow.py', )) diff --git a/ports/stm32/boards/Passport/modules/flows/fcc_test_flow.py b/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py similarity index 56% rename from ports/stm32/boards/Passport/modules/flows/fcc_test_flow.py rename to ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py index 98fa3194c..88f58aefb 100644 --- a/ports/stm32/boards/Passport/modules/flows/fcc_test_flow.py +++ b/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py @@ -7,7 +7,7 @@ import lvgl as lv from flows import Flow import microns -from pages import ScanQRPage, LongTextPage +from pages import ProgressPage, ScanQRPage from styles.colors import COPPER from tasks import fcc_copy_files_task from utils import start_task @@ -22,8 +22,8 @@ class FCCTestFlow(Flow): def __init__(self): - self.long_text_page = None super().__init__(initial_state=self.show_camera, name='FccTestFlow') + self.progress_page = None async def show_camera(self): result = await ScanQRPage().show(auto_close_timeout=_CAMERA_DISPLAY_DURATION_SECS) @@ -35,27 +35,24 @@ async def show_camera(self): self.goto(self.copy_files) async def copy_files(self): - self.long_text_page = LongTextPage( - card_header=('title': 'Copy Files'}, - text='Copying files from microSD to flash and back.', - show_progress=True, - left_micron=microns.Cancel, - right_micron=microns.Cancel) + self.progress_page = ProgressPage(card_header={'title': 'Copy Files'}, + text='Copying files from microSD to flash and back.', + left_micron=microns.Cancel, + right_micron=microns.Cancel) - self.copy_files_task = start_task( - fcc_copy_files_task( - CardSlot.get_file_path('fcc-file-copy-test.bin')[0], - file_size=_FILE_SIZE_TO_CREATE, - set_progress=self.long_text_page.set_progress, - set_message=self.long_text_page.set_message, - on_done=self.on_done)) + copy_files_task = start_task( + fcc_copy_files_task(CardSlot.get_file_path('fcc-file-copy-test.bin')[0], + _FILE_SIZE_TO_CREATE, + self.progress_page.set_progress, + self.progress_page.set_text, + self.on_done)) - result = await self.long_text_page.show() + result = await self.progress_page.show() if result is not None: - # User used a button to back out, so cancel the task and return from the page - self.copy_files_task.cancel() + # User used a button to back out, so cancel the task. and return from the page + copy_files_task.cancel() self.set_result(False) - self.long_text_page = None + self.progress_page = None return # NOTE: This sleep is necessary to avoid starting to animate to the next page @@ -65,15 +62,15 @@ async def copy_files(self): async def on_done(self, error): # If user backed out, long_text_page will be None, so nothing to do - if self.long_text_page is None: + if self.progress_page is None: return common.page_transition_dir = TRANSITION_DIR_POP if error is Error.MICROSD_CARD_MISSING: - self.long_text_page.set_icon(lv.LARGE_ICON_MICROSD, color=COPPER) - self.long_text_page.set_text('Please insert microSD card.') - self.long_text_page.set_result(None) + self.progress_page.set_icon(lv.LARGE_ICON_MICROSD, color=COPPER) + self.progress_page.set_text('Please insert microSD card.') + self.progress_page.set_result(None) else: - self.long_text_page.set_progress(100) - self.long_text_page.set_icon(lv.LARGE_ICON_SUCCESS) - self.long_text_page.set_result(None) + self.progress_page.set_progress(100) + self.progress_page.set_icon(lv.LARGE_ICON_SUCCESS) + self.progress_page.set_result(None) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 0f9ba1190..564b2af55 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -349,6 +349,7 @@ def developer_menu(): BatteryPage, DeleteDerivedKeysFlow, DeveloperFunctionsFlow, + FCCTestFlow, SpinDelayFlow, ) from pages import StatusPage, ShowQRPage @@ -371,9 +372,9 @@ def developer_menu(): {'icon': lv.ICON_SEED, 'label': 'New Seed', 'flow': NewSeedFlow, 'args': {'refresh_cards_when_done': True}}, {'icon': lv.ICON_ONE_KEY, 'label': 'Set PIN', 'flow': SetInitialPINFlow}, {'icon': lv.ICON_ERASE, 'label': 'Erase Child Keys', 'flow': DeleteDerivedKeysFlow}, + {'icon': lv.ICON_SETTINGS, 'label': 'FCC Test', 'flow': FCCTestFlow}, # {'icon': lv.ICON_SETTINGS, 'label': 'I\'m Busy!', 'page': LongTextPage, # 'args': {'show_busy': True, 'message': 'Signing Transaction...'}}, - # {'icon': lv.ICON_SETTINGS, 'label': 'FCC Test', 'flow': FCCTestFlow}, # {'icon': lv.ICON_ABOUT, 'label': 'Color Picker', 'page': ColorPickerPage}, # {'icon': lv.ICON_CHANGE_PIN, 'label': 'Enter PIN', 'page': PINEntryPage, # 'args': {'title': 'Enter Initial PIN'}}, diff --git a/ports/stm32/boards/Passport/modules/tasks/fcc_copy_files_task.py b/ports/stm32/boards/Passport/modules/tasks/fcc_copy_files_task.py index 13b99d000..45c92b92c 100644 --- a/ports/stm32/boards/Passport/modules/tasks/fcc_copy_files_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/fcc_copy_files_task.py @@ -9,7 +9,7 @@ from errors import Error -async def fcc_copy_files_task(file_path, file_size=1024, set_progress=None, set_text=None, on_done=None): +async def fcc_copy_files_task(file_path, file_size, set_progress, set_text, on_done): from common import sf # ========================================================================================================== From a07cf3a110d53ec8ac824279e055a094680e0a71 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Wed, 1 Mar 2023 11:36:13 +0100 Subject: [PATCH 013/187] SFT-1371: Add scan QR flow Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../boards/Passport/modules/flows/__init__.py | 1 + .../Passport/modules/flows/scan_qr_flow.py | 89 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index 791a1f8d8..de2b01e03 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -11,6 +11,7 @@ from .main_flow import * from .login_flow import * from .save_to_microsd_flow import * +from .scan_qr_flow import * from .backup_common_flow import * from .seed_warning_flow import * diff --git a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py new file mode 100644 index 000000000..943c83076 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py @@ -0,0 +1,89 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later + +from data_codecs.qr_type import QRType +from flows import Flow +from pages import ScanQRPage, ErrorPage +from foundation import ur + + +class ScanQRFlow(Flow): + """Flow to scan a QR code or animated QR codes""" + + def __init__(self, + auto_close_timeout=None, + qr_types=None, + ur_types=None, + data_description=None): + """ + Initialize the scan QR flow. + + :param auto_close_timeout: Timeout in seconds for the flow to + automatically close when nothing is scanned. + :param qr_types: List of supported QR types. + :param ur_types: List of supported UR types. + :raises ValueError: qr_types is provided but empty. + :raises ValueError: data_description is not provided. + """ + super().__init__(initial_state=self.scan, name='ScanQRFlow') + + self.auto_close_timeout = auto_close_timeout + self.qr_types = [QRType.QR] if qr_types is None else qr_types + self.ur_types = [] if ur_types is None else ur_types + self.data_description = data_description + self.data = None + + if len(self.qr_types) == 0: + raise ValueError('At least one QR type must be provided') + + if QRType.UR2 in self.qr_types and len(self.ur_types) == 0: + raise ValueError('At least one UR type must be provided') + + if self.data_description is None: + raise ValueError('Data description must be provided') + + async def scan(self): + result = await ScanQRPage().show(auto_close_timeout=self.auto_close_timeout) + + if result is None: + self.set_result(None) + return + + if result.is_failure(): + await ErrorPage(text='Unable to scan QR code.\n\n{}'.format(result.error)).show() + self.set_result(None) + return + + self.data = result.data + if isinstance(self.data, ur.Value): + self.goto(self.handle_ur) + else: + self.goto(self.handle_qr) + + async def handle_ur(self): + if QRType.UR2 not in self.qr_types: + await ErrorPage(text='Scan failed.\n' + 'Expected to scan a QR code containing ' + '{}.'.format(self.data_description)).show() + self.set_result(None) + return + + if self.data.ur_type() not in self.ur_types: + await ErrorPage(text='Scan failed.\n' + 'This type of UR is not expected in this context. ' + '{}.'.format(self.data_description)).show() + + self.set_result(None) + return + + self.set_result(self.data) + + async def handle_qr(self): + if QRType.QR not in self.qr_types: + await ErrorPage(text='Scan. failed.\n' + 'Expected to scan a Uniform Resource containing ' + '{}.'.format(self.data_description)).show() + self.set_result(None) + return + + self.set_result(self.data) From fe2a95d28d54dbdef97aadf7a55b7e616dbf97cd Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Fri, 10 Mar 2023 14:20:01 +0100 Subject: [PATCH 014/187] SFT-1509: Use ScanQRFlow in FCC test flow Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../boards/Passport/modules/developer/__init__.py | 1 + .../boards/Passport/modules/developer/fcc_test_flow.py | 10 ++++++---- ports/stm32/boards/Passport/modules/flows/__init__.py | 1 - 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/developer/__init__.py b/ports/stm32/boards/Passport/modules/developer/__init__.py index bcfa2032f..102e9880b 100644 --- a/ports/stm32/boards/Passport/modules/developer/__init__.py +++ b/ports/stm32/boards/Passport/modules/developer/__init__.py @@ -4,6 +4,7 @@ # __init__.py from .developer_functions_flow import * +from .fcc_test_flow import * from .spin_delay_flow import * from .delete_derived_keys_flow import * from .battery_page import * diff --git a/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py b/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py index 88f58aefb..e887153e2 100644 --- a/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py +++ b/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py @@ -5,9 +5,9 @@ from animations.constants import TRANSITION_DIR_POP import lvgl as lv -from flows import Flow +from flows import Flow, ScanQRFlow import microns -from pages import ProgressPage, ScanQRPage +from pages import ProgressPage from styles.colors import COPPER from tasks import fcc_copy_files_task from utils import start_task @@ -26,9 +26,11 @@ def __init__(self): self.progress_page = None async def show_camera(self): - result = await ScanQRPage().show(auto_close_timeout=_CAMERA_DISPLAY_DURATION_SECS) + result = await ScanQRFlow(auto_close_timeout=_CAMERA_DISPLAY_DURATION_SECS, + data_description='a normal QR code').run() + + # User used a button to back out if result is None: - # User used a button to back out self.set_result(False) return diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index de2b01e03..96572fd2b 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -37,7 +37,6 @@ from .export_multisig_microsd_flow import * from .export_multisig_qr_flow import * from .export_summary_flow import * -# from .fcc_test_flow import * from .selected_file_flow import * from .file_picker_flow import * from .format_microsd_flow import * From e6e4f4c5338d09fcf16540661ee6147f440df802 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Fri, 10 Mar 2023 14:24:12 +0100 Subject: [PATCH 015/187] SFT-1510: Use ScanQRFlow in multisig wallet import flow Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../import_multisig_wallet_from_qr_flow.py | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/import_multisig_wallet_from_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/import_multisig_wallet_from_qr_flow.py index fd9ffdbbb..6dd940c6d 100644 --- a/ports/stm32/boards/Passport/modules/flows/import_multisig_wallet_from_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/import_multisig_wallet_from_qr_flow.py @@ -13,29 +13,21 @@ def __init__(self): self.error = None async def scan_qr_code(self): - from pages import ScanQRPage, ErrorPage - from multisig_wallet import MultisigWallet + from data_codecs.qr_type import QRType from foundation import ur + from flows import ScanQRFlow + from multisig_wallet import MultisigWallet - result = await ScanQRPage().show() + result = await ScanQRFlow(qr_types=[QRType.UR2], + ur_types=[ur.Value.BYTES], + data_description='a multisig wallet configuration file').run() if result is None: self.set_result(False) return - elif result.is_failure(): - self.set_result(False) - await ErrorPage(text='Unable to scan QR code.').show() - return - - if not isinstance(result.data, ur.Value): - await ErrorPage(text='Bad QR format.').show() - return - - data = result.data.unwrap_bytes() - if isinstance(data, (bytes, bytearray)): - data = data.decode('utf-8') try: - self.ms = await MultisigWallet.from_file(data) + file = result.unwrap_bytes().decode('utf-8') + self.ms = await MultisigWallet.from_file(file) except BaseException as e: if e.args is None or len(e.args) == 0: self.error = "Multisig Import Error" @@ -43,7 +35,6 @@ async def scan_qr_code(self): self.error = e.args[0] self.goto(self.show_error) return - # print('New MS: {}'.format(self.ms.serialize())) self.goto(self.do_import) From 94d702fd35d6c7a9f469d614f61edaad35dcf65d Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Wed, 1 Mar 2023 11:37:03 +0100 Subject: [PATCH 016/187] SFT-1511: Use ScanQRFlow in sign PSBT flow Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../modules/flows/sign_psbt_qr_flow.py | 70 ++++++++----------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index a8251afea..a68808073 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -3,7 +3,8 @@ # # sign_psbt_qr_flow.py - Sign a PSBT from a microSD card -from flows import Flow +from flows import Flow, ScanQRFlow +from data_codecs.qr_type import QRType from foundation import FixedBytesIO, ur from passport import mem from pages import ErrorPage @@ -12,50 +13,35 @@ class SignPsbtQRFlow(Flow): def __init__(self): super().__init__(initial_state=self.scan_transaction, name='SignPsbtQRFlow') - self.psbt = None + self.raw_psbt = None self.ur_type = None + self.psbt = None async def scan_transaction(self): - from pages import ScanQRPage, ErrorPage - import microns - - # TODO: May need to set statusbar content here and restore it after - result = await ScanQRPage(right_micron=microns.Checkmark).show() + result = await ScanQRFlow(qr_types=[QRType.QR, QRType.UR2], + ur_types=[ur.Value.CRYPTO_PSBT, ur.Value.BYTES], + data_description='a PSBT file').run() if result is None: # User canceled the scan self.set_result(False) + return + + if isinstance(result, ur.Value): + self.ur_type = result.ur_type() + + if self.ur_type == ur.Value.CRYPTO_PSBT: + self.raw_psbt = result.unwrap_crypto_psbt() + elif self.ur_type == ur.Value.BYTES: + self.raw_psbt = result.unwrap_bytes() else: - # Got a scan result (aka QRScanResult). - if result.is_failure(): - # Unable to scan QR code - show error? - await ErrorPage(text='Unable to scan QR code.\n\n{}'.format(result.error)).show() - self.set_result(False) - else: - # TODO: handle hex not only UR. Wasn't handled before the UR - # rework too. - if isinstance(result.data, ur.Value): - self.qr_type = result.qr_type - self.ur_type = result.data.ur_type() - - if self.ur_type == ur.Value.BYTES: - self.raw_psbt = result.data.unwrap_bytes() - elif self.ur_type == ur.Value.CRYPTO_PSBT: - self.raw_psbt = result.data.unwrap_crypto_psbt() - else: - await ErrorPage(text='The QR code does not contain a transaction.').show() - self.set_result(False) - return - - self.goto(self.copy_to_flash) - else: - await ErrorPage(text='The QR code does not contain a transaction.').show() - self.set_result(False) + self.raw_psbt = result + + self.goto(self.copy_to_flash) async def copy_to_flash(self): import gc from utils import spinner_task from tasks import copy_psbt_to_external_flash_task - from pages import ErrorPage from public_constants import TXN_INPUT_OFFSET from errors import Error @@ -72,6 +58,7 @@ async def copy_to_flash(self): self.set_result(False) return + self.raw_psbt = None gc.collect() # Try to avoid excessive fragmentation # PSBT was copied to external flash @@ -115,16 +102,19 @@ async def show_signed_transaction(self): self.psbt = None gc.collect() - if self.qr_type == QRType.QR: + if self.ur_type is None: + qr_type = QRType.QR qr_data = b2a_hex(signed_bytes) - elif self.qr_type == QRType.UR2 and self.ur_type == ur.Value.BYTES: - qr_data = ur.new_bytes(signed_bytes) - elif self.qr_type == QRType.UR2 and self.ur_type == ur.Value.CRYPTO_PSBT: - qr_data = ur.new_crypto_psbt(signed_bytes) else: - raise RuntimeException("Unsupported output format") + qr_type = QRType.UR2 + if self.ur_type == ur.Value.CRYPTO_PSBT: + qr_data = ur.new_bytes(signed_bytes) + elif self.ur_type == ur.Value.BYTES: + qr_data = ur.new_crypto_psbt(signed_bytes) + else: + raise RuntimeError('Unknown UR type: {}'.format(self.ur_type)) - await ShowQRPage(qr_type=self.qr_type, + await ShowQRPage(qr_type=qr_type, qr_data=qr_data, right_micron=microns.Checkmark).show() self.set_result(True) From 8fe06e39aa00cefcc369375f99fa527f8f23fb68 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Mon, 13 Mar 2023 19:32:30 +0100 Subject: [PATCH 017/187] SFT-1512: Use ask_to_skip in SCV flow Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../boards/Passport/modules/flows/scv_flow.py | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index 167bf74c9..76f2fdbf3 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -60,29 +60,7 @@ async def scan_qr_challenge(self): # User did not scan anything if result is None: - from pages import QuestionPage - if self.envoy: - cancel = await QuestionPage( - text='Cancel Envoy Setup?\n\n{}'.format( - recolor(HIGHLIGHT_TEXT_HEX, '(Not recommended)')) - ).show() - if cancel: - self.set_result(None) - else: - return - else: - if not self.ask_to_skip: - self.set_result(True) - else: - skip = await QuestionPage( - text='Skip Security Check?\n\n{}'.format( - recolor(HIGHLIGHT_TEXT_HEX, '(Not recommended)')) - ).show() - if skip: - common.settings.set('validated_ok', True) - self.set_result(True) - else: - self.back() + self.goto(self.ask_to_skip) return # Scan succeeded -- verify its content From f0497f49ab3a40777b2f01a65ef16c61986c844b Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Mon, 13 Mar 2023 19:26:04 +0100 Subject: [PATCH 018/187] SFT-1512: Remove duplicated imports in SCV Signed-off-by: Jean-Pierre De Jesus DIAZ --- ports/stm32/boards/Passport/modules/flows/scv_flow.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index 76f2fdbf3..5e58fc2e1 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -125,7 +125,6 @@ async def scan_qr_challenge(self): async def show_envoy_scan_msg(self): from pages import InfoPage - from utils import recolor result = await InfoPage( text='On Envoy, select {next}, and scan the following QR code.' @@ -202,9 +201,6 @@ async def ask_if_valid(self): self.goto(self.ask_to_skip) async def ask_to_skip(self): - from pages import QuestionPage - from utils import recolor - skip = await QuestionPage( text='Skip Security Check?\n\n{}'.format( recolor(HIGHLIGHT_TEXT_HEX, '(Not recommended)')) From 3157d345c30fbfdead67ad97ffa3c9b588c66ac4 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Mon, 13 Mar 2023 19:27:15 +0100 Subject: [PATCH 019/187] SFT-1512: Simplify intro text for SCV Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../boards/Passport/modules/flows/scv_flow.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index 5e58fc2e1..6ad1d43f8 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -36,19 +36,16 @@ def __init__(self, envoy=True, ask_to_skip=True): async def show_intro(self): from pages import ShieldPage - text = [] - # Only show the first item for manual flow - if not self.envoy: - text.append('Let\'s confirm Passport was not tampered with during shipping.') - if self.envoy: - text.append('On the next screen, scan the QR code shown in Envoy.') + text = 'On the next screen, scan the QR code shown in Envoy.' else: - text.append('On the next screen, scan the Security Check QR code from validate.foundationdevices.com.') + text = 'Let\'s confirm Passport was not tampered with during shipping.' \ + 'On the next screen, scan the Security Check ' \ + 'QR code from validate.foundationdevices.com.' - result = await ShieldPage( - text=text, - left_micron=microns.Back, right_micron=microns.Forward).show() + result = await ShieldPage(text=text, + left_micron=microns.Back, + right_micron=microns.Forward).show() if result: self.goto(self.scan_qr_challenge) else: From 144e71e106250bacf1e5bc819ced9744972a29dd Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Fri, 10 Mar 2023 14:58:15 +0100 Subject: [PATCH 020/187] SFT-1512: Use ScanQRFlow in SCV flow Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../boards/Passport/modules/flows/scv_flow.py | 113 +++++------------- 1 file changed, 29 insertions(+), 84 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index 6ad1d43f8..8ee8b08c4 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -4,12 +4,11 @@ # scv_flow.py - Supply Chain Validation Flow import lvgl as lv -from flows import Flow -from pages import ScanQRPage, ShowQRPage, QRScanResult -from pages.chooser_page import ChooserPage +from flows import Flow, ScanQRFlow +from pages import ShowQRPage, QuestionPage, ChooserPage from styles.colors import HIGHLIGHT_TEXT_HEX from data_codecs.qr_type import QRType -from utils import a2b_hex +from utils import a2b_hex, recolor from ubinascii import hexlify as b2a_hex from pincodes import PinAttempt from foundation import ur @@ -20,26 +19,25 @@ class ScvFlow(Flow): - def __init__(self, envoy=True, ask_to_skip=True): + def __init__(self, envoy=True): """ :param envoy: True for Envoy App flow. False is manual Supply Chain Validation. """ - super().__init__(initial_state=self.show_intro, name='ScvFlow') + super().__init__(initial_state=self.show_intro, + name='ScvFlow', + statusbar={'title': 'SECURITY CHECK', 'icon': lv.ICON_SHIELD}) self.words = None self.envoy = envoy - self.ask_to_skip = ask_to_skip self.uuid = None - self.statusbar = {'title': 'SECURITY CHECK', 'icon': lv.ICON_SHIELD} - async def show_intro(self): from pages import ShieldPage if self.envoy: text = 'On the next screen, scan the QR code shown in Envoy.' else: - text = 'Let\'s confirm Passport was not tampered with during shipping.' \ + text = 'Let\'s confirm Passport was not tampered with during shipping. ' \ 'On the next screen, scan the Security Check ' \ 'QR code from validate.foundationdevices.com.' @@ -52,69 +50,44 @@ async def show_intro(self): self.set_result(False) async def scan_qr_challenge(self): - from utils import recolor - result = await ScanQRPage(left_micron=microns.Cancel, right_micron=None).show() - - # User did not scan anything + qr_types = [QRType.UR2] if self.envoy else None + ur_types = [ur.Value.PASSPORT_REQUEST] if self.envoy else None + result = await ScanQRFlow(qr_types=qr_types, + ur_types=ur_types, + data_description='a supply chain validation challenge').run() if result is None: self.goto(self.ask_to_skip) return - # Scan succeeded -- verify its content - if self.envoy: - if not is_valid_envoy_qrcode(result): - await self.show_error(("Security Check QR code is invalid.\n" - "Make sure you're scanning an Envoy QR code.")) - return - else: - if not is_valid_website_qrcode(result): - await self.show_error(("Security Check QR code is invalid.\n" - "There was an error scanning the QR code.")) - return - if self.envoy: - passport_request = result.data.unwrap_passport_request() + passport_request = result.unwrap_passport_request() self.uuid = passport_request.uuid() - challenge = { - 'id': passport_request.scv_challenge_id(), - 'signature': passport_request.scv_challenge_signature(), - } + scv_id = passport_request.scv_challenge_id() + scv_signature = passport_request.scv_challenge_signature() else: + parts = result.split(' ') + if len(parts) != 2: + await self.show_error('Security Check QR code is invalid.\n' + 'There\'s not enough information in the QR code.') + return + try: - parts = result.data.split(' ') - if len(parts) != 2: - await self.show_error(("Security Check QR code is invalid.\n" - "There's not enough information in the QR code.")) - return - - challenge = { - 'id': parts[0], - 'signature': parts[1], - } - # print('Manual: challenge={}'.format(challenge)) - except Exception as e: - await self.show_error(("Security Check QR code is invalid.\n" - "Make sure you're scanning a manual setup QR code.")) + scv_id = a2b_hex(parts[0]) + scv_signature = b2a_hex(parts[1]) + except ValueError: + await self.show_error('Security Check QR code is invalid.\n') return id_hash = bytearray(32) - id_bin = a2b_hex(challenge['id']) if isinstance(challenge['id'], str) else challenge['id'] - id_hex = challenge['id'] if isinstance(challenge['id'], str) else b2a_hex(challenge['id']) - foundation.sha256(id_hex, - id_hash) - if isinstance(challenge['signature'], str): - signature = a2b_hex(challenge['signature']) - else: - signature = challenge['signature'] + foundation.sha256(b2a_hex(scv_id), id_hash) - signature_valid = passport.verify_supply_chain_server_signature(id_hash, signature) + signature_valid = passport.verify_supply_chain_server_signature(id_hash, scv_signature) if not signature_valid: await self.show_error('Security Check signature is invalid.') return - self.words = PinAttempt.supply_chain_validation_words(id_bin) - + self.words = PinAttempt.supply_chain_validation_words(scv_id) if self.envoy: self.goto(self.show_envoy_scan_msg) else: @@ -150,7 +123,6 @@ async def show_envoy_response(self): caption='Scan with Envoy', left_micron=microns.Back, right_micron=microns.Forward).show() - if not result: self.back() else: @@ -213,30 +185,3 @@ async def show_error(self, message): await InfoPage(text=message).show() self.reset(self.show_intro) - - -def is_valid_envoy_qrcode(result): - if not isinstance(result, QRScanResult): - return False - - if ( - (result.error is not None) or - (result.data is None) or - (not isinstance(result.data, ur.Value)) - ): - return False - - return True - - -def is_valid_website_qrcode(result): - if not isinstance(result, QRScanResult): - return False - - if ( - (result.error is not None) or - (result.data is None) - ): - return False - - return True From edfc6a30f4be853cac9c730ffdf02a1a2aba7769 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Fri, 10 Mar 2023 15:05:43 +0100 Subject: [PATCH 021/187] SFT-1513: Use ScanQRFlow in system camera test Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../modules/flows/system_test_camera_flow.py | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/system_test_camera_flow.py b/ports/stm32/boards/Passport/modules/flows/system_test_camera_flow.py index 2565c49d7..46b92a8f1 100644 --- a/ports/stm32/boards/Passport/modules/flows/system_test_camera_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/system_test_camera_flow.py @@ -3,31 +3,20 @@ # # system_test_camera_flow.py - Scans a QR code with the camera and shows the data in it -from flows import Flow -import microns -from pages import ScanQRPage -from pages import ErrorPage, SuccessPage, QuestionPage +from flows import Flow, ScanQRFlow +from pages import SuccessPage, QuestionPage +from foundation import ur class TestCameraFlow(Flow): - def __init__(self, card_header=None, statusbar=None): - super().__init__(initial_state=self.scan_qr, name='TestQrScanFlow') - self.card_header = card_header - self.statusbar = statusbar + def __init__(self): + super().__init__(initial_state=self.scan_qr, name='TestCameraFlow') async def scan_qr(self): - result = await ScanQRPage( - card_header=self.card_header, statusbar=self.statusbar, right_micron=microns.Cancel).show() + result = await ScanQRFlow(data_description='a normal QR code').run() if result is None: skip = await QuestionPage(text='Skip the Camera test?').show() self.set_result(skip) else: - # Got a scan result (aka QRScanResult): good data or error - if result.is_failure(): - # Unable to scan QR code - show error? - await ErrorPage(text='Unable to scan QR code.').show() - self.set_result(False) - else: - data = result.data - await SuccessPage(data).show() - self.set_result(True) + await SuccessPage(result).show() + self.set_result(True) From a2c0ac9a36df4ca58de6b16d81651a562361a78f Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Mon, 13 Mar 2023 19:46:15 +0100 Subject: [PATCH 022/187] SFT-1512: Use ErrorPage for errors in SCV Signed-off-by: Jean-Pierre De Jesus DIAZ --- ports/stm32/boards/Passport/modules/flows/scv_flow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index 8ee8b08c4..f3379749d 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -181,7 +181,7 @@ async def ask_to_skip(self): self.back() async def show_error(self, message): - from pages import InfoPage + from pages import ErrorPage - await InfoPage(text=message).show() + await ErrorPage(text=message).show() self.reset(self.show_intro) From 3055a50b4c64654b1e223c8bbce431d1cdc087af Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Wed, 19 Apr 2023 14:24:40 +0200 Subject: [PATCH 023/187] SFT-1371: Use ScanQRFlow in Casa health check Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../flows/casa_health_check_qr_flow.py | 73 ++++++++----------- 1 file changed, 32 insertions(+), 41 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/casa_health_check_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/casa_health_check_qr_flow.py index af87814f3..6e4344a40 100644 --- a/ports/stm32/boards/Passport/modules/flows/casa_health_check_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/casa_health_check_qr_flow.py @@ -16,58 +16,49 @@ class CasaHealthCheckQRFlow(Flow): def __init__(self): super().__init__(initial_state=self.scan_qr, name='CasaHealthCheckQRFlow') - self.lines = None - async def scan_qr(self): - from pages import ScanQRPage, ErrorPage - import microns + self.text = None + self.subpath = None - result = await ScanQRPage(right_micron=microns.Checkmark).show() + async def scan_qr(self): + from pages import ErrorPage + from flows import ScanQRFlow + result = await ScanQRFlow(qr_types=[QRType.UR2], + ur_types=[ur.Value.BYTES], + data_description='a Casa health check').run() if result is None: - # User canceled the scan self.set_result(False) - else: - # Got a scan result (aka QRScanResult). - if result.is_failure(): - await ErrorPage(text='Unable to scan QR code.\n\n{}'.format(result.error)).show() - self.set_result(False) - else: - if not isinstance(result.data, ur.Value): - await ErrorPage(text='Unable to scan QR code.\n\nNot a Uniform Resource.').show() - self.set_result(False) - return - - try: - data = result.data.unwrap_bytes() - self.lines = data.decode('utf-8').split('\n') - except Exception as e: - await ErrorPage('Health check format is invalid.').show() - return - if len(self.lines) != 2: - await ErrorPage('Health check format is invalid.').show() - self.set_result(False) - return + return - # Common function to validate the message - self.text = self.lines[0] - self.subpath = self.lines[1] - # print('text={}'.format(self.text)) - # print('subpath={}'.format(self.subpath)) + try: + data = result.unwrap_bytes().decode('utf-8') + lines = data.split('\n') + if len(lines) != 2: + await ErrorPage('Health check format is invalid.').show() + self.set_result(False) + return - # Validate - (subpath, error) = validate_sign_text(self.text, self.subpath) - if error is not None: - await ErrorPage(text=error).show() - self.set_result(False) - return + self.text = lines[0] + self.subpath = lines[1] + except Exception as e: + await ErrorPage('Health check format is invalid.').show() + self.set_result(False) + return - self.subpath = subpath + # Validate + (subpath, error) = validate_sign_text(self.text, self.subpath) + if error is not None: + await ErrorPage(text=error).show() + self.set_result(False) + return - self.goto(self.sign_health_check) + self.subpath = subpath + self.goto(self.sign_health_check) async def sign_health_check(self): - (signature, address, error) = await spinner_task('Performing Health Check', sign_text_file_task, + (signature, address, error) = await spinner_task('Performing Health Check', + sign_text_file_task, args=[self.text, self.subpath, AF_CLASSIC]) if error is None: self.signature = signature From 1e5942fe35cb1dc022fc92ae5e3674a694d6f013 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 19 Apr 2023 21:23:14 -0500 Subject: [PATCH 024/187] SFT-1924: fixed manifest --- ports/stm32/boards/Passport/manifest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index c8c85881f..a177b34da 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -113,6 +113,8 @@ 'flows/magic_scan_sign_psbt_flow.py', 'flows/magic_scan_validate_address_flow.py', + 'flows/scan_qr_flow.py', + 'flows/system_test_flow.py', 'flows/system_test_camera_flow.py', 'flows/system_test_microsd_flow.py', From 784867f6d3622c4d410f634326db418a449af6ab Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 20 Apr 2023 08:02:55 -0500 Subject: [PATCH 025/187] SFT-1928: added rule to prevent commits to main and dev-v* in pre-commit hook --- .githooks/pre-commit | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 1733dd505..146068e50 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -2,6 +2,12 @@ # SPDX-FileCopyrightText: 2021 Foundation Devices, Inc. # SPDX-License-Identifier: GPL-3.0-or-later +branch=`git symbolic-ref HEAD` +if [ "$branch" = "refs/heads/main" ] || [[ "$branch" == refs/heads/dev-v* ]]; then + echo "Direct commits to the main and dev branches are not allowed." + exit 1 +fi + RESULTS=$(find . -name '*.py' -exec grep -H fake_it[\ ]*=[\ ]*True {} +) LEN=`expr length "$RESULTS"` echo $RESULTS From 0fbd1e0c94547931f009124a6a13c624b073b5d3 Mon Sep 17 00:00:00 2001 From: Ken Carpenter Date: Thu, 20 Apr 2023 17:54:55 -0700 Subject: [PATCH 026/187] SFT-1825: fix 'just images for mono build Also, it now sorts the file list so output order is deterministic between developer machines --- ports/stm32/Justfile | 13 +- .../Passport/bootloader/images/images.h | 34 +-- ports/stm32/boards/Passport/images/images.h | 276 +++++++++--------- 3 files changed, 162 insertions(+), 161 deletions(-) diff --git a/ports/stm32/Justfile b/ports/stm32/Justfile index 82c6124c5..18c870bd7 100644 --- a/ports/stm32/Justfile +++ b/ports/stm32/Justfile @@ -208,14 +208,15 @@ graphics-c: # graphics: graphics-py graphics-c # Build all images. -images: (convert-images 'boards/Passport/images') (convert-images 'boards/Passport/bootloader/images') +images: (convert-images "boards/Passport/images" "true") (convert-images "boards/Passport/bootloader/images" "false") # LVGL Image Conversion Tool -convert-images image_path: +convert-images image_path process_mono='false': #!/usr/bin/python3 import os from os import listdir image_path = '{{image_path}}' + process_mono = '{{process_mono}}' conv_path = '../../../../../../tools/lv_img_conv/lv_img_conv.js' f = open(image_path + '/images.h', 'w') @@ -230,6 +231,7 @@ convert-images image_path: from shutil import copyfile full_folder = image_path + '/{}'.format(folder) image_filenames = [f for f in listdir(full_folder) if f.endswith('.png')] + image_filenames.sort() for filename in image_filenames: base = os.path.splitext(filename)[0] # Trim extension parts = base.split('__') @@ -277,9 +279,10 @@ convert-images image_path: handle_images('color') f.write('#endif\n\n') - f.write('#ifdef SCREEN_MODE_MONO\n') - handle_images('mono') - f.write('#endif\n\n') + if process_mono == "true": + f.write('#ifdef SCREEN_MODE_MONO\n') + handle_images('mono') + f.write('#endif\n\n') f.close() diff --git a/ports/stm32/boards/Passport/bootloader/images/images.h b/ports/stm32/boards/Passport/bootloader/images/images.h index 3a35b06e1..c7607305b 100644 --- a/ports/stm32/boards/Passport/bootloader/images/images.h +++ b/ports/stm32/boards/Passport/bootloader/images/images.h @@ -5,29 +5,27 @@ // #ifdef SCREEN_MODE_COLOR -extern const lv_img_dsc_t LARGE_ICON_ERROR; -extern const lv_img_dsc_t PROGRESS_CAP_RIGHT; -extern const lv_img_dsc_t PROGRESS_CAP_RIGHT_BG; -extern const lv_img_dsc_t PROGRESS_BAR_BG; -extern const lv_img_dsc_t ICON_EMAIL; extern const lv_img_dsc_t BACKGROUND; -extern const lv_img_dsc_t LARGE_ICON_INFO; -extern const lv_img_dsc_t LARGE_ICON_MICROSD; +extern const lv_img_dsc_t ICON_ABOUT; +extern const lv_img_dsc_t ICON_BACK; +extern const lv_img_dsc_t ICON_CANCEL; extern const lv_img_dsc_t ICON_CHECKMARK; -extern const lv_img_dsc_t ICON_FORWARD; -extern const lv_img_dsc_t LARGE_ICON_QUESTION; -extern const lv_img_dsc_t PROGRESS_CAP_LEFT; -extern const lv_img_dsc_t ICON_PAGE_DOT; +extern const lv_img_dsc_t ICON_EMAIL; extern const lv_img_dsc_t ICON_EXIT; -extern const lv_img_dsc_t SPLASH; +extern const lv_img_dsc_t ICON_FORWARD; extern const lv_img_dsc_t ICON_PAGE_DOT_SELECTED; -extern const lv_img_dsc_t ICON_CANCEL; +extern const lv_img_dsc_t ICON_PAGE_DOT; extern const lv_img_dsc_t ICON_RETRY; -extern const lv_img_dsc_t PROGRESS_BAR_FG; extern const lv_img_dsc_t ICON_SHUTDOWN; -extern const lv_img_dsc_t ICON_ABOUT; -extern const lv_img_dsc_t ICON_BACK; +extern const lv_img_dsc_t LARGE_ICON_ERROR; +extern const lv_img_dsc_t LARGE_ICON_INFO; +extern const lv_img_dsc_t LARGE_ICON_MICROSD; +extern const lv_img_dsc_t LARGE_ICON_QUESTION; +extern const lv_img_dsc_t PROGRESS_BAR_BG; +extern const lv_img_dsc_t PROGRESS_BAR_FG; +extern const lv_img_dsc_t PROGRESS_CAP_LEFT; +extern const lv_img_dsc_t PROGRESS_CAP_RIGHT_BG; +extern const lv_img_dsc_t PROGRESS_CAP_RIGHT; +extern const lv_img_dsc_t SPLASH; #endif -#ifdef SCREEN_MODE_MONO -#endif diff --git a/ports/stm32/boards/Passport/images/images.h b/ports/stm32/boards/Passport/images/images.h index 2aca8d234..886ae5f44 100644 --- a/ports/stm32/boards/Passport/images/images.h +++ b/ports/stm32/boards/Passport/images/images.h @@ -5,174 +5,174 @@ // #ifdef SCREEN_MODE_COLOR -extern const lv_img_dsc_t ICON_INPUT_MODE_UPPER_ALPHA; -extern const lv_img_dsc_t LARGE_ICON_ERROR; -extern const lv_img_dsc_t ICON_PAGE_QR_MD; -extern const lv_img_dsc_t ICON_EDIT2; -extern const lv_img_dsc_t ICON_INPUT_MODE_NUMERIC; -extern const lv_img_dsc_t ICON_ERASE; -extern const lv_img_dsc_t ICON_SETTINGS; -extern const lv_img_dsc_t ICON_PIN; -extern const lv_img_dsc_t ICON_DEVICE; -extern const lv_img_dsc_t ICON_WARNING; -extern const lv_img_dsc_t ICON_PAGE_QR_SM; +extern const lv_img_dsc_t ICON_ADD_ACCOUNT; +extern const lv_img_dsc_t ICON_ADVANCED; +extern const lv_img_dsc_t ICON_BACKUP; +extern const lv_img_dsc_t ICON_BACK; +extern const lv_img_dsc_t ICON_BATTERY_CHARGING; +extern const lv_img_dsc_t ICON_BATTERY; +extern const lv_img_dsc_t ICON_BITCOIN; extern const lv_img_dsc_t ICON_BRIGHTNESS; -extern const lv_img_dsc_t ICON_PAGE_DOT; -extern const lv_img_dsc_t ICON_PASSPHRASE; -extern const lv_img_dsc_t LARGE_ICON_INFO; -extern const lv_img_dsc_t LARGE_ICON_MICROSD; -extern const lv_img_dsc_t LARGE_ICON_FIRMWARE; +extern const lv_img_dsc_t ICON_CANCEL; +extern const lv_img_dsc_t ICON_CASA; extern const lv_img_dsc_t ICON_CHECKMARK; -extern const lv_img_dsc_t LARGE_ICON_SETUP_QR; -extern const lv_img_dsc_t ICON_FORWARD; -extern const lv_img_dsc_t ICON_PAGE_PLUS; -extern const lv_img_dsc_t ICON_ADVANCED; -extern const lv_img_dsc_t IMAGE_DIAGONAL_LINES; -extern const lv_img_dsc_t ICON_SPIRAL; -extern const lv_img_dsc_t ICON_ONE_KEY; -extern const lv_img_dsc_t LARGE_ICON_QUESTION; -extern const lv_img_dsc_t ICON_SHIELD; -extern const lv_img_dsc_t LARGE_ICON_CONNECT; -extern const lv_img_dsc_t ICON_PAGE_HOME; -extern const lv_img_dsc_t LARGE_ICON_SUCCESS; -extern const lv_img_dsc_t ICON_SETUP; -extern const lv_img_dsc_t ICON_NOSTR; -extern const lv_img_dsc_t ICON_VERIFY_ADDRESS; -extern const lv_img_dsc_t ICON_HEALTH_CHECK; +extern const lv_img_dsc_t ICON_CIRCLE_CHECK; +extern const lv_img_dsc_t ICON_CLOCK; +extern const lv_img_dsc_t ICON_CONNECT; +extern const lv_img_dsc_t ICON_COUNTDOWN; +extern const lv_img_dsc_t ICON_DEVICE; +extern const lv_img_dsc_t ICON_EDIT1; +extern const lv_img_dsc_t ICON_EDIT2; +extern const lv_img_dsc_t ICON_ERASE; +extern const lv_img_dsc_t ICON_EXTENSIONS; extern const lv_img_dsc_t ICON_FILE; -extern const lv_img_dsc_t LARGE_ICON_SHIELD; +extern const lv_img_dsc_t ICON_FIRMWARE; +extern const lv_img_dsc_t ICON_FOLDER; +extern const lv_img_dsc_t ICON_FORWARD; extern const lv_img_dsc_t ICON_HAMBURGER; +extern const lv_img_dsc_t ICON_HEALTH_CHECK; +extern const lv_img_dsc_t ICON_HOME; extern const lv_img_dsc_t ICON_INFO; -extern const lv_img_dsc_t ICON_CLOCK; -extern const lv_img_dsc_t ICON_CANCEL; -extern const lv_img_dsc_t ICON_MICROSD; -extern const lv_img_dsc_t LARGE_ICON_BRANDMARK; -extern const lv_img_dsc_t ICON_CIRCLE_CHECK; -extern const lv_img_dsc_t ICON_CASA; -extern const lv_img_dsc_t LARGE_ICON_STATIC_PIN_SPINNER; -extern const lv_img_dsc_t ICON_CONNECT; -extern const lv_img_dsc_t ICON_SEED; -extern const lv_img_dsc_t ICON_ADD_ACCOUNT; extern const lv_img_dsc_t ICON_INPUT_MODE_LOWER_ALPHA; -extern const lv_img_dsc_t ICON_TWO_KEYS; -extern const lv_img_dsc_t LARGE_ICON_SEED; -extern const lv_img_dsc_t ICON_SIGN; -extern const lv_img_dsc_t ICON_RETRY; -extern const lv_img_dsc_t ICON_HOME; +extern const lv_img_dsc_t ICON_INPUT_MODE_NUMERIC; +extern const lv_img_dsc_t ICON_INPUT_MODE_PUNCTUATION; +extern const lv_img_dsc_t ICON_INPUT_MODE_UPPER_ALPHA; +extern const lv_img_dsc_t ICON_MICROSD; extern const lv_img_dsc_t ICON_MULTISIG; -extern const lv_img_dsc_t ICON_FIRMWARE; +extern const lv_img_dsc_t ICON_NETWORK; +extern const lv_img_dsc_t ICON_NOSTR; +extern const lv_img_dsc_t ICON_ONE_KEY; +extern const lv_img_dsc_t ICON_PAGE_DOT; +extern const lv_img_dsc_t ICON_PAGE_HOME; +extern const lv_img_dsc_t ICON_PAGE_PLUS; +extern const lv_img_dsc_t ICON_PAGE_QR_LG; +extern const lv_img_dsc_t ICON_PAGE_QR_MD; +extern const lv_img_dsc_t ICON_PAGE_QR_SM; +extern const lv_img_dsc_t ICON_PASSPHRASE; +extern const lv_img_dsc_t ICON_PIN; extern const lv_img_dsc_t ICON_PLUS; -extern const lv_img_dsc_t ICON_SMALL_CHECKMARK; +extern const lv_img_dsc_t ICON_RETRY; extern const lv_img_dsc_t ICON_SCAN_QR; +extern const lv_img_dsc_t ICON_SEED; +extern const lv_img_dsc_t ICON_SETTINGS; +extern const lv_img_dsc_t ICON_SETUP; +extern const lv_img_dsc_t ICON_SHIELD; extern const lv_img_dsc_t ICON_SHUTDOWN; +extern const lv_img_dsc_t ICON_SIGN; +extern const lv_img_dsc_t ICON_SMALL_CHECKMARK; +extern const lv_img_dsc_t ICON_SPIRAL; +extern const lv_img_dsc_t ICON_TWO_KEYS; +extern const lv_img_dsc_t ICON_VERIFY_ADDRESS; +extern const lv_img_dsc_t ICON_WARNING; extern const lv_img_dsc_t IMAGE_CARD_BOTTOM; +extern const lv_img_dsc_t IMAGE_DIAGONAL_LINES; +extern const lv_img_dsc_t IMAGE_REGULATORY; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY; extern const lv_img_dsc_t LARGE_ICON_BACKUP; -extern const lv_img_dsc_t ICON_BACKUP; -extern const lv_img_dsc_t ICON_INPUT_MODE_PUNCTUATION; -extern const lv_img_dsc_t LARGE_ICON_PIN; -extern const lv_img_dsc_t ICON_EXTENSIONS; -extern const lv_img_dsc_t ICON_BATTERY_CHARGING; -extern const lv_img_dsc_t ICON_COUNTDOWN; +extern const lv_img_dsc_t LARGE_ICON_BRANDMARK; extern const lv_img_dsc_t LARGE_ICON_CLOCK; -extern const lv_img_dsc_t ICON_BITCOIN; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY; -extern const lv_img_dsc_t ICON_PAGE_QR_LG; -extern const lv_img_dsc_t ICON_NETWORK; -extern const lv_img_dsc_t ICON_BACK; -extern const lv_img_dsc_t ICON_EDIT1; -extern const lv_img_dsc_t ICON_BATTERY; -extern const lv_img_dsc_t IMAGE_REGULATORY; +extern const lv_img_dsc_t LARGE_ICON_CONNECT; +extern const lv_img_dsc_t LARGE_ICON_ERROR; +extern const lv_img_dsc_t LARGE_ICON_FIRMWARE; +extern const lv_img_dsc_t LARGE_ICON_INFO; +extern const lv_img_dsc_t LARGE_ICON_MICROSD; +extern const lv_img_dsc_t LARGE_ICON_PIN; +extern const lv_img_dsc_t LARGE_ICON_QUESTION; +extern const lv_img_dsc_t LARGE_ICON_SEED; +extern const lv_img_dsc_t LARGE_ICON_SETUP_QR; extern const lv_img_dsc_t LARGE_ICON_SETUP; -extern const lv_img_dsc_t ICON_FOLDER; +extern const lv_img_dsc_t LARGE_ICON_SHIELD; +extern const lv_img_dsc_t LARGE_ICON_STATIC_PIN_SPINNER; +extern const lv_img_dsc_t LARGE_ICON_SUCCESS; #endif #ifdef SCREEN_MODE_MONO -extern const lv_img_dsc_t ICON_CANCEL; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_1; -extern const lv_img_dsc_t ICON_PAGE_QR_MD; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_6; -extern const lv_img_dsc_t ICON_HOME; -extern const lv_img_dsc_t IMAGE_DIAGONAL_LINES; -extern const lv_img_dsc_t ICON_INFO; -extern const lv_img_dsc_t IMAGE_CARD_BOTTOM; -extern const lv_img_dsc_t ICON_EXTENSIONS; -extern const lv_img_dsc_t ICON_ONE_KEY; -extern const lv_img_dsc_t LARGE_ICON_PIN; -extern const lv_img_dsc_t ICON_PAGE_QR_SM; -extern const lv_img_dsc_t ICON_PAGE_DOT; -extern const lv_img_dsc_t ICON_SHUTDOWN; -extern const lv_img_dsc_t ICON_FOLDER; -extern const lv_img_dsc_t LARGE_ICON_BRANDMARK; +extern const lv_img_dsc_t ICON_ADD_ACCOUNT; +extern const lv_img_dsc_t ICON_ADVANCED; extern const lv_img_dsc_t ICON_BACKUP; -extern const lv_img_dsc_t LARGE_ICON_SETUP_QR; -extern const lv_img_dsc_t ICON_SIGN; -extern const lv_img_dsc_t LARGE_ICON_SHIELD; -extern const lv_img_dsc_t ICON_PAGE_PLUS; -extern const lv_img_dsc_t ICON_SHIELD; -extern const lv_img_dsc_t ICON_NETWORK; -extern const lv_img_dsc_t ICON_SPIRAL; -extern const lv_img_dsc_t ICON_SETUP; -extern const lv_img_dsc_t ICON_HAMBURGER; -extern const lv_img_dsc_t LARGE_ICON_CLOCK; -extern const lv_img_dsc_t ICON_INPUT_MODE_PUNCTUATION; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_5; -extern const lv_img_dsc_t ICON_RETRY; +extern const lv_img_dsc_t ICON_BACK; +extern const lv_img_dsc_t ICON_BATTERY_CHARGING; +extern const lv_img_dsc_t ICON_BATTERY; +extern const lv_img_dsc_t ICON_BITCOIN; extern const lv_img_dsc_t ICON_BRIGHTNESS; -extern const lv_img_dsc_t ICON_PAGE_HOME; -extern const lv_img_dsc_t LARGE_ICON_SUCCESS; -extern const lv_img_dsc_t ICON_SMALL_CHECKMARK; -extern const lv_img_dsc_t ICON_WARNING; -extern const lv_img_dsc_t ICON_NOSTR; -extern const lv_img_dsc_t ICON_VERIFY_ADDRESS; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_2; -extern const lv_img_dsc_t LARGE_ICON_STATIC_PIN_SPINNER; +extern const lv_img_dsc_t ICON_CANCEL; +extern const lv_img_dsc_t ICON_CASA; +extern const lv_img_dsc_t ICON_CHECKMARK; extern const lv_img_dsc_t ICON_CIRCLE_CHECK; -extern const lv_img_dsc_t ICON_ADVANCED; -extern const lv_img_dsc_t ICON_MICROSD; extern const lv_img_dsc_t ICON_CLOCK; -extern const lv_img_dsc_t ICON_SETTINGS; -extern const lv_img_dsc_t LARGE_ICON_QUESTION; -extern const lv_img_dsc_t ICON_SEED; +extern const lv_img_dsc_t ICON_CONNECT; extern const lv_img_dsc_t ICON_COUNTDOWN; extern const lv_img_dsc_t ICON_DEVICE; -extern const lv_img_dsc_t ICON_PAGE_INDICATOR; -extern const lv_img_dsc_t ICON_FORWARD; -extern const lv_img_dsc_t ICON_BATTERY_CHARGING; -extern const lv_img_dsc_t ICON_CASA; +extern const lv_img_dsc_t ICON_EDIT1; extern const lv_img_dsc_t ICON_EDIT2; -extern const lv_img_dsc_t ICON_PASSPHRASE; -extern const lv_img_dsc_t LARGE_ICON_SETUP; -extern const lv_img_dsc_t ICON_BACK; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_0; -extern const lv_img_dsc_t ICON_BATTERY; -extern const lv_img_dsc_t ICON_TWO_KEYS; -extern const lv_img_dsc_t LARGE_ICON_FIRMWARE; -extern const lv_img_dsc_t LARGE_ICON_SEED; -extern const lv_img_dsc_t ICON_INPUT_MODE_NUMERIC; -extern const lv_img_dsc_t ICON_HEALTH_CHECK; extern const lv_img_dsc_t ICON_ERASE; -extern const lv_img_dsc_t ICON_ADD_ACCOUNT; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_4; -extern const lv_img_dsc_t LARGE_ICON_BACKUP; -extern const lv_img_dsc_t ICON_BITCOIN; -extern const lv_img_dsc_t ICON_CHECKMARK; -extern const lv_img_dsc_t LARGE_ICON_INFO; -extern const lv_img_dsc_t ICON_MULTISIG; -extern const lv_img_dsc_t LARGE_ICON_ERROR; -extern const lv_img_dsc_t LARGE_ICON_MICROSD; -extern const lv_img_dsc_t ICON_PLUS; -extern const lv_img_dsc_t IMAGE_REGULATORY; -extern const lv_img_dsc_t ICON_CONNECT; -extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_3; +extern const lv_img_dsc_t ICON_EXTENSIONS; +extern const lv_img_dsc_t ICON_FILE; +extern const lv_img_dsc_t ICON_FIRMWARE; +extern const lv_img_dsc_t ICON_FOLDER; +extern const lv_img_dsc_t ICON_FORWARD; +extern const lv_img_dsc_t ICON_HAMBURGER; +extern const lv_img_dsc_t ICON_HEALTH_CHECK; +extern const lv_img_dsc_t ICON_HOME; +extern const lv_img_dsc_t ICON_INFO; extern const lv_img_dsc_t ICON_INPUT_MODE_LOWER_ALPHA; -extern const lv_img_dsc_t ICON_PIN; +extern const lv_img_dsc_t ICON_INPUT_MODE_NUMERIC; +extern const lv_img_dsc_t ICON_INPUT_MODE_PUNCTUATION; extern const lv_img_dsc_t ICON_INPUT_MODE_UPPER_ALPHA; +extern const lv_img_dsc_t ICON_MICROSD; +extern const lv_img_dsc_t ICON_MULTISIG; +extern const lv_img_dsc_t ICON_NETWORK; +extern const lv_img_dsc_t ICON_NOSTR; +extern const lv_img_dsc_t ICON_ONE_KEY; +extern const lv_img_dsc_t ICON_PAGE_DOT; +extern const lv_img_dsc_t ICON_PAGE_HOME; +extern const lv_img_dsc_t ICON_PAGE_INDICATOR; +extern const lv_img_dsc_t ICON_PAGE_PLUS; extern const lv_img_dsc_t ICON_PAGE_QR_LG; +extern const lv_img_dsc_t ICON_PAGE_QR_MD; +extern const lv_img_dsc_t ICON_PAGE_QR_SM; +extern const lv_img_dsc_t ICON_PASSPHRASE; +extern const lv_img_dsc_t ICON_PIN; +extern const lv_img_dsc_t ICON_PLUS; +extern const lv_img_dsc_t ICON_RETRY; extern const lv_img_dsc_t ICON_SCAN_QR; +extern const lv_img_dsc_t ICON_SEED; +extern const lv_img_dsc_t ICON_SETTINGS; +extern const lv_img_dsc_t ICON_SETUP; +extern const lv_img_dsc_t ICON_SHIELD; +extern const lv_img_dsc_t ICON_SHUTDOWN; +extern const lv_img_dsc_t ICON_SIGN; +extern const lv_img_dsc_t ICON_SMALL_CHECKMARK; +extern const lv_img_dsc_t ICON_SPIRAL; +extern const lv_img_dsc_t ICON_TWO_KEYS; +extern const lv_img_dsc_t ICON_VERIFY_ADDRESS; +extern const lv_img_dsc_t ICON_WARNING; +extern const lv_img_dsc_t IMAGE_CARD_BOTTOM; +extern const lv_img_dsc_t IMAGE_DIAGONAL_LINES; +extern const lv_img_dsc_t IMAGE_REGULATORY; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_0; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_1; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_2; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_3; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_4; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_5; +extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY_6; extern const lv_img_dsc_t IMAGE_SCREEN_OVERLAY; +extern const lv_img_dsc_t LARGE_ICON_BACKUP; +extern const lv_img_dsc_t LARGE_ICON_BRANDMARK; +extern const lv_img_dsc_t LARGE_ICON_CLOCK; extern const lv_img_dsc_t LARGE_ICON_CONNECT; -extern const lv_img_dsc_t ICON_EDIT1; -extern const lv_img_dsc_t ICON_FIRMWARE; -extern const lv_img_dsc_t ICON_FILE; +extern const lv_img_dsc_t LARGE_ICON_ERROR; +extern const lv_img_dsc_t LARGE_ICON_FIRMWARE; +extern const lv_img_dsc_t LARGE_ICON_INFO; +extern const lv_img_dsc_t LARGE_ICON_MICROSD; +extern const lv_img_dsc_t LARGE_ICON_PIN; +extern const lv_img_dsc_t LARGE_ICON_QUESTION; +extern const lv_img_dsc_t LARGE_ICON_SEED; +extern const lv_img_dsc_t LARGE_ICON_SETUP_QR; +extern const lv_img_dsc_t LARGE_ICON_SETUP; +extern const lv_img_dsc_t LARGE_ICON_SHIELD; +extern const lv_img_dsc_t LARGE_ICON_STATIC_PIN_SPINNER; +extern const lv_img_dsc_t LARGE_ICON_SUCCESS; #endif From 8afff9918fe900e656f2de0003d910b6dcc59962 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Sun, 16 Apr 2023 10:28:56 -0500 Subject: [PATCH 027/187] SFT-1003: set foundation for scanning SeedQR codes for initial setup --- .../data_codecs/compact_seedqr_codec.py | 2 +- .../modules/data_codecs/qr_factory.py | 19 +++++-- .../modules/data_codecs/seedqr_codec.py | 2 +- .../modules/flows/restore_seed_flow.py | 53 ++++++++++++++++--- .../Passport/modules/flows/scan_qr_flow.py | 14 +++-- .../Passport/modules/pages/scan_qr_page.py | 6 ++- .../modules/pages/seed_words_list_page.py | 2 + .../boards/Passport/modules/views/camera.py | 10 ++-- 8 files changed, 85 insertions(+), 23 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py b/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py index 1a2483086..b0de6082a 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py @@ -32,7 +32,7 @@ def decode(self, **kwargs): return self.data def qr_type(self): - return QRType.QR + return QRType.COMPACT_SEED_QR class CompactSeedQREncoder(DataEncoder): diff --git a/ports/stm32/boards/Passport/modules/data_codecs/qr_factory.py b/ports/stm32/boards/Passport/modules/data_codecs/qr_factory.py index 55d432b64..7e4477ba2 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/qr_factory.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/qr_factory.py @@ -9,16 +9,20 @@ from .qr_codec import QREncoder, QRDecoder, QRSampler from .ur1_codec import UR1Encoder, UR1Decoder, UR1Sampler from .ur2_codec import UR2Encoder, UR2Decoder, UR2Sampler -from .compact_seedqr_codec import CompactSeedQREncoder -from .seedqr_codec import SeedQREncoder +from .compact_seedqr_codec import CompactSeedQREncoder, CompactSeedQRDecoder, CompactSeedQRSampler +from .seedqr_codec import SeedQREncoder, SeedQRDecoder, SeedQRSampler from .qr_type import QRType qrs = [ {'type': QRType.UR2, 'encoder': UR2Encoder, 'decoder': UR2Decoder, 'sampler': UR2Sampler}, {'type': QRType.UR1, 'encoder': UR1Encoder, 'decoder': UR1Decoder, 'sampler': UR1Sampler}, {'type': QRType.QR, 'encoder': QREncoder, 'decoder': QRDecoder, 'sampler': QRSampler}, - {'type': QRType.COMPACT_SEED_QR, 'encoder': CompactSeedQREncoder, 'decoder': None, 'sampler': None}, - {'type': QRType.SEED_QR, 'encoder': SeedQREncoder, 'decoder': None, 'sampler': None}, + # All QR codecs that accept any data (sample always returns true) should go after QR type + # And they should explicitly pass their type to the ScanQRPage or ScanQRFlow + {'type': QRType.COMPACT_SEED_QR, 'encoder': CompactSeedQREncoder, + 'decoder': CompactSeedQRDecoder, 'sampler': CompactSeedQRSampler}, + {'type': QRType.SEED_QR, 'encoder': SeedQREncoder, + 'decoder': SeedQRDecoder, 'sampler': SeedQRSampler}, ] @@ -29,6 +33,13 @@ def make_qr_encoder(qr_type): return None +def make_qr_decoder(qr_type): + for entry in qrs: + if entry['type'] == qr_type: + return entry['decoder']() + return None + + def make_qr_decoder_from_data(data): """Given a data sample, return its decoder.""" diff --git a/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py b/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py index 914899032..a1733eb03 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py @@ -32,7 +32,7 @@ def decode(self, **kwargs): return self.data def qr_type(self): - return QRType.QR + return QRType.SEED_QR class SeedQREncoder(DataEncoder): diff --git a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py index dd8eb655d..f438ae0a1 100644 --- a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py @@ -15,13 +15,19 @@ class RestoreSeedFlow(Flow): def __init__(self, refresh_cards_when_done=False): super().__init__(initial_state=self.choose_restore_method, name='RestoreSeedFlow') self.refresh_cards_when_done = refresh_cards_when_done + self.seed_format = None + self.seed_length = None + self.validate_text = None self.seed_words = [] async def choose_restore_method(self): from pages import ChooserPage + from data_codecs.qr_type import QRType options = [{'label': '24 words', 'value': 24}, - {'label': '12 words', 'value': 12}] + {'label': '12 words', 'value': 12}, + {'label': 'Compact SeedQR', 'value': QRType.COMPACT_SEED_QR}, + {'label': 'SeedQR', 'value': QRType.SEED_QR}] choice = await ChooserPage(card_header={'title': 'Seed Format'}, options=options).show() @@ -29,17 +35,47 @@ async def choose_restore_method(self): self.set_result(False) return - if isinstance(choice, int): + self.seed_format = choice + if self.seed_format in [12, 24]: self.seed_length = choice + self.validate_text = 'Seed phrase' self.goto(self.explain_input_method) else: - self.goto(choice) + self.validate_text = 'SeedQR' + self.goto(self.scan_qr) async def scan_qr(self): - from flows import ScanPrivateKeyQRFlow - result = await ScanPrivateKeyQRFlow( - refresh_cards_when_done=self.refresh_cards_when_done).run() - self.set_result(result) + from flows import ScanQRFlow + from pages import InfoPage, SeedWordsListPage + import microns + from data_codecs.qr_type import QRType + + compact_label = 'Compact ' if self.seed_format == QRType.COMPACT_SEED_QR else '' + result = await ScanQRFlow(explicit_type=self.seed_format, + data_description='{}SeedQR' + .format(compact_label)).run() + + if result is None: + self.back() + return + + self.seed_words + + plural_label = 's' if len(result) == 24 else '' + result = await InfoPage('Confirm the seed words in the following page{}.'.format(plural_label)).show() + + if not result: + self.back() + return + + # TODO: check that microns work right in this page + result = await SeedWordsListPage(words=self.seed_words, left_micron=microns.Cancel).show() + + if not result: + self.back() + return + + self.goto(self.validate_seed_words) async def explain_input_method(self): from pages import InfoPage @@ -76,7 +112,8 @@ async def validate_seed_words(self): self.goto(self.valid_seed) async def invalid_seed(self): - result = await ErrorPage(text='Seed phrase is invalid. One or more of your seed words is incorrect.', + result = await ErrorPage(text='{} is invalid. One or more of your seed words is incorrect.' + .format(self.validate_text), left_micron=microns.Cancel, right_micron=microns.Retry).show() if result is None: cancel = await QuestionPage( diff --git a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py index 943c83076..ac905b79b 100644 --- a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py @@ -14,6 +14,7 @@ def __init__(self, auto_close_timeout=None, qr_types=None, ur_types=None, + explicit_type=None, data_description=None): """ Initialize the scan QR flow. @@ -28,8 +29,13 @@ def __init__(self, super().__init__(initial_state=self.scan, name='ScanQRFlow') self.auto_close_timeout = auto_close_timeout + + if explicit_type is not None and (qr_types is not None or ur_types is not None): + raise ValueError('No QR or UR types may be provided along with an explicit type') + self.qr_types = [QRType.QR] if qr_types is None else qr_types self.ur_types = [] if ur_types is None else ur_types + self.explicit_type = explicit_type self.data_description = data_description self.data = None @@ -43,7 +49,7 @@ def __init__(self, raise ValueError('Data description must be provided') async def scan(self): - result = await ScanQRPage().show(auto_close_timeout=self.auto_close_timeout) + result = await ScanQRPage(qr_type=self.explicit_type).show(auto_close_timeout=self.auto_close_timeout) if result is None: self.set_result(None) @@ -61,14 +67,14 @@ async def scan(self): self.goto(self.handle_qr) async def handle_ur(self): - if QRType.UR2 not in self.qr_types: + if QRType.UR2 not in self.qr_types and QRType.UR2 != self.explicit_type: await ErrorPage(text='Scan failed.\n' 'Expected to scan a QR code containing ' '{}.'.format(self.data_description)).show() self.set_result(None) return - if self.data.ur_type() not in self.ur_types: + if self.data.ur_type() not in self.ur_types and self.data.ur_type() != self.explicit_type: await ErrorPage(text='Scan failed.\n' 'This type of UR is not expected in this context. ' '{}.'.format(self.data_description)).show() @@ -79,7 +85,7 @@ async def handle_ur(self): self.set_result(self.data) async def handle_qr(self): - if QRType.QR not in self.qr_types: + if QRType.QR not in self.qr_types and QRType.QR != self.explicit_type: await ErrorPage(text='Scan. failed.\n' 'Expected to scan a Uniform Resource containing ' '{}.'.format(self.data_description)).show() diff --git a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py index 0c5c35255..bce228e78 100644 --- a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py +++ b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py @@ -26,7 +26,8 @@ def __init__(self, card_header=None, statusbar=None, left_micron=microns.Back, - right_micron=None): + right_micron=None, + qr_type=None): super().__init__(flex_flow=None, card_header=card_header, statusbar=statusbar, @@ -36,7 +37,8 @@ def __init__(self, self.prev_card_header = None self.timer = None - self.camera = CameraQRScanner() + self.camera = CameraQRScanner(qr_type) + self.qr_type = qr_type # TODO: # lv.pct(100) just makes the widget inside the camera view to return diff --git a/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py b/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py index 1f9707938..73ae8c13a 100644 --- a/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py +++ b/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py @@ -175,6 +175,8 @@ def left_action(self, is_pressed): # Go back a page self.page_idx -= 1 self.update() + else: + self.set_result(False) def right_action(self, is_pressed): if not is_pressed: diff --git a/ports/stm32/boards/Passport/modules/views/camera.py b/ports/stm32/boards/Passport/modules/views/camera.py index fd6681cc9..9811c57ce 100644 --- a/ports/stm32/boards/Passport/modules/views/camera.py +++ b/ports/stm32/boards/Passport/modules/views/camera.py @@ -11,7 +11,7 @@ from views import View from styles import Stylize from styles.colors import WHITE -from data_codecs.qr_factory import make_qr_decoder_from_data +from data_codecs.qr_factory import make_qr_decoder_from_data, make_qr_decoder class Camera(View): @@ -143,9 +143,10 @@ def framebuffer(self): class CameraQRScanner(Camera): """Camera QR code scanner and decoder""" - def __init__(self): + def __init__(self, qr_type=None): super().__init__() self.qr_decoder = None + self.qr_type = qr_type qr.init(self.HOR_RES, self.VER_RES) def hook(self): @@ -175,7 +176,10 @@ def update(self): return if self.qr_decoder is None: - self.qr_decoder = make_qr_decoder_from_data(data) + if self.qr_type is not None: + self.qr_decoder = make_qr_decoder(self.qr_type) + else: + self.qr_decoder = make_qr_decoder_from_data(data) self.qr_decoder.add_data(data) From 053615722e10d44d4b8b84a8f5b58d8fe6d33615 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 17 Apr 2023 20:25:56 -0500 Subject: [PATCH 028/187] SFT-1003: seedqr import codec complete --- .../modtrezorcrypto/modtrezorcrypto-bip39.h | 14 ++++++++++++++ .../data_codecs/compact_seedqr_codec.py | 11 +++++++++-- .../modules/data_codecs/seedqr_codec.py | 19 +++++++++++++++++-- .../modules/flows/restore_seed_flow.py | 9 ++++++--- .../Passport/modules/public_constants.py | 3 +++ 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h index 30b84a2ae..4428b1efd 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip39.h @@ -158,6 +158,19 @@ STATIC mp_obj_t mod_trezorcrypto_bip39_find_word(mp_obj_t word) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_find_word_obj, mod_trezorcrypto_bip39_find_word); +// Returns BIP39 English word of the given index +STATIC mp_obj_t mod_trezorcrypto_bip39_get_word(mp_obj_t index_obj) { + int index = mp_obj_int_get_checked(index_obj); + const char * word = mnemonic_get_word(index); + if (word) { + return mp_obj_new_str(word, strlen(word)); + } else { + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_get_word_obj, + mod_trezorcrypto_bip39_get_word); + STATIC const mp_rom_map_elem_t mod_trezorcrypto_bip39_globals_table[] = { {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bip39)}, {MP_ROM_QSTR(MP_QSTR_complete_word), @@ -171,6 +184,7 @@ STATIC const mp_rom_map_elem_t mod_trezorcrypto_bip39_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_check), MP_ROM_PTR(&mod_trezorcrypto_bip39_check_obj)}, {MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_trezorcrypto_bip39_seed_obj)}, {MP_ROM_QSTR(MP_QSTR_find_word), MP_ROM_PTR(&mod_trezorcrypto_bip39_find_word_obj)}, + {MP_ROM_QSTR(MP_QSTR_get_word), MP_ROM_PTR(&mod_trezorcrypto_bip39_get_word_obj)}, }; STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_bip39_globals, mod_trezorcrypto_bip39_globals_table); diff --git a/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py b/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py index b0de6082a..6c7f19cec 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/compact_seedqr_codec.py @@ -29,7 +29,14 @@ def is_complete(self): return self.data is not None def decode(self, **kwargs): - return self.data + from utils import get_words_from_seed + + (seed_phrase, error) = get_words_from_seed(self.data) + + if error is not None or seed_phrase is None: + return None + + return seed_phrase def qr_type(self): return QRType.COMPACT_SEED_QR @@ -83,4 +90,4 @@ def sample(cls, data): # Number of bytes required to successfully recognize this format @classmethod def min_sample_size(cls): - return 1 + return 16 diff --git a/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py b/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py index a1733eb03..67e2e2da8 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/seedqr_codec.py @@ -13,6 +13,7 @@ from .data_decoder import DataDecoder from .data_sampler import DataSampler from .qr_type import QRType +from public_constants import SEED_LENGTHS class SeedQRDecoder(DataDecoder): @@ -29,7 +30,21 @@ def is_complete(self): return self.data is not None def decode(self, **kwargs): - return self.data + import trezorcrypto + + try: + seed_phrase = [] + num_words = int(len(self.data) / 4) + for i in range(0, num_words): + index = int(self.data[i * 4: (i * 4) + 4]) + word = trezorcrypto.bip39.get_word(index) + seed_phrase.append(word) + if len(seed_phrase) in SEED_LENGTHS: + return seed_phrase + else: + return None + except Exception as e: + return None def qr_type(self): return QRType.SEED_QR @@ -65,4 +80,4 @@ def sample(cls, data): # Number of bytes required to successfully recognize this format @classmethod def min_sample_size(cls): - return 1 + return 48 diff --git a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py index f438ae0a1..5ef99fbde 100644 --- a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py @@ -9,6 +9,7 @@ from pages import ErrorPage, PredictiveTextInputPage, SuccessPage, QuestionPage from utils import spinner_task from tasks import save_seed_task +from public_constants import SEED_LENGTHS class RestoreSeedFlow(Flow): @@ -36,7 +37,7 @@ async def choose_restore_method(self): return self.seed_format = choice - if self.seed_format in [12, 24]: + if self.seed_format in SEED_LENGTHS: self.seed_length = choice self.validate_text = 'Seed phrase' self.goto(self.explain_input_method) @@ -46,7 +47,7 @@ async def choose_restore_method(self): async def scan_qr(self): from flows import ScanQRFlow - from pages import InfoPage, SeedWordsListPage + from pages import InfoPage, SeedWordsListPage, ErrorPage import microns from data_codecs.qr_type import QRType @@ -56,10 +57,12 @@ async def scan_qr(self): .format(compact_label)).run() if result is None: + await ErrorPage("Invalid {}SeedQR detected. Make sure you're using the right format." + .format(compact_label)).show() self.back() return - self.seed_words + self.seed_words = result plural_label = 's' if len(result) == 24 else '' result = await InfoPage('Confirm the seed words in the following page{}.'.format(plural_label)).show() diff --git a/ports/stm32/boards/Passport/modules/public_constants.py b/ports/stm32/boards/Passport/modules/public_constants.py index 41de79281..717d34317 100644 --- a/ports/stm32/boards/Passport/modules/public_constants.py +++ b/ports/stm32/boards/Passport/modules/public_constants.py @@ -13,6 +13,9 @@ from constants import PSBT_MAX_SIZE +# Seed phrase lengths accepted +SEED_LENGTHS = [12, 24] + # Max PSBT txn we support (896k as PSBT) # - the max on the wire for mainnet is 100k # - but a PSBT might contain a full txn for each input From f57099b83c8528fc8f94e5bb8f7db5e1a6034d42 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 19 Apr 2023 16:33:10 -0500 Subject: [PATCH 029/187] SFT-1003: cleaned up SeedQR import UI --- .../Passport/modules/flows/restore_seed_flow.py | 14 +++++++------- .../Passport/modules/pages/seed_words_list_page.py | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py index 5ef99fbde..8dbd11290 100644 --- a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py @@ -42,7 +42,10 @@ async def choose_restore_method(self): self.validate_text = 'Seed phrase' self.goto(self.explain_input_method) else: - self.validate_text = 'SeedQR' + if self.seed_format == QRType.SEED_QR: + self.validate_text = 'SeedQR' + else: + self.validate_text = 'Compact SeedQR' self.goto(self.scan_qr) async def scan_qr(self): @@ -51,14 +54,12 @@ async def scan_qr(self): import microns from data_codecs.qr_type import QRType - compact_label = 'Compact ' if self.seed_format == QRType.COMPACT_SEED_QR else '' result = await ScanQRFlow(explicit_type=self.seed_format, - data_description='{}SeedQR' - .format(compact_label)).run() + data_description=self.validate_text).run() if result is None: - await ErrorPage("Invalid {}SeedQR detected. Make sure you're using the right format." - .format(compact_label)).show() + await ErrorPage("Invalid {} detected. Make sure you're using the right format." + .format(self.validate_text)).show() self.back() return @@ -71,7 +72,6 @@ async def scan_qr(self): self.back() return - # TODO: check that microns work right in this page result = await SeedWordsListPage(words=self.seed_words, left_micron=microns.Cancel).show() if not result: diff --git a/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py b/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py index 73ae8c13a..61acdc732 100644 --- a/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py +++ b/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py @@ -28,6 +28,7 @@ def __init__( self.page_idx = 0 self.prev_card_descs = None self.prev_card_idx = None + self.left_micron = left_micron if len(self.words) == 24: self.num_pages = 2 @@ -137,13 +138,13 @@ def update(self): # Update microns if self.num_pages > 1: if self.page_idx == 0: - common.ui.set_left_micron(None) + common.ui.set_left_micron(self.left_micron) common.ui.set_right_micron(microns.Forward) else: common.ui.set_left_micron(microns.Back) common.ui.set_right_micron(microns.Checkmark) else: - common.ui.set_left_micron(None) + common.ui.set_left_micron(self.left_micron) common.ui.set_right_micron(microns.Checkmark) def attach(self, group): From 9be7df03584b5b197f2880633af0ec76a2a5c1f5 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 12 Apr 2023 16:42:06 -0500 Subject: [PATCH 030/187] SFT-1843: optimized SaveToMicroSD --- .../modules/flows/save_to_microsd_flow.py | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index 694b5183f..64f1ef21d 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -31,6 +31,10 @@ def __init__(self, self.return_bool = True super().__init__(initial_state=self.save, name='SaveToMicroSDFlow') + async def default_write_fn(self, filename): + with open(self.out_full, 'w' + self.mode) as fd: + fd.write(self.data) + async def save(self): from files import CardSlot, CardMissingError from pages import ErrorPage @@ -38,30 +42,30 @@ async def save(self): from errors import Error from tasks import custom_microsd_write_task + if (not self.data and not self.write_fn) or (self.data and self.write_fn): + await ErrorPage("Either data or a write function is required to save a file.").show() + self.set_result(False) + return + + if self.data: + self.write_fn = self.default_write_fn + written = False for path in [self.path, None]: try: with CardSlot() as card: ensure_folder_exists(self.path) - self.out_full, _ = card.pick_filename(self.filename, path) - - if self.data: - with open(self.out_full, 'w' + self.mode) as fd: - fd.write(self.data) - written = True - elif self.write_fn: - error = await spinner_task("Writing {}".format(self.success_text), - custom_microsd_write_task, - args=[self.out_full, self.write_fn]) - if error is Error.MICROSD_CARD_MISSING: - raise CardMissingError() - elif error is Error.FILE_WRITE_ERROR: - raise Exception("write task failed") - written = True - if written: - break + error = await spinner_task("Writing {}.".format(self.success_text), + custom_microsd_write_task, + args=[self.out_full, self.write_fn]) + if error is Error.MICROSD_CARD_MISSING: + raise CardMissingError() + elif error is Error.FILE_WRITE_ERROR: + raise Exception("write task failed") + written = True + break except CardMissingError: # show_card_missing is a global flow state @@ -78,7 +82,7 @@ async def save(self): if written: self.goto(self.success) else: - await ErrorPage("Failed to write file: no data or write task.", + await ErrorPage("Failed to write file.", right_micron=self.show_check) \ .show(auto_close_timeout=self.auto_timeout) From 455234169ff1a6c7bfe5c982df80e138f468cda7 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 1 May 2023 10:28:40 -0500 Subject: [PATCH 031/187] SFT-1470: fixed brick message formatting --- ports/stm32/boards/Passport/modules/flows/login_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/login_flow.py b/ports/stm32/boards/Passport/modules/flows/login_flow.py index 2c68cf882..824d2fb11 100644 --- a/ports/stm32/boards/Passport/modules/flows/login_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/login_flow.py @@ -77,7 +77,7 @@ async def show_bricked_message(self): msg = '''This Passport is now permanently disabled. -Restore a microSD backup or seed phrase onto a new Passport to recover your funds.''' % pa.num_fails +Restore a microSD backup or seed phrase onto a new Passport to recover your funds.''' result = await ErrorPage(text=msg, left_micron=microns.Shutdown, From 9d8b7ca428fd6112bdbf7e1419f14b761f0bc594 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 24 Apr 2023 17:51:45 -0500 Subject: [PATCH 032/187] SFT-1088: refactored passphrase flow, untested --- .../modules/flows/apply_passphrase_flow.py | 139 ++++++++++++------ 1 file changed, 91 insertions(+), 48 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index fc57a9af7..5feb7aa0e 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -4,74 +4,117 @@ # apply_passphrase_flow.py - Ask user to enter a passphrase, then apply it. from flows import Flow -from pages import SuccessPage, TextInputPage, ErrorPage, QuestionPage -from tasks import apply_passphrase_task -from utils import spinner_task -from errors import Error +from pages import SuccessPage, QuestionPage from translations import t, T from constants import MAX_PASSPHRASE_LENGTH class ApplyPassphraseFlow(Flow): def __init__(self, passphrase=None): + import stash # Caller wants to set this passphrase - if passphrase is not None: - self.passphrase = passphrase - super().__init__(initial_state=self.apply_passphrase, name='ApplyPassphraseFlow') + self.attempted = False + self.prev_passphrase = stash.bip39_passphrasea + self.passphrase = passphrase + self.msg = 'Apply' + if self.passphrase is not None: + if len(self.passphrase) == 0: + super().__init__(initial_state=self.clear_passphrase, name='ApplyPassphraseFlow') + else: + super().__init__(initial_state=self.apply_passphrase, name='ApplyPassphraseFlow') else: - self.passphrase = '' super().__init__(initial_state=self.enter_passphrase, name='ApplyPassphraseFlow') - async def enter_passphrase(self): - self.passphrase = await TextInputPage(card_header={'title': 'Enter Passphrase'}, - initial_text=self.passphrase, - max_length=MAX_PASSPHRASE_LENGTH).show() - if self.passphrase is not None: + def check_attempt(self): + if self.attempted: + self.passphrase = self.prev_passphrase + self.msg = 'Clear' if len(self.passphrase == 0) else 'Revert' self.goto(self.apply_passphrase) else: self.set_result(False) + async def enter_passphrase(self): + from pages import TextInputPage + + passphrase = await TextInputPage(card_header={'title': 'Enter Passphrase'}, + initial_text=self.passphrase, + max_length=MAX_PASSPHRASE_LENGTH).show() + + # Exit text input, means we want to go back, and no need to prompt for reverting to no passphrase + if passphrase is None or (len(passphrase) == 0 and passphrase == self.prev_passphrase): + self.check_attempt() + return + + # Clear passphrase, previous passphrase is in use + if len(passphrase) == 0: + self.goto(self.clear_passphrase) + return + + # Revert passphrase to entered field, no need to check xfp + if passphrase == self.prev_passphrase: + self.check_attempt() + return + + self.msg = 'Apply' + self.passphrase = passphrase + self.goto(self.apply_passphrase) + + async def clear_passphrase(self): + from pages import QuestionPage + result = await QuestionPage(text='Clear the active passphrase?').show() + + if not result: + self.back() + return + + self.msg = 'Clear' + self.goto(self.apply_passphrase) + async def apply_passphrase(self): - if len(self.passphrase) == 0: - result = await QuestionPage(text='Clear the active passphrase?').show() - if result: - msg = 'Clearing passphrase' - else: - self.set_result(False) - return - else: - msg = 'Applying passphrase' + from utils import spinner_task + from errors import Error + from tasks import apply_passphrase_task + from pages import ErrorPage - (error,) = await spinner_task(msg, apply_passphrase_task, args=[self.passphrase]) - if error is None: - import common - from utils import start_task, xfp2str + (error,) = await spinner_task("{}ing passphrase".format(self.msg), + apply_passphrase_task, + args=[self.passphrase]) - # Make a success page - if len(self.passphrase) == 0: - await SuccessPage( - text='Passphrase cleared\n\nFingerprint:\n\n{}'.format( - xfp2str(common.settings.get('xfp', '---'))) - ).show() - else: - result = await QuestionPage( - text='Passphrase applied\n\nFingerprint correct?\n\n{}'.format( - xfp2str(common.settings.get('xfp', '---'))) - ).show() - if result is False: - self.goto(self.enter_passphrase) - return + if error is Error.NOT_BIP39_MODE: + await ErrorPage(text='Unable to {} passphrase. Not in BIP39 mode.'.format(self.msg.lower())).show() + self.set_result(False) + return + + self.goto(self.confirm_xfp) + + async def confirm_xfp(self): + import common + from utils import start_task, xfp2str + + # Make a success page + if len(self.passphrase) == 0: + await SuccessPage( + text='Passphrase cleared\n\nFingerprint:\n\n{}'.format( + xfp2str(common.settings.get('xfp', '---'))) + ).show() + else: + self.attempted = True + result = await QuestionPage( + text='Passphrase applied\n\nFingerprint correct?\n\n{}'.format( + xfp2str(common.settings.get('xfp', '---'))) + ).show() + if result is False: + self.goto(self.enter_passphrase) + return - common.ui.update_cards(stay_on_same_card=True) + common.ui.update_cards(stay_on_same_card=True) - async def start_main_task(): - common.ui.start_card_task(card_idx=common.ui.active_card_idx) + async def start_main_task(): + common.ui.start_card_task(card_idx=common.ui.active_card_idx) - start_task(start_main_task()) + start_task(start_main_task()) - await self.wait_to_die() - elif error is Error.NOT_BIP39_MODE: - await ErrorPage(text='Unable to apply passphrase. Not in BIP39 mode.').show() + await self.wait_to_die() - self.set_result(error is None) + self.set_result(True) From a9cc0c7cb91d91a5009636c07bab72afba8a1fd3 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 24 Apr 2023 17:56:07 -0500 Subject: [PATCH 033/187] SFT-1088: added custom message to cleared page, untested --- .../boards/Passport/modules/flows/apply_passphrase_flow.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index 5feb7aa0e..02efd19c4 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -93,9 +93,10 @@ async def confirm_xfp(self): from utils import start_task, xfp2str # Make a success page - if len(self.passphrase) == 0: + if len(self.passphrase) == 0 or self.passphrase == self.prev_passphrase: await SuccessPage( - text='Passphrase cleared\n\nFingerprint:\n\n{}'.format( + text='Passphrase {}ed\n\nFingerprint:\n\n{}'.format( + self.msg.lower() xfp2str(common.settings.get('xfp', '---'))) ).show() else: @@ -104,6 +105,7 @@ async def confirm_xfp(self): text='Passphrase applied\n\nFingerprint correct?\n\n{}'.format( xfp2str(common.settings.get('xfp', '---'))) ).show() + if result is False: self.goto(self.enter_passphrase) return From 1e9c11d2f9a51d53ccdd1fbcc8c646411ae85302 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 25 Apr 2023 16:00:07 -0500 Subject: [PATCH 034/187] SFT-1088: fixed bugs and tested flow --- .../modules/flows/apply_passphrase_flow.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index 02efd19c4..614397c98 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -15,7 +15,7 @@ def __init__(self, passphrase=None): # Caller wants to set this passphrase self.attempted = False - self.prev_passphrase = stash.bip39_passphrasea + self.prev_passphrase = stash.bip39_passphrase self.passphrase = passphrase self.msg = 'Apply' if self.passphrase is not None: @@ -29,7 +29,7 @@ def __init__(self, passphrase=None): def check_attempt(self): if self.attempted: self.passphrase = self.prev_passphrase - self.msg = 'Clear' if len(self.passphrase == 0) else 'Revert' + self.msg = 'Clear' if len(self.passphrase) == 0 else 'Revert' self.goto(self.apply_passphrase) else: self.set_result(False) @@ -38,7 +38,7 @@ async def enter_passphrase(self): from pages import TextInputPage passphrase = await TextInputPage(card_header={'title': 'Enter Passphrase'}, - initial_text=self.passphrase, + initial_text=self.passphrase or '', max_length=MAX_PASSPHRASE_LENGTH).show() # Exit text input, means we want to go back, and no need to prompt for reverting to no passphrase @@ -69,6 +69,7 @@ async def clear_passphrase(self): return self.msg = 'Clear' + self.passphrase = '' self.goto(self.apply_passphrase) async def apply_passphrase(self): @@ -81,8 +82,11 @@ async def apply_passphrase(self): apply_passphrase_task, args=[self.passphrase]) - if error is Error.NOT_BIP39_MODE: - await ErrorPage(text='Unable to {} passphrase. Not in BIP39 mode.'.format(self.msg.lower())).show() + if error is not None: + if error is Error.NOT_BIP39_MODE: + await ErrorPage(text='Unable to {} passphrase. Not in BIP39 mode.'.format(self.msg.lower())).show() + else: + await ErrorPage(text='Unable to {} passphrase.'.format(self.msg.lower())).show() self.set_result(False) return @@ -96,7 +100,7 @@ async def confirm_xfp(self): if len(self.passphrase) == 0 or self.passphrase == self.prev_passphrase: await SuccessPage( text='Passphrase {}ed\n\nFingerprint:\n\n{}'.format( - self.msg.lower() + self.msg.lower(), xfp2str(common.settings.get('xfp', '---'))) ).show() else: From f7c98961ca129e3191a849e72edde17078aaea93 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 25 Apr 2023 16:03:32 -0500 Subject: [PATCH 035/187] SFT-1088: added comment about grammar --- .../boards/Passport/modules/flows/apply_passphrase_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index 614397c98..439fa19e7 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -100,7 +100,7 @@ async def confirm_xfp(self): if len(self.passphrase) == 0 or self.passphrase == self.prev_passphrase: await SuccessPage( text='Passphrase {}ed\n\nFingerprint:\n\n{}'.format( - self.msg.lower(), + self.msg.lower(), # this is either 'revert' or 'clear' at this point xfp2str(common.settings.get('xfp', '---'))) ).show() else: From ce5589d3ccf9b9c4670500871e1726c3dc10d2d4 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 25 Apr 2023 16:08:10 -0500 Subject: [PATCH 036/187] SFT-1088: cleaned up imports --- .../boards/Passport/modules/flows/apply_passphrase_flow.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index 439fa19e7..bf1732c61 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -4,9 +4,6 @@ # apply_passphrase_flow.py - Ask user to enter a passphrase, then apply it. from flows import Flow -from pages import SuccessPage, QuestionPage -from translations import t, T -from constants import MAX_PASSPHRASE_LENGTH class ApplyPassphraseFlow(Flow): @@ -36,6 +33,7 @@ def check_attempt(self): async def enter_passphrase(self): from pages import TextInputPage + from constants import MAX_PASSPHRASE_LENGTH passphrase = await TextInputPage(card_header={'title': 'Enter Passphrase'}, initial_text=self.passphrase or '', @@ -95,6 +93,7 @@ async def apply_passphrase(self): async def confirm_xfp(self): import common from utils import start_task, xfp2str + from pages import QuestionPage, SuccessPage # Make a success page if len(self.passphrase) == 0 or self.passphrase == self.prev_passphrase: From 7dbeb3a08e1d14308fc28f0470f7776d52089512 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 26 Apr 2023 10:05:27 -0500 Subject: [PATCH 037/187] SFT-1807: added passphrase explainer first draft --- .../modules/flows/apply_passphrase_flow.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index bf1732c61..40add3371 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -21,7 +21,7 @@ def __init__(self, passphrase=None): else: super().__init__(initial_state=self.apply_passphrase, name='ApplyPassphraseFlow') else: - super().__init__(initial_state=self.enter_passphrase, name='ApplyPassphraseFlow') + super().__init__(initial_state=self.explainer, name='ApplyPassphraseFlow') def check_attempt(self): if self.attempted: @@ -31,6 +31,19 @@ def check_attempt(self): else: self.set_result(False) + async def explainer(self): + from pages import InfoPage + import microns + + result = await InfoPage(text='All passphrases are valid, and passphrases are forgotten upon shutdown.', + left_micron=microns.Back).show() + + if not result: + self.set_result(False) + return + + self.goto(self.enter_passphrase) + async def enter_passphrase(self): from pages import TextInputPage from constants import MAX_PASSPHRASE_LENGTH From 0ced02c2e767526390be6cd4428ce2ac53152209 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 3 May 2023 13:40:14 -0500 Subject: [PATCH 038/187] SFT-2017: fixed default write function --- .../stm32/boards/Passport/modules/flows/save_to_microsd_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index 64f1ef21d..9e2c27ab7 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -31,7 +31,7 @@ def __init__(self, self.return_bool = True super().__init__(initial_state=self.save, name='SaveToMicroSDFlow') - async def default_write_fn(self, filename): + def default_write_fn(self, filename): with open(self.out_full, 'w' + self.mode) as fd: fd.write(self.data) From 9e76c48da6a04a1bcbd9d95daa25e135d97045b5 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 17:22:51 -0500 Subject: [PATCH 039/187] SFT-1807: Zach's take on passphrase messaging --- .../boards/Passport/modules/flows/apply_passphrase_flow.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index 40add3371..ce4460220 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -35,7 +35,9 @@ async def explainer(self): from pages import InfoPage import microns - result = await InfoPage(text='All passphrases are valid, and passphrases are forgotten upon shutdown.', + text = '''Type with care. All passphrases are valid.\n +Passport will clear your passphrase upon shutdown.''' + result = await InfoPage(text=text, left_micron=microns.Back).show() if not result: From 43c0609a23dc78f45f93d7245edb91c338ae52b4 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 1 May 2023 11:23:34 -0500 Subject: [PATCH 040/187] SFT-1994: first pass verifying SeedQR words after export --- .../modules/flows/export_derived_key_flow.py | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index 9dfe9a514..1b296d3f5 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -11,6 +11,7 @@ def __init__(self, context=None): self.key = context self.key_type = None self.pk = None + self.qr_data = None super().__init__(initial_state=self.generate_key, name="NewDerivedKeyFlow") async def generate_key(self): @@ -73,13 +74,13 @@ async def show_qr_code(self): if qr_type is QRType.QR: if isinstance(self.pk, str): - qr_data = self.pk + self.qr_data = self.pk else: - qr_data = B2A(self.pk) + self.qr_data = B2A(self.pk) else: # SeedQR or Compact SeedQR - qr_data = await GetSeedWordsFlow(self.pk).run() + self.qr_data = await GetSeedWordsFlow(self.pk).run() - if qr_data is None: + if self.qr_data is None: self.set_result(False) return @@ -91,7 +92,31 @@ async def show_qr_code(self): self.set_result(False) return - await ShowQRPage(qr_type=qr_type, qr_data=qr_data, right_micron=microns.Checkmark).show() + await ShowQRPage(qr_type=qr_type, qr_data=self.qr_data, right_micron=microns.Checkmark).show() + + if qr_type in [QRType.COMPACT_SEED_QR, QRType.SEED_QR]: + self.goto(self.confirm_seedqr) + return + + self.set_result(True) + + async def confirm_seedqr(self): + from pages import InfoPage, SeedWordsListPage + import microns + + plural_label = 's' if len(self.qr_data) == 24 else '' + text = 'Confirm the seed words in the following page{}.'.format(plural_label) + result = await InfoPage(text=text, left_micron=microns.Back).show() + + if not result: + self.back() + return + + result = await SeedWordsListPage(words=self.qr_data, left_micron=microns.Back).show() + + if not result: + return + self.set_result(True) async def save_to_sd(self): From 4fe55edd43239daed0b400d61d519e4fd4e8cb61 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 14:06:55 -0500 Subject: [PATCH 041/187] SFT-1994: refactored derived key export --- .../modules/flows/export_derived_key_flow.py | 90 ++++++++++++------- .../modules/flows/get_seed_words_flow.py | 7 +- 2 files changed, 60 insertions(+), 37 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index 1b296d3f5..a43fe0df1 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -11,13 +11,15 @@ def __init__(self, context=None): self.key = context self.key_type = None self.pk = None - self.qr_data = None + self.qr_type = None + self.words = None super().__init__(initial_state=self.generate_key, name="NewDerivedKeyFlow") async def generate_key(self): from utils import spinner_task from derived_key import get_key_type_from_tn from pages import ErrorPage + from flows import GetSeedWordsFlow self.key_type = get_key_type_from_tn(self.key['tn']) @@ -34,12 +36,19 @@ async def generate_key(self): self.set_result(False) return + if self.key_type['words']: + self.words = await GetSeedWordsFlow(external_key=self.pk, text='Generating Key').run() + + if self.words is None: + self.set_result(False) + return + self.goto(self.choose_export_mode) async def choose_export_mode(self): from pages import ChooserPage - options = [{'label': 'Export via QR', 'value': self.show_qr_code}, + options = [{'label': 'Export via QR', 'value': self.choose_qr_type}, {'label': 'Export via microSD', 'value': self.save_to_sd}] if self.key_type['words']: @@ -47,55 +56,69 @@ async def choose_export_mode(self): mode = await ChooserPage(card_header={'title': 'Export Mode'}, options=options).show() + # TODO: if key_type['words'] and not save_to_sd, use ViewSeedWordsFlow + if mode is None: self.set_result(False) return self.goto(mode) - async def show_qr_code(self): - from flows import GetSeedWordsFlow, SeedWarningFlow - from pages import ShowQRPage, ChooserPage - from utils import B2A + async def choose_qr_type(self): + from pages import ChooserPage + from flows import SeedWarningFlow from data_codecs.qr_type import QRType - import microns + + self.qr_type = QRType.QR if self.key_type['words']: options = [{'label': 'Compact SeedQR', 'value': QRType.COMPACT_SEED_QR}, {'label': 'SeedQR', 'value': QRType.SEED_QR}] - qr_type = await ChooserPage(card_header={'title': 'QR Format'}, options=options).show() - else: - qr_type = QRType.QR + self.qr_type = await ChooserPage(card_header={'title': 'QR Format'}, options=options).show() - if qr_type is None: - self.set_result(False) + if self.qr_type is None: + self.back() return - if qr_type is QRType.QR: - if isinstance(self.pk, str): - self.qr_data = self.pk - else: - self.qr_data = B2A(self.pk) - else: # SeedQR or Compact SeedQR - self.qr_data = await GetSeedWordsFlow(self.pk).run() + result = await SeedWarningFlow(action_text="display your {} as a QR code" + .format(self.key_type['title'])).run() + if not result: + self.back() + return - if self.qr_data is None: - self.set_result(False) - return + if self.qr_type in [QRType.SEED_QR, QRType.COMPACT_SEED_QR]: + self.goto(self.show_seed_qr) + return - result = await SeedWarningFlow(action_text="display your {} as a QR code" - .format(self.key_type['title']), - continue_text=self.key_type.get('continue_text', None)).run() + self.goto(show_qr_code) + + async def show_seed_qr(self): + from pages import ShowQRPage + import microns + + result = await ShowQRPage(qr_type=self.qr_type, qr_data=self.words, right_micron=microns.Checkmark).show() if not result: - self.set_result(False) + self.back() return - await ShowQRPage(qr_type=qr_type, qr_data=self.qr_data, right_micron=microns.Checkmark).show() + self.goto(self.confirm_seedqr) - if qr_type in [QRType.COMPACT_SEED_QR, QRType.SEED_QR]: - self.goto(self.confirm_seedqr) + async def show_qr_code(self): + from pages import ShowQRPage + from utils import B2A + import microns + + if isinstance(self.pk, str): + qr_data = self.pk + else: + qr_data = B2A(self.pk) + + result = await ShowQRPage(qr_type=self.qr_type, qr_data=qr_data, right_micron=microns.Checkmark).show() + + if not result: + self.back() return self.set_result(True) @@ -104,7 +127,7 @@ async def confirm_seedqr(self): from pages import InfoPage, SeedWordsListPage import microns - plural_label = 's' if len(self.qr_data) == 24 else '' + plural_label = 's' if len(self.words) == 24 else '' text = 'Confirm the seed words in the following page{}.'.format(plural_label) result = await InfoPage(text=text, left_micron=microns.Back).show() @@ -112,7 +135,7 @@ async def confirm_seedqr(self): self.back() return - result = await SeedWordsListPage(words=self.qr_data, left_micron=microns.Back).show() + result = await SeedWordsListPage(words=self.words, left_micron=microns.Back).show() if not result: return @@ -121,11 +144,10 @@ async def confirm_seedqr(self): async def save_to_sd(self): from utils import B2A - from flows import GetSeedWordsFlow, SaveToMicroSDFlow, SeedWarningFlow + from flows import SaveToMicroSDFlow, SeedWarningFlow if self.key_type['words']: - words = await GetSeedWordsFlow(self.pk).run() - text = " ".join(words) + text = " ".join(self.words) elif isinstance(self.pk, str): text = self.pk else: diff --git a/ports/stm32/boards/Passport/modules/flows/get_seed_words_flow.py b/ports/stm32/boards/Passport/modules/flows/get_seed_words_flow.py index fd1c50b9e..4b7a47f43 100644 --- a/ports/stm32/boards/Passport/modules/flows/get_seed_words_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/get_seed_words_flow.py @@ -7,9 +7,10 @@ class GetSeedWordsFlow(Flow): - def __init__(self, external_key=None): - super().__init__(initial_state=self.get_words, name='GetSeedWordsFlow') + def __init__(self, external_key=None, text='Retrieving Seed'): self.external_key = external_key + self.text = text + super().__init__(initial_state=self.get_words, name='GetSeedWordsFlow') async def get_words(self): from tasks import get_seed_words_task @@ -19,7 +20,7 @@ async def get_words(self): if self.external_key: (words, error) = get_words_from_seed(self.external_key) else: - (words, error) = await spinner_task(text='Retrieving Seed', + (words, error) = await spinner_task(text=self.text, task=get_seed_words_task) if error is not None or words is None: From fd6dd773340ba265ea97aaefd4a14e00f31f9678 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 16:03:19 -0500 Subject: [PATCH 042/187] SFT-1994: refactored derived key and seed words flows for better reuse --- .../modules/flows/export_derived_key_flow.py | 117 +++++----------- .../modules/flows/seed_warning_flow.py | 6 +- .../modules/flows/view_seed_words_flow.py | 131 ++++++++++++++---- 3 files changed, 140 insertions(+), 114 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index a43fe0df1..30945b222 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -11,15 +11,15 @@ def __init__(self, context=None): self.key = context self.key_type = None self.pk = None - self.qr_type = None - self.words = None + self.data = None + self.filename = None super().__init__(initial_state=self.generate_key, name="NewDerivedKeyFlow") async def generate_key(self): - from utils import spinner_task + from utils import spinner_task, B2A from derived_key import get_key_type_from_tn from pages import ErrorPage - from flows import GetSeedWordsFlow + from flows import ViewSeedWordsFlow self.key_type = get_key_type_from_tn(self.key['tn']) @@ -36,27 +36,30 @@ async def generate_key(self): self.set_result(False) return + self.filename = '{}-{}.txt'.format(self.key_type['title'], self.key['name']) + if self.key_type['words']: - self.words = await GetSeedWordsFlow(external_key=self.pk, text='Generating Key').run() + result = await ViewSeedWordsFlow(external_key=self.pk, + qr_option=True, + sd_option=True, + filename=self.filename).run() + self.set_result(result) + return - if self.words is None: - self.set_result(False) - return + if isinstance(self.pk, str): + self.data = self.pk + else: + self.data = B2A(self.pk) self.goto(self.choose_export_mode) async def choose_export_mode(self): from pages import ChooserPage - options = [{'label': 'Export via QR', 'value': self.choose_qr_type}, + options = [{'label': 'Export via QR', 'value': self.show_qr_code}, {'label': 'Export via microSD', 'value': self.save_to_sd}] - if self.key_type['words']: - options.append({'label': 'Show seed words', 'value': self.show_seed_words}) - - mode = await ChooserPage(card_header={'title': 'Export Mode'}, options=options).show() - - # TODO: if key_type['words'] and not save_to_sd, use ViewSeedWordsFlow + mode = await ChooserPage(card_header={'title': 'Format'}, options=options).show() if mode is None: self.set_result(False) @@ -64,78 +67,40 @@ async def choose_export_mode(self): self.goto(mode) - async def choose_qr_type(self): - from pages import ChooserPage - from flows import SeedWarningFlow - from data_codecs.qr_type import QRType - - self.qr_type = QRType.QR - - if self.key_type['words']: - options = [{'label': 'Compact SeedQR', 'value': QRType.COMPACT_SEED_QR}, - {'label': 'SeedQR', 'value': QRType.SEED_QR}] - - self.qr_type = await ChooserPage(card_header={'title': 'QR Format'}, options=options).show() - - if self.qr_type is None: - self.back() - return - - result = await SeedWarningFlow(action_text="display your {} as a QR code" - .format(self.key_type['title'])).run() - if not result: - self.back() - return - - if self.qr_type in [QRType.SEED_QR, QRType.COMPACT_SEED_QR]: - self.goto(self.show_seed_qr) - return - - self.goto(show_qr_code) - - async def show_seed_qr(self): + async def show_qr_code(self): from pages import ShowQRPage + from flows import SaveToMicroSDFlow, SeedWarningFlow import microns - result = await ShowQRPage(qr_type=self.qr_type, qr_data=self.words, right_micron=microns.Checkmark).show() + result = await SeedWarningFlow(action_text="display your {} as a QR code" + .format(self.key_type['title'])).run() if not result: self.back() return - self.goto(self.confirm_seedqr) - - async def show_qr_code(self): - from pages import ShowQRPage - from utils import B2A - import microns - - if isinstance(self.pk, str): - qr_data = self.pk - else: - qr_data = B2A(self.pk) - - result = await ShowQRPage(qr_type=self.qr_type, qr_data=qr_data, right_micron=microns.Checkmark).show() + result = await ShowQRPage(qr_data=self.data, right_micron=microns.Checkmark).show() if not result: - self.back() return - self.set_result(True) + self.goto(self.confirm_qr) - async def confirm_seedqr(self): - from pages import InfoPage, SeedWordsListPage + async def confirm_qr(self): + from pages import InfoPage, LongTextPage import microns - plural_label = 's' if len(self.words) == 24 else '' - text = 'Confirm the seed words in the following page{}.'.format(plural_label) + text = 'Confirm the exported {} in the following page.'.format(self.key_type['title']) result = await InfoPage(text=text, left_micron=microns.Back).show() if not result: self.back() return - result = await SeedWordsListPage(words=self.words, left_micron=microns.Back).show() + result = await LongTextPage(text="\n" + self.data, + centered=True, + card_header={'title': 'Confirm Key'}, + left_micron=microns.Back).show() if not result: return @@ -143,31 +108,17 @@ async def confirm_seedqr(self): self.set_result(True) async def save_to_sd(self): - from utils import B2A from flows import SaveToMicroSDFlow, SeedWarningFlow - if self.key_type['words']: - text = " ".join(self.words) - elif isinstance(self.pk, str): - text = self.pk - else: - text = B2A(self.pk) - result = await SeedWarningFlow(action_text="copy your {} to the microSD card" .format(self.key_type['title']), continue_text=self.key_type.get('continue_text', None)).run() if not result: - self.set_result(False) + self.back() return - filename = '{}-{}.txt'.format(self.key_type['title'], self.key['name']) - result = await SaveToMicroSDFlow(filename=filename, - data=text, + result = await SaveToMicroSDFlow(filename=self.filename, + data=self.data, success_text="key").run() self.set_result(result) - - async def show_seed_words(self): - from flows import ViewSeedWordsFlow - await ViewSeedWordsFlow(external_key=self.pk).run() - self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py index 4ca63116e..7f7b2637c 100644 --- a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py @@ -8,11 +8,9 @@ class SeedWarningFlow(Flow): def __init__(self, mention_passphrase=False, - action_text="display your seed words", - continue_text=None): + action_text=None): self.mention_passphrase = mention_passphrase - self.action_text = action_text - self.continue_text = continue_text or "control your funds" + self.action_text = action_text or "display your seed words" super().__init__(initial_state=self.show_intro, name='SeedWarningFlow') async def show_intro(self): diff --git a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py index 3f8100fd7..fe7881993 100644 --- a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py @@ -7,23 +7,23 @@ class ViewSeedWordsFlow(Flow): - def __init__(self, external_key=None, qr_option=False): + def __init__(self, external_key=None, qr_option=False, sd_option=False, filename=None): self.external_key = external_key self.qr_option = qr_option - self.mode = None - self.words = None - super().__init__(initial_state=self.show_warning, name='ViewSeedWordsFlow') - async def show_warning(self): - from flows import SeedWarningFlow - from flows import GetSeedWordsFlow + if sd_option: + filename = filename or 'Seed.txt' # Caller should never let this happen - mention_passphrase = False if self.external_key else True - result = await SeedWarningFlow(mention_passphrase=mention_passphrase).run() + self.sd_option = sd_option + self.filename = filename + self.qr_type = None + self.words = None + self.seed_micron = None + self.mention_passphrase = True if not external_key else False + super().__init__(initial_state=self.generate_words, name='ViewSeedWordsFlow') - if not result: - self.set_result(False) - return + async def generate_words(self): + from flows import GetSeedWordsFlow self.words = await GetSeedWordsFlow(self.external_key).run() @@ -31,39 +31,116 @@ async def show_warning(self): self.set_result(False) return - if self.qr_option: - self.goto(self.choose_mode) - else: - self.goto(self.show_seed_words) + self.goto(self.choose_mode) async def choose_mode(self): from pages import ChooserPage from data_codecs.qr_type import QRType + import microns + + if not (self.qr_option or self.sd_option): + self.goto(self.show_seed_words) + return - options = [{'label': 'Seed Words', 'value': self.show_seed_words}, - {'label': 'Compact SeedQR', 'value': QRType.COMPACT_SEED_QR}, - {'label': 'SeedQr', 'value': QRType.SEED_QR}] - self.mode = await ChooserPage(card_header={'title': 'View'}, options=options).show() - if self.mode is None: + options = [{'label': 'Seed Words', 'value': self.show_seed_words}] + + if self.qr_option: + options.extend([{'label': 'Compact SeedQR', + 'value': QRType.COMPACT_SEED_QR}, + {'label': 'SeedQr', + 'value': QRType.SEED_QR}]) + + if self.sd_option: + options.append({'label': 'microSD', + 'value': self.save_to_sd}) + + mode = await ChooserPage(card_header={'title': 'Format'}, options=options).show() + + if mode is None: self.set_result(False) return - if isinstance(self.mode, int): - self.goto(self.show_qr) - else: - self.goto(self.show_seed_words) + if isinstance(mode, int) and mode in [QRType.SEED_QR, QRType.COMPACT_SEED_QR]: + self.qr_type = mode + mode = self.show_qr + self.seed_micron = microns.Cancel + + self.goto(mode) async def show_qr(self): + from flows import SeedWarningFlow from pages import ShowQRPage import microns - await ShowQRPage(qr_type=self.mode, qr_data=self.words, right_micron=microns.Checkmark).show() + result = await SeedWarningFlow(action_text="display your seed as a QR code", + mention_passphrase=self.mention_passphrase).run() + + if not result: + self.back() + return + + result = await ShowQRPage(qr_type=self.qr_type, qr_data=self.words, right_micron=microns.Checkmark).show() + + if not result: + return + + self.goto(self.confirm_qr) + + async def confirm_qr(self): + from pages import InfoPage + import microns + + plural_label = 's' if len(self.words) == 24 else '' + text = 'Confirm the seed words in the following page{}.'.format(plural_label) + result = await InfoPage(text=text, left_micron=microns.Back).show() + + if not result: + self.back() + return + + self.goto(self.show_seed_words) + + async def save_to_sd(self): + from flows import SeedWarningFlow + from utils import B2A + from flows import SaveToMicroSDFlow + + result = await SeedWarningFlow(action_text="copy your seed to the microSD card", + mention_passphrase=self.mention_passphrase).run() + + if not result: + self.back() + return + + text = " ".join(self.words) + result = await SaveToMicroSDFlow(filename=self.filename, + data=text, + success_text="seed").run() + + if not result: + return + self.goto(self.show_passphrase) async def show_seed_words(self): + from flows import SeedWarningFlow from pages import SeedWordsListPage - await SeedWordsListPage(words=self.words).show() + if not self.qr_type: # We already gave the seed warning flow + result = await SeedWarningFlow(mention_passphrase=self.mention_passphrase).run() + + if not result: + self.back() + return + + result = await SeedWordsListPage(words=self.words, + left_micron=self.seed_micron).show() + + if not result: + if self.qr_type: + self.back() + return + self.goto(self.show_passphrase) async def show_passphrase(self): From 907ae8a4e07eebbcefe9bf645831dffd7bf8cb47 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 16:14:20 -0500 Subject: [PATCH 043/187] SFT-1994: minimized diff --- .../Passport/modules/flows/export_derived_key_flow.py | 2 +- .../boards/Passport/modules/flows/get_seed_words_flow.py | 7 +++---- .../boards/Passport/modules/flows/seed_warning_flow.py | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index 30945b222..83120279a 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -69,7 +69,7 @@ async def choose_export_mode(self): async def show_qr_code(self): from pages import ShowQRPage - from flows import SaveToMicroSDFlow, SeedWarningFlow + from flows import SeedWarningFlow import microns result = await SeedWarningFlow(action_text="display your {} as a QR code" diff --git a/ports/stm32/boards/Passport/modules/flows/get_seed_words_flow.py b/ports/stm32/boards/Passport/modules/flows/get_seed_words_flow.py index 4b7a47f43..fd1c50b9e 100644 --- a/ports/stm32/boards/Passport/modules/flows/get_seed_words_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/get_seed_words_flow.py @@ -7,10 +7,9 @@ class GetSeedWordsFlow(Flow): - def __init__(self, external_key=None, text='Retrieving Seed'): - self.external_key = external_key - self.text = text + def __init__(self, external_key=None): super().__init__(initial_state=self.get_words, name='GetSeedWordsFlow') + self.external_key = external_key async def get_words(self): from tasks import get_seed_words_task @@ -20,7 +19,7 @@ async def get_words(self): if self.external_key: (words, error) = get_words_from_seed(self.external_key) else: - (words, error) = await spinner_task(text=self.text, + (words, error) = await spinner_task(text='Retrieving Seed', task=get_seed_words_task) if error is not None or words is None: diff --git a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py index 7f7b2637c..6c533d3c6 100644 --- a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py @@ -8,9 +8,9 @@ class SeedWarningFlow(Flow): def __init__(self, mention_passphrase=False, - action_text=None): + action_text="display your seed words"): self.mention_passphrase = mention_passphrase - self.action_text = action_text or "display your seed words" + self.action_text = action_text super().__init__(initial_state=self.show_intro, name='SeedWarningFlow') async def show_intro(self): From ae40fbb899f1cae69415bcb2c52c4bff5fb05e99 Mon Sep 17 00:00:00 2001 From: Ken Carpenter <62639971+FoundationKen@users.noreply.github.com> Date: Wed, 3 May 2023 15:57:33 -0700 Subject: [PATCH 044/187] Update export_derived_key_flow.py --- .../boards/Passport/modules/flows/export_derived_key_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index 83120279a..ca7410ccd 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -90,7 +90,7 @@ async def confirm_qr(self): from pages import InfoPage, LongTextPage import microns - text = 'Confirm the exported {} in the following page.'.format(self.key_type['title']) + text = 'Confirm the exported {} on the following page.'.format(self.key_type['title']) result = await InfoPage(text=text, left_micron=microns.Back).show() if not result: From de9af58333476a8346d11db1c4a2d498c64adc04 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 11:23:45 -0500 Subject: [PATCH 045/187] SFT-2001: fixed scv_flow from menu --- ports/stm32/boards/Passport/modules/menus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 564b2af55..7a92515e7 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -331,7 +331,7 @@ def advanced_menu(): {'icon': lv.ICON_MICROSD, 'label': 'microSD', 'submenu': microsd_menu}, {'icon': lv.ICON_ERASE, 'label': 'Erase Passport', 'flow': ErasePassportFlow}, {'icon': lv.ICON_SHIELD, 'label': 'Security Check', 'flow': ScvFlow, - 'args': {'envoy': False, 'ask_to_skip': False}}, + 'args': {'envoy': False}}, ] From fa04c208e56ed2a22212c4b0a2aa936de1661ca0 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 17:01:16 -0500 Subject: [PATCH 046/187] SFT-2001: restored "ask_to_skip" parameter --- .../boards/Passport/modules/flows/scv_flow.py | 15 +++++++++++---- ports/stm32/boards/Passport/modules/menus.py | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index f3379749d..c382099d8 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -19,7 +19,7 @@ class ScvFlow(Flow): - def __init__(self, envoy=True): + def __init__(self, envoy=True, ask_to_skip=True): """ :param envoy: True for Envoy App flow. False is manual Supply Chain Validation. """ @@ -29,6 +29,7 @@ def __init__(self, envoy=True): statusbar={'title': 'SECURITY CHECK', 'icon': lv.ICON_SHIELD}) self.words = None self.envoy = envoy + self.ask_to_skip = ask_to_skip self.uuid = None async def show_intro(self): @@ -56,7 +57,7 @@ async def scan_qr_challenge(self): ur_types=ur_types, data_description='a supply chain validation challenge').run() if result is None: - self.goto(self.ask_to_skip) + self.goto(self.prompt_skip) return if self.envoy: @@ -167,9 +168,15 @@ async def ask_if_valid(self): if result: self.goto(self.scan_qr_challenge) else: - self.goto(self.ask_to_skip) + self.goto(self.prompt_skip) + + async def prompt_skip(self): + + if not self.ask_to_skip: + common.settings.set('validated_ok', True) + self.set_result(True) + return - async def ask_to_skip(self): skip = await QuestionPage( text='Skip Security Check?\n\n{}'.format( recolor(HIGHLIGHT_TEXT_HEX, '(Not recommended)')) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 7a92515e7..564b2af55 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -331,7 +331,7 @@ def advanced_menu(): {'icon': lv.ICON_MICROSD, 'label': 'microSD', 'submenu': microsd_menu}, {'icon': lv.ICON_ERASE, 'label': 'Erase Passport', 'flow': ErasePassportFlow}, {'icon': lv.ICON_SHIELD, 'label': 'Security Check', 'flow': ScvFlow, - 'args': {'envoy': False}}, + 'args': {'envoy': False, 'ask_to_skip': False}}, ] From 8c891bc546e3c89bb5dd8abb50c780486a1c5a7f Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 17:10:55 -0500 Subject: [PATCH 047/187] SFT-2001: center security check words --- ports/stm32/boards/Passport/modules/flows/scv_flow.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index c382099d8..7980af4ea 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -132,12 +132,10 @@ async def show_envoy_response(self): async def show_manual_response(self): from pages import ShieldPage - words = '' - for idx, word in enumerate(self.words): - words += ' {}. {}\n'.format(idx + 1, word) - words = words[:-1] + lines = ['{}. {}\n'.format(idx + 1, word) for idx, word in enumerate(self.words)] + words = ''.join(lines) - result = await ShieldPage(text=words, card_header={'title': 'Security Check'}, centered=False, + result = await ShieldPage(text=words, card_header={'title': 'Security Check'}, left_micron=microns.Retry, right_micron=microns.Forward).show() if not result: self.back() From fab556d1583fd0639932c2ce0228e78c3a171071 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 19 Apr 2023 21:31:22 -0500 Subject: [PATCH 048/187] SFT-1028: 2 bit per pixel font first pass --- .../lvgl/src/font/lv_font_montserrat_16.c | 2480 ++++------------- 1 file changed, 576 insertions(+), 1904 deletions(-) diff --git a/lib/lv_bindings/lvgl/src/font/lv_font_montserrat_16.c b/lib/lv_bindings/lvgl/src/font/lv_font_montserrat_16.c index 2b0dccf92..d2a7c8708 100644 --- a/lib/lv_bindings/lvgl/src/font/lv_font_montserrat_16.c +++ b/lib/lv_bindings/lvgl/src/font/lv_font_montserrat_16.c @@ -1,17 +1,17 @@ /******************************************************************************* * Size: 16 px - * Bpp: 4 - * Opts: --no-compress --no-prefilter --bpp 4 --size 16 --font Montserrat-Medium.ttf -r 0x20-0x7F,0xB0,0x2022 --font FontAwesome5-Solid+Brands+Regular.woff -r 61441,61448,61451,61452,61452,61453,61457,61459,61461,61465,61468,61473,61478,61479,61480,61502,61507,61512,61515,61516,61517,61521,61522,61523,61524,61543,61544,61550,61552,61553,61556,61559,61560,61561,61563,61587,61589,61636,61637,61639,61641,61664,61671,61674,61683,61724,61732,61787,61931,62016,62017,62018,62019,62020,62087,62099,62212,62189,62810,63426,63650 --format lvgl -o lv_font_montserrat_16.c --force-fast-kern-format + * Bpp: 2 + * Opts: ******************************************************************************/ #ifdef LV_LVGL_H_INCLUDE_SIMPLE - #include "lvgl.h" +#include "lvgl.h" #else - #include "../../lvgl.h" +#include "lvgl/lvgl.h" #endif #ifndef LV_FONT_MONTSERRAT_16 - #define LV_FONT_MONTSERRAT_16 1 +#define LV_FONT_MONTSERRAT_16 1 #endif #if LV_FONT_MONTSERRAT_16 @@ -25,1758 +25,522 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { /* U+0020 " " */ /* U+0021 "!" */ - 0xbf, 0xb, 0xf0, 0xaf, 0xa, 0xe0, 0x9e, 0x8, - 0xd0, 0x8c, 0x7, 0xc0, 0x0, 0x0, 0x10, 0xbf, - 0x1a, 0xe0, + 0xb2, 0xcb, 0x2c, 0xb2, 0xcb, 0x1c, 0x0, 0xb, + 0x2c, /* U+0022 "\"" */ - 0xf5, 0x1f, 0x3f, 0x51, 0xf3, 0xe4, 0xf, 0x3e, - 0x40, 0xf2, 0x72, 0x8, 0x10, + 0xd3, 0x34, 0xcd, 0x33, 0x4c, 0x42, 0x0, /* U+0023 "#" */ - 0x0, 0x5, 0xc0, 0x3, 0xe0, 0x0, 0x0, 0x7a, - 0x0, 0x5c, 0x0, 0x0, 0x9, 0x80, 0x7, 0xa0, - 0x1, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x3, 0x3e, - 0x73, 0x3c, 0x83, 0x30, 0x0, 0xf2, 0x0, 0xc5, - 0x0, 0x0, 0xf, 0x10, 0xe, 0x30, 0x0, 0x2, - 0xf0, 0x0, 0xf2, 0x0, 0x9f, 0xff, 0xff, 0xff, - 0xff, 0x41, 0x38, 0xc3, 0x36, 0xe3, 0x30, 0x0, - 0x89, 0x0, 0x5c, 0x0, 0x0, 0xa, 0x70, 0x7, - 0xa0, 0x0, + 0x1, 0xc0, 0xc0, 0x6, 0x7, 0x0, 0x28, 0x18, + 0xf, 0xff, 0xff, 0x3, 0x43, 0x80, 0xc, 0xd, + 0x0, 0x30, 0x30, 0x0, 0xc0, 0xc0, 0xbf, 0xff, + 0xf4, 0x2c, 0x1c, 0x0, 0xa0, 0x70, 0x2, 0x41, + 0x80, /* U+0024 "$" */ - 0x0, 0x0, 0x79, 0x0, 0x0, 0x0, 0x0, 0x79, - 0x0, 0x0, 0x0, 0x5c, 0xff, 0xe9, 0x20, 0x6, - 0xfc, 0xbc, 0x9e, 0x90, 0xe, 0xb0, 0x79, 0x0, - 0x10, 0xf, 0x80, 0x79, 0x0, 0x0, 0xd, 0xf5, - 0x79, 0x0, 0x0, 0x3, 0xef, 0xfd, 0x50, 0x0, - 0x0, 0x6, 0xcf, 0xfe, 0x40, 0x0, 0x0, 0x79, - 0x5e, 0xf1, 0x0, 0x0, 0x79, 0x5, 0xf3, 0x7, - 0x0, 0x79, 0x7, 0xf1, 0x2f, 0xe9, 0xbc, 0xaf, - 0xa0, 0x3, 0xae, 0xff, 0xd7, 0x0, 0x0, 0x0, - 0x79, 0x0, 0x0, 0x0, 0x0, 0x79, 0x0, 0x0, + 0x0, 0x60, 0x0, 0x6, 0x0, 0x7, 0xfe, 0x1, + 0xfb, 0xb8, 0x38, 0x60, 0x3, 0x86, 0x0, 0x3d, + 0x60, 0x0, 0xff, 0x40, 0x1, 0xff, 0x40, 0x6, + 0x7c, 0x0, 0x61, 0xc1, 0x6, 0x1c, 0x3e, 0xbb, + 0x80, 0xbf, 0xd0, 0x0, 0x60, 0x0, 0x6, 0x0, /* U+0025 "%" */ - 0x3, 0xde, 0x80, 0x0, 0x5, 0xd0, 0x0, 0xe4, - 0xc, 0x50, 0x1, 0xe3, 0x0, 0x4c, 0x0, 0x5a, - 0x0, 0xa9, 0x0, 0x6, 0xa0, 0x4, 0xc0, 0x4e, - 0x0, 0x0, 0x4c, 0x0, 0x5a, 0xd, 0x50, 0x0, - 0x0, 0xe4, 0x1c, 0x58, 0xa0, 0x0, 0x0, 0x3, - 0xce, 0x73, 0xe1, 0x3c, 0xe9, 0x0, 0x0, 0x0, - 0xd6, 0xe, 0x40, 0xa8, 0x0, 0x0, 0x7c, 0x3, - 0xc0, 0x3, 0xd0, 0x0, 0x2e, 0x20, 0x3c, 0x0, - 0x3d, 0x0, 0xb, 0x70, 0x0, 0xe2, 0x9, 0x80, - 0x6, 0xd0, 0x0, 0x4, 0xdd, 0xa0, + 0xf, 0x80, 0x1c, 0xd, 0x34, 0xc, 0x7, 0x6, + 0xa, 0x1, 0x81, 0xc7, 0x0, 0x70, 0x63, 0x40, + 0xd, 0x36, 0x80, 0x0, 0xf4, 0xc3, 0xe0, 0x0, + 0xd3, 0x4a, 0x0, 0x70, 0xc0, 0xc0, 0x30, 0x30, + 0x30, 0x24, 0xc, 0x28, 0x1c, 0x1, 0xf8, /* U+0026 "&" */ - 0x0, 0x9, 0xef, 0xb1, 0x0, 0x0, 0x9, 0xe4, - 0x3c, 0xa0, 0x0, 0x0, 0xd9, 0x0, 0x7d, 0x0, - 0x0, 0xc, 0xc0, 0x1c, 0xa0, 0x0, 0x0, 0x3f, - 0xae, 0xc1, 0x0, 0x0, 0x1, 0xdf, 0xc0, 0x0, - 0x0, 0x3, 0xeb, 0x8f, 0x70, 0x18, 0x0, 0xdb, - 0x0, 0x7f, 0x65, 0xf0, 0x3f, 0x40, 0x0, 0x8f, - 0xea, 0x3, 0xf7, 0x0, 0x0, 0xcf, 0x70, 0xb, - 0xf9, 0x66, 0xcf, 0xbf, 0x40, 0x8, 0xdf, 0xea, - 0x30, 0xa5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x2, 0xf8, 0x0, 0x2d, 0x38, 0x0, 0xe0, 0x70, + 0x3, 0xc3, 0x80, 0x3, 0xbc, 0x0, 0xf, 0xc0, + 0x0, 0xeb, 0x42, 0xe, 0x7, 0x5c, 0x34, 0xb, + 0xe0, 0xd0, 0xf, 0x42, 0xe5, 0xfb, 0x42, 0xfe, + 0x9, 0x0, 0x0, 0x0, /* U+0027 "'" */ - 0xf5, 0xf5, 0xe4, 0xe4, 0x72, + 0xdd, 0xdd, 0x40, /* U+0028 "(" */ - 0x0, 0xda, 0x5, 0xf2, 0xb, 0xc0, 0xf, 0x70, - 0x3f, 0x40, 0x5f, 0x20, 0x6f, 0x10, 0x7f, 0x0, - 0x6f, 0x10, 0x5f, 0x20, 0x3f, 0x40, 0xf, 0x70, - 0xb, 0xc0, 0x5, 0xf2, 0x0, 0xda, + 0xe, 0x1c, 0x2c, 0x34, 0x34, 0x70, 0x70, 0x70, + 0x70, 0x70, 0x34, 0x34, 0x2c, 0x1c, 0xe, /* U+0029 ")" */ - 0x3f, 0x30, 0xc, 0xb0, 0x6, 0xf1, 0x1, 0xf6, - 0x0, 0xe9, 0x0, 0xbc, 0x0, 0xad, 0x0, 0xae, - 0x0, 0xad, 0x0, 0xbc, 0x0, 0xe9, 0x1, 0xf6, - 0x6, 0xf1, 0xc, 0xb0, 0x3f, 0x30, + 0x30, 0x38, 0x1c, 0xd, 0xe, 0xb, 0xb, 0xb, + 0xb, 0xb, 0xe, 0xd, 0x1c, 0x38, 0x30, /* U+002A "*" */ - 0x0, 0x4a, 0x0, 0x6, 0x74, 0xa4, 0xa0, 0x2b, - 0xff, 0xe5, 0x0, 0x7f, 0xfb, 0x20, 0x7b, 0x6b, - 0x8d, 0x0, 0x4, 0xa0, 0x0, 0x0, 0x13, 0x0, - 0x0, + 0x6, 0x1, 0x59, 0x82, 0xfd, 0x7, 0xe0, 0x66, + 0xb0, 0x18, 0x0, 0x0, 0x0, /* U+002B "+" */ - 0x0, 0x5, 0x10, 0x0, 0x0, 0xf, 0x50, 0x0, - 0x0, 0xf, 0x50, 0x0, 0x1, 0x1f, 0x51, 0x10, - 0xef, 0xff, 0xff, 0xf3, 0x34, 0x4f, 0x74, 0x40, - 0x0, 0xf, 0x50, 0x0, 0x0, 0xf, 0x50, 0x0, + 0x1, 0x0, 0x3, 0x40, 0x3, 0x40, 0x3, 0x40, + 0xff, 0xfc, 0x17, 0x54, 0x3, 0x40, 0x3, 0x40, /* U+002C "," */ - 0x9, 0x52, 0xfd, 0xb, 0xa0, 0xc5, 0xf, 0x0, + 0x24, 0xf2, 0x8d, 0x30, /* U+002D "-" */ - 0x1, 0x11, 0x10, 0x1f, 0xff, 0xf3, 0x4, 0x44, - 0x40, + 0x0, 0x3, 0xfc, 0x15, 0x40, /* U+002E "." */ - 0x3, 0x12, 0xfc, 0x1e, 0x90, + 0x0, 0xf3, 0x80, /* U+002F "/" */ - 0x0, 0x0, 0x5, 0xf1, 0x0, 0x0, 0xa, 0xb0, - 0x0, 0x0, 0xf, 0x60, 0x0, 0x0, 0x5f, 0x10, - 0x0, 0x0, 0xab, 0x0, 0x0, 0x0, 0xf6, 0x0, - 0x0, 0x5, 0xf1, 0x0, 0x0, 0xa, 0xb0, 0x0, - 0x0, 0xf, 0x60, 0x0, 0x0, 0x4f, 0x10, 0x0, - 0x0, 0xac, 0x0, 0x0, 0x0, 0xf6, 0x0, 0x0, - 0x4, 0xf1, 0x0, 0x0, 0xa, 0xc0, 0x0, 0x0, - 0xe, 0x60, 0x0, 0x0, 0x4f, 0x10, 0x0, 0x0, + 0x0, 0x1c, 0x0, 0x28, 0x0, 0x34, 0x0, 0x70, + 0x0, 0xa0, 0x0, 0xd0, 0x1, 0xc0, 0x2, 0x80, + 0x3, 0x40, 0x7, 0x0, 0xb, 0x0, 0xd, 0x0, + 0x1c, 0x0, 0x2c, 0x0, 0x34, 0x0, 0x70, 0x0, /* U+0030 "0" */ - 0x0, 0x8, 0xef, 0xc5, 0x0, 0x0, 0xcf, 0xa8, - 0xcf, 0x70, 0x7, 0xf5, 0x0, 0xa, 0xf2, 0xd, - 0xc0, 0x0, 0x1, 0xf8, 0x1f, 0x80, 0x0, 0x0, - 0xdc, 0x3f, 0x60, 0x0, 0x0, 0xbd, 0x3f, 0x60, - 0x0, 0x0, 0xbd, 0x1f, 0x80, 0x0, 0x0, 0xdc, - 0xd, 0xc0, 0x0, 0x1, 0xf8, 0x7, 0xf5, 0x0, - 0xa, 0xf2, 0x0, 0xcf, 0xa8, 0xcf, 0x70, 0x0, - 0x8, 0xef, 0xc5, 0x0, + 0x2, 0xfd, 0x0, 0xfa, 0xf4, 0x1d, 0x2, 0xc3, + 0xc0, 0xe, 0x38, 0x0, 0xf3, 0x40, 0xb, 0x34, + 0x0, 0xb3, 0x80, 0xf, 0x3c, 0x0, 0xe1, 0xd0, + 0x2c, 0xf, 0xaf, 0x40, 0x2f, 0xd0, /* U+0031 "1" */ - 0xef, 0xff, 0x36, 0x7a, 0xf3, 0x0, 0x5f, 0x30, - 0x5, 0xf3, 0x0, 0x5f, 0x30, 0x5, 0xf3, 0x0, - 0x5f, 0x30, 0x5, 0xf3, 0x0, 0x5f, 0x30, 0x5, - 0xf3, 0x0, 0x5f, 0x30, 0x5, 0xf3, + 0xff, 0x16, 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, + 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1c, /* U+0032 "2" */ - 0x4, 0xbe, 0xfd, 0x70, 0x7, 0xfd, 0x98, 0xcf, - 0x90, 0x28, 0x0, 0x0, 0xbf, 0x0, 0x0, 0x0, - 0x7, 0xf2, 0x0, 0x0, 0x0, 0xaf, 0x0, 0x0, - 0x0, 0x4f, 0x80, 0x0, 0x0, 0x3f, 0xc0, 0x0, - 0x0, 0x3e, 0xc1, 0x0, 0x0, 0x2e, 0xc1, 0x0, - 0x0, 0x2e, 0xd1, 0x0, 0x0, 0x2e, 0xf8, 0x77, - 0x77, 0x46, 0xff, 0xff, 0xff, 0xfa, + 0x1b, 0xf4, 0x1f, 0xaf, 0x82, 0x0, 0xb0, 0x0, + 0x1c, 0x0, 0xb, 0x0, 0x7, 0x80, 0x3, 0xc0, + 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xc0, 0x3, 0xe5, + 0x55, 0xff, 0xfe, /* U+0033 "3" */ - 0x6f, 0xff, 0xff, 0xff, 0x2, 0x77, 0x77, 0x9f, - 0xb0, 0x0, 0x0, 0xc, 0xe1, 0x0, 0x0, 0x9, - 0xf3, 0x0, 0x0, 0x5, 0xf6, 0x0, 0x0, 0x0, - 0xdf, 0xe9, 0x10, 0x0, 0x4, 0x59, 0xfd, 0x0, - 0x0, 0x0, 0x6, 0xf4, 0x0, 0x0, 0x0, 0x3f, - 0x64, 0x40, 0x0, 0x8, 0xf3, 0xbf, 0xc9, 0x8c, - 0xfb, 0x0, 0x7c, 0xff, 0xd7, 0x0, + 0x7f, 0xff, 0x5, 0x5b, 0x80, 0x3, 0xc0, 0x2, + 0xc0, 0x1, 0xd0, 0x0, 0xfe, 0x0, 0x16, 0xf0, + 0x0, 0x1d, 0x0, 0x3, 0x54, 0x2, 0xcb, 0xeb, + 0xe0, 0x7f, 0xd0, /* U+0034 "4" */ - 0x0, 0x0, 0x1, 0xeb, 0x0, 0x0, 0x0, 0x0, - 0xbe, 0x10, 0x0, 0x0, 0x0, 0x6f, 0x50, 0x0, - 0x0, 0x0, 0x2f, 0x90, 0x0, 0x0, 0x0, 0xc, - 0xd0, 0x0, 0x0, 0x0, 0x8, 0xf3, 0x1, 0xd5, - 0x0, 0x3, 0xf8, 0x0, 0x2f, 0x60, 0x0, 0xed, - 0x22, 0x23, 0xf7, 0x21, 0x6f, 0xff, 0xff, 0xff, - 0xff, 0x81, 0x55, 0x55, 0x56, 0xf9, 0x52, 0x0, - 0x0, 0x0, 0x2f, 0x60, 0x0, 0x0, 0x0, 0x2, - 0xf6, 0x0, + 0x0, 0xe, 0x0, 0x0, 0xb0, 0x0, 0x7, 0x40, + 0x0, 0x38, 0x0, 0x3, 0xc0, 0x0, 0x2c, 0xd, + 0x0, 0xe0, 0x34, 0xf, 0x0, 0xd0, 0x7f, 0xff, + 0xf8, 0x55, 0x5e, 0x40, 0x0, 0x34, 0x0, 0x0, + 0xd0, /* U+0035 "5" */ - 0x5, 0xff, 0xff, 0xff, 0x0, 0x7f, 0x77, 0x77, - 0x70, 0x8, 0xe0, 0x0, 0x0, 0x0, 0xad, 0x0, - 0x0, 0x0, 0xb, 0xc2, 0x10, 0x0, 0x0, 0xdf, - 0xff, 0xfb, 0x30, 0x4, 0x55, 0x68, 0xff, 0x20, - 0x0, 0x0, 0x4, 0xf8, 0x0, 0x0, 0x0, 0xf, - 0x92, 0x50, 0x0, 0x5, 0xf6, 0x8f, 0xd9, 0x8a, - 0xfd, 0x10, 0x5b, 0xef, 0xe9, 0x10, + 0x1f, 0xff, 0x7, 0x55, 0x42, 0xc0, 0x0, 0xb0, + 0x0, 0x2c, 0x0, 0xf, 0xfe, 0x1, 0x56, 0xf0, + 0x0, 0x1e, 0x0, 0x3, 0x84, 0x1, 0xdb, 0xea, + 0xf0, 0x6f, 0xe0, /* U+0036 "6" */ - 0x0, 0x5, 0xce, 0xfc, 0x60, 0x0, 0x9f, 0xc8, - 0x8b, 0x70, 0x5, 0xf8, 0x0, 0x0, 0x0, 0xc, - 0xd0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x0, 0x0, - 0x0, 0x2f, 0x68, 0xef, 0xfa, 0x10, 0x3f, 0xee, - 0x64, 0x8f, 0xd0, 0x2f, 0xf1, 0x0, 0x6, 0xf4, - 0xe, 0xc0, 0x0, 0x2, 0xf6, 0x9, 0xf1, 0x0, - 0x6, 0xf3, 0x1, 0xde, 0x86, 0x9f, 0xb0, 0x0, - 0x19, 0xef, 0xd8, 0x0, + 0x1, 0xff, 0x40, 0xbe, 0xa4, 0x1e, 0x0, 0x3, + 0xc0, 0x0, 0x38, 0x0, 0x3, 0x6f, 0xe0, 0x3f, + 0x5b, 0xc3, 0xc0, 0x1d, 0x3c, 0x0, 0xd2, 0xc0, + 0x1c, 0xf, 0x9b, 0x80, 0x2f, 0xe0, /* U+0037 "7" */ - 0x8f, 0xff, 0xff, 0xff, 0xe8, 0xf7, 0x77, 0x77, - 0xfc, 0x8f, 0x0, 0x0, 0x4f, 0x55, 0x90, 0x0, - 0xb, 0xe0, 0x0, 0x0, 0x2, 0xf8, 0x0, 0x0, - 0x0, 0x9f, 0x10, 0x0, 0x0, 0xf, 0xb0, 0x0, - 0x0, 0x6, 0xf4, 0x0, 0x0, 0x0, 0xdd, 0x0, - 0x0, 0x0, 0x3f, 0x70, 0x0, 0x0, 0xa, 0xf1, - 0x0, 0x0, 0x1, 0xf9, 0x0, 0x0, + 0xbf, 0xff, 0xed, 0x55, 0xfb, 0x0, 0x75, 0x80, + 0x2c, 0x0, 0xe, 0x0, 0xb, 0x0, 0x3, 0x80, + 0x1, 0xd0, 0x0, 0xf0, 0x0, 0x34, 0x0, 0x2c, + 0x0, 0xe, 0x0, /* U+0038 "8" */ - 0x0, 0x5c, 0xff, 0xd7, 0x0, 0x6, 0xfc, 0x76, - 0xaf, 0xa0, 0xc, 0xd0, 0x0, 0x9, 0xf1, 0xd, - 0xc0, 0x0, 0x7, 0xf2, 0x7, 0xf7, 0x11, 0x5e, - 0xc0, 0x0, 0xbf, 0xff, 0xfe, 0x10, 0x9, 0xf9, - 0x54, 0x7e, 0xd0, 0x2f, 0x80, 0x0, 0x4, 0xf6, - 0x4f, 0x50, 0x0, 0x0, 0xf8, 0x1f, 0xa0, 0x0, - 0x5, 0xf6, 0x9, 0xfb, 0x76, 0xaf, 0xd0, 0x0, - 0x6c, 0xff, 0xd8, 0x10, + 0x7, 0xfd, 0x1, 0xf5, 0xb8, 0x3c, 0x2, 0xc3, + 0xc0, 0x1c, 0x1d, 0x7, 0xc0, 0xbf, 0xf0, 0x2e, + 0x57, 0xc3, 0x80, 0x1d, 0x74, 0x0, 0xe3, 0x80, + 0x1d, 0x2e, 0x5b, 0xc0, 0x7f, 0xe0, /* U+0039 "9" */ - 0x0, 0x8e, 0xfd, 0x80, 0x0, 0xc, 0xf8, 0x68, - 0xfc, 0x0, 0x5f, 0x50, 0x0, 0x3f, 0x70, 0x8f, - 0x0, 0x0, 0xe, 0xc0, 0x7f, 0x30, 0x0, 0x1f, - 0xf0, 0x1f, 0xd4, 0x13, 0xcf, 0xf1, 0x4, 0xef, - 0xff, 0xa9, 0xf0, 0x0, 0x2, 0x31, 0xa, 0xf0, - 0x0, 0x0, 0x0, 0xe, 0xa0, 0x0, 0x0, 0x0, - 0x9f, 0x30, 0x9, 0xa7, 0x8d, 0xf7, 0x0, 0x7, - 0xdf, 0xeb, 0x40, 0x0, + 0xb, 0xf8, 0x3, 0xe6, 0xf0, 0x74, 0x3, 0x4b, + 0x0, 0x3c, 0x70, 0x3, 0xc3, 0xd0, 0xfc, 0x1f, + 0xfa, 0xc0, 0x0, 0x2c, 0x0, 0x3, 0x80, 0x0, + 0xb0, 0x29, 0xbd, 0x1, 0xfe, 0x40, /* U+003A ":" */ - 0x1e, 0x92, 0xfc, 0x3, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x3, 0x12, 0xfc, 0x1e, 0x90, + 0x38, 0xf0, 0x0, 0x0, 0x0, 0xf, 0x38, /* U+003B ";" */ - 0x1e, 0x92, 0xfc, 0x3, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xe9, 0x1f, 0xd0, 0xa8, 0xe, - 0x30, 0xa0, + 0x38, 0xf0, 0x0, 0x0, 0x0, 0xe, 0x3c, 0xa3, + 0x8, /* U+003C "<" */ - 0x0, 0x0, 0x0, 0x42, 0x0, 0x1, 0x7d, 0xf3, - 0x3, 0x9f, 0xe8, 0x10, 0xbf, 0xb5, 0x0, 0x0, - 0xee, 0x81, 0x0, 0x0, 0x17, 0xdf, 0xb4, 0x0, - 0x0, 0x4, 0xaf, 0xd2, 0x0, 0x0, 0x1, 0x82, + 0x0, 0x4, 0x0, 0x7c, 0xb, 0xe0, 0xb9, 0x0, + 0xf8, 0x0, 0x1f, 0x90, 0x1, 0xbc, 0x0, 0x8, /* U+003D "=" */ - 0xef, 0xff, 0xff, 0xf3, 0x45, 0x55, 0x55, 0x51, - 0x0, 0x0, 0x0, 0x0, 0x1, 0x11, 0x11, 0x10, - 0xef, 0xff, 0xff, 0xf3, 0x34, 0x44, 0x44, 0x40, + 0xff, 0xfc, 0x55, 0x54, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xfc, 0x15, 0x54, /* U+003E ">" */ - 0x50, 0x0, 0x0, 0x0, 0xef, 0x92, 0x0, 0x0, - 0x6, 0xcf, 0xb5, 0x0, 0x0, 0x3, 0x9f, 0xe2, - 0x0, 0x0, 0x6c, 0xf3, 0x2, 0x9e, 0xe9, 0x20, - 0xbf, 0xc6, 0x0, 0x0, 0x93, 0x0, 0x0, 0x0, + 0x40, 0x0, 0xf8, 0x0, 0x1f, 0x90, 0x0, 0xbc, + 0x0, 0x7c, 0xb, 0xe0, 0xbd, 0x0, 0x80, 0x0, /* U+003F "?" */ - 0x4, 0xbe, 0xfd, 0x70, 0x7, 0xfc, 0x77, 0xbf, - 0xa0, 0x27, 0x0, 0x0, 0xcf, 0x0, 0x0, 0x0, - 0x9, 0xf0, 0x0, 0x0, 0x1, 0xea, 0x0, 0x0, - 0x1, 0xdd, 0x10, 0x0, 0x0, 0xce, 0x10, 0x0, - 0x0, 0x3f, 0x60, 0x0, 0x0, 0x1, 0x30, 0x0, - 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x6, 0xf5, - 0x0, 0x0, 0x0, 0x5f, 0x40, 0x0, + 0x1b, 0xf4, 0x1f, 0x5b, 0x81, 0x0, 0xf0, 0x0, + 0x2c, 0x0, 0xe, 0x0, 0xf, 0x0, 0xf, 0x0, + 0x3, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, + 0x0, 0x7, 0x40, /* U+0040 "@" */ - 0x0, 0x0, 0x17, 0xce, 0xfd, 0xb5, 0x0, 0x0, - 0x0, 0x5, 0xfb, 0x53, 0x23, 0x7d, 0xc2, 0x0, - 0x0, 0x6e, 0x40, 0x0, 0x0, 0x0, 0x8e, 0x10, - 0x2, 0xf4, 0x1, 0xae, 0xfa, 0x3f, 0x49, 0xb0, - 0xa, 0x90, 0x1e, 0xe6, 0x5b, 0xef, 0x40, 0xe3, - 0xf, 0x30, 0x8f, 0x10, 0x0, 0xaf, 0x40, 0x98, - 0x1f, 0x0, 0xd9, 0x0, 0x0, 0x3f, 0x40, 0x6a, - 0x3f, 0x0, 0xe8, 0x0, 0x0, 0x1f, 0x40, 0x5c, - 0x1f, 0x0, 0xd9, 0x0, 0x0, 0x3f, 0x40, 0x6a, - 0xf, 0x30, 0x8f, 0x10, 0x0, 0xaf, 0x40, 0x98, - 0xa, 0x90, 0x1e, 0xd6, 0x5a, 0xde, 0xa6, 0xf2, - 0x3, 0xf3, 0x1, 0xaf, 0xfa, 0x16, 0xee, 0x50, - 0x0, 0x6e, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x6, 0xfb, 0x53, 0x23, 0x75, 0x0, 0x0, - 0x0, 0x0, 0x17, 0xce, 0xfd, 0xa3, 0x0, 0x0, + 0x0, 0x1f, 0xf9, 0x0, 0x1, 0xe4, 0x7, 0xc0, + 0x7, 0x40, 0x0, 0xb0, 0xd, 0xb, 0xe3, 0x68, + 0x28, 0x3d, 0x6f, 0x4c, 0x30, 0xb0, 0xb, 0x4a, + 0x30, 0xe0, 0x3, 0x46, 0x30, 0xe0, 0x3, 0x47, + 0x30, 0xe0, 0x3, 0x46, 0x30, 0xb0, 0xb, 0x4a, + 0x28, 0x3d, 0x6f, 0x9c, 0xc, 0xb, 0xe1, 0xf4, + 0x7, 0x40, 0x0, 0x0, 0x1, 0xe4, 0x5, 0x0, + 0x0, 0x1f, 0xf8, 0x0, /* U+0041 "A" */ - 0x0, 0x0, 0x2, 0xfd, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x9f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0xf, - 0x9e, 0xb0, 0x0, 0x0, 0x0, 0x6, 0xf2, 0x7f, - 0x20, 0x0, 0x0, 0x0, 0xdc, 0x1, 0xf8, 0x0, - 0x0, 0x0, 0x4f, 0x60, 0xb, 0xe0, 0x0, 0x0, - 0xb, 0xf0, 0x0, 0x4f, 0x60, 0x0, 0x1, 0xfa, - 0x11, 0x11, 0xed, 0x0, 0x0, 0x8f, 0xff, 0xff, - 0xff, 0xf3, 0x0, 0xe, 0xc4, 0x44, 0x44, 0x4f, - 0xa0, 0x6, 0xf4, 0x0, 0x0, 0x0, 0xaf, 0x10, - 0xcd, 0x0, 0x0, 0x0, 0x2, 0xf8, + 0x0, 0xf, 0x0, 0x0, 0xb, 0xd0, 0x0, 0x3, + 0xb8, 0x0, 0x1, 0xdb, 0x0, 0x0, 0xf0, 0xe0, + 0x0, 0x74, 0x3c, 0x0, 0x2c, 0x7, 0x40, 0xe, + 0x0, 0xf0, 0xb, 0xff, 0xfc, 0x3, 0xd5, 0x57, + 0x81, 0xd0, 0x0, 0xb0, 0xf0, 0x0, 0xe, /* U+0042 "B" */ - 0x5f, 0xff, 0xff, 0xeb, 0x40, 0x5, 0xf8, 0x55, - 0x57, 0xdf, 0x40, 0x5f, 0x40, 0x0, 0x1, 0xfa, - 0x5, 0xf4, 0x0, 0x0, 0xf, 0xa0, 0x5f, 0x51, - 0x11, 0x3a, 0xf4, 0x5, 0xff, 0xff, 0xff, 0xfa, - 0x0, 0x5f, 0x74, 0x44, 0x59, 0xfa, 0x5, 0xf4, - 0x0, 0x0, 0x8, 0xf2, 0x5f, 0x40, 0x0, 0x0, - 0x5f, 0x45, 0xf4, 0x0, 0x0, 0x9, 0xf2, 0x5f, - 0x85, 0x55, 0x6a, 0xfb, 0x5, 0xff, 0xff, 0xff, - 0xd7, 0x0, + 0x7f, 0xfe, 0x41, 0xe5, 0x5f, 0x47, 0x40, 0xe, + 0x1d, 0x0, 0x38, 0x74, 0x2, 0xd1, 0xff, 0xfe, + 0x7, 0x55, 0x6e, 0x1d, 0x0, 0x2c, 0x74, 0x0, + 0x75, 0xd0, 0x2, 0xc7, 0x95, 0x6e, 0x1f, 0xff, + 0xd0, /* U+0043 "C" */ - 0x0, 0x2, 0x8d, 0xfe, 0xb4, 0x0, 0x4, 0xff, - 0xb8, 0x9d, 0xf9, 0x2, 0xfd, 0x20, 0x0, 0x8, - 0x50, 0xbf, 0x20, 0x0, 0x0, 0x0, 0xf, 0xa0, - 0x0, 0x0, 0x0, 0x2, 0xf6, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0x60, 0x0, 0x0, 0x0, 0x0, 0xfa, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xf2, 0x0, 0x0, - 0x0, 0x0, 0x2f, 0xd2, 0x0, 0x0, 0x85, 0x0, - 0x5f, 0xfb, 0x89, 0xdf, 0x80, 0x0, 0x29, 0xdf, - 0xeb, 0x40, + 0x0, 0xbf, 0x90, 0x1f, 0xab, 0xe0, 0xf0, 0x2, + 0x4b, 0x0, 0x0, 0x38, 0x0, 0x0, 0xd0, 0x0, + 0x3, 0x40, 0x0, 0xe, 0x0, 0x0, 0x2c, 0x0, + 0x0, 0x3c, 0x0, 0x90, 0x7e, 0xaf, 0x80, 0x2f, + 0xe4, /* U+0044 "D" */ - 0x5f, 0xff, 0xff, 0xea, 0x30, 0x0, 0x5f, 0x97, - 0x77, 0x9e, 0xf8, 0x0, 0x5f, 0x40, 0x0, 0x0, - 0xaf, 0x60, 0x5f, 0x40, 0x0, 0x0, 0xd, 0xe0, - 0x5f, 0x40, 0x0, 0x0, 0x6, 0xf4, 0x5f, 0x40, - 0x0, 0x0, 0x3, 0xf6, 0x5f, 0x40, 0x0, 0x0, - 0x3, 0xf6, 0x5f, 0x40, 0x0, 0x0, 0x6, 0xf4, - 0x5f, 0x40, 0x0, 0x0, 0xd, 0xe0, 0x5f, 0x40, - 0x0, 0x0, 0xaf, 0x60, 0x5f, 0x97, 0x77, 0x9e, - 0xf8, 0x0, 0x5f, 0xff, 0xff, 0xea, 0x30, 0x0, + 0x7f, 0xfe, 0x0, 0x79, 0x5b, 0xe0, 0x74, 0x0, + 0xb4, 0x74, 0x0, 0x3c, 0x74, 0x0, 0x1d, 0x74, + 0x0, 0xd, 0x74, 0x0, 0xd, 0x74, 0x0, 0x1d, + 0x74, 0x0, 0x3c, 0x74, 0x0, 0xb4, 0x79, 0x5b, + 0xe0, 0x7f, 0xfe, 0x0, /* U+0045 "E" */ - 0x5f, 0xff, 0xff, 0xff, 0x95, 0xf9, 0x77, 0x77, - 0x74, 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf4, 0x0, - 0x0, 0x0, 0x5f, 0x51, 0x11, 0x11, 0x5, 0xff, - 0xff, 0xff, 0xe0, 0x5f, 0x74, 0x44, 0x44, 0x5, - 0xf4, 0x0, 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, - 0x5, 0xf4, 0x0, 0x0, 0x0, 0x5f, 0x97, 0x77, - 0x77, 0x65, 0xff, 0xff, 0xff, 0xfd, + 0x7f, 0xff, 0x9e, 0x55, 0x57, 0x40, 0x1, 0xd0, + 0x0, 0x74, 0x0, 0x1f, 0xff, 0xc7, 0x55, 0x51, + 0xd0, 0x0, 0x74, 0x0, 0x1d, 0x0, 0x7, 0x95, + 0x55, 0xff, 0xff, /* U+0046 "F" */ - 0x5f, 0xff, 0xff, 0xff, 0x95, 0xf9, 0x77, 0x77, - 0x74, 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf4, 0x0, - 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf5, - 0x22, 0x22, 0x10, 0x5f, 0xff, 0xff, 0xfe, 0x5, - 0xf8, 0x55, 0x55, 0x40, 0x5f, 0x40, 0x0, 0x0, - 0x5, 0xf4, 0x0, 0x0, 0x0, 0x5f, 0x40, 0x0, - 0x0, 0x5, 0xf4, 0x0, 0x0, 0x0, + 0x7f, 0xff, 0x9e, 0x55, 0x57, 0x40, 0x1, 0xd0, + 0x0, 0x74, 0x0, 0x1d, 0x0, 0x7, 0xff, 0xf1, + 0xe5, 0x54, 0x74, 0x0, 0x1d, 0x0, 0x7, 0x40, + 0x1, 0xd0, 0x0, /* U+0047 "G" */ - 0x0, 0x1, 0x8d, 0xfe, 0xb5, 0x0, 0x0, 0x4f, - 0xfb, 0x89, 0xdf, 0xb0, 0x2, 0xfd, 0x20, 0x0, - 0x6, 0x60, 0xb, 0xf2, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0x60, - 0x0, 0x0, 0x0, 0x0, 0x2f, 0x60, 0x0, 0x0, - 0x9, 0xf0, 0xf, 0xa0, 0x0, 0x0, 0x9, 0xf0, - 0xb, 0xf2, 0x0, 0x0, 0x9, 0xf0, 0x2, 0xfd, - 0x20, 0x0, 0xa, 0xf0, 0x0, 0x4f, 0xfb, 0x89, - 0xdf, 0xc0, 0x0, 0x2, 0x8d, 0xfe, 0xc6, 0x0, + 0x0, 0xbf, 0x90, 0x7, 0xea, 0xf8, 0xf, 0x0, + 0x14, 0x2c, 0x0, 0x0, 0x38, 0x0, 0x0, 0x34, + 0x0, 0x0, 0x34, 0x0, 0x2c, 0x38, 0x0, 0x2c, + 0x2c, 0x0, 0x2c, 0xf, 0x0, 0x2c, 0x7, 0xea, + 0xfc, 0x0, 0xbf, 0xd0, /* U+0048 "H" */ - 0x5f, 0x40, 0x0, 0x0, 0x4f, 0x55, 0xf4, 0x0, - 0x0, 0x4, 0xf5, 0x5f, 0x40, 0x0, 0x0, 0x4f, - 0x55, 0xf4, 0x0, 0x0, 0x4, 0xf5, 0x5f, 0x52, - 0x22, 0x22, 0x5f, 0x55, 0xff, 0xff, 0xff, 0xff, - 0xf5, 0x5f, 0x85, 0x55, 0x55, 0x8f, 0x55, 0xf4, - 0x0, 0x0, 0x4, 0xf5, 0x5f, 0x40, 0x0, 0x0, - 0x4f, 0x55, 0xf4, 0x0, 0x0, 0x4, 0xf5, 0x5f, - 0x40, 0x0, 0x0, 0x4f, 0x55, 0xf4, 0x0, 0x0, - 0x4, 0xf5, + 0x74, 0x0, 0x75, 0xd0, 0x1, 0xd7, 0x40, 0x7, + 0x5d, 0x0, 0x1d, 0x74, 0x0, 0x75, 0xff, 0xff, + 0xd7, 0x95, 0x5b, 0x5d, 0x0, 0x1d, 0x74, 0x0, + 0x75, 0xd0, 0x1, 0xd7, 0x40, 0x7, 0x5d, 0x0, + 0x1d, /* U+0049 "I" */ - 0x5f, 0x45, 0xf4, 0x5f, 0x45, 0xf4, 0x5f, 0x45, - 0xf4, 0x5f, 0x45, 0xf4, 0x5f, 0x45, 0xf4, 0x5f, - 0x45, 0xf4, + 0x75, 0xd7, 0x5d, 0x75, 0xd7, 0x5d, 0x75, 0xd7, + 0x5d, /* U+004A "J" */ - 0x0, 0xff, 0xff, 0xfa, 0x0, 0x77, 0x77, 0xfa, - 0x0, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0xfa, - 0x0, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0xfa, - 0x0, 0x0, 0x0, 0xfa, 0x0, 0x0, 0x0, 0xfa, - 0x0, 0x0, 0x0, 0xf9, 0x7, 0x20, 0x3, 0xf6, - 0xd, 0xe9, 0x8e, 0xf1, 0x1, 0xae, 0xfb, 0x30, + 0xf, 0xfe, 0x5, 0x5e, 0x0, 0xe, 0x0, 0xe, + 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, 0x0, 0xe, + 0x0, 0xe, 0x10, 0xd, 0x3e, 0xbc, 0xb, 0xe0, /* U+004B "K" */ - 0x5f, 0x40, 0x0, 0x2, 0xeb, 0x5, 0xf4, 0x0, - 0x1, 0xec, 0x0, 0x5f, 0x40, 0x1, 0xde, 0x10, - 0x5, 0xf4, 0x0, 0xce, 0x20, 0x0, 0x5f, 0x40, - 0xbf, 0x30, 0x0, 0x5, 0xf4, 0x9f, 0x90, 0x0, - 0x0, 0x5f, 0xcf, 0xef, 0x40, 0x0, 0x5, 0xff, - 0x91, 0xee, 0x10, 0x0, 0x5f, 0xa0, 0x3, 0xfc, - 0x0, 0x5, 0xf4, 0x0, 0x6, 0xf8, 0x0, 0x5f, - 0x40, 0x0, 0x9, 0xf5, 0x5, 0xf4, 0x0, 0x0, - 0xc, 0xf2, + 0x74, 0x0, 0xe1, 0xd0, 0xf, 0x7, 0x40, 0xf0, + 0x1d, 0xf, 0x0, 0x74, 0xb0, 0x1, 0xdb, 0x80, + 0x7, 0xff, 0x40, 0x1f, 0x8f, 0x0, 0x78, 0xf, + 0x1, 0xd0, 0x1e, 0x7, 0x40, 0x2d, 0x1d, 0x0, + 0x3c, /* U+004C "L" */ - 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf4, 0x0, 0x0, - 0x0, 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf4, 0x0, - 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, 0x5, 0xf4, - 0x0, 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, 0x5, - 0xf4, 0x0, 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, - 0x5, 0xf4, 0x0, 0x0, 0x0, 0x5f, 0x97, 0x77, - 0x77, 0x25, 0xff, 0xff, 0xff, 0xf5, + 0x74, 0x0, 0x1d, 0x0, 0x7, 0x40, 0x1, 0xd0, + 0x0, 0x74, 0x0, 0x1d, 0x0, 0x7, 0x40, 0x1, + 0xd0, 0x0, 0x74, 0x0, 0x1d, 0x0, 0x7, 0x95, + 0x51, 0xff, 0xfd, /* U+004D "M" */ - 0x5f, 0x40, 0x0, 0x0, 0x0, 0x1e, 0x95, 0xfc, - 0x0, 0x0, 0x0, 0x8, 0xf9, 0x5f, 0xf5, 0x0, - 0x0, 0x2, 0xff, 0x95, 0xfd, 0xe0, 0x0, 0x0, - 0xae, 0xf9, 0x5f, 0x5f, 0x70, 0x0, 0x3f, 0x5f, - 0x95, 0xf3, 0x8f, 0x10, 0xb, 0xc0, 0xf9, 0x5f, - 0x31, 0xe9, 0x4, 0xf3, 0xf, 0x95, 0xf3, 0x7, - 0xf2, 0xdb, 0x0, 0xf9, 0x5f, 0x30, 0xd, 0xef, - 0x20, 0xf, 0x95, 0xf3, 0x0, 0x5f, 0x90, 0x0, - 0xf9, 0x5f, 0x30, 0x0, 0x71, 0x0, 0xf, 0x95, - 0xf3, 0x0, 0x0, 0x0, 0x0, 0xf9, + 0x74, 0x0, 0x3, 0x9f, 0x0, 0x2, 0xe7, 0xd0, + 0x0, 0xf9, 0xfc, 0x0, 0xbe, 0x77, 0x40, 0x37, + 0x9c, 0xb0, 0x2c, 0xe7, 0xe, 0x1c, 0x39, 0xc1, + 0xce, 0xe, 0x70, 0x3f, 0x3, 0x9c, 0x7, 0x80, + 0xe7, 0x0, 0x40, 0x39, 0xc0, 0x0, 0xe, /* U+004E "N" */ - 0x5f, 0x50, 0x0, 0x0, 0x4f, 0x55, 0xff, 0x20, - 0x0, 0x4, 0xf5, 0x5f, 0xfd, 0x0, 0x0, 0x4f, - 0x55, 0xfa, 0xf9, 0x0, 0x4, 0xf5, 0x5f, 0x4a, - 0xf5, 0x0, 0x4f, 0x55, 0xf4, 0xd, 0xf2, 0x4, - 0xf5, 0x5f, 0x40, 0x2f, 0xd0, 0x4f, 0x55, 0xf4, - 0x0, 0x6f, 0x94, 0xf5, 0x5f, 0x40, 0x0, 0xaf, - 0xaf, 0x55, 0xf4, 0x0, 0x0, 0xdf, 0xf5, 0x5f, - 0x40, 0x0, 0x2, 0xff, 0x55, 0xf4, 0x0, 0x0, - 0x6, 0xf5, + 0x74, 0x0, 0x75, 0xf0, 0x1, 0xd7, 0xf0, 0x7, + 0x5e, 0xe0, 0x1d, 0x76, 0xd0, 0x75, 0xd3, 0xc1, + 0xd7, 0x43, 0xc7, 0x5d, 0x7, 0x9d, 0x74, 0xb, + 0xb5, 0xd0, 0xf, 0xd7, 0x40, 0xf, 0x5d, 0x0, + 0x1d, /* U+004F "O" */ - 0x0, 0x1, 0x8d, 0xfe, 0xb5, 0x0, 0x0, 0x4, - 0xff, 0xb8, 0x9e, 0xfa, 0x0, 0x2, 0xfd, 0x20, - 0x0, 0x8, 0xf9, 0x0, 0xbf, 0x20, 0x0, 0x0, - 0xa, 0xf2, 0xf, 0xa0, 0x0, 0x0, 0x0, 0x3f, - 0x72, 0xf6, 0x0, 0x0, 0x0, 0x0, 0xf9, 0x2f, - 0x60, 0x0, 0x0, 0x0, 0xf, 0x90, 0xfa, 0x0, - 0x0, 0x0, 0x3, 0xf7, 0xb, 0xf2, 0x0, 0x0, - 0x0, 0xaf, 0x20, 0x2f, 0xd2, 0x0, 0x0, 0x8f, - 0x90, 0x0, 0x4f, 0xfb, 0x89, 0xef, 0xa0, 0x0, - 0x0, 0x28, 0xdf, 0xeb, 0x50, 0x0, + 0x0, 0xbf, 0x90, 0x1, 0xfa, 0xbe, 0x0, 0xf0, + 0x2, 0xe0, 0xb0, 0x0, 0x2c, 0x38, 0x0, 0x3, + 0x4d, 0x0, 0x0, 0xe3, 0x40, 0x0, 0x38, 0xe0, + 0x0, 0xd, 0x2c, 0x0, 0xb, 0x3, 0xc0, 0xb, + 0x80, 0x7e, 0xaf, 0x80, 0x2, 0xfe, 0x40, /* U+0050 "P" */ - 0x5f, 0xff, 0xff, 0xd7, 0x0, 0x5f, 0x97, 0x78, - 0xbf, 0xc0, 0x5f, 0x40, 0x0, 0x7, 0xf6, 0x5f, - 0x40, 0x0, 0x0, 0xfa, 0x5f, 0x40, 0x0, 0x0, - 0xfa, 0x5f, 0x40, 0x0, 0x3, 0xf8, 0x5f, 0x62, - 0x23, 0x6e, 0xf1, 0x5f, 0xff, 0xff, 0xfd, 0x30, - 0x5f, 0x85, 0x54, 0x20, 0x0, 0x5f, 0x40, 0x0, - 0x0, 0x0, 0x5f, 0x40, 0x0, 0x0, 0x0, 0x5f, - 0x40, 0x0, 0x0, 0x0, + 0x7f, 0xfd, 0x7, 0x96, 0xbc, 0x74, 0x1, 0xd7, + 0x40, 0xe, 0x74, 0x0, 0xe7, 0x40, 0xe, 0x74, + 0x7, 0xc7, 0xff, 0xf0, 0x79, 0x50, 0x7, 0x40, + 0x0, 0x74, 0x0, 0x7, 0x40, 0x0, /* U+0051 "Q" */ - 0x0, 0x1, 0x8d, 0xfe, 0xb5, 0x0, 0x0, 0x0, - 0x4e, 0xfb, 0x89, 0xef, 0xa0, 0x0, 0x2, 0xfd, - 0x20, 0x0, 0x8, 0xf9, 0x0, 0xa, 0xf2, 0x0, - 0x0, 0x0, 0xaf, 0x20, 0xf, 0xa0, 0x0, 0x0, - 0x0, 0x3f, 0x70, 0x2f, 0x60, 0x0, 0x0, 0x0, - 0xf, 0x90, 0x2f, 0x60, 0x0, 0x0, 0x0, 0xf, - 0x90, 0x1f, 0x90, 0x0, 0x0, 0x0, 0x2f, 0x70, - 0xb, 0xf1, 0x0, 0x0, 0x0, 0xaf, 0x20, 0x3, - 0xfc, 0x10, 0x0, 0x7, 0xf9, 0x0, 0x0, 0x6f, - 0xfa, 0x78, 0xdf, 0xb0, 0x0, 0x0, 0x3, 0xae, - 0xff, 0xc5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3e, - 0xd4, 0x15, 0xb0, 0x0, 0x0, 0x0, 0x2, 0xbf, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x1, 0x31, - 0x0, + 0x0, 0xbf, 0x90, 0x0, 0x7e, 0xaf, 0x80, 0xf, + 0x0, 0x2e, 0x2, 0xc0, 0x0, 0xb0, 0x38, 0x0, + 0x3, 0x43, 0x40, 0x0, 0x38, 0x34, 0x0, 0x3, + 0x83, 0x80, 0x0, 0x34, 0x2c, 0x0, 0xb, 0x0, + 0xf0, 0x1, 0xe0, 0x7, 0xe6, 0xf8, 0x0, 0xb, + 0xfd, 0x0, 0x0, 0x3, 0xd1, 0x80, 0x0, 0xb, + 0xf8, 0x0, 0x0, 0x0, 0x0, /* U+0052 "R" */ - 0x5f, 0xff, 0xff, 0xd7, 0x0, 0x5f, 0x97, 0x78, - 0xbf, 0xc0, 0x5f, 0x40, 0x0, 0x7, 0xf6, 0x5f, - 0x40, 0x0, 0x0, 0xfa, 0x5f, 0x40, 0x0, 0x0, - 0xfa, 0x5f, 0x40, 0x0, 0x3, 0xf8, 0x5f, 0x52, - 0x23, 0x6e, 0xe1, 0x5f, 0xff, 0xff, 0xfc, 0x30, - 0x5f, 0x85, 0x55, 0xf9, 0x0, 0x5f, 0x40, 0x0, - 0x7f, 0x40, 0x5f, 0x40, 0x0, 0xc, 0xe0, 0x5f, - 0x40, 0x0, 0x2, 0xf9, + 0x7f, 0xfd, 0x7, 0x96, 0xbc, 0x74, 0x1, 0xd7, + 0x40, 0xe, 0x74, 0x0, 0xe7, 0x40, 0xe, 0x74, + 0x7, 0xc7, 0xff, 0xf0, 0x79, 0x5e, 0x7, 0x40, + 0x74, 0x74, 0x3, 0xc7, 0x40, 0xe, /* U+0053 "S" */ - 0x0, 0x5c, 0xef, 0xd9, 0x20, 0x7, 0xfc, 0x87, - 0xaf, 0x90, 0xe, 0xc0, 0x0, 0x1, 0x10, 0xf, - 0x80, 0x0, 0x0, 0x0, 0xd, 0xf5, 0x0, 0x0, - 0x0, 0x3, 0xef, 0xea, 0x50, 0x0, 0x0, 0x5, - 0xae, 0xfe, 0x40, 0x0, 0x0, 0x0, 0x4e, 0xf1, - 0x0, 0x0, 0x0, 0x5, 0xf3, 0x8, 0x0, 0x0, - 0x8, 0xf2, 0x2f, 0xfa, 0x77, 0xbf, 0xa0, 0x2, - 0x9d, 0xff, 0xc7, 0x0, + 0x7, 0xfe, 0x1, 0xf9, 0xb8, 0x3c, 0x0, 0x3, + 0x80, 0x0, 0x3d, 0x0, 0x0, 0xfe, 0x40, 0x1, + 0xbf, 0x40, 0x0, 0x7c, 0x0, 0x1, 0xc2, 0x0, + 0x2c, 0x3e, 0x5b, 0x80, 0xbf, 0xd0, /* U+0054 "T" */ - 0xff, 0xff, 0xff, 0xff, 0xf5, 0x67, 0x78, 0xfb, - 0x77, 0x72, 0x0, 0x1, 0xf7, 0x0, 0x0, 0x0, - 0x1, 0xf7, 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, - 0x0, 0x0, 0x1, 0xf7, 0x0, 0x0, 0x0, 0x1, - 0xf7, 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, 0x0, - 0x0, 0x1, 0xf7, 0x0, 0x0, 0x0, 0x1, 0xf7, - 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, 0x0, 0x0, - 0x1, 0xf7, 0x0, 0x0, + 0xff, 0xff, 0xd5, 0x6e, 0x54, 0x0, 0xd0, 0x0, + 0xd, 0x0, 0x0, 0xd0, 0x0, 0xd, 0x0, 0x0, + 0xd0, 0x0, 0xd, 0x0, 0x0, 0xd0, 0x0, 0xd, + 0x0, 0x0, 0xd0, 0x0, 0xd, 0x0, /* U+0055 "U" */ - 0x6f, 0x30, 0x0, 0x0, 0x8f, 0x16, 0xf3, 0x0, - 0x0, 0x8, 0xf1, 0x6f, 0x30, 0x0, 0x0, 0x8f, - 0x16, 0xf3, 0x0, 0x0, 0x8, 0xf1, 0x6f, 0x30, - 0x0, 0x0, 0x8f, 0x16, 0xf3, 0x0, 0x0, 0x8, - 0xf1, 0x6f, 0x30, 0x0, 0x0, 0x8f, 0x5, 0xf4, - 0x0, 0x0, 0x9, 0xf0, 0x3f, 0x70, 0x0, 0x0, - 0xcd, 0x0, 0xde, 0x20, 0x0, 0x5f, 0x80, 0x4, - 0xff, 0xa8, 0xbf, 0xd0, 0x0, 0x3, 0xbe, 0xfd, - 0x81, 0x0, + 0x70, 0x0, 0xb1, 0xc0, 0x2, 0xc7, 0x0, 0xb, + 0x1c, 0x0, 0x2c, 0x70, 0x0, 0xb1, 0xc0, 0x2, + 0xc7, 0x0, 0xb, 0x1d, 0x0, 0x2c, 0x34, 0x0, + 0xf0, 0xf0, 0x7, 0x81, 0xfa, 0xbc, 0x0, 0xbf, + 0x80, /* U+0056 "V" */ - 0xc, 0xe0, 0x0, 0x0, 0x0, 0x6f, 0x30, 0x6f, - 0x50, 0x0, 0x0, 0xc, 0xc0, 0x0, 0xfb, 0x0, - 0x0, 0x3, 0xf6, 0x0, 0x9, 0xf2, 0x0, 0x0, - 0xae, 0x0, 0x0, 0x2f, 0x80, 0x0, 0x1f, 0x90, - 0x0, 0x0, 0xce, 0x0, 0x7, 0xf2, 0x0, 0x0, - 0x5, 0xf6, 0x0, 0xdb, 0x0, 0x0, 0x0, 0xe, - 0xc0, 0x4f, 0x50, 0x0, 0x0, 0x0, 0x8f, 0x3b, - 0xe0, 0x0, 0x0, 0x0, 0x2, 0xfb, 0xf8, 0x0, - 0x0, 0x0, 0x0, 0xb, 0xff, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x4f, 0xb0, 0x0, 0x0, + 0x3c, 0x0, 0x7, 0x7, 0x40, 0x3, 0xc0, 0xf0, + 0x0, 0xd0, 0x2c, 0x0, 0xb0, 0x3, 0x80, 0x38, + 0x0, 0xf0, 0x2c, 0x0, 0x1d, 0xe, 0x0, 0x3, + 0xc7, 0x40, 0x0, 0xb7, 0xc0, 0x0, 0xf, 0xe0, + 0x0, 0x2, 0xf0, 0x0, 0x0, 0x78, 0x0, /* U+0057 "W" */ - 0x5f, 0x40, 0x0, 0x0, 0xdf, 0x0, 0x0, 0x2, - 0xf5, 0xf, 0x90, 0x0, 0x2, 0xff, 0x40, 0x0, - 0x7, 0xf0, 0xb, 0xe0, 0x0, 0x7, 0xfe, 0x90, - 0x0, 0xc, 0xb0, 0x6, 0xf3, 0x0, 0xc, 0xaa, - 0xe0, 0x0, 0x1f, 0x60, 0x1, 0xf8, 0x0, 0x1f, - 0x54, 0xf3, 0x0, 0x6f, 0x10, 0x0, 0xcd, 0x0, - 0x7f, 0x10, 0xf8, 0x0, 0xcc, 0x0, 0x0, 0x7f, - 0x20, 0xcb, 0x0, 0xad, 0x1, 0xf7, 0x0, 0x0, - 0x2f, 0x71, 0xf6, 0x0, 0x5f, 0x26, 0xf2, 0x0, - 0x0, 0xd, 0xc6, 0xf1, 0x0, 0xf, 0x7b, 0xd0, - 0x0, 0x0, 0x8, 0xfd, 0xc0, 0x0, 0xb, 0xdf, - 0x80, 0x0, 0x0, 0x3, 0xff, 0x70, 0x0, 0x6, - 0xff, 0x30, 0x0, 0x0, 0x0, 0xef, 0x20, 0x0, - 0x1, 0xfe, 0x0, 0x0, + 0x74, 0x0, 0xf0, 0x0, 0xd3, 0x80, 0xf, 0x40, + 0x2c, 0x2c, 0x1, 0xf8, 0x3, 0x81, 0xc0, 0x3a, + 0xc0, 0x34, 0xe, 0x3, 0x5d, 0x7, 0x0, 0xf0, + 0x70, 0xe0, 0xf0, 0x7, 0xe, 0xb, 0xd, 0x0, + 0x34, 0xd0, 0x71, 0xc0, 0x3, 0xdc, 0x3, 0xbc, + 0x0, 0x2f, 0xc0, 0x2f, 0x80, 0x0, 0xf4, 0x1, + 0xf0, 0x0, 0xf, 0x0, 0xf, 0x0, /* U+0058 "X" */ - 0x3f, 0x90, 0x0, 0x0, 0xcd, 0x0, 0x8f, 0x40, - 0x0, 0x7f, 0x30, 0x0, 0xde, 0x10, 0x2f, 0x80, - 0x0, 0x3, 0xfa, 0xc, 0xd0, 0x0, 0x0, 0x7, - 0xfb, 0xf3, 0x0, 0x0, 0x0, 0xc, 0xf8, 0x0, - 0x0, 0x0, 0x1, 0xef, 0xc0, 0x0, 0x0, 0x0, - 0xbf, 0x7f, 0x70, 0x0, 0x0, 0x6f, 0x60, 0xaf, - 0x20, 0x0, 0x2f, 0xb0, 0x1, 0xed, 0x0, 0xc, - 0xf1, 0x0, 0x4, 0xf8, 0x7, 0xf6, 0x0, 0x0, - 0x9, 0xf3, + 0x38, 0x0, 0xf0, 0xb4, 0x7, 0x0, 0xf0, 0x38, + 0x0, 0xe3, 0xc0, 0x1, 0xec, 0x0, 0x3, 0xe0, + 0x0, 0xf, 0xc0, 0x0, 0xb7, 0x40, 0x7, 0x4b, + 0x0, 0x38, 0xf, 0x3, 0xc0, 0x1e, 0x1d, 0x0, + 0x2c, /* U+0059 "Y" */ - 0xc, 0xe0, 0x0, 0x0, 0x7, 0xf2, 0x3, 0xf7, - 0x0, 0x0, 0x1f, 0x90, 0x0, 0xaf, 0x10, 0x0, - 0x9e, 0x10, 0x0, 0x1f, 0xa0, 0x2, 0xf6, 0x0, - 0x0, 0x8, 0xf3, 0xb, 0xd0, 0x0, 0x0, 0x0, - 0xec, 0x4f, 0x40, 0x0, 0x0, 0x0, 0x5f, 0xfb, - 0x0, 0x0, 0x0, 0x0, 0xc, 0xf2, 0x0, 0x0, - 0x0, 0x0, 0x9, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x9, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0x9, 0xf0, 0x0, 0x0, + 0x3c, 0x0, 0x1c, 0xd, 0x0, 0x38, 0xb, 0x0, + 0xb0, 0x3, 0x80, 0xd0, 0x2, 0xc2, 0xc0, 0x0, + 0xf7, 0x40, 0x0, 0x7e, 0x0, 0x0, 0x3c, 0x0, + 0x0, 0x2c, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x2c, + 0x0, 0x0, 0x2c, 0x0, /* U+005A "Z" */ - 0x3f, 0xff, 0xff, 0xff, 0xfd, 0x1, 0x77, 0x77, - 0x77, 0xbf, 0x90, 0x0, 0x0, 0x0, 0x1e, 0xc0, - 0x0, 0x0, 0x0, 0xc, 0xf2, 0x0, 0x0, 0x0, - 0x8, 0xf5, 0x0, 0x0, 0x0, 0x4, 0xf9, 0x0, - 0x0, 0x0, 0x1, 0xec, 0x0, 0x0, 0x0, 0x0, - 0xcf, 0x20, 0x0, 0x0, 0x0, 0x8f, 0x50, 0x0, - 0x0, 0x0, 0x4f, 0x90, 0x0, 0x0, 0x0, 0x1e, - 0xf8, 0x77, 0x77, 0x77, 0x5, 0xff, 0xff, 0xff, - 0xff, 0xf0, + 0x3f, 0xff, 0xf0, 0x55, 0x5b, 0x80, 0x0, 0x3c, + 0x0, 0x3, 0xc0, 0x0, 0x2d, 0x0, 0x1, 0xe0, + 0x0, 0xf, 0x0, 0x0, 0xf0, 0x0, 0xb, 0x40, + 0x0, 0x78, 0x0, 0x3, 0xe5, 0x55, 0x1f, 0xff, + 0xfc, /* U+005B "[" */ - 0x5f, 0xff, 0x5, 0xf7, 0x50, 0x5f, 0x30, 0x5, - 0xf3, 0x0, 0x5f, 0x30, 0x5, 0xf3, 0x0, 0x5f, - 0x30, 0x5, 0xf3, 0x0, 0x5f, 0x30, 0x5, 0xf3, - 0x0, 0x5f, 0x30, 0x5, 0xf3, 0x0, 0x5f, 0x30, - 0x5, 0xf7, 0x50, 0x5f, 0xff, 0x0, + 0x7f, 0x1d, 0x47, 0x1, 0xc0, 0x70, 0x1c, 0x7, + 0x1, 0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, + 0x1d, 0x47, 0xf0, /* U+005C "\\" */ - 0x7e, 0x0, 0x0, 0x0, 0x1f, 0x40, 0x0, 0x0, - 0xc, 0x90, 0x0, 0x0, 0x7, 0xe0, 0x0, 0x0, - 0x2, 0xf4, 0x0, 0x0, 0x0, 0xc9, 0x0, 0x0, - 0x0, 0x7e, 0x0, 0x0, 0x0, 0x2f, 0x40, 0x0, - 0x0, 0xc, 0x90, 0x0, 0x0, 0x7, 0xe0, 0x0, - 0x0, 0x2, 0xf3, 0x0, 0x0, 0x0, 0xd9, 0x0, - 0x0, 0x0, 0x7e, 0x0, 0x0, 0x0, 0x2f, 0x30, - 0x0, 0x0, 0xd, 0x90, 0x0, 0x0, 0x7, 0xe0, + 0x70, 0x0, 0x34, 0x0, 0x38, 0x0, 0x1c, 0x0, + 0xd, 0x0, 0xe, 0x0, 0x7, 0x0, 0x3, 0x40, + 0x3, 0x80, 0x1, 0xc0, 0x0, 0xc0, 0x0, 0xe0, + 0x0, 0x70, 0x0, 0x30, 0x0, 0x38, 0x0, 0x1c, /* U+005D "]" */ - 0xbf, 0xfa, 0x35, 0xea, 0x0, 0xea, 0x0, 0xea, - 0x0, 0xea, 0x0, 0xea, 0x0, 0xea, 0x0, 0xea, - 0x0, 0xea, 0x0, 0xea, 0x0, 0xea, 0x0, 0xea, - 0x0, 0xea, 0x35, 0xea, 0xbf, 0xfa, + 0xbe, 0x1e, 0xe, 0xe, 0xe, 0xe, 0xe, 0xe, + 0xe, 0xe, 0xe, 0xe, 0xe, 0x1e, 0xbe, /* U+005E "^" */ - 0x0, 0x2f, 0x80, 0x0, 0x0, 0x9d, 0xe0, 0x0, - 0x0, 0xf3, 0xd5, 0x0, 0x6, 0xd0, 0x7b, 0x0, - 0xc, 0x60, 0x1f, 0x20, 0x3f, 0x10, 0xb, 0x80, - 0x9a, 0x0, 0x4, 0xe0, + 0x3, 0x80, 0xb, 0xc0, 0xc, 0xd0, 0x1c, 0x60, + 0x34, 0x30, 0x30, 0x28, 0xa0, 0x1c, /* U+005F "_" */ - 0xff, 0xff, 0xff, 0xff, 0x11, 0x11, 0x11, 0x11, + 0xff, 0xff, 0x0, 0x0, /* U+0060 "`" */ - 0x7, 0xf6, 0x0, 0x3, 0xe7, + 0x1d, 0x0, 0xd0, /* U+0061 "a" */ - 0x1, 0x9e, 0xfd, 0x80, 0x0, 0xce, 0x87, 0xaf, - 0x90, 0x2, 0x0, 0x0, 0xaf, 0x0, 0x0, 0x0, - 0x6, 0xf2, 0x2, 0xbe, 0xff, 0xff, 0x20, 0xec, - 0x42, 0x27, 0xf2, 0x2f, 0x50, 0x0, 0x7f, 0x20, - 0xec, 0x42, 0x7f, 0xf2, 0x2, 0xbf, 0xfb, 0x6f, - 0x20, + 0xb, 0xf8, 0xf, 0x9b, 0x80, 0x0, 0xb0, 0x0, + 0x1c, 0xb, 0xff, 0xf, 0x41, 0xc3, 0x40, 0x70, + 0xf4, 0x7c, 0xb, 0xe7, 0x0, /* U+0062 "b" */ - 0x8f, 0x0, 0x0, 0x0, 0x0, 0x8f, 0x0, 0x0, - 0x0, 0x0, 0x8f, 0x0, 0x0, 0x0, 0x0, 0x8f, - 0x2b, 0xfe, 0xb3, 0x0, 0x8f, 0xec, 0x78, 0xef, - 0x30, 0x8f, 0xa0, 0x0, 0x1e, 0xc0, 0x8f, 0x20, - 0x0, 0x7, 0xf1, 0x8f, 0x0, 0x0, 0x5, 0xf3, - 0x8f, 0x20, 0x0, 0x7, 0xf1, 0x8f, 0xa0, 0x0, - 0x1e, 0xd0, 0x8f, 0xec, 0x78, 0xef, 0x30, 0x8e, - 0x2b, 0xfe, 0xb3, 0x0, + 0xb0, 0x0, 0xb, 0x0, 0x0, 0xb0, 0x0, 0xb, + 0x2f, 0x80, 0xbf, 0x6f, 0xb, 0x80, 0x3c, 0xb0, + 0x1, 0xcb, 0x0, 0x1c, 0xb0, 0x1, 0xcb, 0x80, + 0x3c, 0xbf, 0x6f, 0xb, 0x2f, 0x80, /* U+0063 "c" */ - 0x0, 0x3a, 0xef, 0xc4, 0x0, 0x4f, 0xd8, 0x7c, - 0xf4, 0xd, 0xd0, 0x0, 0x7, 0x13, 0xf6, 0x0, - 0x0, 0x0, 0x4f, 0x30, 0x0, 0x0, 0x3, 0xf6, - 0x0, 0x0, 0x0, 0xd, 0xd0, 0x0, 0x6, 0x10, - 0x4f, 0xd7, 0x7c, 0xf4, 0x0, 0x3a, 0xef, 0xc4, - 0x0, + 0x2, 0xfd, 0x7, 0xe7, 0xd3, 0xc0, 0x10, 0xd0, + 0x0, 0x70, 0x0, 0xd, 0x0, 0x3, 0xc0, 0x10, + 0x7d, 0x7d, 0x2, 0xfd, 0x0, /* U+0064 "d" */ - 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, 0x0, 0x0, - 0x1, 0xf7, 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, - 0x3b, 0xff, 0xa3, 0xf7, 0x4, 0xfd, 0x87, 0xce, - 0xf7, 0xe, 0xd0, 0x0, 0xb, 0xf7, 0x3f, 0x60, - 0x0, 0x3, 0xf7, 0x4f, 0x30, 0x0, 0x1, 0xf7, - 0x3f, 0x50, 0x0, 0x3, 0xf7, 0xe, 0xc0, 0x0, - 0xa, 0xf7, 0x4, 0xfc, 0x65, 0xbe, 0xf7, 0x0, - 0x3b, 0xff, 0xb2, 0xf7, + 0x0, 0x0, 0xd0, 0x0, 0xd, 0x0, 0x0, 0xd0, + 0x2f, 0x8d, 0x1f, 0x9f, 0xd3, 0xc0, 0x2d, 0x34, + 0x0, 0xd7, 0x0, 0xd, 0x34, 0x0, 0xd3, 0xc0, + 0x2d, 0x1f, 0x5b, 0xd0, 0x2f, 0x8d, /* U+0065 "e" */ - 0x0, 0x3b, 0xfe, 0xa2, 0x0, 0x4, 0xfc, 0x67, - 0xee, 0x20, 0xe, 0xc0, 0x0, 0x1e, 0xa0, 0x3f, - 0x50, 0x0, 0x7, 0xf0, 0x4f, 0xff, 0xff, 0xff, - 0xf1, 0x3f, 0x72, 0x22, 0x22, 0x20, 0xe, 0xc0, - 0x0, 0x2, 0x0, 0x4, 0xfd, 0x87, 0xaf, 0x50, - 0x0, 0x3a, 0xef, 0xd6, 0x0, + 0x2, 0xf8, 0x1, 0xf5, 0xf0, 0x3c, 0x3, 0x83, + 0x40, 0x1c, 0x7f, 0xff, 0xc3, 0x40, 0x0, 0x3c, + 0x0, 0x1, 0xf9, 0xb4, 0x2, 0xfd, 0x0, /* U+0066 "f" */ - 0x0, 0x5d, 0xfc, 0x0, 0x2f, 0xb5, 0x70, 0x4, - 0xf3, 0x0, 0xc, 0xff, 0xff, 0xa0, 0x48, 0xf7, - 0x53, 0x0, 0x5f, 0x30, 0x0, 0x5, 0xf3, 0x0, - 0x0, 0x5f, 0x30, 0x0, 0x5, 0xf3, 0x0, 0x0, - 0x5f, 0x30, 0x0, 0x5, 0xf3, 0x0, 0x0, 0x5f, - 0x30, 0x0, + 0x7, 0xf0, 0x39, 0x41, 0xc0, 0x3f, 0xf8, 0x6d, + 0x40, 0x70, 0x1, 0xc0, 0x7, 0x0, 0x1c, 0x0, + 0x70, 0x1, 0xc0, 0x7, 0x0, /* U+0067 "g" */ - 0x0, 0x3b, 0xff, 0xb2, 0xe9, 0x4, 0xfe, 0x87, - 0xcf, 0xf9, 0xe, 0xd1, 0x0, 0xa, 0xf9, 0x3f, - 0x60, 0x0, 0x1, 0xf9, 0x4f, 0x40, 0x0, 0x0, - 0xf9, 0x3f, 0x60, 0x0, 0x1, 0xf9, 0xe, 0xd0, - 0x0, 0x9, 0xf9, 0x4, 0xfd, 0x87, 0xcf, 0xf8, - 0x0, 0x3b, 0xff, 0xb3, 0xf7, 0x0, 0x0, 0x0, - 0x5, 0xf4, 0x9, 0xe9, 0x77, 0xaf, 0xb0, 0x1, - 0x7c, 0xff, 0xd8, 0x0, + 0x2, 0xf8, 0xe1, 0xf5, 0xbe, 0x3c, 0x2, 0xe3, + 0x40, 0xe, 0x74, 0x0, 0xe3, 0x40, 0xe, 0x3c, + 0x2, 0xe1, 0xf9, 0xfe, 0x2, 0xf8, 0xd0, 0x0, + 0x1d, 0x2e, 0x5b, 0x80, 0x7f, 0xe0, /* U+0068 "h" */ - 0x8f, 0x0, 0x0, 0x0, 0x8, 0xf0, 0x0, 0x0, - 0x0, 0x8f, 0x0, 0x0, 0x0, 0x8, 0xf2, 0xbf, - 0xea, 0x10, 0x8f, 0xfb, 0x89, 0xfd, 0x8, 0xf8, - 0x0, 0x6, 0xf4, 0x8f, 0x10, 0x0, 0x1f, 0x78, - 0xf0, 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, 0xf, - 0x88, 0xf0, 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, - 0xf, 0x88, 0xf0, 0x0, 0x0, 0xf8, + 0xb0, 0x0, 0x2c, 0x0, 0xb, 0x0, 0x2, 0xcb, + 0xe0, 0xbe, 0xaf, 0x2e, 0x1, 0xdb, 0x0, 0x36, + 0xc0, 0xe, 0xb0, 0x3, 0xac, 0x0, 0xeb, 0x0, + 0x3a, 0xc0, 0xe, /* U+0069 "i" */ - 0x9e, 0x1a, 0xf2, 0x0, 0x8, 0xf0, 0x8f, 0x8, - 0xf0, 0x8f, 0x8, 0xf0, 0x8f, 0x8, 0xf0, 0x8f, - 0x8, 0xf0, + 0xb2, 0xc0, 0x2c, 0xb2, 0xcb, 0x2c, 0xb2, 0xcb, + 0x2c, /* U+006A "j" */ - 0x0, 0x7, 0xe2, 0x0, 0x9, 0xf3, 0x0, 0x0, - 0x0, 0x0, 0x7, 0xf1, 0x0, 0x7, 0xf1, 0x0, - 0x7, 0xf1, 0x0, 0x7, 0xf1, 0x0, 0x7, 0xf1, - 0x0, 0x7, 0xf1, 0x0, 0x7, 0xf1, 0x0, 0x7, - 0xf1, 0x0, 0x7, 0xf1, 0x0, 0x8, 0xf0, 0x18, - 0x6e, 0xc0, 0x3e, 0xfc, 0x20, + 0x1, 0xc0, 0x2c, 0x0, 0x0, 0x1c, 0x1, 0xc0, + 0x1c, 0x1, 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x1, + 0xc0, 0x1c, 0x2, 0xc2, 0x7c, 0x3f, 0x0, /* U+006B "k" */ - 0x8f, 0x0, 0x0, 0x0, 0x8, 0xf0, 0x0, 0x0, - 0x0, 0x8f, 0x0, 0x0, 0x0, 0x8, 0xf0, 0x0, - 0x1d, 0xd1, 0x8f, 0x0, 0x1d, 0xe2, 0x8, 0xf0, - 0x1d, 0xe2, 0x0, 0x8f, 0x2d, 0xf3, 0x0, 0x8, - 0xfe, 0xff, 0x70, 0x0, 0x8f, 0xe2, 0xbf, 0x30, - 0x8, 0xf2, 0x1, 0xee, 0x10, 0x8f, 0x0, 0x3, - 0xfb, 0x8, 0xf0, 0x0, 0x7, 0xf7, + 0xb0, 0x0, 0x2c, 0x0, 0xb, 0x0, 0x2, 0xc0, + 0x3c, 0xb0, 0x3c, 0x2c, 0x3c, 0xb, 0x3c, 0x2, + 0xff, 0x40, 0xbc, 0xb0, 0x2c, 0xf, 0xb, 0x0, + 0xe2, 0xc0, 0x1d, /* U+006C "l" */ - 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, - 0x8f, 0x8f, 0x8f, 0x8f, + 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, /* U+006D "m" */ - 0x8e, 0x3c, 0xfe, 0x91, 0x3b, 0xfe, 0xa2, 0x8, - 0xff, 0x96, 0x9f, 0xcf, 0xc6, 0x8f, 0xd0, 0x8f, - 0x70, 0x0, 0x9f, 0xc0, 0x0, 0x5f, 0x58, 0xf1, - 0x0, 0x5, 0xf6, 0x0, 0x1, 0xf7, 0x8f, 0x0, - 0x0, 0x4f, 0x40, 0x0, 0xf, 0x88, 0xf0, 0x0, - 0x4, 0xf4, 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, - 0x4f, 0x40, 0x0, 0xf, 0x88, 0xf0, 0x0, 0x4, - 0xf4, 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, 0x4f, - 0x40, 0x0, 0xf, 0x80, + 0xb3, 0xf8, 0x2f, 0x82, 0xf9, 0xbf, 0xdb, 0xcb, + 0x40, 0xbc, 0x7, 0x6c, 0x1, 0xd0, 0xd, 0xb0, + 0x7, 0x40, 0x3a, 0xc0, 0x1d, 0x0, 0xeb, 0x0, + 0x74, 0x3, 0xac, 0x1, 0xd0, 0xe, 0xb0, 0x7, + 0x40, 0x38, /* U+006E "n" */ - 0x8e, 0x3b, 0xfe, 0xa1, 0x8, 0xff, 0xa6, 0x8f, - 0xd0, 0x8f, 0x80, 0x0, 0x6f, 0x48, 0xf1, 0x0, - 0x1, 0xf7, 0x8f, 0x0, 0x0, 0xf, 0x88, 0xf0, - 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, 0xf, 0x88, - 0xf0, 0x0, 0x0, 0xf8, 0x8f, 0x0, 0x0, 0xf, - 0x80, + 0xb2, 0xf8, 0x2f, 0x9b, 0xcb, 0x80, 0x76, 0xc0, + 0xd, 0xb0, 0x3, 0xac, 0x0, 0xeb, 0x0, 0x3a, + 0xc0, 0xe, 0xb0, 0x3, 0x80, /* U+006F "o" */ - 0x0, 0x3b, 0xef, 0xc4, 0x0, 0x4, 0xfd, 0x87, - 0xcf, 0x60, 0xe, 0xd0, 0x0, 0xb, 0xf1, 0x3f, - 0x60, 0x0, 0x3, 0xf5, 0x4f, 0x30, 0x0, 0x1, - 0xf7, 0x3f, 0x60, 0x0, 0x3, 0xf5, 0xe, 0xd0, - 0x0, 0xb, 0xf1, 0x4, 0xfd, 0x77, 0xcf, 0x60, - 0x0, 0x3b, 0xef, 0xc4, 0x0, + 0x2, 0xfd, 0x1, 0xf9, 0xf4, 0x3c, 0x2, 0xc3, + 0x40, 0xd, 0x70, 0x0, 0xd3, 0x40, 0xd, 0x3c, + 0x2, 0xc1, 0xf5, 0xf4, 0x2, 0xfd, 0x0, /* U+0070 "p" */ - 0x8e, 0x3b, 0xfe, 0xb3, 0x0, 0x8f, 0xfb, 0x57, - 0xdf, 0x30, 0x8f, 0x90, 0x0, 0xd, 0xc0, 0x8f, - 0x10, 0x0, 0x7, 0xf1, 0x8f, 0x0, 0x0, 0x5, - 0xf3, 0x8f, 0x20, 0x0, 0x7, 0xf1, 0x8f, 0xa0, - 0x0, 0x1e, 0xd0, 0x8f, 0xec, 0x78, 0xef, 0x30, - 0x8f, 0x2b, 0xfe, 0xb3, 0x0, 0x8f, 0x0, 0x0, - 0x0, 0x0, 0x8f, 0x0, 0x0, 0x0, 0x0, 0x8f, - 0x0, 0x0, 0x0, 0x0, + 0xb2, 0xf8, 0xb, 0xe5, 0xf0, 0xb8, 0x3, 0xcb, + 0x0, 0x1c, 0xb0, 0x1, 0xcb, 0x0, 0x1c, 0xb8, + 0x3, 0xcb, 0xf6, 0xf0, 0xb2, 0xf8, 0xb, 0x0, + 0x0, 0xb0, 0x0, 0xb, 0x0, 0x0, /* U+0071 "q" */ - 0x0, 0x3b, 0xff, 0xa2, 0xf7, 0x4, 0xfd, 0x87, - 0xde, 0xf7, 0xe, 0xd0, 0x0, 0xb, 0xf7, 0x3f, - 0x60, 0x0, 0x3, 0xf7, 0x4f, 0x30, 0x0, 0x1, - 0xf7, 0x3f, 0x60, 0x0, 0x3, 0xf7, 0xe, 0xd0, - 0x0, 0xb, 0xf7, 0x4, 0xfd, 0x77, 0xce, 0xf7, - 0x0, 0x3b, 0xff, 0xa3, 0xf7, 0x0, 0x0, 0x0, - 0x1, 0xf7, 0x0, 0x0, 0x0, 0x1, 0xf7, 0x0, - 0x0, 0x0, 0x1, 0xf7, + 0x2, 0xf8, 0xd1, 0xf5, 0xbd, 0x3c, 0x2, 0xd3, + 0x40, 0xd, 0x70, 0x0, 0xd3, 0x40, 0xd, 0x3c, + 0x2, 0xd1, 0xf5, 0xfd, 0x2, 0xf8, 0xd0, 0x0, + 0xd, 0x0, 0x0, 0xd0, 0x0, 0xd, /* U+0072 "r" */ - 0x8e, 0x2b, 0xf0, 0x8f, 0xed, 0x90, 0x8f, 0xa0, - 0x0, 0x8f, 0x20, 0x0, 0x8f, 0x0, 0x0, 0x8f, - 0x0, 0x0, 0x8f, 0x0, 0x0, 0x8f, 0x0, 0x0, - 0x8f, 0x0, 0x0, + 0xb2, 0xcb, 0xf8, 0xb8, 0xb, 0x0, 0xb0, 0xb, + 0x0, 0xb0, 0xb, 0x0, 0xb0, 0x0, /* U+0073 "s" */ - 0x2, 0xae, 0xfd, 0x91, 0x1e, 0xd7, 0x69, 0xd0, - 0x4f, 0x30, 0x0, 0x0, 0x2f, 0xb4, 0x10, 0x0, - 0x6, 0xef, 0xfd, 0x60, 0x0, 0x1, 0x5b, 0xf5, - 0x1, 0x0, 0x0, 0xf7, 0x5f, 0xa7, 0x6b, 0xf3, - 0x19, 0xdf, 0xec, 0x40, + 0xb, 0xf8, 0x3d, 0x6c, 0x70, 0x0, 0x39, 0x0, + 0x1f, 0xf4, 0x0, 0x6d, 0x0, 0xd, 0x79, 0x6c, + 0x2f, 0xf4, /* U+0074 "t" */ - 0x5, 0xf3, 0x0, 0x0, 0x5f, 0x30, 0x0, 0xcf, - 0xff, 0xfa, 0x4, 0x8f, 0x75, 0x30, 0x5, 0xf3, - 0x0, 0x0, 0x5f, 0x30, 0x0, 0x5, 0xf3, 0x0, - 0x0, 0x5f, 0x30, 0x0, 0x4, 0xf4, 0x0, 0x0, - 0x1f, 0xc6, 0x80, 0x0, 0x5d, 0xfc, 0x10, + 0x1c, 0x0, 0x70, 0xf, 0xfe, 0x1b, 0x50, 0x1c, + 0x0, 0x70, 0x1, 0xc0, 0x7, 0x0, 0x1d, 0x0, + 0x3d, 0x80, 0x7f, 0x0, /* U+0075 "u" */ - 0xae, 0x0, 0x0, 0x2f, 0x5a, 0xe0, 0x0, 0x2, - 0xf5, 0xae, 0x0, 0x0, 0x2f, 0x5a, 0xe0, 0x0, - 0x2, 0xf5, 0xae, 0x0, 0x0, 0x2f, 0x59, 0xf0, - 0x0, 0x4, 0xf5, 0x6f, 0x30, 0x0, 0xaf, 0x51, - 0xee, 0x76, 0xbf, 0xf5, 0x2, 0xbe, 0xfb, 0x3f, - 0x50, + 0xb0, 0x3, 0x6c, 0x0, 0xdb, 0x0, 0x36, 0xc0, + 0xd, 0xb0, 0x3, 0x6c, 0x1, 0xd7, 0x0, 0xb4, + 0xf5, 0xbd, 0xb, 0xe3, 0x40, /* U+0076 "v" */ - 0xd, 0xc0, 0x0, 0x0, 0xcb, 0x6, 0xf2, 0x0, - 0x2, 0xf5, 0x0, 0xf9, 0x0, 0x9, 0xe0, 0x0, - 0x9e, 0x0, 0xf, 0x80, 0x0, 0x2f, 0x60, 0x6f, - 0x10, 0x0, 0xc, 0xc0, 0xcb, 0x0, 0x0, 0x5, - 0xf6, 0xf4, 0x0, 0x0, 0x0, 0xef, 0xd0, 0x0, - 0x0, 0x0, 0x8f, 0x70, 0x0, + 0x3c, 0x0, 0xe1, 0xc0, 0xd, 0xe, 0x2, 0xc0, + 0xb0, 0x38, 0x3, 0x47, 0x0, 0x3c, 0xe0, 0x1, + 0xdd, 0x0, 0xf, 0xc0, 0x0, 0xb4, 0x0, /* U+0077 "w" */ - 0xbb, 0x0, 0x0, 0x9f, 0x10, 0x0, 0x4f, 0x16, - 0xf1, 0x0, 0xe, 0xf6, 0x0, 0x9, 0xc0, 0xf, - 0x60, 0x5, 0xfc, 0xb0, 0x0, 0xf6, 0x0, 0xac, - 0x0, 0xab, 0x5f, 0x10, 0x5f, 0x10, 0x5, 0xf1, - 0xf, 0x50, 0xf7, 0xa, 0xb0, 0x0, 0xf, 0x76, - 0xf0, 0x9, 0xc0, 0xf5, 0x0, 0x0, 0xac, 0xba, - 0x0, 0x4f, 0x8f, 0x0, 0x0, 0x4, 0xff, 0x40, - 0x0, 0xef, 0xa0, 0x0, 0x0, 0xe, 0xe0, 0x0, - 0x8, 0xf4, 0x0, 0x0, + 0xa0, 0xb, 0x0, 0x71, 0xc0, 0x3d, 0x2, 0xc3, + 0x41, 0xfc, 0xd, 0xb, 0xa, 0x70, 0x70, 0x1c, + 0x34, 0xd2, 0x80, 0x35, 0xc2, 0xcd, 0x0, 0xba, + 0x7, 0xb0, 0x1, 0xf4, 0xf, 0x80, 0x3, 0xc0, + 0x2d, 0x0, /* U+0078 "x" */ - 0x4f, 0x70, 0x0, 0x9f, 0x20, 0x8f, 0x30, 0x5f, - 0x50, 0x0, 0xcd, 0x2e, 0x90, 0x0, 0x2, 0xff, - 0xd0, 0x0, 0x0, 0xa, 0xf6, 0x0, 0x0, 0x4, - 0xfd, 0xe1, 0x0, 0x1, 0xeb, 0xd, 0xc0, 0x0, - 0xbe, 0x10, 0x3f, 0x80, 0x6f, 0x40, 0x0, 0x7f, - 0x40, + 0x74, 0xb, 0xb, 0x7, 0x40, 0xf3, 0x80, 0xf, + 0xc0, 0x2, 0xd0, 0x1, 0xfc, 0x0, 0xe3, 0xc0, + 0xb0, 0x38, 0x74, 0x7, 0x40, /* U+0079 "y" */ - 0xd, 0xc0, 0x0, 0x0, 0xcb, 0x6, 0xf3, 0x0, - 0x2, 0xf4, 0x0, 0xea, 0x0, 0x9, 0xd0, 0x0, - 0x8f, 0x10, 0x1f, 0x70, 0x0, 0x1f, 0x70, 0x7f, - 0x10, 0x0, 0xa, 0xe0, 0xd9, 0x0, 0x0, 0x3, - 0xf9, 0xf2, 0x0, 0x0, 0x0, 0xcf, 0xb0, 0x0, - 0x0, 0x0, 0x6f, 0x40, 0x0, 0x0, 0x0, 0xad, - 0x0, 0x0, 0x1c, 0x79, 0xf5, 0x0, 0x0, 0x1a, - 0xee, 0x70, 0x0, 0x0, + 0x3c, 0x0, 0xe1, 0xc0, 0xd, 0xe, 0x2, 0xc0, + 0xb0, 0x34, 0x3, 0x47, 0x0, 0x2c, 0xe0, 0x0, + 0xec, 0x0, 0xf, 0x80, 0x0, 0x74, 0x0, 0xb, + 0x0, 0x36, 0xd0, 0x2, 0xf4, 0x0, /* U+007A "z" */ - 0x4f, 0xff, 0xff, 0xf9, 0x15, 0x55, 0x5b, 0xf4, - 0x0, 0x0, 0x4f, 0x80, 0x0, 0x1, 0xec, 0x0, - 0x0, 0xb, 0xe1, 0x0, 0x0, 0x8f, 0x40, 0x0, - 0x4, 0xf7, 0x0, 0x0, 0x1e, 0xe5, 0x55, 0x53, - 0x5f, 0xff, 0xff, 0xfc, + 0x7f, 0xfe, 0x15, 0x6d, 0x0, 0x78, 0x0, 0xf0, + 0x2, 0xc0, 0xb, 0x40, 0x1d, 0x0, 0x3d, 0x54, + 0x7f, 0xff, /* U+007B "{" */ - 0x0, 0x2c, 0xf5, 0x0, 0xaf, 0x61, 0x0, 0xcc, - 0x0, 0x0, 0xdb, 0x0, 0x0, 0xdb, 0x0, 0x0, - 0xdb, 0x0, 0x2, 0xea, 0x0, 0x1f, 0xf4, 0x0, - 0x5, 0xfa, 0x0, 0x0, 0xdb, 0x0, 0x0, 0xdb, - 0x0, 0x0, 0xdb, 0x0, 0x0, 0xcc, 0x0, 0x0, - 0xaf, 0x61, 0x0, 0x2c, 0xf5, + 0x3, 0xd0, 0xb4, 0xf, 0x0, 0xe0, 0xe, 0x0, + 0xe0, 0xe, 0x3, 0xd0, 0x1e, 0x0, 0xe0, 0xe, + 0x0, 0xe0, 0xf, 0x0, 0xb4, 0x3, 0xd0, /* U+007C "|" */ - 0x5f, 0x15, 0xf1, 0x5f, 0x15, 0xf1, 0x5f, 0x15, - 0xf1, 0x5f, 0x15, 0xf1, 0x5f, 0x15, 0xf1, 0x5f, - 0x15, 0xf1, 0x5f, 0x15, 0xf1, 0x5f, 0x10, + 0x71, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xc7, + 0x1c, 0x71, 0xc7, 0x0, /* U+007D "}" */ - 0xbe, 0x80, 0x3, 0xaf, 0x40, 0x1, 0xf6, 0x0, - 0x1f, 0x70, 0x1, 0xf7, 0x0, 0x1f, 0x70, 0x0, - 0xf9, 0x0, 0xa, 0xfb, 0x0, 0xfb, 0x20, 0x1f, - 0x70, 0x1, 0xf7, 0x0, 0x1f, 0x70, 0x1, 0xf6, - 0x3, 0xaf, 0x40, 0xbe, 0x90, 0x0, + 0xb8, 0xb, 0x40, 0xd0, 0x34, 0xd, 0x3, 0x40, + 0xe0, 0x2e, 0xe, 0x3, 0x40, 0xd0, 0x34, 0xd, + 0xb, 0x4b, 0x80, /* U+007E "~" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3d, 0xe4, 0x0, - 0xb5, 0xc, 0x86, 0xf5, 0x1e, 0x20, 0xf0, 0x3, - 0xef, 0x90, 0x2, 0x0, 0x0, 0x10, 0x0, - - /* U+00B0 "°" */ - 0x2, 0xce, 0x90, 0xd, 0x40, 0x89, 0x3b, 0x0, - 0xe, 0x3b, 0x0, 0xe, 0xd, 0x40, 0x89, 0x2, - 0xce, 0x90, - - /* U+2022 "•" */ - 0x0, 0x8, 0xf8, 0xef, 0xe7, 0xf7, - - /* U+F001 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x49, 0xdc, - 0x0, 0x0, 0x0, 0x0, 0x16, 0xbf, 0xff, 0xff, - 0x0, 0x0, 0x3, 0x8d, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, - 0x0, 0x0, 0xff, 0xff, 0xea, 0x51, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x83, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0x2b, 0xff, 0xff, - 0x0, 0x0, 0xff, 0x0, 0x0, 0xdf, 0xff, 0xff, - 0x2b, 0xff, 0xff, 0x0, 0x0, 0xdf, 0xff, 0xfd, - 0xdf, 0xff, 0xff, 0x0, 0x0, 0x2b, 0xff, 0xb2, - 0xdf, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x2b, 0xff, 0xb2, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F008 "" */ - 0xd0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xd, - 0xff, 0xff, 0xc8, 0x88, 0x88, 0x8c, 0xff, 0xff, - 0xf0, 0xf, 0x80, 0x0, 0x0, 0x8, 0xf0, 0xf, - 0xf0, 0xf, 0x80, 0x0, 0x0, 0x8, 0xf0, 0xf, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x8, 0xff, 0xff, - 0xf0, 0xf, 0xec, 0xcc, 0xcc, 0xce, 0xf0, 0xf, - 0xf0, 0xf, 0xec, 0xcc, 0xcc, 0xce, 0xf0, 0xf, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x8, 0xff, 0xff, - 0xf0, 0xf, 0x80, 0x0, 0x0, 0x8, 0xf0, 0xf, - 0xf0, 0xf, 0x80, 0x0, 0x0, 0x8, 0xf0, 0xf, - 0xff, 0xff, 0xc8, 0x88, 0x88, 0x8c, 0xff, 0xff, - 0xd0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xd, - - /* U+F00B "" */ - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0xff, 0x73, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+F00C "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xb1, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfc, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xfb, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xc0, - 0x1b, 0xa0, 0x0, 0x0, 0xb, 0xff, 0xfc, 0x0, - 0xcf, 0xfb, 0x0, 0x0, 0xbf, 0xff, 0xc0, 0x0, - 0xbf, 0xff, 0xb0, 0xb, 0xff, 0xfc, 0x0, 0x0, - 0xc, 0xff, 0xfb, 0xbf, 0xff, 0xc0, 0x0, 0x0, - 0x0, 0xcf, 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, - 0x0, 0xc, 0xff, 0xff, 0xb0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xfb, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xb0, 0x0, 0x0, 0x0, 0x0, - - /* U+F00D "" */ - 0x3, 0x0, 0x0, 0x0, 0x3, 0x8, 0xfc, 0x10, - 0x0, 0x1c, 0xf8, 0xff, 0xfc, 0x10, 0x1c, 0xff, - 0xf5, 0xff, 0xfc, 0x2c, 0xff, 0xf5, 0x5, 0xff, - 0xff, 0xff, 0xf5, 0x0, 0x5, 0xff, 0xff, 0xf5, - 0x0, 0x0, 0x1d, 0xff, 0xfd, 0x10, 0x0, 0x1c, - 0xff, 0xff, 0xfc, 0x10, 0x1c, 0xff, 0xf9, 0xff, - 0xfc, 0x1c, 0xff, 0xf5, 0x5, 0xff, 0xfc, 0xdf, - 0xf5, 0x0, 0x5, 0xff, 0xd1, 0xa4, 0x0, 0x0, - 0x4, 0xa1, - - /* U+F011 "" */ - 0x0, 0x0, 0x0, 0x4f, 0xe0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0x10, 0x6f, 0xf1, 0x3, 0x10, 0x0, - 0x0, 0x5f, 0xd0, 0x6f, 0xf1, 0x3f, 0xd1, 0x0, - 0x3, 0xff, 0xf1, 0x6f, 0xf1, 0x5f, 0xfd, 0x0, - 0xd, 0xff, 0x40, 0x6f, 0xf1, 0x9, 0xff, 0x70, - 0x4f, 0xf7, 0x0, 0x6f, 0xf1, 0x0, 0xcf, 0xe0, - 0x9f, 0xf0, 0x0, 0x6f, 0xf1, 0x0, 0x5f, 0xf3, - 0xbf, 0xc0, 0x0, 0x6f, 0xf1, 0x0, 0x2f, 0xf5, - 0xbf, 0xc0, 0x0, 0x4f, 0xe0, 0x0, 0x1f, 0xf6, - 0xaf, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xf4, - 0x6f, 0xf4, 0x0, 0x0, 0x0, 0x0, 0xaf, 0xf0, - 0xf, 0xfe, 0x10, 0x0, 0x0, 0x5, 0xff, 0xa0, - 0x6, 0xff, 0xd3, 0x0, 0x0, 0x7f, 0xff, 0x20, - 0x0, 0x9f, 0xff, 0xda, 0xbe, 0xff, 0xf4, 0x0, - 0x0, 0x6, 0xff, 0xff, 0xff, 0xfd, 0x30, 0x0, - 0x0, 0x0, 0x17, 0xbd, 0xca, 0x50, 0x0, 0x0, - - /* U+F013 "" */ - 0x0, 0x0, 0x0, 0x8b, 0xb8, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x30, 0x6, 0xff, 0xff, 0x60, 0x3, 0x0, - 0x4, 0xfd, 0xdf, 0xff, 0xff, 0xfd, 0xef, 0x40, - 0xd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, - 0x4f, 0xff, 0xff, 0xf9, 0x9f, 0xff, 0xff, 0xf4, - 0x8, 0xff, 0xff, 0x20, 0x2, 0xff, 0xff, 0x80, - 0x0, 0xff, 0xf9, 0x0, 0x0, 0x9f, 0xff, 0x0, - 0x0, 0xff, 0xf9, 0x0, 0x0, 0x9f, 0xff, 0x0, - 0x8, 0xff, 0xff, 0x20, 0x2, 0xff, 0xff, 0x80, - 0x4f, 0xff, 0xff, 0xf9, 0x9f, 0xff, 0xff, 0xf4, - 0xd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, - 0x4, 0xfe, 0xdf, 0xff, 0xff, 0xfd, 0xdf, 0x40, - 0x0, 0x30, 0x6, 0xff, 0xff, 0x60, 0x3, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x8b, 0xb8, 0x0, 0x0, 0x0, - - /* U+F015 "" */ - 0x0, 0x0, 0x0, 0x3, 0xdd, 0x30, 0x3f, 0xf3, - 0x0, 0x0, 0x0, 0x0, 0x6f, 0xff, 0xf5, 0x4f, - 0xf4, 0x0, 0x0, 0x0, 0x9, 0xff, 0x99, 0xff, - 0xbf, 0xf4, 0x0, 0x0, 0x1, 0xbf, 0xf6, 0x22, - 0x6f, 0xff, 0xf4, 0x0, 0x0, 0x2d, 0xfe, 0x35, - 0xff, 0x53, 0xef, 0xf4, 0x0, 0x4, 0xff, 0xc1, - 0x8f, 0xff, 0xf8, 0x2d, 0xfe, 0x40, 0x7f, 0xfa, - 0x1a, 0xff, 0xff, 0xff, 0xa1, 0xaf, 0xf7, 0xcf, - 0x82, 0xdf, 0xff, 0xff, 0xff, 0xfd, 0x28, 0xfc, - 0x14, 0xe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - 0x41, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0xf, 0xff, 0xf9, 0x0, 0x8f, - 0xff, 0xf0, 0x0, 0x0, 0xf, 0xff, 0xf8, 0x0, - 0x8f, 0xff, 0xf0, 0x0, 0x0, 0xf, 0xff, 0xf8, - 0x0, 0x8f, 0xff, 0xf0, 0x0, 0x0, 0xe, 0xff, - 0xf6, 0x0, 0x6f, 0xff, 0xe0, 0x0, - - /* U+F019 "" */ - 0x0, 0x0, 0x0, 0xdf, 0xfd, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x4f, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xb0, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xfb, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xb0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xfb, 0x0, 0x0, 0x0, - 0xdf, 0xff, 0xfc, 0x1b, 0xb1, 0xcf, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0xc2, 0x2c, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xe0, 0xff, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+F01C "" */ - 0x0, 0x4, 0xef, 0xff, 0xff, 0xff, 0xfe, 0x40, - 0x0, 0x0, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xe1, 0x0, 0x0, 0xaf, 0xb0, 0x0, 0x0, 0x0, - 0xb, 0xfa, 0x0, 0x5, 0xff, 0x10, 0x0, 0x0, - 0x0, 0x1, 0xff, 0x50, 0x1e, 0xf6, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6f, 0xe1, 0xaf, 0xb0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xb, 0xfa, 0xff, 0xff, - 0xff, 0x80, 0x0, 0x8, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf1, 0x0, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, - - /* U+F021 "" */ - 0x0, 0x0, 0x6, 0xbd, 0xda, 0x50, 0x2, 0xff, - 0x0, 0x5, 0xef, 0xff, 0xff, 0xfe, 0x42, 0xff, - 0x0, 0x7f, 0xff, 0xa7, 0x7b, 0xff, 0xf9, 0xff, - 0x5, 0xff, 0xc1, 0x0, 0x0, 0x2c, 0xff, 0xff, - 0xe, 0xfc, 0x0, 0x0, 0x2, 0x22, 0xdf, 0xff, - 0x5f, 0xf2, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0x8f, 0xb0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0xb, 0xf8, - 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x2f, 0xf4, - 0xff, 0xfd, 0x22, 0x20, 0x0, 0x0, 0xcf, 0xe0, - 0xff, 0xff, 0xc2, 0x0, 0x0, 0x2c, 0xff, 0x40, - 0xff, 0x9f, 0xff, 0xb7, 0x6a, 0xff, 0xf7, 0x0, - 0xff, 0x24, 0xdf, 0xff, 0xff, 0xfe, 0x50, 0x0, - 0xff, 0x20, 0x5, 0xac, 0xdb, 0x60, 0x0, 0x0, - - /* U+F026 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8d, - 0x0, 0x0, 0x8, 0xff, 0x0, 0x0, 0x8f, 0xff, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, - 0x0, 0x0, 0x8f, 0xff, 0x0, 0x0, 0x8, 0xff, - 0x0, 0x0, 0x0, 0x8d, 0x0, 0x0, 0x0, 0x0, - - /* U+F027 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x8d, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x8f, 0xff, 0x0, 0x0, - 0xcf, 0xff, 0xff, 0xff, 0x1, 0x50, 0xff, 0xff, - 0xff, 0xff, 0x6, 0xf7, 0xff, 0xff, 0xff, 0xff, - 0x0, 0xbe, 0xff, 0xff, 0xff, 0xff, 0x0, 0xae, - 0xff, 0xff, 0xff, 0xff, 0x5, 0xf8, 0xdf, 0xff, - 0xff, 0xff, 0x2, 0x60, 0x0, 0x0, 0x9f, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x9, 0xff, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x9e, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+F028 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, - 0xd2, 0x0, 0x0, 0x0, 0x0, 0x8d, 0x0, 0x0, - 0x3, 0xee, 0x10, 0x0, 0x0, 0x8, 0xff, 0x0, - 0xa, 0xb1, 0x2f, 0xb0, 0x0, 0x0, 0x8f, 0xff, - 0x0, 0x5, 0xfc, 0x7, 0xf4, 0xdf, 0xff, 0xff, - 0xff, 0x2, 0x50, 0x5f, 0x60, 0xf9, 0xff, 0xff, - 0xff, 0xff, 0x6, 0xf7, 0xd, 0xc0, 0xbd, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xae, 0x9, 0xf0, 0x9f, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xae, 0x9, 0xf0, - 0x8f, 0xff, 0xff, 0xff, 0xff, 0x6, 0xf7, 0xd, - 0xc0, 0xad, 0xdf, 0xff, 0xff, 0xff, 0x2, 0x50, - 0x5f, 0x60, 0xe9, 0x0, 0x0, 0x8f, 0xff, 0x0, - 0x5, 0xfc, 0x6, 0xf4, 0x0, 0x0, 0x8, 0xff, - 0x0, 0xa, 0xb1, 0x2f, 0xb0, 0x0, 0x0, 0x0, - 0x8d, 0x0, 0x0, 0x2, 0xee, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xd2, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0x10, 0x0, - - /* U+F03E "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x20, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x0, 0xc, 0xff, 0xff, 0xee, 0xff, 0xff, - 0xff, 0x20, 0x2f, 0xff, 0xfe, 0x22, 0xef, 0xff, - 0xff, 0xfc, 0xff, 0xff, 0xe2, 0x0, 0x2e, 0xff, - 0xff, 0xfe, 0x4e, 0xfe, 0x20, 0x0, 0x2, 0xff, - 0xff, 0xe2, 0x2, 0xc2, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - - /* U+F043 "" */ - 0x0, 0x0, 0x4e, 0x40, 0x0, 0x0, 0x0, 0xb, - 0xfb, 0x0, 0x0, 0x0, 0x1, 0xff, 0xf1, 0x0, - 0x0, 0x0, 0x9f, 0xff, 0x90, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0x30, 0x0, 0xc, 0xff, 0xff, 0xfc, - 0x0, 0x7, 0xff, 0xff, 0xff, 0xf8, 0x2, 0xff, - 0xff, 0xff, 0xff, 0xf2, 0x9f, 0xff, 0xff, 0xff, - 0xff, 0x9e, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, - 0x2f, 0xff, 0xff, 0xff, 0xfe, 0xf2, 0xbf, 0xff, - 0xff, 0xfe, 0x9f, 0xa1, 0xbf, 0xff, 0xff, 0x92, - 0xff, 0xa2, 0x2f, 0xff, 0xf2, 0x4, 0xff, 0xff, - 0xff, 0xf4, 0x0, 0x2, 0x9e, 0xfe, 0x92, 0x0, - - /* U+F048 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x30, 0x0, - 0x1, 0xcc, 0xff, 0x40, 0x0, 0x2d, 0xff, 0xff, - 0x40, 0x3, 0xef, 0xff, 0xff, 0x40, 0x3f, 0xff, - 0xff, 0xff, 0x44, 0xff, 0xff, 0xff, 0xff, 0x9f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, - 0xff, 0xff, 0xff, 0x45, 0xff, 0xff, 0xff, 0xff, - 0x40, 0x4f, 0xff, 0xff, 0xff, 0x40, 0x3, 0xef, - 0xff, 0xff, 0x40, 0x0, 0x2e, 0xff, 0xff, 0x30, - 0x0, 0x1, 0xcc, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F04B "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f, - 0x91, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0x70, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xfd, - 0x40, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfa, - 0x10, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf7, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb2, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xb2, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd5, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xf7, 0x0, 0x0, 0xff, 0xff, 0xff, 0xfa, 0x10, - 0x0, 0x0, 0xff, 0xff, 0xfd, 0x40, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, - 0x8e, 0xa1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F04C "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f, - 0xff, 0xf8, 0x0, 0x8f, 0xff, 0xf8, 0xff, 0xff, - 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0xff, - 0xff, 0xff, 0x7f, 0xff, 0xf7, 0x0, 0x7f, 0xff, - 0xf7, - - /* U+F04D "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf8, - - /* U+F051 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0xcc, 0x10, 0x0, - 0x3, 0xff, 0xff, 0xd2, 0x0, 0x4, 0xff, 0xff, - 0xfe, 0x30, 0x4, 0xff, 0xff, 0xff, 0xf4, 0x4, - 0xff, 0xff, 0xff, 0xff, 0x54, 0xff, 0xff, 0xff, - 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf9, 0xff, 0xff, 0xff, 0xff, 0x44, 0xff, 0xff, - 0xff, 0xf3, 0x4, 0xff, 0xff, 0xfe, 0x30, 0x4, - 0xff, 0xff, 0xd2, 0x0, 0x4, 0xff, 0xcc, 0x10, - 0x0, 0x3, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F052 "" */ - 0x0, 0x0, 0x0, 0x2d, 0xd2, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xef, 0xfe, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x1d, 0xff, 0xff, 0xd1, 0x0, 0x0, - 0x0, 0x0, 0xcf, 0xff, 0xff, 0xfc, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xb0, 0x0, - 0x0, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x0, - 0x9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x90, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0xc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - - /* U+F053 "" */ - 0x0, 0x0, 0x0, 0x1a, 0x40, 0x0, 0x0, 0x1, - 0xdf, 0xf0, 0x0, 0x0, 0x1d, 0xff, 0xa0, 0x0, - 0x1, 0xdf, 0xfa, 0x0, 0x0, 0x1d, 0xff, 0xa0, - 0x0, 0x1, 0xdf, 0xfa, 0x0, 0x0, 0xc, 0xff, - 0xa0, 0x0, 0x0, 0xd, 0xff, 0x80, 0x0, 0x0, - 0x1, 0xdf, 0xf8, 0x0, 0x0, 0x0, 0x1d, 0xff, - 0x80, 0x0, 0x0, 0x1, 0xdf, 0xf8, 0x0, 0x0, - 0x0, 0x1d, 0xff, 0x80, 0x0, 0x0, 0x1, 0xdf, - 0xf0, 0x0, 0x0, 0x0, 0x1b, 0x50, - - /* U+F054 "" */ - 0x4, 0xa1, 0x0, 0x0, 0x0, 0xf, 0xfd, 0x10, - 0x0, 0x0, 0xa, 0xff, 0xd1, 0x0, 0x0, 0x0, - 0xaf, 0xfd, 0x10, 0x0, 0x0, 0xa, 0xff, 0xd1, - 0x0, 0x0, 0x0, 0xaf, 0xfd, 0x10, 0x0, 0x0, - 0xa, 0xff, 0xc0, 0x0, 0x0, 0x8, 0xff, 0xd0, - 0x0, 0x0, 0x8f, 0xfd, 0x10, 0x0, 0x8, 0xff, - 0xd1, 0x0, 0x0, 0x8f, 0xfd, 0x10, 0x0, 0x8, - 0xff, 0xd1, 0x0, 0x0, 0xf, 0xfd, 0x10, 0x0, - 0x0, 0x5, 0xb1, 0x0, 0x0, 0x0, - - /* U+F067 "" */ - 0x0, 0x0, 0x4, 0xff, 0x40, 0x0, 0x0, 0x0, - 0x0, 0x8, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x8, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x8, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, - 0x80, 0x0, 0x0, 0x48, 0x88, 0x8c, 0xff, 0xc8, - 0x88, 0x84, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x48, 0x88, 0x8c, 0xff, 0xc8, 0x88, 0x84, 0x0, - 0x0, 0x8, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, - 0x8, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x8, - 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0x40, - 0x0, 0x0, - - /* U+F068 "" */ - 0x14, 0x44, 0x44, 0x44, 0x44, 0x44, 0x41, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0xbb, 0xbb, - 0xbb, 0xbb, 0xbb, 0xb7, - - /* U+F06E "" */ - 0x0, 0x0, 0x5, 0xad, 0xff, 0xda, 0x50, 0x0, - 0x0, 0x0, 0x4, 0xdf, 0xfc, 0x88, 0xcf, 0xfd, - 0x40, 0x0, 0x0, 0x7f, 0xfe, 0x40, 0x0, 0x4, - 0xef, 0xf7, 0x0, 0x7, 0xff, 0xf4, 0x0, 0x9e, - 0x80, 0x4f, 0xff, 0x70, 0x4f, 0xff, 0xc0, 0x0, - 0xaf, 0xf8, 0xc, 0xff, 0xf4, 0xdf, 0xff, 0x80, - 0x9a, 0xff, 0xfe, 0x8, 0xff, 0xfd, 0xdf, 0xff, - 0x80, 0xef, 0xff, 0xfe, 0x8, 0xff, 0xfd, 0x4f, - 0xff, 0xc0, 0x8f, 0xff, 0xf8, 0xc, 0xff, 0xf4, - 0x7, 0xff, 0xf4, 0x8, 0xee, 0x80, 0x4f, 0xff, - 0x70, 0x0, 0x7f, 0xfe, 0x40, 0x0, 0x4, 0xef, - 0xf8, 0x0, 0x0, 0x4, 0xdf, 0xfc, 0x88, 0xcf, - 0xfd, 0x40, 0x0, 0x0, 0x0, 0x5, 0xad, 0xff, - 0xda, 0x50, 0x0, 0x0, - - /* U+F070 "" */ - 0x8c, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xdf, 0xe4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1b, 0xff, 0x80, 0x49, - 0xdf, 0xfd, 0xa5, 0x0, 0x0, 0x0, 0x0, 0x7f, - 0xff, 0xff, 0xd8, 0x8c, 0xff, 0xd4, 0x0, 0x0, - 0x0, 0x4, 0xef, 0xf8, 0x0, 0x0, 0x4e, 0xff, - 0x70, 0x0, 0x0, 0x0, 0x1c, 0xff, 0x69, 0xe8, - 0x4, 0xff, 0xf7, 0x0, 0x4, 0xe3, 0x0, 0x9f, - 0xfe, 0xff, 0x80, 0xcf, 0xff, 0x40, 0xd, 0xff, - 0x70, 0x5, 0xff, 0xff, 0xe0, 0x8f, 0xff, 0xd0, - 0xd, 0xff, 0xf7, 0x0, 0x2d, 0xff, 0xe0, 0x8f, - 0xff, 0xd0, 0x4, 0xff, 0xfc, 0x0, 0x0, 0xaf, - 0xf8, 0xcf, 0xff, 0x30, 0x0, 0x7f, 0xff, 0x40, - 0x0, 0x6, 0xff, 0xff, 0xf7, 0x0, 0x0, 0x8, - 0xff, 0xf4, 0x0, 0x0, 0x3e, 0xff, 0xa0, 0x0, - 0x0, 0x0, 0x4d, 0xff, 0xc8, 0x82, 0x1, 0xbf, - 0xf7, 0x0, 0x0, 0x0, 0x0, 0x5a, 0xdf, 0xfc, - 0x10, 0x8, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x4e, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xc8, - - /* U+F071 "" */ - 0x0, 0x0, 0x0, 0x0, 0x2d, 0xd2, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xfb, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xd, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xf7, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xd8, 0x8d, - 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, 0xa, 0xff, - 0xa0, 0xa, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xb0, 0xb, 0xff, 0xf3, 0x0, 0x0, - 0x0, 0x0, 0xcf, 0xff, 0xc0, 0xc, 0xff, 0xfc, - 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xd0, 0xd, - 0xff, 0xff, 0x50, 0x0, 0x0, 0xe, 0xff, 0xff, - 0xf9, 0x9f, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x8f, - 0xff, 0xff, 0xe2, 0x2e, 0xff, 0xff, 0xf8, 0x0, - 0x2, 0xff, 0xff, 0xff, 0x90, 0x9, 0xff, 0xff, - 0xff, 0x10, 0xa, 0xff, 0xff, 0xff, 0xe3, 0x3e, - 0xff, 0xff, 0xff, 0xa0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - - /* U+F074 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, - 0xff, 0xff, 0x70, 0x0, 0x7, 0xff, 0xff, 0xf8, - 0xff, 0xff, 0xf6, 0x0, 0x6f, 0xff, 0xff, 0xfd, - 0x78, 0x8e, 0xff, 0x15, 0xff, 0xe8, 0xff, 0xe2, - 0x0, 0x2, 0xe5, 0x4f, 0xfe, 0x20, 0xfe, 0x20, - 0x0, 0x0, 0x13, 0xff, 0xf3, 0x0, 0x52, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0x31, 0x0, 0x52, 0x0, - 0x0, 0x2, 0xef, 0xf4, 0x5e, 0x20, 0xfe, 0x20, - 0x78, 0x8e, 0xff, 0x51, 0xff, 0xe8, 0xff, 0xe2, - 0xff, 0xff, 0xf6, 0x0, 0x6f, 0xff, 0xff, 0xfd, - 0xff, 0xff, 0x70, 0x0, 0x7, 0xff, 0xff, 0xf8, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd8, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F077 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1, 0xdd, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x1d, 0xff, 0xd1, 0x0, 0x0, 0x0, 0x1, 0xdf, - 0xff, 0xfd, 0x10, 0x0, 0x0, 0x1d, 0xff, 0x99, - 0xff, 0xd1, 0x0, 0x1, 0xdf, 0xf9, 0x0, 0x9f, - 0xfd, 0x10, 0x1d, 0xff, 0x90, 0x0, 0x9, 0xff, - 0xd1, 0xbf, 0xf9, 0x0, 0x0, 0x0, 0x9f, 0xfb, - 0x5f, 0x90, 0x0, 0x0, 0x0, 0x9, 0xf5, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F078 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, - 0x90, 0x0, 0x0, 0x0, 0x9, 0xf5, 0xbf, 0xf9, - 0x0, 0x0, 0x0, 0x9f, 0xfb, 0x1d, 0xff, 0x90, - 0x0, 0x9, 0xff, 0xd1, 0x1, 0xdf, 0xf9, 0x0, - 0x9f, 0xfd, 0x10, 0x0, 0x1d, 0xff, 0x99, 0xff, - 0xd1, 0x0, 0x0, 0x1, 0xdf, 0xff, 0xfd, 0x10, - 0x0, 0x0, 0x0, 0x1d, 0xff, 0xd1, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xdd, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - - /* U+F079 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1d, 0xd1, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xdf, 0xfd, 0x10, - 0xef, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x1d, 0xff, - 0xff, 0xd1, 0xaf, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0xcf, 0xcf, 0xfc, 0xfc, 0x0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x6b, 0x1f, 0xf1, 0xb6, 0x0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0xf, 0xf0, 0x0, - 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0xf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, - 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x6b, 0x1f, - 0xf1, 0xb6, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, - 0xcf, 0xcf, 0xfc, 0xfc, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xfa, 0x1d, 0xff, 0xff, 0xd1, 0x0, 0xd, - 0xff, 0xff, 0xff, 0xfe, 0x1, 0xdf, 0xfd, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, - 0xd1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - - /* U+F07B "" */ - 0x8f, 0xff, 0xff, 0xe2, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xfe, 0x20, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - - /* U+F093 "" */ - 0x0, 0x0, 0x0, 0xb, 0xb0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xbf, 0xfb, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xb, 0xff, 0xff, 0xb0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xfb, 0x0, 0x0, - 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xb0, 0x0, - 0x0, 0x4f, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0xdf, 0xff, 0xf0, 0xdf, 0xfd, 0xf, 0xff, 0xfd, - 0xff, 0xff, 0xf9, 0x0, 0x0, 0x9f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xe0, 0xff, - 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+F095 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xea, - 0x62, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3, 0xef, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x4, 0xff, 0xf2, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xfb, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x6f, 0xff, 0x30, 0x0, 0x0, 0x2, - 0x0, 0x0, 0x4f, 0xff, 0x90, 0x0, 0x2, 0x8f, - 0xf3, 0x0, 0x6f, 0xff, 0xd0, 0x0, 0xa, 0xff, - 0xff, 0xe4, 0xbf, 0xff, 0xd1, 0x0, 0x0, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xd1, 0x0, 0x0, 0xa, - 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, - 0x6f, 0xff, 0xff, 0xfb, 0x30, 0x0, 0x0, 0x0, - 0x2, 0xff, 0xdb, 0x72, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F0C4 "" */ - 0x8, 0xee, 0x80, 0x0, 0x0, 0x6, 0x61, 0x8, - 0xff, 0xff, 0x80, 0x0, 0x2d, 0xff, 0xd0, 0xef, - 0x33, 0xfe, 0x0, 0x2e, 0xff, 0xf3, 0xe, 0xf3, - 0x3f, 0xe0, 0x2e, 0xff, 0xf3, 0x0, 0x8f, 0xff, - 0xff, 0x6e, 0xff, 0xf3, 0x0, 0x0, 0x8e, 0xff, - 0xff, 0xff, 0xf3, 0x0, 0x0, 0x0, 0x2, 0xef, - 0xff, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x2e, 0xff, - 0xff, 0x30, 0x0, 0x0, 0x8, 0xef, 0xff, 0xff, - 0xff, 0x30, 0x0, 0x8, 0xff, 0xff, 0xf6, 0xef, - 0xff, 0x30, 0x0, 0xef, 0x33, 0xfe, 0x2, 0xef, - 0xff, 0x30, 0xe, 0xf3, 0x3f, 0xe0, 0x2, 0xef, - 0xff, 0x30, 0x8f, 0xff, 0xf8, 0x0, 0x2, 0xdf, - 0xfd, 0x0, 0x8e, 0xe8, 0x0, 0x0, 0x0, 0x66, - 0x10, - - /* U+F0C5 "" */ - 0x0, 0x0, 0xdf, 0xff, 0xff, 0xd, 0x20, 0x0, - 0x0, 0xff, 0xff, 0xff, 0xf, 0xe2, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xf, 0xfd, 0xdf, 0xf0, 0xff, - 0xff, 0xff, 0x20, 0x0, 0xff, 0xf0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xdf, 0xff, - 0xff, 0xff, 0xfd, 0xff, 0xf9, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x0, 0xdf, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - - /* U+F0C7 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x0, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x20, 0xff, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xe2, 0xff, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xfc, 0xff, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfb, 0x11, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xf1, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, - 0xf1, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfb, - 0x11, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf8, - - /* U+F0C9 "" */ - 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x12, 0x22, 0x22, - 0x22, 0x22, 0x22, 0x21, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x12, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x12, 0x22, 0x22, 0x22, 0x22, 0x22, 0x21, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x22, - 0x22, 0x22, 0x22, 0x22, 0x21, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x12, 0x22, 0x22, 0x22, 0x22, - 0x22, 0x21, - - /* U+F0E0 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x90, - 0xd2, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xf5, 0x2d, - 0xff, 0x62, 0xcf, 0xff, 0xff, 0xfc, 0x26, 0xff, - 0xff, 0xfa, 0x18, 0xff, 0xff, 0x81, 0xaf, 0xff, - 0xff, 0xff, 0xe3, 0x4d, 0xd4, 0x3e, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x81, 0x18, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - - /* U+F0E7 "" */ - 0x0, 0xdf, 0xff, 0xfd, 0x0, 0x0, 0x1, 0xff, - 0xff, 0xfc, 0x0, 0x0, 0x3, 0xff, 0xff, 0xf7, - 0x0, 0x0, 0x6, 0xff, 0xff, 0xf2, 0x0, 0x0, - 0x8, 0xff, 0xff, 0xd0, 0x0, 0x0, 0xa, 0xff, - 0xff, 0xff, 0xff, 0xd0, 0xc, 0xff, 0xff, 0xff, - 0xff, 0xa0, 0xe, 0xff, 0xff, 0xff, 0xff, 0x20, - 0xd, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0xa, 0xff, 0xe0, 0x0, 0x0, 0x0, 0xe, 0xff, - 0x50, 0x0, 0x0, 0x0, 0x2f, 0xfc, 0x0, 0x0, - 0x0, 0x0, 0x5f, 0xf3, 0x0, 0x0, 0x0, 0x0, - 0x9f, 0xa0, 0x0, 0x0, 0x0, 0x0, 0xdf, 0x10, - 0x0, 0x0, 0x0, 0x0, 0xd7, 0x0, 0x0, 0x0, - - /* U+F0EA "" */ - 0x0, 0x4, 0xee, 0x40, 0x0, 0x0, 0x0, 0xdf, - 0xff, 0x99, 0xff, 0xfd, 0x0, 0x0, 0xff, 0xff, - 0x99, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x90, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xd, 0xff, 0xff, - 0xd, 0x20, 0xff, 0xff, 0xf, 0xff, 0xff, 0xf, - 0xe2, 0xff, 0xff, 0xf, 0xff, 0xff, 0xf, 0xfd, - 0xff, 0xff, 0xf, 0xff, 0xff, 0x20, 0x0, 0xff, - 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xf, 0xff, - 0xff, 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xff, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0x0, 0x0, 0xd, 0xff, 0xff, 0xff, 0xfd, - - /* U+F0F3 "" */ - 0x0, 0x0, 0x0, 0xcc, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0x30, 0x0, 0x0, 0x0, 0x1, - 0xbf, 0xff, 0xfc, 0x20, 0x0, 0x0, 0x1e, 0xff, - 0xff, 0xff, 0xe1, 0x0, 0x0, 0x9f, 0xff, 0xff, - 0xff, 0xf8, 0x0, 0x0, 0xef, 0xff, 0xff, 0xff, - 0xfd, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, - 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x1e, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe1, 0xcf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0xcf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xe, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x4, 0xee, 0x40, 0x0, 0x0, - - /* U+F11C "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x0, 0xf0, 0xf, 0x0, 0xf0, - 0xf, 0x0, 0xff, 0xff, 0x0, 0xf0, 0xf, 0x0, - 0xf0, 0xf, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x8, - 0x80, 0x88, 0x8, 0x80, 0x8f, 0xff, 0xff, 0xf8, - 0x8, 0x80, 0x88, 0x8, 0x80, 0x8f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x0, 0xf0, 0x0, 0x0, 0x0, 0xf, 0x0, - 0xff, 0xff, 0x0, 0xf0, 0x0, 0x0, 0x0, 0xf, - 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, - - /* U+F124 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xaf, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, - 0xcf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x6, - 0xdf, 0xff, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x17, - 0xef, 0xff, 0xff, 0xff, 0x30, 0x0, 0x0, 0x18, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x2a, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x60, - 0x0, 0x8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xff, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xf2, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x8f, 0x80, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, - - /* U+F15B "" */ - 0xdf, 0xff, 0xff, 0xf0, 0xd2, 0x0, 0xff, 0xff, - 0xff, 0xf0, 0xfe, 0x20, 0xff, 0xff, 0xff, 0xf0, - 0xff, 0xe2, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xfd, - 0xff, 0xff, 0xff, 0xf2, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xfd, - - /* U+F1EB "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x4, 0x9c, 0xef, 0xfe, - 0xc9, 0x40, 0x0, 0x0, 0x0, 0x7, 0xef, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x70, 0x0, 0x4, 0xdf, - 0xff, 0xfc, 0xa8, 0x8a, 0xcf, 0xff, 0xfd, 0x40, - 0x6f, 0xff, 0xd5, 0x0, 0x0, 0x0, 0x0, 0x5d, - 0xff, 0xf6, 0xcf, 0xf6, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x6f, 0xfc, 0x1a, 0x30, 0x0, 0x5a, - 0xdf, 0xfd, 0xa5, 0x0, 0x3, 0xa1, 0x0, 0x0, - 0x4d, 0xff, 0xff, 0xff, 0xff, 0xd4, 0x0, 0x0, - 0x0, 0x5, 0xff, 0xfe, 0xa8, 0x8a, 0xef, 0xff, - 0x50, 0x0, 0x0, 0x1, 0xdf, 0x70, 0x0, 0x0, - 0x7, 0xfd, 0x10, 0x0, 0x0, 0x0, 0x12, 0x0, - 0x0, 0x0, 0x0, 0x21, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x4e, 0xe4, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xef, 0xfe, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xfe, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x4e, 0xe4, 0x0, 0x0, 0x0, 0x0, - - /* U+F240 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, - 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+F241 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xf, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xf, 0xff, - 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, - 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x0, 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+F242 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xf, - 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xf, 0xff, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xf, 0xff, 0xff, - 0xff, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+F243 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0xf, - 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xf, 0xff, 0xf0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0xf, 0xff, 0xf0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+F244 "" */ - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, - 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, - - /* U+F287 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, - 0xfd, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x1, 0xcf, 0xff, 0xf5, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xb9, 0x29, 0xfe, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x10, 0x2, - 0x0, 0x0, 0x0, 0x0, 0x3, 0xdf, 0x80, 0xa, - 0x90, 0x0, 0x0, 0x0, 0x3, 0x70, 0x0, 0xdf, - 0xff, 0x77, 0xf7, 0x55, 0x55, 0x55, 0x55, 0x8f, - 0xd3, 0xf, 0xff, 0xfd, 0xcc, 0xdf, 0xdc, 0xcc, - 0xcc, 0xcd, 0xff, 0xb0, 0x8f, 0xfe, 0x10, 0x0, - 0xaa, 0x0, 0x0, 0x0, 0x4d, 0x40, 0x0, 0x46, - 0x10, 0x0, 0x1, 0xf2, 0x2, 0x33, 0x10, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xb1, 0xcf, - 0xf9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xa, 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xf9, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x22, - 0x0, 0x0, 0x0, - - /* U+F293 "" */ - 0x0, 0x18, 0xdf, 0xfd, 0x92, 0x0, 0x2, 0xef, - 0xfb, 0xef, 0xff, 0x30, 0xd, 0xff, 0xfa, 0x2e, - 0xff, 0xe0, 0x4f, 0xff, 0xfa, 0x3, 0xff, 0xf5, - 0x9f, 0xfa, 0xfa, 0x35, 0x4f, 0xfa, 0xcf, 0xc0, - 0x8a, 0x3d, 0xb, 0xfd, 0xef, 0xfb, 0x3, 0x12, - 0x8f, 0xfe, 0xff, 0xff, 0xb0, 0x6, 0xff, 0xff, - 0xff, 0xff, 0xd1, 0x8, 0xff, 0xff, 0xef, 0xfd, - 0x11, 0x10, 0x9f, 0xff, 0xdf, 0xd1, 0x59, 0x3b, - 0xb, 0xfd, 0xaf, 0xd7, 0xfa, 0x38, 0x1d, 0xfb, - 0x5f, 0xff, 0xfa, 0x1, 0xdf, 0xf7, 0xd, 0xff, - 0xfa, 0x1d, 0xff, 0xf1, 0x3, 0xef, 0xfc, 0xdf, - 0xff, 0x50, 0x0, 0x18, 0xdf, 0xfe, 0xa3, 0x0, - - /* U+F2ED "" */ - 0x0, 0x0, 0x7f, 0xff, 0xf7, 0x0, 0x0, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xef, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf0, 0xf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0xf, 0xf9, 0x9f, 0x99, 0xf9, 0x9f, - 0xf0, 0xf, 0xf8, 0x8f, 0x88, 0xf8, 0x8f, 0xf0, - 0xf, 0xf8, 0x8f, 0x88, 0xf8, 0x8f, 0xf0, 0xf, - 0xf8, 0x8f, 0x88, 0xf8, 0x8f, 0xf0, 0xf, 0xf8, - 0x8f, 0x88, 0xf8, 0x8f, 0xf0, 0xf, 0xf8, 0x8f, - 0x88, 0xf8, 0x8f, 0xf0, 0xf, 0xf8, 0x8f, 0x88, - 0xf8, 0x8f, 0xf0, 0xf, 0xf9, 0x9f, 0x99, 0xf9, - 0x9f, 0xf0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - - /* U+F304 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xa0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xb0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xff, - 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x8a, 0x1d, - 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xfa, - 0x1d, 0xff, 0x70, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xfa, 0x1d, 0x80, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x6f, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0xb, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0xdf, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0xe, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xde, 0xdb, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - - /* U+F55A "" */ - 0x0, 0x0, 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe4, 0x0, 0x1, 0xdf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x0, 0x1d, 0xff, 0xff, - 0xfa, 0xef, 0xfe, 0xaf, 0xff, 0xff, 0x1, 0xdf, - 0xff, 0xff, 0xa0, 0x2e, 0xe2, 0xa, 0xff, 0xff, - 0x1d, 0xff, 0xff, 0xff, 0xe2, 0x2, 0x20, 0x2e, - 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xfe, 0x20, - 0x2, 0xef, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, - 0xfe, 0x20, 0x2, 0xef, 0xff, 0xff, 0x1d, 0xff, - 0xff, 0xff, 0xe2, 0x2, 0x20, 0x2e, 0xff, 0xff, - 0x1, 0xdf, 0xff, 0xff, 0xa0, 0x2e, 0xe2, 0xa, - 0xff, 0xff, 0x0, 0x1d, 0xff, 0xff, 0xfa, 0xef, - 0xfe, 0xaf, 0xff, 0xff, 0x0, 0x1, 0xdf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, - 0x1b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, - - /* U+F7C2 "" */ - 0x0, 0x8, 0xff, 0xff, 0xff, 0xe4, 0x0, 0x8f, - 0xff, 0xff, 0xff, 0xfe, 0x8, 0xf8, 0xf, 0xb, - 0x40, 0xff, 0x8f, 0xf8, 0xf, 0xb, 0x40, 0xff, - 0xff, 0xf8, 0xf, 0xb, 0x40, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x4e, 0xff, 0xff, 0xff, 0xff, 0xe4, - - /* U+F8A2 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xe0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x2, - 0xef, 0x10, 0x0, 0xbf, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xf1, 0x0, 0xcf, 0xf1, 0x0, 0x0, 0x0, - 0x7, 0xff, 0x11, 0xcf, 0xff, 0x77, 0x77, 0x77, - 0x77, 0xbf, 0xf1, 0xcf, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x17, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x7, 0xff, 0xf1, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xa0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + 0x0, 0x0, 0x3, 0xd0, 0x93, 0x9d, 0x30, 0xc0, + 0xf8, 0x0, 0x0, 0x0 }; @@ -1788,187 +552,113 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, {.bitmap_index = 0, .adv_w = 69, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, {.bitmap_index = 0, .adv_w = 69, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 18, .adv_w = 100, .box_w = 5, .box_h = 5, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 31, .adv_w = 180, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 97, .adv_w = 159, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 177, .adv_w = 216, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 255, .adv_w = 176, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 327, .adv_w = 54, .box_w = 2, .box_h = 5, .ofs_x = 1, .ofs_y = 7}, - {.bitmap_index = 332, .adv_w = 86, .box_w = 4, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 362, .adv_w = 87, .box_w = 4, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 392, .adv_w = 102, .box_w = 7, .box_h = 7, .ofs_x = 0, .ofs_y = 5}, - {.bitmap_index = 417, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 449, .adv_w = 58, .box_w = 3, .box_h = 5, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 457, .adv_w = 98, .box_w = 6, .box_h = 3, .ofs_x = 0, .ofs_y = 3}, - {.bitmap_index = 466, .adv_w = 58, .box_w = 3, .box_h = 3, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 471, .adv_w = 90, .box_w = 8, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 535, .adv_w = 171, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 595, .adv_w = 95, .box_w = 5, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 625, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 679, .adv_w = 146, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 733, .adv_w = 171, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 799, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 853, .adv_w = 158, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 913, .adv_w = 153, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 967, .adv_w = 165, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1027, .adv_w = 158, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1087, .adv_w = 58, .box_w = 3, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1101, .adv_w = 58, .box_w = 3, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 1119, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 1151, .adv_w = 149, .box_w = 8, .box_h = 6, .ofs_x = 1, .ofs_y = 3}, - {.bitmap_index = 1175, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 1207, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1261, .adv_w = 265, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 1381, .adv_w = 187, .box_w = 13, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 1459, .adv_w = 194, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1525, .adv_w = 185, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1591, .adv_w = 211, .box_w = 12, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1663, .adv_w = 172, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1717, .adv_w = 163, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1771, .adv_w = 198, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 1843, .adv_w = 208, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1909, .adv_w = 79, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 1927, .adv_w = 131, .box_w = 8, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 1975, .adv_w = 184, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2041, .adv_w = 152, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2095, .adv_w = 244, .box_w = 13, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2173, .adv_w = 208, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2239, .adv_w = 215, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2317, .adv_w = 185, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2377, .adv_w = 215, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 2482, .adv_w = 186, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2542, .adv_w = 159, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2602, .adv_w = 150, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2662, .adv_w = 202, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 2728, .adv_w = 182, .box_w = 13, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 2806, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2914, .adv_w = 172, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 2980, .adv_w = 166, .box_w = 12, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 3052, .adv_w = 168, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3118, .adv_w = 85, .box_w = 5, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 3156, .adv_w = 90, .box_w = 8, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 3220, .adv_w = 85, .box_w = 4, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3250, .adv_w = 149, .box_w = 8, .box_h = 7, .ofs_x = 1, .ofs_y = 2}, - {.bitmap_index = 3278, .adv_w = 128, .box_w = 8, .box_h = 2, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 3286, .adv_w = 154, .box_w = 5, .box_h = 2, .ofs_x = 1, .ofs_y = 10}, - {.bitmap_index = 3291, .adv_w = 153, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3332, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3392, .adv_w = 146, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3433, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3493, .adv_w = 157, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3538, .adv_w = 90, .box_w = 7, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3580, .adv_w = 177, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 3640, .adv_w = 174, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3694, .adv_w = 71, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3712, .adv_w = 73, .box_w = 6, .box_h = 15, .ofs_x = -2, .ofs_y = -3}, - {.bitmap_index = 3757, .adv_w = 158, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3811, .adv_w = 71, .box_w = 2, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3823, .adv_w = 271, .box_w = 15, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3891, .adv_w = 174, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 3932, .adv_w = 163, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 3977, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 4037, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 4097, .adv_w = 105, .box_w = 6, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 4124, .adv_w = 128, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4160, .adv_w = 106, .box_w = 7, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4199, .adv_w = 173, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, - {.bitmap_index = 4240, .adv_w = 143, .box_w = 10, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, - {.bitmap_index = 4285, .adv_w = 230, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4353, .adv_w = 141, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4394, .adv_w = 143, .box_w = 10, .box_h = 12, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 4454, .adv_w = 133, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4490, .adv_w = 90, .box_w = 6, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 4535, .adv_w = 77, .box_w = 3, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, - {.bitmap_index = 4558, .adv_w = 90, .box_w = 5, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 4596, .adv_w = 149, .box_w = 9, .box_h = 5, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 4619, .adv_w = 107, .box_w = 6, .box_h = 6, .ofs_x = 0, .ofs_y = 6}, - {.bitmap_index = 4637, .adv_w = 80, .box_w = 3, .box_h = 4, .ofs_x = 1, .ofs_y = 3}, - {.bitmap_index = 4643, .adv_w = 256, .box_w = 16, .box_h = 17, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 4779, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 4875, .adv_w = 256, .box_w = 16, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 4987, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 5083, .adv_w = 176, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 5149, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 5277, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 5405, .adv_w = 288, .box_w = 18, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 5531, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 5659, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 5767, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 5895, .adv_w = 128, .box_w = 8, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 5951, .adv_w = 192, .box_w = 12, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 6035, .adv_w = 288, .box_w = 18, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 6179, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 6275, .adv_w = 176, .box_w = 11, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 6363, .adv_w = 224, .box_w = 10, .box_h = 16, .ofs_x = 2, .ofs_y = -2}, - {.bitmap_index = 6443, .adv_w = 224, .box_w = 14, .box_h = 18, .ofs_x = 0, .ofs_y = -3}, - {.bitmap_index = 6569, .adv_w = 224, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 6674, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 6772, .adv_w = 224, .box_w = 10, .box_h = 16, .ofs_x = 2, .ofs_y = -2}, - {.bitmap_index = 6852, .adv_w = 224, .box_w = 16, .box_h = 14, .ofs_x = -1, .ofs_y = -1}, - {.bitmap_index = 6964, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 7034, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 7104, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 7202, .adv_w = 224, .box_w = 14, .box_h = 4, .ofs_x = 0, .ofs_y = 4}, - {.bitmap_index = 7230, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 7338, .adv_w = 320, .box_w = 20, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 7498, .adv_w = 288, .box_w = 20, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 7658, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 7786, .adv_w = 224, .box_w = 14, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 7856, .adv_w = 224, .box_w = 14, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 7926, .adv_w = 320, .box_w = 20, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 8066, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 8162, .adv_w = 256, .box_w = 16, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 8290, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 8435, .adv_w = 224, .box_w = 15, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 8540, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 8652, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 8750, .adv_w = 224, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 8848, .adv_w = 256, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 8944, .adv_w = 160, .box_w = 12, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, - {.bitmap_index = 9040, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 9152, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 9264, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 9372, .adv_w = 256, .box_w = 18, .box_h = 18, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 9534, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 9630, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 9780, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 9880, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 9980, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 10080, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 10180, .adv_w = 320, .box_w = 20, .box_h = 10, .ofs_x = 0, .ofs_y = 1}, - {.bitmap_index = 10280, .adv_w = 320, .box_w = 21, .box_h = 14, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 10427, .adv_w = 224, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = -2}, - {.bitmap_index = 10523, .adv_w = 224, .box_w = 14, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 10635, .adv_w = 256, .box_w = 17, .box_h = 17, .ofs_x = -1, .ofs_y = -3}, - {.bitmap_index = 10780, .adv_w = 320, .box_w = 20, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, - {.bitmap_index = 10900, .adv_w = 192, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, - {.bitmap_index = 10996, .adv_w = 258, .box_w = 17, .box_h = 11, .ofs_x = 0, .ofs_y = 1} + {.bitmap_index = 9, .adv_w = 100, .box_w = 5, .box_h = 5, .ofs_x = 1, .ofs_y = 7}, + {.bitmap_index = 16, .adv_w = 180, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 49, .adv_w = 159, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 89, .adv_w = 216, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 128, .adv_w = 176, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 164, .adv_w = 54, .box_w = 2, .box_h = 5, .ofs_x = 1, .ofs_y = 7}, + {.bitmap_index = 167, .adv_w = 86, .box_w = 4, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 182, .adv_w = 87, .box_w = 4, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 197, .adv_w = 102, .box_w = 7, .box_h = 7, .ofs_x = 0, .ofs_y = 5}, + {.bitmap_index = 210, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 226, .adv_w = 58, .box_w = 3, .box_h = 5, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 230, .adv_w = 98, .box_w = 6, .box_h = 3, .ofs_x = 0, .ofs_y = 3}, + {.bitmap_index = 235, .adv_w = 58, .box_w = 3, .box_h = 3, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 238, .adv_w = 90, .box_w = 8, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 270, .adv_w = 171, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 300, .adv_w = 95, .box_w = 5, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 315, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 342, .adv_w = 146, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 369, .adv_w = 171, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 402, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 429, .adv_w = 158, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 459, .adv_w = 153, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 486, .adv_w = 165, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 516, .adv_w = 158, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 546, .adv_w = 58, .box_w = 3, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 553, .adv_w = 58, .box_w = 3, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 562, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 578, .adv_w = 149, .box_w = 8, .box_h = 6, .ofs_x = 1, .ofs_y = 3}, + {.bitmap_index = 590, .adv_w = 149, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 606, .adv_w = 147, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 633, .adv_w = 265, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 693, .adv_w = 187, .box_w = 13, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 732, .adv_w = 194, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 765, .adv_w = 185, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 798, .adv_w = 211, .box_w = 12, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 834, .adv_w = 172, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 861, .adv_w = 163, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 888, .adv_w = 198, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 924, .adv_w = 208, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 957, .adv_w = 79, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 966, .adv_w = 131, .box_w = 8, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 990, .adv_w = 184, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1023, .adv_w = 152, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1050, .adv_w = 244, .box_w = 13, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1089, .adv_w = 208, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1122, .adv_w = 215, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1161, .adv_w = 185, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1191, .adv_w = 215, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1244, .adv_w = 186, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1274, .adv_w = 159, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1304, .adv_w = 150, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1334, .adv_w = 202, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1367, .adv_w = 182, .box_w = 13, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 1406, .adv_w = 288, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1460, .adv_w = 172, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1493, .adv_w = 166, .box_w = 12, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 1529, .adv_w = 168, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1562, .adv_w = 85, .box_w = 5, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 1581, .adv_w = 90, .box_w = 8, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 1613, .adv_w = 85, .box_w = 4, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1628, .adv_w = 149, .box_w = 8, .box_h = 7, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 1642, .adv_w = 128, .box_w = 8, .box_h = 2, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1646, .adv_w = 154, .box_w = 5, .box_h = 2, .ofs_x = 1, .ofs_y = 10}, + {.bitmap_index = 1649, .adv_w = 153, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1670, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1700, .adv_w = 146, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1721, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1751, .adv_w = 157, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1774, .adv_w = 90, .box_w = 7, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1795, .adv_w = 177, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1825, .adv_w = 174, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1852, .adv_w = 71, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1861, .adv_w = 73, .box_w = 6, .box_h = 15, .ofs_x = -2, .ofs_y = -3}, + {.bitmap_index = 1884, .adv_w = 158, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1911, .adv_w = 71, .box_w = 2, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1917, .adv_w = 271, .box_w = 15, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1951, .adv_w = 174, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1972, .adv_w = 163, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1995, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 2025, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2055, .adv_w = 105, .box_w = 6, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2069, .adv_w = 128, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2087, .adv_w = 106, .box_w = 7, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2107, .adv_w = 173, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2128, .adv_w = 143, .box_w = 10, .box_h = 9, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 2151, .adv_w = 230, .box_w = 15, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2185, .adv_w = 141, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2206, .adv_w = 143, .box_w = 10, .box_h = 12, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 2236, .adv_w = 133, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2254, .adv_w = 90, .box_w = 6, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2277, .adv_w = 77, .box_w = 3, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 2289, .adv_w = 90, .box_w = 5, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2308, .adv_w = 149, .box_w = 9, .box_h = 5, .ofs_x = 0, .ofs_y = 4} }; /*--------------------- * CHARACTER MAPPING *--------------------*/ -static const uint16_t unicode_list_1[] = { - 0x0, 0x1f72, 0xef51, 0xef58, 0xef5b, 0xef5c, 0xef5d, 0xef61, - 0xef63, 0xef65, 0xef69, 0xef6c, 0xef71, 0xef76, 0xef77, 0xef78, - 0xef8e, 0xef93, 0xef98, 0xef9b, 0xef9c, 0xef9d, 0xefa1, 0xefa2, - 0xefa3, 0xefa4, 0xefb7, 0xefb8, 0xefbe, 0xefc0, 0xefc1, 0xefc4, - 0xefc7, 0xefc8, 0xefc9, 0xefcb, 0xefe3, 0xefe5, 0xf014, 0xf015, - 0xf017, 0xf019, 0xf030, 0xf037, 0xf03a, 0xf043, 0xf06c, 0xf074, - 0xf0ab, 0xf13b, 0xf190, 0xf191, 0xf192, 0xf193, 0xf194, 0xf1d7, - 0xf1e3, 0xf23d, 0xf254, 0xf4aa, 0xf712, 0xf7f2 -}; + /*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ { .range_start = 32, .range_length = 95, .glyph_id_start = 1, .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY - }, - { - .range_start = 176, .range_length = 63475, .glyph_id_start = 96, - .unicode_list = unicode_list_1, .glyph_id_ofs_list = NULL, .list_length = 62, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY } }; @@ -1978,7 +668,8 @@ static const lv_font_fmt_txt_cmap_t cmaps[] = { /*Map glyph_ids to kern left classes*/ -static const uint8_t kern_left_class_mapping[] = { +static const uint8_t kern_left_class_mapping[] = +{ 0, 0, 1, 2, 0, 3, 4, 5, 2, 6, 7, 8, 9, 10, 9, 10, 11, 12, 0, 13, 14, 15, 16, 17, @@ -1990,19 +681,12 @@ static const uint8_t kern_left_class_mapping[] = { 44, 0, 45, 46, 47, 48, 49, 50, 51, 45, 52, 52, 53, 48, 45, 45, 46, 46, 54, 55, 56, 57, 51, 58, - 58, 59, 58, 60, 41, 0, 0, 9, - 61, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 + 58, 59, 58, 60, 41, 0, 0, 9 }; /*Map glyph_ids to kern right classes*/ -static const uint8_t kern_right_class_mapping[] = { +static const uint8_t kern_right_class_mapping[] = +{ 0, 0, 1, 2, 0, 3, 4, 5, 2, 6, 7, 8, 9, 10, 9, 10, 11, 12, 13, 14, 15, 16, 17, 12, @@ -2011,58 +695,51 @@ static const uint8_t kern_right_class_mapping[] = { 23, 25, 25, 26, 25, 25, 25, 25, 23, 25, 23, 25, 3, 27, 28, 29, 29, 30, 31, 32, 33, 34, 35, 0, - 36, 0, 37, 38, 39, 39, 39, 0, - 39, 38, 40, 41, 38, 38, 42, 42, - 39, 42, 39, 42, 43, 44, 45, 46, - 46, 47, 46, 48, 0, 0, 35, 9, - 49, 9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 + 36, 0, 37, 38, 39, 39, 39, 40, + 39, 38, 41, 42, 38, 38, 43, 43, + 39, 43, 39, 43, 44, 45, 46, 47, + 47, 48, 47, 49, 0, 0, 35, 9 }; /*Kern values between classes*/ -static const int8_t kern_class_values[] = { - 0, 1, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 3, 0, 0, 0, +static const int8_t kern_class_values[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 12, 0, 7, -6, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 7, -6, 0, 0, 0, 0, -14, -15, 2, 12, 6, 4, - -10, 2, 13, 1, 11, 3, 8, 0, + -10, 2, 13, 0, 11, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5, 0, -8, 0, 0, 0, 0, + 0, 0, 0, -8, 0, 0, 0, 0, 0, -5, 4, 5, 0, 0, -3, 0, -2, 3, 0, -3, 0, -3, -1, -5, 0, 0, 0, 0, -3, 0, 0, -3, -4, 0, 0, -3, 0, -5, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -3, - -3, 0, -4, 0, -7, 0, -31, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + -3, -3, 0, 0, -7, 0, -31, 0, 0, -5, 0, 5, 8, 0, 0, -5, 3, 3, 8, 5, -4, 5, 0, 0, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -7, -3, -13, 0, -10, + 0, 0, 0, 0, -3, -13, 0, -10, -2, 0, 0, 0, 0, 1, 10, 0, - -8, -2, -1, 1, 0, -4, 0, 0, + -8, -2, 0, 0, 0, -4, 0, 0, -2, -19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -20, -2, 10, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -10, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 3, 0, 0, -5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 2, - 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2071,79 +748,79 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 3, 8, -3, 0, 0, 5, -3, - -8, -35, 2, 7, 5, 1, -3, 0, + -8, -35, 2, 7, 5, 0, -3, 0, 9, 0, 8, 0, 8, 0, -24, 0, -3, 8, 0, 8, -3, 5, 3, 0, - 0, 1, -3, 0, 0, -4, 20, 0, - 20, 0, 8, 0, 11, 3, 4, 8, + 0, 0, -3, 0, 0, -4, 0, 0, + 0, 20, 0, 8, 0, 11, 3, 4, 0, 0, 0, -9, 0, 0, 0, 0, - 1, -2, 0, 2, -5, -3, -5, 2, + 0, -2, 0, 2, -5, -3, -5, 2, 0, -3, 0, 0, 0, -10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, -14, 0, -16, 0, 0, 0, + 0, 0, -14, 0, -16, 0, 0, 0, 0, -2, 0, 25, -3, -3, 3, 3, -2, 0, -3, 3, 0, 0, -14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -25, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -16, 0, 15, 0, 0, -9, 0, + 0, 0, 0, 15, 0, 0, -9, 0, 8, 0, -17, -25, -17, -5, 8, 0, 0, -17, 0, 3, -6, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 8, -31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 12, 0, 2, 0, 0, 0, - 0, 0, 2, 2, -3, -5, 0, -1, - -1, -3, 0, 0, -2, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 2, 2, -3, -5, 0, 0, + 0, -3, 0, 0, -2, 0, 0, 0, -5, 0, -2, 0, -6, -5, 0, -6, -8, -8, -5, 0, -5, 0, -5, 0, - 0, 0, 0, -2, 0, 0, 3, 0, - 2, -3, 0, 1, 0, 0, 0, 3, - -2, 0, 0, 0, -2, 3, 3, -1, - 0, 0, 0, -5, 0, -1, 0, 0, - 0, 0, 0, 1, 0, 3, -2, 0, + 0, 0, 0, 0, -2, 0, 0, 3, + 0, 2, -3, 0, 0, 0, 0, 3, + -2, 0, 0, 0, -2, 3, 3, 0, + 0, 0, 0, -5, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, -2, 0, -3, 0, -4, 0, 0, -2, 0, 8, 0, 0, -3, 0, 0, 0, 0, 0, - -1, 1, -2, -2, 0, 0, -3, 0, + 0, 0, 0, -2, -2, 0, -3, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, -3, -3, 0, - 0, 0, 0, 0, 1, 0, 0, -2, + 0, 0, 0, 0, 0, 0, 0, -2, 0, -3, -3, -3, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -2, 0, 0, - 0, 0, -2, -3, 0, -4, 0, -8, + 0, 0, 0, 0, 0, 0, -2, 0, + 0, 0, 0, -2, -3, 0, 0, -8, -2, -8, 5, 0, 0, -5, 3, 5, - 7, 0, -6, -1, -3, 0, -1, -12, - 3, -2, 2, -14, 3, 0, 0, 1, + 7, 0, -6, 0, -3, 0, 0, -12, + 3, -2, 2, -14, 3, 0, 0, 0, -13, 0, -14, -2, -22, -2, 0, -13, 0, 5, 7, 0, 3, 0, 0, 0, - 0, 1, 0, -5, -3, 0, -8, 0, + 0, 0, 0, 0, -5, -3, 0, 0, 0, 0, -3, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1, -1, 0, -1, -3, 0, 0, 0, 0, 0, 0, 0, -3, -3, 0, -2, -3, -2, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -2, -2, 0, -3, + 0, 0, 0, 0, 0, -2, -2, 0, 0, -2, 0, -5, 3, 0, 0, -3, 1, 3, 3, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 2, 0, 0, -3, 0, -3, -2, -3, 0, 0, 0, 0, 0, 0, 0, 2, 0, - -2, 0, 0, 0, 0, -3, -4, 0, - -5, 0, 8, -2, 1, -8, 0, 0, + 0, -2, 0, 0, 0, 0, -3, -4, + 0, 0, 8, -2, 0, -8, 0, 0, 7, -13, -13, -11, -5, 3, 0, -2, -17, -5, 0, -5, 0, -5, 4, -5, - -16, 0, -7, 0, 0, 1, -1, 2, - -2, 0, 3, 0, -8, -10, 0, -13, - -6, -5, -6, -8, -3, -7, -1, -5, - -7, 2, 0, 1, 0, -3, 0, 0, + -16, 0, -7, 0, 0, 1, 0, 2, + -2, 0, 3, -1, -8, -10, 0, -13, + 0, 0, -5, -6, -8, -3, -7, -1, + -5, -7, 0, 0, 0, -3, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, - 0, -1, 0, -1, -3, 0, -4, -6, - -6, -1, 0, -8, 0, 0, 0, 0, - 0, 0, -2, 0, 0, 0, 0, 1, - -2, 0, 0, 0, 3, 0, 0, 0, + 0, -1, 0, 0, -3, 0, -4, -6, + -6, 0, 0, -8, 0, 0, 0, 0, + 0, 0, 0, -2, 0, 0, 0, 0, + 1, -2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0, @@ -2155,44 +832,44 @@ static const int8_t kern_class_values[] = { 0, -7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, -5, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, -5, 0, + 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 0, 3, 0, 2, -5, -5, 0, -3, -3, -3, 0, 0, 0, 0, 0, 0, -8, 0, -3, 0, -4, -3, 0, -6, -6, -8, -2, 0, -5, 0, - -8, 0, 0, 0, 0, 20, 0, 0, - 1, 0, 0, -3, 0, 3, 0, -11, + -8, 0, 0, 0, 0, 0, 20, 0, + 0, 1, 0, 0, -3, 0, 0, -11, 0, 0, 0, 0, 0, -24, -5, 8, 8, -2, -11, 0, 3, -4, 0, -13, -1, -3, 3, -18, -3, 3, 0, 4, -9, -4, -9, -8, -11, 0, 0, -15, 0, 15, 0, 0, -1, 0, 0, 0, - -1, -1, -3, -7, -8, -1, -24, 0, + 0, -1, -1, -3, -7, -8, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, -1, -3, -4, 0, 0, -5, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, -5, 0, 0, 5, - -1, 3, 0, -6, 3, -2, -1, -7, + 0, 0, 0, 0, -5, 0, 0, 5, + 0, 3, 0, -6, 3, -2, 0, -7, -3, 0, -3, -3, -2, 0, -4, -4, - 0, 0, -2, -1, -2, -4, -3, 0, + 0, 0, -2, 0, -2, -4, -3, 0, 0, -3, 0, 3, -2, 0, -6, 0, - 0, 0, -5, 0, -4, 0, -4, -4, - 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -5, 0, -4, 0, -4, + -4, 0, 0, 0, 0, 0, 0, 0, 0, -5, 3, 0, -4, 0, -2, -3, - -8, -2, -2, -2, -1, -2, -3, -1, + -8, -2, -2, -2, 0, -2, -3, 0, 0, 0, 0, 0, 0, -3, -2, -2, 0, 0, 0, 0, 3, -2, 0, -2, - 0, 0, 0, -2, -3, -2, -2, -3, - -2, 0, 2, 10, -1, 0, -7, 0, + 0, 0, 0, 0, -2, -3, -2, -2, + -3, -2, 2, 10, 0, 0, -7, 0, -2, 5, 0, -3, -11, -3, 4, 0, 0, -12, -4, 3, -4, 2, 0, -2, -2, -8, 0, -4, 1, 0, 0, -4, 0, 0, 0, 3, 3, -5, -5, 0, - -4, -3, -4, -3, -3, 0, -4, 1, - -5, -4, 8, 0, 0, 0, 0, 0, + -4, 0, 0, -4, -3, -3, 0, -4, + 1, -5, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2209,89 +886,89 @@ static const int8_t kern_class_values[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, -3, 0, 0, -3, -3, 0, 0, 0, 0, - -3, 0, 0, 0, 0, -1, 0, 0, - 0, 0, 0, -2, 0, 0, 0, 0, + -3, 0, 0, 0, 0, 0, -1, 0, + 0, 0, 0, 0, -2, 0, 0, 0, -4, 0, -5, 0, 0, 0, -8, 0, - 2, -6, 5, 1, -2, -12, 0, 0, + 2, -6, 5, 0, -2, -12, 0, 0, -6, -3, 0, -10, -6, -7, 0, 0, -11, -3, -10, -10, -12, 0, -7, 0, - 2, 17, -3, 0, -6, -3, -1, -3, - -4, -7, -5, -9, -10, -6, -3, 0, - 0, -2, 0, 1, 0, 0, -18, -2, - 8, 6, -6, -9, 0, 1, -8, 0, - -13, -2, -3, 5, -24, -3, 1, 0, + 2, 17, -3, 0, -6, 0, 0, 0, + -3, -4, -7, -5, -9, -10, -6, 0, + 0, -2, 0, 0, 0, 0, -18, -2, + 8, 6, -6, -9, 0, 0, -8, 0, + -13, -2, -3, 5, -24, -3, 0, 0, 0, -17, -3, -13, -3, -19, 0, 0, - -18, 0, 15, 1, 0, -2, 0, 0, - 0, 0, -1, -2, -10, -2, 0, -17, + -18, 0, 15, 0, 0, -2, 0, 0, + 0, 0, 0, -1, -2, -10, -2, 0, 0, 0, 0, 0, -8, 0, -2, 0, - -1, -7, -12, 0, 0, -1, -4, -8, + 0, -7, -12, 0, 0, -1, -4, -8, -3, 0, -2, 0, 0, 0, 0, -12, -3, -8, -8, -2, -4, -6, -3, -4, - 0, -5, -2, -8, -4, 0, -3, -5, - -3, -5, 0, 1, 0, -2, -8, 0, - 5, 0, -5, 0, 0, 0, 0, 3, + 0, -5, -2, -8, -4, 0, -3, 0, + 0, -3, -5, 0, 1, 0, -2, -8, + 0, 0, -5, 0, 0, 0, 0, 3, 0, 2, -5, 10, 0, -3, -3, -3, 0, 0, 0, 0, 0, 0, -8, 0, -3, 0, -4, -3, 0, -6, -6, -8, -2, 0, -5, 2, 10, 0, 0, 0, - 0, 20, 0, 0, 1, 0, 0, -3, - 0, 3, 0, 0, 0, 0, 0, 0, - 0, 0, -1, 0, 0, 0, 0, 0, + 0, 0, 20, 0, 0, 1, 0, 0, + -3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -2, -5, 0, 0, 0, 0, 0, -1, 0, 0, 0, -3, -3, 0, 0, -5, -3, 0, 0, -5, 0, 4, -1, 0, - 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 4, 5, 2, -2, 0, -8, + 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 5, 2, -2, 0, -8, -4, 0, 8, -8, -8, -5, -5, 10, 5, 3, -22, -2, 5, -3, 0, -3, 3, -3, -9, 0, -3, 3, -3, -2, -8, -2, 0, 0, 8, 5, 0, -7, - 0, -14, -3, 7, -3, -10, 1, -3, - -8, -8, -3, 10, 3, 0, -4, 0, + 0, -14, 0, 0, 7, -3, -10, 0, + -3, -8, -8, -3, 3, 0, -4, 0, -7, 0, 2, 8, -6, -9, -10, -6, - 8, 0, 1, -19, -2, 3, -4, -2, + 8, 0, 0, -19, -2, 3, -4, -2, -6, 0, -6, -9, -4, -4, -2, 0, 0, -6, -5, -3, 0, 8, 6, -3, - -14, 0, -14, -4, 0, -9, -15, -1, - -8, -4, -8, -7, 7, 0, 0, -3, + -14, 0, -14, 0, -4, -5, -9, -15, + 0, -8, -4, -8, -7, 0, 0, -3, 0, -5, -2, 0, -3, -5, 0, 4, -8, 3, 0, 0, -14, 0, -3, -6, -4, -2, -8, -6, -8, -6, 0, -8, - -3, -6, -5, -8, -3, 0, 0, 1, - 12, -4, 0, -8, -3, 0, -3, -5, - -6, -7, -7, -10, -3, -5, 5, 0, + -3, -6, -5, -8, -3, 0, 0, 0, + 12, -4, 0, -8, 0, 0, 0, -3, + -5, -6, -7, -7, -10, -3, 5, 0, -4, 0, -13, -3, 2, 5, -8, -9, -5, -8, 8, -3, 1, -24, -5, 5, -6, -4, -9, 0, -8, -11, -3, -3, - -2, -3, -5, -8, -1, 0, 0, 8, - 7, -2, -17, 0, -15, -6, 6, -10, - -17, -5, -9, -11, -13, -8, 5, 0, + -2, -3, -5, -8, 0, 0, 0, 8, + 7, -2, -17, 0, -15, 0, -4, 6, + -10, -17, -5, -9, -11, -13, -8, 0, 0, 0, 0, -3, 0, 0, 3, -3, - 5, 2, -5, 5, 0, 0, -8, -1, - 0, -1, 0, 1, 1, -2, 0, 0, + 5, 2, -5, 5, 0, 0, -8, 0, + 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, - 0, 2, 8, 1, 0, -3, 0, 0, - 0, 0, -2, -2, -3, 0, 0, 0, - 1, 2, 0, 0, 0, 0, 2, 0, - -2, 0, 10, 0, 5, 1, 1, -3, + 0, 2, 8, 0, 0, -3, 0, 0, + 0, 0, 0, -2, -2, -3, 0, 0, + 0, 2, 0, 0, 0, 0, 2, 0, + -2, 0, 10, 0, 5, 0, 0, -3, 0, 5, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15, 0, -3, 4, 0, 8, 0, 0, 25, 3, -5, -5, 3, 3, - -2, 1, -13, 0, 0, 12, -15, 0, + -2, 0, -13, 0, 0, 12, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -17, 10, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -15, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, -5, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -7, 0, - 0, 1, 0, 0, 3, 33, -5, -2, + 0, 0, 0, 0, 3, 33, -5, -2, 8, 7, -7, 3, 0, 0, 3, 3, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -33, 7, 0, 0, @@ -2301,39 +978,39 @@ static const int8_t kern_class_values[] = { -6, -1, 0, 0, 0, -6, 0, -3, 0, -12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -17, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, - 0, -3, 0, 0, -5, 0, -4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -3, 0, 0, 0, -4, 0, -7, 0, 0, 0, -4, 3, -3, 0, 0, -7, -3, -6, 0, 0, -7, 0, -3, 0, -12, 0, -3, 0, 0, -21, -5, -10, -3, -9, 0, 0, -17, 0, -7, -1, 0, 0, 0, 0, 0, 0, - 0, 0, -4, -5, -2, -4, 0, 0, + 0, 0, 0, -4, -5, -2, 0, 0, 0, 0, -6, 0, -6, 3, -3, 5, 0, -2, -6, -2, -4, -5, 0, -3, - -1, -2, 2, -7, -1, 0, 0, 0, + -1, -2, 2, -7, 0, 0, 0, 0, -23, -2, -4, 0, -6, 0, -2, -12, - -2, 0, 0, -2, -2, 0, 0, 0, - 0, 2, 0, -2, -4, -2, 4, 0, + -2, 0, 0, -2, -2, 0, -2, 0, + 0, 0, 2, 0, -2, -4, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, 0, -6, 0, -2, 0, 0, 0, -5, 3, 0, 0, 0, -7, -3, -5, 0, 0, -7, 0, -3, 0, -12, 0, 0, 0, 0, -25, 0, -5, -9, -13, 0, 0, -17, 0, -2, -4, 0, 0, 0, - 0, 0, 0, 0, 0, -3, -4, -1, - -4, 1, 0, 0, 4, -3, 0, 8, + 0, 0, 0, 0, 0, 0, -3, -4, + -1, 0, 0, 0, 4, -3, 0, 8, 13, -3, -3, -8, 3, 13, 4, 6, -7, 3, 11, 3, 7, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 12, -5, -3, 0, -2, - 20, 11, 20, 0, 0, 0, 3, 0, - 0, 9, 0, 0, -4, 0, 0, 0, + 0, 0, 11, 0, 0, 0, 0, 3, + 0, 0, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, -22, -3, -2, -10, @@ -2350,66 +1027,61 @@ static const int8_t kern_class_values[] = { 2, 5, 3, -8, 0, -1, -2, 3, 0, 2, 0, 0, 0, 0, -6, 0, -2, -2, -5, 0, -2, -10, 0, 16, - -3, 0, -6, -2, 0, -2, -4, 0, - -3, -7, -5, -3, 0, 0, 0, -4, + -3, 0, -6, 0, 0, 0, -2, -4, + 0, -3, -7, -5, -3, 0, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, -22, -3, -2, -10, -13, 0, 0, -17, 0, - 0, 0, 0, 0, 0, 13, 0, 0, + 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, 0, -8, -3, -2, 8, -2, -3, - -10, 1, -2, 1, -2, -7, 1, 6, - 1, 2, 1, 2, -6, -10, -3, 0, + -10, 0, -1, 0, -2, -7, 0, 6, + 0, 2, 0, 2, -6, -10, -3, 0, -10, -5, -7, -11, -10, 0, -4, -5, - -3, -3, -2, -2, -3, -2, 0, -2, - -1, 4, 0, 4, -2, 0, 8, 0, + -3, -3, -12, -2, -3, 0, -2, 0, + -2, 0, 4, 0, 4, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -3, -3, 0, 0, -7, 0, -1, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -3, -3, 0, -3, + 0, 0, 0, 0, 0, -3, -3, 0, 0, 0, 0, 0, -2, 0, 0, -4, -3, 3, 0, -4, -5, -2, 0, -7, -2, -6, -2, -3, 0, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -17, 0, 8, 0, 0, -5, 0, - 0, 0, 0, -3, 0, -3, 0, 0, - -1, 0, 0, -2, 0, -6, 0, 0, + 0, 0, 0, 0, -3, 0, -3, 0, + 0, 0, 0, -2, 0, -6, 0, 0, 11, -3, -8, -8, 2, 3, 3, -1, -7, 2, 4, 2, 8, 2, 8, -2, -7, 0, 0, -10, 0, 0, -8, -7, 0, 0, -5, 0, -3, -4, 0, -4, - 0, -4, 0, -2, 4, 0, -2, -8, - -3, 9, 0, 0, -2, 0, -5, 0, - 0, 3, -6, 0, 3, -3, 2, 0, - 0, -8, 0, -2, -1, 0, -3, 3, + 0, 0, -4, 0, -2, 4, 0, -2, + -8, -3, 0, 0, -2, 0, -5, 0, + 0, 3, -6, 0, 3, -3, 2, -1, + 0, -8, 0, -2, 0, 0, -3, 3, -2, 0, 0, 0, -10, -3, -6, 0, -8, 0, 0, -12, 0, 9, -3, 0, - -5, 0, 2, 0, -3, 0, -3, -8, - 0, -3, 3, 0, 0, 0, 0, -2, - 0, 0, 3, -3, 1, 0, 0, -3, + -5, 0, 0, 2, 0, -3, 0, -3, + -8, 0, -3, 0, 0, 0, 0, -2, + 0, 0, 3, -3, 0, 0, 0, -3, -2, 0, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -16, 0, 6, 0, - 0, -2, 0, 0, 0, 0, 1, 0, - -3, -3, 0, 0, 0, 5, 0, 6, - 0, 0, 0, 0, 0, -16, -15, 1, - 11, 8, 4, -10, 2, 11, 0, 9, - 0, 5, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 14, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 + 0, -2, 0, 0, 0, 0, 0, 0, + 0, -3, -3, 0 }; /*Collect the kern class' data in one place*/ -static const lv_font_fmt_txt_kern_classes_t kern_classes = { +static const lv_font_fmt_txt_kern_classes_t kern_classes = +{ .class_pair_values = kern_class_values, .left_class_mapping = kern_left_class_mapping, .right_class_mapping = kern_right_class_mapping, - .left_class_cnt = 61, + .left_class_cnt = 60, .right_class_cnt = 49, }; @@ -2429,8 +1101,8 @@ static lv_font_fmt_txt_dsc_t font_dsc = { .cmaps = cmaps, .kern_dsc = &kern_classes, .kern_scale = 16, - .cmap_num = 2, - .bpp = 4, + .cmap_num = 1, + .bpp = 2, .kern_classes = 1, .bitmap_format = 0, #if LV_VERSION_CHECK(8, 0, 0) @@ -2451,7 +1123,7 @@ lv_font_t lv_font_montserrat_16 = { #endif .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 18, /*The maximum line height required by the font*/ + .line_height = 17, /*The maximum line height required by the font*/ .base_line = 3, /*Baseline measured from the bottom of the line*/ #if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) .subpx = LV_FONT_SUBPX_NONE, From 4e1de6f7ce064562675d8dfef47e02faa118ee00 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 3 May 2023 15:02:07 -0500 Subject: [PATCH 049/187] SFT-1028: made text darker to fit 2bpp font change --- ports/stm32/boards/Passport/modules/styles/colors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/styles/colors.py b/ports/stm32/boards/Passport/modules/styles/colors.py index 332c46ef7..bbababdfd 100644 --- a/ports/stm32/boards/Passport/modules/styles/colors.py +++ b/ports/stm32/boards/Passport/modules/styles/colors.py @@ -20,7 +20,7 @@ LIGHT_GREY_HEX = 0xDDDDDD MEDIUM_GREY_HEX = 0xA0A0A0 MICRON_GREY_HEX = 0x808080 - TEXT_GREY_HEX = 0x666666 + TEXT_GREY_HEX = 0x6D6D6D DARK_GREY_HEX = 0x626262 CHARCOAL_HEX = 0x262626 RED_HEX = 0xFF0000 From e07b7896df06ff5f8a4830020d94833ad3aac39d Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 3 May 2023 11:46:30 -0500 Subject: [PATCH 050/187] SFT-1938: changed default filenames to start at 001 --- ports/stm32/boards/Passport/modules/files.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/files.py b/ports/stm32/boards/Passport/modules/files.py index 08a3d6ae3..fecbf5cb1 100644 --- a/ports/stm32/boards/Passport/modules/files.py +++ b/ports/stm32/boards/Passport/modules/files.py @@ -168,8 +168,8 @@ def pick_filename(self, pattern, path=None): basename, ext = pattern.rsplit('.', 1) ext = '.' + ext - # try w/o any number first - fname = path + '/' + basename + ext + # try with 001 first + fname = path + '/' + basename + '-001' + ext try: os.stat(fname) except OSError as e: @@ -190,7 +190,7 @@ def pick_filename(self, pattern, path=None): continue highest = max(highest, int(m.group(1))) - fname = path + '/' + basename + ('-%d' % (highest + 1)) + ext + fname = path + '/' + basename + ('-%03d' % (highest + 1)) + ext return fname, fname[len(path):] From 2c47f71d21d94949e64def8db733f3a045ae0c5e Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 3 May 2023 12:17:49 -0500 Subject: [PATCH 051/187] SFT-1938: reversed backup files list for easy access to most recent backup --- .../boards/Passport/modules/flows/file_picker_flow.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py index d6698ae16..8ca167abd 100644 --- a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py @@ -94,7 +94,7 @@ async def on_file_result(self, res): return True async def show_file_picker(self): - from utils import show_page_with_sd_card + from utils import show_page_with_sd_card, get_backups_folder_path while True: # Get list of files/folders at the current path @@ -108,7 +108,10 @@ async def show_file_picker(self): suffix=self.suffix, filter_fn=self.filter_fn) - files = sorted(files, key=file_key) + reverse = False + if active_path == get_backups_folder_path(): + reverse = True + files = sorted(files, key=file_key, reverse=reverse) except CardMissingError: self.reset_paths() From 2ce521c776a3bf7bf70b6b27e2a906b8292eee08 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 3 May 2023 14:01:58 -0500 Subject: [PATCH 052/187] SFT-1938: first pass renaming existing files to match new scheme --- ports/stm32/boards/Passport/modules/files.py | 24 +++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/files.py b/ports/stm32/boards/Passport/modules/files.py index fecbf5cb1..9d4c888b3 100644 --- a/ports/stm32/boards/Passport/modules/files.py +++ b/ports/stm32/boards/Passport/modules/files.py @@ -168,19 +168,19 @@ def pick_filename(self, pattern, path=None): basename, ext = pattern.rsplit('.', 1) ext = '.' + ext - # try with 001 first + # rename numberless first + numberless_fname = path + '/' + basename + ext fname = path + '/' + basename + '-001' + ext try: - os.stat(fname) + os.stat(numberless_fname) + print("renaming {} to {}".format(numberless_fname, fname)) + uos.rename(numberless_fname, fname) except OSError as e: - if e.args[0] == ENOENT: - # file doesn't exist, done - return fname, basename + ext - pass + pass # file doesn't exist, move on # look for existing numbered files, even if some are deleted, and pick next # highest filename - highest = 1 + highest = 0 pat = ure.compile(basename + r'-(\d+)' + ext) files = uos.ilistdir(path) @@ -188,7 +188,15 @@ def pick_filename(self, pattern, path=None): m = pat.match(fn) if not m: continue - highest = max(highest, int(m.group(1))) + + # Rename older files to fit 3 digit numbering scheme + old_num = int(m.group(1)) + new_fn = basename + ('-%03d' % old_num) + ext + if fn != new_fn: + print("renaming {} to {}".format(fn, new_fn)) + uos.rename(path + '/' + fn, path + '/' + new_fn) + + highest = max(highest, old_num) fname = path + '/' + basename + ('-%03d' % (highest + 1)) + ext From c1368a7085d626e17f890bd38951622314c0372d Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 4 May 2023 08:28:37 -0500 Subject: [PATCH 053/187] SFT-1938: removed prints --- ports/stm32/boards/Passport/modules/files.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/files.py b/ports/stm32/boards/Passport/modules/files.py index 9d4c888b3..f7e3726aa 100644 --- a/ports/stm32/boards/Passport/modules/files.py +++ b/ports/stm32/boards/Passport/modules/files.py @@ -173,7 +173,6 @@ def pick_filename(self, pattern, path=None): fname = path + '/' + basename + '-001' + ext try: os.stat(numberless_fname) - print("renaming {} to {}".format(numberless_fname, fname)) uos.rename(numberless_fname, fname) except OSError as e: pass # file doesn't exist, move on @@ -193,7 +192,6 @@ def pick_filename(self, pattern, path=None): old_num = int(m.group(1)) new_fn = basename + ('-%03d' % old_num) + ext if fn != new_fn: - print("renaming {} to {}".format(fn, new_fn)) uos.rename(path + '/' + fn, path + '/' + new_fn) highest = max(highest, old_num) From 0b9b298015529ef1dbc0ceb6619e0f09e6ebfafc Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 3 May 2023 14:39:09 -0500 Subject: [PATCH 054/187] SFT-2018: new default directories for wallet configs, key manager exports, and multisig configs --- .../boards/Passport/modules/flows/connect_wallet_flow.py | 7 +++++-- .../Passport/modules/flows/export_derived_key_flow.py | 3 +++ .../modules/flows/export_multisig_microsd_flow.py | 7 ++++++- ports/stm32/boards/Passport/modules/public_constants.py | 8 ++++++++ ports/stm32/boards/Passport/modules/utils.py | 7 ++++++- 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py b/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py index d2f3cb342..75b4bba00 100644 --- a/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py @@ -313,8 +313,9 @@ async def export_by_qr(self): self.goto_address_verification_method(save_curr=False) async def export_by_microsd(self): - from utils import xfp2str + from utils import xfp2str, get_folder_path from flows import SaveToMicroSDFlow + from public_constants import DIR_WALLET_CONFIGS # Run the software wallet's associated export function to get the data (data, self.acct_info, _error) = await spinner_task( @@ -343,7 +344,9 @@ async def export_by_microsd(self): acct=self.acct_num, xfp=xfp2str(common.settings.get('xfp')).lower()) - save_result = await SaveToMicroSDFlow(filename=filename, data=data).run() + save_result = await SaveToMicroSDFlow(filename=filename, + path=get_folder_path(DIR_WALLET_CONFIGS), + data=data).run() if not save_result: self.set_result(False) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index ca7410ccd..0c5167c28 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -109,6 +109,8 @@ async def confirm_qr(self): async def save_to_sd(self): from flows import SaveToMicroSDFlow, SeedWarningFlow + from utils import get_folder_path + from public_constants import DIR_KEY_MNGR result = await SeedWarningFlow(action_text="copy your {} to the microSD card" .format(self.key_type['title']), @@ -119,6 +121,7 @@ async def save_to_sd(self): return result = await SaveToMicroSDFlow(filename=self.filename, + path=get_folder_path(DIR_KEY_MNGR), data=self.data, success_text="key").run() self.set_result(result) diff --git a/ports/stm32/boards/Passport/modules/flows/export_multisig_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/export_multisig_microsd_flow.py index 23d14fe7d..eb1e4a740 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_multisig_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_multisig_microsd_flow.py @@ -9,8 +9,13 @@ class ExportMultisigMicrosdFlow(SaveToMicroSDFlow): def __init__(self, context=None): from multisig_wallet import MultisigWallet + from utils import get_folder_path + from public_constants import DIR_MULTISIGS ms = MultisigWallet.get_by_idx(context) # context is multisig index data = ms.to_file() filename = "{}-multisig.txt".format(ms.name) - super().__init__(filename=filename, data=data, success_text="multisig config") + super().__init__(filename=filename, + path=get_folder_path(DIR_MULTISIGS), + data=data, + success_text="multisig config") diff --git a/ports/stm32/boards/Passport/modules/public_constants.py b/ports/stm32/boards/Passport/modules/public_constants.py index 717d34317..66420ec0e 100644 --- a/ports/stm32/boards/Passport/modules/public_constants.py +++ b/ports/stm32/boards/Passport/modules/public_constants.py @@ -97,6 +97,14 @@ TRUST_OFFER = const(1) TRUST_PSBT = const(2) +# Default Directories +DIR_BACKUPS = 'backups' +DIR_KEY_MNGR = 'key_manager' +DIR_MULTISIGS = 'multisigs' +DIR_WALLET_CONFIGS = 'wallet_configs' +DIR_TRANSACTIONS = 'transactions' +DIR_HEALTH_CHECKS = 'health_checks' + RFC_SIGNATURE_TEMPLATE = '''\ -----BEGIN {blockchain} SIGNED MESSAGE----- {msg} diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index 159833f18..c57e48aea 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -12,6 +12,7 @@ import lvgl as lv from constants import NUM_BACKUP_CODE_SECTIONS, NUM_DIGITS_PER_BACKUP_CODE_SECTION +from public_constants import DIR_BACKUPS from files import CardSlot from styles.colors import DEFAULT_LARGE_ICON_COLOR import ustruct @@ -1017,7 +1018,11 @@ def format_btc_address(address, addr_type): def get_backups_folder_path(): - return '{}/backups'.format(CardSlot.get_sd_root()) + return get_folder_path() + + +def get_folder_path(folder=DIR_BACKUPS): + return '{}/{}'.format(CardSlot.get_sd_root(), folder) def split_to_lines(s, width): From 840332e877f7f348b4ef8c724b701858a7e42fbb Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 3 May 2023 18:30:59 -0500 Subject: [PATCH 055/187] SFT-2018: fixed rebase conflict with derived key export refactor --- .../Passport/modules/flows/export_derived_key_flow.py | 10 ++++++---- .../Passport/modules/flows/view_seed_words_flow.py | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index 0c5167c28..1888dd7af 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -12,14 +12,16 @@ def __init__(self, context=None): self.key_type = None self.pk = None self.data = None + self.path = None self.filename = None super().__init__(initial_state=self.generate_key, name="NewDerivedKeyFlow") async def generate_key(self): - from utils import spinner_task, B2A + from utils import spinner_task, B2A, get_folder_path from derived_key import get_key_type_from_tn from pages import ErrorPage from flows import ViewSeedWordsFlow + from public_constants import DIR_KEY_MNGR self.key_type = get_key_type_from_tn(self.key['tn']) @@ -36,12 +38,14 @@ async def generate_key(self): self.set_result(False) return + self.path = get_folder_path(DIR_KEY_MNGR) self.filename = '{}-{}.txt'.format(self.key_type['title'], self.key['name']) if self.key_type['words']: result = await ViewSeedWordsFlow(external_key=self.pk, qr_option=True, sd_option=True, + path=self.path, filename=self.filename).run() self.set_result(result) return @@ -109,8 +113,6 @@ async def confirm_qr(self): async def save_to_sd(self): from flows import SaveToMicroSDFlow, SeedWarningFlow - from utils import get_folder_path - from public_constants import DIR_KEY_MNGR result = await SeedWarningFlow(action_text="copy your {} to the microSD card" .format(self.key_type['title']), @@ -121,7 +123,7 @@ async def save_to_sd(self): return result = await SaveToMicroSDFlow(filename=self.filename, - path=get_folder_path(DIR_KEY_MNGR), + path=self.path, data=self.data, success_text="key").run() self.set_result(result) diff --git a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py index fe7881993..f577a2fff 100644 --- a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py @@ -7,7 +7,7 @@ class ViewSeedWordsFlow(Flow): - def __init__(self, external_key=None, qr_option=False, sd_option=False, filename=None): + def __init__(self, external_key=None, qr_option=False, sd_option=False, path=None, filename=None): self.external_key = external_key self.qr_option = qr_option @@ -15,6 +15,7 @@ def __init__(self, external_key=None, qr_option=False, sd_option=False, filename filename = filename or 'Seed.txt' # Caller should never let this happen self.sd_option = sd_option + self.path = path self.filename = filename self.qr_type = None self.words = None @@ -114,6 +115,7 @@ async def save_to_sd(self): text = " ".join(self.words) result = await SaveToMicroSDFlow(filename=self.filename, + path=self.path, data=text, success_text="seed").run() From b90462ee759972428d0c2e64a26dabd0457d2256 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 4 May 2023 13:15:52 -0500 Subject: [PATCH 056/187] SFT-936: added microSD option to QR signing flow --- .../modules/flows/sign_psbt_qr_flow.py | 107 ++++++++++++++---- .../Passport/modules/microns/__init__.py | 8 ++ 2 files changed, 93 insertions(+), 22 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index a68808073..19a30c7f0 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -3,11 +3,7 @@ # # sign_psbt_qr_flow.py - Sign a PSBT from a microSD card -from flows import Flow, ScanQRFlow -from data_codecs.qr_type import QRType -from foundation import FixedBytesIO, ur -from passport import mem -from pages import ErrorPage +from flows import Flow class SignPsbtQRFlow(Flow): @@ -16,8 +12,15 @@ def __init__(self): self.raw_psbt = None self.ur_type = None self.psbt = None + self.txid = None + self.out_fn = None + self.signed_bytes = None async def scan_transaction(self): + from foundation import ur + from data_codecs.qr_type import QRType + from flows import ScanQRFlow + result = await ScanQRFlow(qr_types=[QRType.QR, QRType.UR2], ur_types=[ur.Value.CRYPTO_PSBT, ur.Value.BYTES], data_description='a PSBT file').run() @@ -44,6 +47,7 @@ async def copy_to_flash(self): from tasks import copy_psbt_to_external_flash_task from public_constants import TXN_INPUT_OFFSET from errors import Error + from pages import ErrorPage gc.collect() # Try to avoid excessive fragmentation @@ -73,25 +77,22 @@ async def common_flow(self): if self.psbt is None: self.set_result(False) else: - self.goto(self.show_signed_transaction) + self.goto(self.get_signed_bytes) - async def show_signed_transaction(self): - import gc - from pages import ShowQRPage - from data_codecs.qr_type import QRType - from ubinascii import hexlify as b2a_hex - import microns + async def get_signed_bytes(self): + from foundation import FixedBytesIO + from pages import ErrorPage + from passport import mem # Copy signed txn into a bytearray and show the data as a UR # try: - signed_bytes = None try: with FixedBytesIO(mem.psbt_output) as bfd: with self.output_encoder(bfd) as fd: # Always serialize back to PSBT for QR codes self.psbt.serialize(fd) bfd.seek(0) - signed_bytes = bfd.getvalue() + self.signed_bytes = bfd.getvalue() # print('len(signed_bytes)={}'.format(len(signed_bytes))) # print('signed_bytes={}'.format(signed_bytes)) except MemoryError as e: @@ -99,22 +100,84 @@ async def show_signed_transaction(self): self.set_result(False) return - self.psbt = None - gc.collect() + self.goto(self.show_signed_transaction) + + async def show_signed_transaction(self): + from pages import ShowQRPage + from data_codecs.qr_type import QRType + from ubinascii import hexlify as b2a_hex + import microns + from foundation import ur if self.ur_type is None: qr_type = QRType.QR - qr_data = b2a_hex(signed_bytes) + qr_data = b2a_hex(self.signed_bytes) else: qr_type = QRType.UR2 if self.ur_type == ur.Value.CRYPTO_PSBT: - qr_data = ur.new_bytes(signed_bytes) + qr_data = ur.new_bytes(self.signed_bytes) elif self.ur_type == ur.Value.BYTES: - qr_data = ur.new_crypto_psbt(signed_bytes) + qr_data = ur.new_crypto_psbt(self.signed_bytes) else: raise RuntimeError('Unknown UR type: {}'.format(self.ur_type)) - await ShowQRPage(qr_type=qr_type, - qr_data=qr_data, - right_micron=microns.Checkmark).show() + result = await ShowQRPage(qr_type=qr_type, + qr_data=qr_data, + left_micron=microns.MicroSD, + right_micron=microns.Checkmark).show() + + if not result: + self.goto(self.save_to_microsd) + return + + self.set_result(True) + + def write_final_fn(self, filename): + from utils import HexWriter + + # write psbt to file as hex + with HexWriter(open(filename, 'w+t')) as fd: + self.txid = self.psbt.finalize(fd) + self.out_fn = filename + + async def save_to_microsd(self): + from flows import SaveToMicroSDFlow + + if self.out_fn is not None: + self.goto(self.show_success) + return + + result = await SaveToMicroSDFlow(filename='QR.txn', + write_fn=self.write_final_fn, + success_text="transaction", + # add default path + automatic=True).run() + if not result: + self.back() + return + + self.goto(self.show_success) + + async def show_success(self): + import microns + from lvgl import LARGE_ICON_SUCCESS + from styles.colors import DEFAULT_LARGE_ICON_COLOR + from pages import LongTextPage + + msg = 'Finalized transaction (ready for broadcast):\n\n%s' % self.out_fn + + if self.txid: + msg += '\n\nFinal TXID:\n' + self.txid + + result = await LongTextPage(text=msg, + centered=True, + left_micron=microns.ScanQR, + right_micron=microns.Checkmark, + icon=LARGE_ICON_SUCCESS, + icon_color=DEFAULT_LARGE_ICON_COLOR,).show() + + if not result: + self.goto(self.show_signed_transaction) + return + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/microns/__init__.py b/ports/stm32/boards/Passport/modules/microns/__init__.py index 217d6e758..402afd39d 100644 --- a/ports/stm32/boards/Passport/modules/microns/__init__.py +++ b/ports/stm32/boards/Passport/modules/microns/__init__.py @@ -36,6 +36,14 @@ def Retry(color=FD_BLUE): return IconButton(icon=lv.ICON_RETRY, color=color) +def MicroSD(color=FD_BLUE): + return IconButton(icon=lv.ICON_MICROSD, color=color) + + +def ScanQR(color=FD_BLUE): + return IconButton(icon=lv.ICON_SCAN_QR, color=color) + + def PageHome(color=MICRON_GREY): return Icon(icon=lv.ICON_PAGE_HOME, color=color) From 3811f490515d387c503053a985dede3c505bdf40 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 4 May 2023 13:58:38 -0500 Subject: [PATCH 057/187] SFT-936: removed periods from microsd messages --- .../stm32/boards/Passport/modules/flows/save_to_microsd_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index 9e2c27ab7..a2c5f2935 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -57,7 +57,7 @@ async def save(self): with CardSlot() as card: ensure_folder_exists(self.path) self.out_full, _ = card.pick_filename(self.filename, path) - error = await spinner_task("Writing {}.".format(self.success_text), + error = await spinner_task("Writing {}".format(self.success_text), custom_microsd_write_task, args=[self.out_full, self.write_fn]) if error is Error.MICROSD_CARD_MISSING: From 40c39d9f6d15af271aab23f6c174df4daf55734c Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 4 May 2023 14:09:19 -0500 Subject: [PATCH 058/187] SFT-936: saved QR->MicroSD transactions in a default folder --- .../stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 19a30c7f0..2d3f37e31 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -142,6 +142,8 @@ def write_final_fn(self, filename): async def save_to_microsd(self): from flows import SaveToMicroSDFlow + from utils import get_folder_path + from public_constants import DIR_TRANSACTIONS if self.out_fn is not None: self.goto(self.show_success) @@ -150,7 +152,7 @@ async def save_to_microsd(self): result = await SaveToMicroSDFlow(filename='QR.txn', write_fn=self.write_final_fn, success_text="transaction", - # add default path + path=get_folder_path(DIR_TRANSACTIONS), automatic=True).run() if not result: self.back() From b990fd44e52b2fca6747daadc0da899aa276611f Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 4 May 2023 17:24:00 -0500 Subject: [PATCH 059/187] SFT-936: made microsd option non-automatic --- ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 2d3f37e31..6e9ca45f3 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -152,8 +152,7 @@ async def save_to_microsd(self): result = await SaveToMicroSDFlow(filename='QR.txn', write_fn=self.write_final_fn, success_text="transaction", - path=get_folder_path(DIR_TRANSACTIONS), - automatic=True).run() + path=get_folder_path(DIR_TRANSACTIONS)).run() if not result: self.back() return From 73ce1357f6ef29224e46f7bf4bacd556712bd2ba Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 9 May 2023 12:33:50 -0500 Subject: [PATCH 060/187] SFT-2065: fixed continue text inconsistency --- .../boards/Passport/modules/flows/export_derived_key_flow.py | 3 ++- .../stm32/boards/Passport/modules/flows/seed_warning_flow.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index 1888dd7af..aa693c0a7 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -77,7 +77,8 @@ async def show_qr_code(self): import microns result = await SeedWarningFlow(action_text="display your {} as a QR code" - .format(self.key_type['title'])).run() + .format(self.key_type['title']), + continue_text=self.key_type.get('continue_text', None)).run() if not result: self.back() diff --git a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py index 6c533d3c6..4ca63116e 100644 --- a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py @@ -8,9 +8,11 @@ class SeedWarningFlow(Flow): def __init__(self, mention_passphrase=False, - action_text="display your seed words"): + action_text="display your seed words", + continue_text=None): self.mention_passphrase = mention_passphrase self.action_text = action_text + self.continue_text = continue_text or "control your funds" super().__init__(initial_state=self.show_intro, name='SeedWarningFlow') async def show_intro(self): From 440372bec3818c1aa69677636743b6cd796a6742 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 10 May 2023 11:43:50 -0500 Subject: [PATCH 061/187] SFT-2070: removed SeedQR export options for the master key --- ports/stm32/boards/Passport/modules/menus.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 564b2af55..d2d693511 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -324,8 +324,7 @@ def advanced_menu(): return [ {'icon': lv.ICON_SETTINGS, 'label': 'Security Words', 'flow': ShowSecurityWordsSettingFlow}, {'icon': lv.ICON_SEED, 'label': 'View Seed Words', 'flow': ViewSeedWordsFlow, 'is_visible': has_seed, - 'statusbar': {'title': 'SEED WORDS', 'icon': lv.ICON_SEED}, - 'args': {'external_key': None, 'qr_option': True}}, + 'statusbar': {'title': 'SEED WORDS', 'icon': lv.ICON_SEED}}, {'icon': lv.ICON_ONE_KEY, 'label': 'Developer Pubkey', 'submenu': developer_pubkey_menu, 'statusbar': {'title': 'DEV. PUBKEY'}}, {'icon': lv.ICON_MICROSD, 'label': 'microSD', 'submenu': microsd_menu}, From 653ebb09c009e678ab4a3a9bd1dd2564b6188719 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 9 May 2023 13:21:54 -0500 Subject: [PATCH 062/187] SFT-2066: split out input checking to improve UX --- .../modules/flows/save_to_microsd_flow.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index a2c5f2935..f3128683f 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -29,24 +29,29 @@ def __init__(self, self.show_check = None if automatic else microns.Checkmark # return_bool attribute required to use show_card_missing self.return_bool = True - super().__init__(initial_state=self.save, name='SaveToMicroSDFlow') + super().__init__(initial_state=self.check_inputs, name='SaveToMicroSDFlow') def default_write_fn(self, filename): with open(self.out_full, 'w' + self.mode) as fd: fd.write(self.data) - async def save(self): - from files import CardSlot, CardMissingError + async def check_inputs(self): from pages import ErrorPage - from utils import spinner_task, ensure_folder_exists - from errors import Error - from tasks import custom_microsd_write_task if (not self.data and not self.write_fn) or (self.data and self.write_fn): await ErrorPage("Either data or a write function is required to save a file.").show() self.set_result(False) return + self.goto(self.save) + + async def save(self): + from files import CardSlot, CardMissingError + from pages import ErrorPage + from utils import spinner_task, ensure_folder_exists + from errors import Error + from tasks import custom_microsd_write_task + if self.data: self.write_fn = self.default_write_fn From 35229fa605daecc9c57220355c66d98ab4837d5c Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 19 Apr 2023 10:11:48 -0500 Subject: [PATCH 063/187] SFT-1374: first attempt at an oversized UR warning, doesn't compile --- extmod/foundation-rust/include/foundation.h | 5 +++++ extmod/foundation-rust/src/ur/decoder.rs | 8 ++++++++ extmod/foundation/modfoundation-ur.h | 11 +++++++++++ .../modules/data_codecs/data_decoder.py | 3 +++ .../Passport/modules/data_codecs/ur2_codec.py | 3 +++ .../Passport/modules/flows/scan_qr_flow.py | 19 +++++++++++++++++-- .../modules/flows/sign_psbt_qr_flow.py | 6 +++++- .../Passport/modules/pages/scan_qr_page.py | 18 ++++++++++++++++-- .../boards/Passport/modules/views/camera.py | 5 +++++ 9 files changed, 73 insertions(+), 5 deletions(-) diff --git a/extmod/foundation-rust/include/foundation.h b/extmod/foundation-rust/include/foundation.h index 0aebac4aa..03a4e6aab 100644 --- a/extmod/foundation-rust/include/foundation.h +++ b/extmod/foundation-rust/include/foundation.h @@ -387,6 +387,11 @@ bool ur_decoder_is_complete(UR_Decoder *decoder); */ uint32_t ur_decoder_estimated_percent_complete(UR_Decoder *decoder); +/** + * Returns the number of expected parts. + */ +uint32_t ur_decoder_num_frames(UR_Decoder *decoder); + /** * Clear the decoder in order so a new message can be received. */ diff --git a/extmod/foundation-rust/src/ur/decoder.rs b/extmod/foundation-rust/src/ur/decoder.rs index a68e32fae..f27a9d25b 100644 --- a/extmod/foundation-rust/src/ur/decoder.rs +++ b/extmod/foundation-rust/src/ur/decoder.rs @@ -139,6 +139,14 @@ pub extern "C" fn ur_decoder_estimated_percent_complete( (decoder.inner.estimated_percent_complete() * 100.0) as u32 } +/// Returns the expected number of frames. +#[no_mangle] +pub extern "C" fn ur_decoder_num_frames( + decoder: &mut UR_Decoder, +) -> u32 { + decoder.inner.expected_part_count() as u32 +} + /// Clear the decoder in order so a new message can be received. #[no_mangle] pub extern "C" fn ur_decoder_clear(decoder: &mut UR_Decoder) { diff --git a/extmod/foundation/modfoundation-ur.h b/extmod/foundation/modfoundation-ur.h index 1402f0270..a6c0916bc 100644 --- a/extmod/foundation/modfoundation-ur.h +++ b/extmod/foundation/modfoundation-ur.h @@ -585,6 +585,16 @@ STATIC mp_obj_t mod_foundation_ur_decoder_estimated_percent_complete(void) STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_foundation_ur_decoder_estimated_percent_complete_obj, mod_foundation_ur_decoder_estimated_percent_complete); +/// def decoder_num_frames() -> int: +/// """ +/// """ +STATIC mp_obj_t mod_foundation_ur_decoder_num_frames(void) +{ + return mp_obj_new_int(ur_decoder_num_frames(&UR_DECODER)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_foundation_ur_decoder_num_frames_obj, + mod_foundation_ur_decoder_num_frames); + /// def decoder_clear() -> None: /// """ @@ -684,6 +694,7 @@ STATIC const mp_rom_map_elem_t mod_foundation_ur_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_decoder_receive), MP_ROM_PTR(&mod_foundation_ur_decoder_receive_obj)}, {MP_ROM_QSTR(MP_QSTR_decoder_is_complete), MP_ROM_PTR(&mod_foundation_ur_decoder_is_complete_obj)}, {MP_ROM_QSTR(MP_QSTR_decoder_estimated_percent_complete), MP_ROM_PTR(&mod_foundation_ur_decoder_estimated_percent_complete_obj)}, + {MP_ROM_QSTR(MP_QSTR_decoder_num_frames), MP_ROM_PTR(&mod_foundation_ur_decoder_num_frames_obj)}, {MP_ROM_QSTR(MP_QSTR_decoder_clear), MP_ROM_PTR(&mod_foundation_ur_decoder_clear_obj)}, {MP_ROM_QSTR(MP_QSTR_decoder_is_empty), MP_ROM_PTR(&mod_foundation_ur_decoder_is_empty_obj)}, {MP_ROM_QSTR(MP_QSTR_decoder_decode_message), MP_ROM_PTR(&mod_foundation_ur_decoder_decode_message_obj)}, diff --git a/ports/stm32/boards/Passport/modules/data_codecs/data_decoder.py b/ports/stm32/boards/Passport/modules/data_codecs/data_decoder.py index ef101b909..c8c56b410 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/data_decoder.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/data_decoder.py @@ -37,3 +37,6 @@ def decode(self): # - etc. def qr_type(self): pass + + def num_frames(self): + return 1 diff --git a/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py b/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py index 2da37133d..e047cc31e 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py @@ -68,6 +68,9 @@ def decode(self): def qr_type(self): return QRType.UR2 + def num_frames(self): + return ur.decoder_num_frames() + class UR2Encoder(DataEncoder): def encode(self, value, max_fragment_len=200): diff --git a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py index ac905b79b..d8f3cafb7 100644 --- a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py @@ -15,7 +15,9 @@ def __init__(self, qr_types=None, ur_types=None, explicit_type=None, - data_description=None): + data_description=None, + max_frames=None, + max_frames_text=None): """ Initialize the scan QR flow. @@ -38,6 +40,8 @@ def __init__(self, self.explicit_type = explicit_type self.data_description = data_description self.data = None + self.max_frames = max_frames + self.max_frames_text = max_frames_text if len(self.qr_types) == 0: raise ValueError('At least one QR type must be provided') @@ -49,7 +53,9 @@ def __init__(self, raise ValueError('Data description must be provided') async def scan(self): - result = await ScanQRPage(qr_type=self.explicit_type).show(auto_close_timeout=self.auto_close_timeout) + from pages import QuestionPage + + result = await ScanQRPage(max_frames=self.max_frames, qr_type=self.explicit_type).show(auto_close_timeout=self.auto_close_timeout) if result is None: self.set_result(None) @@ -60,6 +66,15 @@ async def scan(self): self.set_result(None) return + if result.is_too_large(): + result = await QuestionPage(self.max_frames_text).show() + + if result: + self.set_result(None) + else: + self.max_frames = None + return + self.data = result.data if isinstance(self.data, ur.Value): self.goto(self.handle_ur) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 6e9ca45f3..5c7245671 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -15,15 +15,19 @@ def __init__(self): self.txid = None self.out_fn = None self.signed_bytes = None + self.max_frames = 5 async def scan_transaction(self): from foundation import ur from data_codecs.qr_type import QRType from flows import ScanQRFlow + text = "This PSBT is very large. Would you like to cancel and sign with microSD?" result = await ScanQRFlow(qr_types=[QRType.QR, QRType.UR2], ur_types=[ur.Value.CRYPTO_PSBT, ur.Value.BYTES], - data_description='a PSBT file').run() + data_description='a PSBT file', + max_frames=self.max_frames, + max_frames_text=text).run() if result is None: # User canceled the scan self.set_result(False) diff --git a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py index bce228e78..6dd6b57a4 100644 --- a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py +++ b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py @@ -33,12 +33,14 @@ def __init__(self, statusbar=statusbar, left_micron=left_micron, right_micron=right_micron, - extend_timeout=True) + extend_timeout=True, + max_frames=None) self.prev_card_header = None self.timer = None self.camera = CameraQRScanner(qr_type) self.qr_type = qr_type + self.max_frames = max_frames # TODO: # lv.pct(100) just makes the widget inside the camera view to return @@ -107,6 +109,13 @@ def update(self): self.camera.update() self.progress_label.set_text(progress_text(self.camera.estimated_percent_complete())) + + num_frames = self.camera.num_frames() + if self.max_frames is not None and num_frames > self.max_frames: + self.set_result(QRScanResult(num_frames=num_frames, + max_frames=self.max_frames)) + return + if self.camera.is_complete(): data = self.camera.qr_decoder.decode() qr_type = self.camera.qr_decoder.qr_type() @@ -134,10 +143,15 @@ class QRScanResult: and between a cancelled result (`None` returned by ScanQRPage). """ - def __init__(self, data=None, error=None, qr_type=None): + def __init__(self, data=None, error=None, qr_type=None, num_frames=None, max_frames=None): self.data = data self.error = error self.qr_type = qr_type + self.num_frames = num_frames + self.max_frames = max_frames def is_failure(self): return self.error is not None + + def is_too_large(self): + return self.max_frames is not None and self.num_frames > self.max_frames diff --git a/ports/stm32/boards/Passport/modules/views/camera.py b/ports/stm32/boards/Passport/modules/views/camera.py index 9811c57ce..16dd39c20 100644 --- a/ports/stm32/boards/Passport/modules/views/camera.py +++ b/ports/stm32/boards/Passport/modules/views/camera.py @@ -197,3 +197,8 @@ def is_complete(self): if self.qr_decoder is not None: return self.qr_decoder.is_complete() return False + + def num_frames(self): + if self.qr_decoder is not None: + return self.qr_decoder.num_frames() + return 0 From 1259423ca9e3c3e8e76061b5da12143e088665be Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 19 Apr 2023 18:12:37 -0500 Subject: [PATCH 064/187] SFT-1374: first complete pass at microsd suggestion in psbt signing --- extmod/foundation-rust/include/foundation.h | 8 ++------ extmod/foundation-rust/src/ur/decoder.rs | 20 ++++++++++--------- extmod/foundation/modfoundation-ur.h | 17 ++++------------ .../Passport/modules/data_codecs/ur2_codec.py | 5 +++-- .../Passport/modules/pages/scan_qr_page.py | 7 ++++--- .../boards/Passport/modules/views/camera.py | 2 +- 6 files changed, 25 insertions(+), 34 deletions(-) diff --git a/extmod/foundation-rust/include/foundation.h b/extmod/foundation-rust/include/foundation.h index 03a4e6aab..2a74674b4 100644 --- a/extmod/foundation-rust/include/foundation.h +++ b/extmod/foundation-rust/include/foundation.h @@ -375,7 +375,8 @@ extern UR_Encoder UR_ENCODER; bool ur_decoder_receive(UR_Decoder *decoder, const uint8_t *ur, size_t ur_len, - UR_Error *error); + UR_Error *error, + uint32_t *num_frames); /** * Returns `true` if the decoder is complete and no more data is needed. @@ -387,11 +388,6 @@ bool ur_decoder_is_complete(UR_Decoder *decoder); */ uint32_t ur_decoder_estimated_percent_complete(UR_Decoder *decoder); -/** - * Returns the number of expected parts. - */ -uint32_t ur_decoder_num_frames(UR_Decoder *decoder); - /** * Clear the decoder in order so a new message can be received. */ diff --git a/extmod/foundation-rust/src/ur/decoder.rs b/extmod/foundation-rust/src/ur/decoder.rs index f27a9d25b..976bb9a5b 100644 --- a/extmod/foundation-rust/src/ur/decoder.rs +++ b/extmod/foundation-rust/src/ur/decoder.rs @@ -83,6 +83,7 @@ pub unsafe extern "C" fn ur_decoder_receive( ur: *const u8, ur_len: usize, error: &mut UR_Error, + num_frames: &mut u32, ) -> bool { // SAFETY: ur and ur_len are assumed to be valid. let ur = unsafe { slice::from_raw_parts(ur, ur_len) }; @@ -109,6 +110,8 @@ pub unsafe extern "C" fn ur_decoder_receive( } }; + let sequence_count = ur.sequence_count(); + let result = decoder.inner.receive(ur).map_err(|e| match e { Error::NotMultiPart => unsafe { UR_Error::new(&e, super::UR_ErrorKind::UR_ERROR_KIND_NOT_MULTI_PART) @@ -117,7 +120,14 @@ pub unsafe extern "C" fn ur_decoder_receive( }); match result { - Ok(_) => true, + Ok(_) => { + *num_frames = match sequence_count { + Some(n) => n, + None => 0, + }; + + true + } Err(e) => { *error = e; false @@ -139,14 +149,6 @@ pub extern "C" fn ur_decoder_estimated_percent_complete( (decoder.inner.estimated_percent_complete() * 100.0) as u32 } -/// Returns the expected number of frames. -#[no_mangle] -pub extern "C" fn ur_decoder_num_frames( - decoder: &mut UR_Decoder, -) -> u32 { - decoder.inner.expected_part_count() as u32 -} - /// Clear the decoder in order so a new message can be received. #[no_mangle] pub extern "C" fn ur_decoder_clear(decoder: &mut UR_Decoder) { diff --git a/extmod/foundation/modfoundation-ur.h b/extmod/foundation/modfoundation-ur.h index a6c0916bc..8187006d1 100644 --- a/extmod/foundation/modfoundation-ur.h +++ b/extmod/foundation/modfoundation-ur.h @@ -555,12 +555,14 @@ STATIC mp_obj_t mod_foundation_ur_decoder_receive(mp_obj_t ur_obj) mp_check_self(mp_obj_is_str(ur_obj)); GET_STR_DATA_LEN(ur_obj, ur, ur_len); + + uint32_t num_frames = 0; - if (!ur_decoder_receive(&UR_DECODER, ur, ur_len, &error)) { + if (!ur_decoder_receive(&UR_DECODER, ur, ur_len, &error, &num_frames)) { mod_foundation_ur_raise(&error); } - return mp_const_none; + return mp_obj_new_int(num_frames); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_foundation_ur_decoder_receive_obj, mod_foundation_ur_decoder_receive); @@ -585,16 +587,6 @@ STATIC mp_obj_t mod_foundation_ur_decoder_estimated_percent_complete(void) STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_foundation_ur_decoder_estimated_percent_complete_obj, mod_foundation_ur_decoder_estimated_percent_complete); -/// def decoder_num_frames() -> int: -/// """ -/// """ -STATIC mp_obj_t mod_foundation_ur_decoder_num_frames(void) -{ - return mp_obj_new_int(ur_decoder_num_frames(&UR_DECODER)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_foundation_ur_decoder_num_frames_obj, - mod_foundation_ur_decoder_num_frames); - /// def decoder_clear() -> None: /// """ @@ -694,7 +686,6 @@ STATIC const mp_rom_map_elem_t mod_foundation_ur_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_decoder_receive), MP_ROM_PTR(&mod_foundation_ur_decoder_receive_obj)}, {MP_ROM_QSTR(MP_QSTR_decoder_is_complete), MP_ROM_PTR(&mod_foundation_ur_decoder_is_complete_obj)}, {MP_ROM_QSTR(MP_QSTR_decoder_estimated_percent_complete), MP_ROM_PTR(&mod_foundation_ur_decoder_estimated_percent_complete_obj)}, - {MP_ROM_QSTR(MP_QSTR_decoder_num_frames), MP_ROM_PTR(&mod_foundation_ur_decoder_num_frames_obj)}, {MP_ROM_QSTR(MP_QSTR_decoder_clear), MP_ROM_PTR(&mod_foundation_ur_decoder_clear_obj)}, {MP_ROM_QSTR(MP_QSTR_decoder_is_empty), MP_ROM_PTR(&mod_foundation_ur_decoder_is_empty_obj)}, {MP_ROM_QSTR(MP_QSTR_decoder_decode_message), MP_ROM_PTR(&mod_foundation_ur_decoder_decode_message_obj)}, diff --git a/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py b/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py index e047cc31e..957f25f56 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py @@ -20,12 +20,13 @@ class UR2Decoder(DataDecoder): def __init__(self): ur.decoder_clear() self.value = None + self.frames = None def add_data(self, data): data = data.lower() try: - ur.decoder_receive(data) + self.frames = ur.decoder_receive(data) except ur.NotMultiPartError as exc: if ur.decoder_is_empty(): try: @@ -69,7 +70,7 @@ def qr_type(self): return QRType.UR2 def num_frames(self): - return ur.decoder_num_frames() + return self.frames class UR2Encoder(DataEncoder): diff --git a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py index 6dd6b57a4..c481d4c10 100644 --- a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py +++ b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py @@ -27,14 +27,14 @@ def __init__(self, statusbar=None, left_micron=microns.Back, right_micron=None, - qr_type=None): + qr_type=None, + max_frames=None): super().__init__(flex_flow=None, card_header=card_header, statusbar=statusbar, left_micron=left_micron, right_micron=right_micron, - extend_timeout=True, - max_frames=None) + extend_timeout=True) self.prev_card_header = None self.timer = None @@ -112,6 +112,7 @@ def update(self): num_frames = self.camera.num_frames() if self.max_frames is not None and num_frames > self.max_frames: + print("num_frames: {}, max_frames: {}".format(self.max_frames, num_frames)) self.set_result(QRScanResult(num_frames=num_frames, max_frames=self.max_frames)) return diff --git a/ports/stm32/boards/Passport/modules/views/camera.py b/ports/stm32/boards/Passport/modules/views/camera.py index 16dd39c20..7b2214f7d 100644 --- a/ports/stm32/boards/Passport/modules/views/camera.py +++ b/ports/stm32/boards/Passport/modules/views/camera.py @@ -200,5 +200,5 @@ def is_complete(self): def num_frames(self): if self.qr_decoder is not None: - return self.qr_decoder.num_frames() + return self.qr_decoder.num_frames() or 0 return 0 From 09fc710a817127206d27bf71d37433a7ae9be487 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 21 Apr 2023 14:44:48 -0500 Subject: [PATCH 065/187] SFT-1374: improved too long message --- ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py | 8 ++++++-- .../boards/Passport/modules/flows/sign_psbt_qr_flow.py | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py index d8f3cafb7..f0aabbc8f 100644 --- a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py @@ -53,7 +53,8 @@ def __init__(self, raise ValueError('Data description must be provided') async def scan(self): - from pages import QuestionPage + from pages import LongTextPage + import microns result = await ScanQRPage(max_frames=self.max_frames, qr_type=self.explicit_type).show(auto_close_timeout=self.auto_close_timeout) @@ -67,7 +68,10 @@ async def scan(self): return if result.is_too_large(): - result = await QuestionPage(self.max_frames_text).show() + result = await LongTextPage(text=self.max_frames_text, + centered=True, + left_micron=microns.Cancel, + right_micron=microns.Checkmark).show() if result: self.set_result(None) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 5c7245671..d908f01df 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -22,7 +22,8 @@ async def scan_transaction(self): from data_codecs.qr_type import QRType from flows import ScanQRFlow - text = "This PSBT is very large. Would you like to cancel and sign with microSD?" + text = "\nThis transaction is quite large, and may take some time to scan. \ +Would you like to sign with microSD instead?" result = await ScanQRFlow(qr_types=[QRType.QR, QRType.UR2], ur_types=[ur.Value.CRYPTO_PSBT, ur.Value.BYTES], data_description='a PSBT file', From cd1a2097b0cf9698c8beefc5b6a8cbd8775c5c32 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 10:43:09 -0500 Subject: [PATCH 066/187] SFT-1374: fixed print order of max_frames and num_frames --- ports/stm32/boards/Passport/modules/pages/scan_qr_page.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py index c481d4c10..ca1eabbe8 100644 --- a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py +++ b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py @@ -112,7 +112,7 @@ def update(self): num_frames = self.camera.num_frames() if self.max_frames is not None and num_frames > self.max_frames: - print("num_frames: {}, max_frames: {}".format(self.max_frames, num_frames)) + print("num_frames: {}, max_frames: {}".format(num_frames, self.max_frames)) self.set_result(QRScanResult(num_frames=num_frames, max_frames=self.max_frames)) return From 69e9e1ca1d3941cda562dcd69f74e2df92e7135d Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 11:33:36 -0500 Subject: [PATCH 067/187] SFT-1374: fixed linting error --- ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py index f0aabbc8f..5b1e34476 100644 --- a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py @@ -56,7 +56,9 @@ async def scan(self): from pages import LongTextPage import microns - result = await ScanQRPage(max_frames=self.max_frames, qr_type=self.explicit_type).show(auto_close_timeout=self.auto_close_timeout) + result = await ScanQRPage(max_frames=self.max_frames, + qr_type=self.explicit_type) \ + .show(auto_close_timeout=self.auto_close_timeout) if result is None: self.set_result(None) From a99a69c784bf2f0d72971bf8928191bc6effe88c Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 11:38:52 -0500 Subject: [PATCH 068/187] SFT-1374: simplified sequence count fetching --- extmod/foundation-rust/src/ur/decoder.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/extmod/foundation-rust/src/ur/decoder.rs b/extmod/foundation-rust/src/ur/decoder.rs index 976bb9a5b..b2c316045 100644 --- a/extmod/foundation-rust/src/ur/decoder.rs +++ b/extmod/foundation-rust/src/ur/decoder.rs @@ -110,7 +110,7 @@ pub unsafe extern "C" fn ur_decoder_receive( } }; - let sequence_count = ur.sequence_count(); + *num_frames = ur.sequence_count().unwrap_or(0); let result = decoder.inner.receive(ur).map_err(|e| match e { Error::NotMultiPart => unsafe { @@ -121,11 +121,6 @@ pub unsafe extern "C" fn ur_decoder_receive( match result { Ok(_) => { - *num_frames = match sequence_count { - Some(n) => n, - None => 0, - }; - true } Err(e) => { From b6135206d7bee8860b1252a8a06f4bb34dfe5969 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 2 May 2023 11:46:45 -0500 Subject: [PATCH 069/187] SFT-1374: fixed rust-fmt linting error --- extmod/foundation-rust/src/ur/decoder.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/extmod/foundation-rust/src/ur/decoder.rs b/extmod/foundation-rust/src/ur/decoder.rs index b2c316045..d2871bbfe 100644 --- a/extmod/foundation-rust/src/ur/decoder.rs +++ b/extmod/foundation-rust/src/ur/decoder.rs @@ -120,9 +120,7 @@ pub unsafe extern "C" fn ur_decoder_receive( }); match result { - Ok(_) => { - true - } + Ok(_) => true, Err(e) => { *error = e; false From 0ffb90362f2914eb78725ffc1c4acbc2e713a728 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 3 May 2023 10:33:57 -0500 Subject: [PATCH 070/187] SFT-1374: bumped UR frame limit to 35 --- ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index d908f01df..96a720354 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -15,7 +15,7 @@ def __init__(self): self.txid = None self.out_fn = None self.signed_bytes = None - self.max_frames = 5 + self.max_frames = 35 async def scan_transaction(self): from foundation import ur From b3fda3c80a1acb74ecd473d0de31baa0368c6041 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 4 May 2023 09:43:16 -0500 Subject: [PATCH 071/187] SFT-1374: jump straight to microsd flow from oversized PSBT scan --- ports/stm32/boards/Passport/modules/errors.py | 1 + .../Passport/modules/flows/scan_qr_flow.py | 19 ++++----------- .../modules/flows/sign_psbt_qr_flow.py | 23 ++++++++++++++++--- .../Passport/modules/pages/scan_qr_page.py | 2 +- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/errors.py b/ports/stm32/boards/Passport/modules/errors.py index 059f1c88b..e99f12b93 100644 --- a/ports/stm32/boards/Passport/modules/errors.py +++ b/ports/stm32/boards/Passport/modules/errors.py @@ -24,4 +24,5 @@ 'SECURE_ELEMENT_ERROR', 'USER_SETTINGS_FULL', 'PSBT_TOO_LARGE', + 'PSBT_OVERSIZED', ) diff --git a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py index 5b1e34476..0c302a0f0 100644 --- a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py @@ -16,8 +16,7 @@ def __init__(self, ur_types=None, explicit_type=None, data_description=None, - max_frames=None, - max_frames_text=None): + max_frames=None): """ Initialize the scan QR flow. @@ -41,7 +40,6 @@ def __init__(self, self.data_description = data_description self.data = None self.max_frames = max_frames - self.max_frames_text = max_frames_text if len(self.qr_types) == 0: raise ValueError('At least one QR type must be provided') @@ -53,8 +51,7 @@ def __init__(self, raise ValueError('Data description must be provided') async def scan(self): - from pages import LongTextPage - import microns + from errors import Error result = await ScanQRPage(max_frames=self.max_frames, qr_type=self.explicit_type) \ @@ -69,16 +66,8 @@ async def scan(self): self.set_result(None) return - if result.is_too_large(): - result = await LongTextPage(text=self.max_frames_text, - centered=True, - left_micron=microns.Cancel, - right_micron=microns.Checkmark).show() - - if result: - self.set_result(None) - else: - self.max_frames = None + if result.is_oversized(): + self.set_result(Error.PSBT_OVERSIZED) return self.data = result.data diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 96a720354..835c35016 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -20,20 +20,37 @@ def __init__(self): async def scan_transaction(self): from foundation import ur from data_codecs.qr_type import QRType - from flows import ScanQRFlow + from flows import ScanQRFlow, SignPsbtMicroSDFlow + from errors import Error + from pages import LongTextPage + import microns text = "\nThis transaction is quite large, and may take some time to scan. \ Would you like to sign with microSD instead?" result = await ScanQRFlow(qr_types=[QRType.QR, QRType.UR2], ur_types=[ur.Value.CRYPTO_PSBT, ur.Value.BYTES], data_description='a PSBT file', - max_frames=self.max_frames, - max_frames_text=text).run() + max_frames=self.max_frames).run() if result is None: # User canceled the scan self.set_result(False) return + if result == Error.PSBT_OVERSIZED: + text = "\nThis transaction is quite large, and may take some time to scan. \ +Would you like to sign with microSD instead?" + result = await LongTextPage(text=text, + centered=True, + left_micron=microns.Cancel, + right_micron=microns.Checkmark).show() + + if result: + result = await SignPsbtMicroSDFlow().run() + self.set_result(result) + else: + self.max_frames = None + return # Run it again with no max frames if the user wants + if isinstance(result, ur.Value): self.ur_type = result.ur_type() diff --git a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py index ca1eabbe8..053ba91c3 100644 --- a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py +++ b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py @@ -154,5 +154,5 @@ def __init__(self, data=None, error=None, qr_type=None, num_frames=None, max_fra def is_failure(self): return self.error is not None - def is_too_large(self): + def is_oversized(self): return self.max_frames is not None and self.num_frames > self.max_frames From 9af0c956cf166015b2614f9a0ef31a2ad74b34bf Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 4 May 2023 10:04:21 -0500 Subject: [PATCH 072/187] SFT-1374: added microSD micron for oversized PSBT choice --- ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 835c35016..304901c9f 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -42,7 +42,7 @@ async def scan_transaction(self): result = await LongTextPage(text=text, centered=True, left_micron=microns.Cancel, - right_micron=microns.Checkmark).show() + right_micron=microns.MicroSD).show() if result: result = await SignPsbtMicroSDFlow().run() From 15f980ec87f11e8850c1273b2d4802da453a80e5 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 4 May 2023 13:54:14 -0500 Subject: [PATCH 073/187] SFT-1374: replaced LongTextPage with YesNoChooserPage for microSD bailout --- .../boards/Passport/modules/flows/sign_psbt_qr_flow.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 304901c9f..50b3b2787 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -22,7 +22,7 @@ async def scan_transaction(self): from data_codecs.qr_type import QRType from flows import ScanQRFlow, SignPsbtMicroSDFlow from errors import Error - from pages import LongTextPage + from pages import YesNoChooserPage import microns text = "\nThis transaction is quite large, and may take some time to scan. \ @@ -39,10 +39,7 @@ async def scan_transaction(self): if result == Error.PSBT_OVERSIZED: text = "\nThis transaction is quite large, and may take some time to scan. \ Would you like to sign with microSD instead?" - result = await LongTextPage(text=text, - centered=True, - left_micron=microns.Cancel, - right_micron=microns.MicroSD).show() + result = await YesNoChooserPage(text=text).show() if result: result = await SignPsbtMicroSDFlow().run() From 1e97aba193333e093cb8ae91a34c931c55434a2b Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 4 May 2023 17:28:25 -0500 Subject: [PATCH 074/187] SFT-1374: changed to QuestionPage for microSD bailout --- .../boards/Passport/modules/flows/sign_psbt_qr_flow.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 50b3b2787..4336d833b 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -22,7 +22,7 @@ async def scan_transaction(self): from data_codecs.qr_type import QRType from flows import ScanQRFlow, SignPsbtMicroSDFlow from errors import Error - from pages import YesNoChooserPage + from pages import QuestionPage import microns text = "\nThis transaction is quite large, and may take some time to scan. \ @@ -37,9 +37,9 @@ async def scan_transaction(self): return if result == Error.PSBT_OVERSIZED: - text = "\nThis transaction is quite large, and may take some time to scan. \ + text = "This transaction is quite large, and may take some time to scan. \ Would you like to sign with microSD instead?" - result = await YesNoChooserPage(text=text).show() + result = await QuestionPage(text=text).show() if result: result = await SignPsbtMicroSDFlow().run() From 002f8b94fe27d307ef36f4c938452a3e1464d509 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 5 May 2023 10:40:44 -0500 Subject: [PATCH 075/187] SFT-1374: fixed rebase conflict and prevented an error --- ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py | 2 +- ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py b/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py index 957f25f56..1710da6db 100644 --- a/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py +++ b/ports/stm32/boards/Passport/modules/data_codecs/ur2_codec.py @@ -20,7 +20,7 @@ class UR2Decoder(DataDecoder): def __init__(self): ur.decoder_clear() self.value = None - self.frames = None + self.frames = 0 def add_data(self, data): data = data.lower() diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 4336d833b..6393036de 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -25,8 +25,6 @@ async def scan_transaction(self): from pages import QuestionPage import microns - text = "\nThis transaction is quite large, and may take some time to scan. \ -Would you like to sign with microSD instead?" result = await ScanQRFlow(qr_types=[QRType.QR, QRType.UR2], ur_types=[ur.Value.CRYPTO_PSBT, ur.Value.BYTES], data_description='a PSBT file', From 824d01f068657bbc916f6a59b66fb8bd96aea823 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 5 May 2023 10:52:14 -0500 Subject: [PATCH 076/187] SFT-1374: refined choice page for microSD bailout --- .../boards/Passport/modules/flows/sign_psbt_qr_flow.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 6393036de..9516ba040 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -22,7 +22,7 @@ async def scan_transaction(self): from data_codecs.qr_type import QRType from flows import ScanQRFlow, SignPsbtMicroSDFlow from errors import Error - from pages import QuestionPage + from pages import YesNoChooserPage import microns result = await ScanQRFlow(qr_types=[QRType.QR, QRType.UR2], @@ -35,9 +35,11 @@ async def scan_transaction(self): return if result == Error.PSBT_OVERSIZED: - text = "This transaction is quite large, and may take some time to scan. \ -Would you like to sign with microSD instead?" - result = await QuestionPage(text=text).show() + text = "\nThis transaction is large and will take some time to scan. \ +How would you like to proceed?" + result = await YesNoChooserPage(text=text, + yes_text='Continue with QR', + no_text='Sign with MicroSD').show() if result: result = await SignPsbtMicroSDFlow().run() From d8e2a0be38682fb41bf91f6083ceb66d6a6a467c Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 5 May 2023 13:44:43 -0500 Subject: [PATCH 077/187] SFT-1374: improved chooser page micron logic, used back arrow for microSD bailout page --- .../Passport/modules/flows/sign_psbt_qr_flow.py | 9 +++++---- .../boards/Passport/modules/pages/chooser_page.py | 5 ++++- .../Passport/modules/pages/yes_no_chooser_page.py | 14 ++++++++++++-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 9516ba040..53a371663 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -39,13 +39,14 @@ async def scan_transaction(self): How would you like to proceed?" result = await YesNoChooserPage(text=text, yes_text='Continue with QR', - no_text='Sign with MicroSD').show() + no_text='Sign with MicroSD', + left_micron=microns.Back).show() - if result: + if result is None or result: + self.max_frames = None + else: result = await SignPsbtMicroSDFlow().run() self.set_result(result) - else: - self.max_frames = None return # Run it again with no max frames if the user wants if isinstance(result, ur.Value): diff --git a/ports/stm32/boards/Passport/modules/pages/chooser_page.py b/ports/stm32/boards/Passport/modules/pages/chooser_page.py index b12277623..db265d5b2 100644 --- a/ports/stm32/boards/Passport/modules/pages/chooser_page.py +++ b/ports/stm32/boards/Passport/modules/pages/chooser_page.py @@ -23,10 +23,13 @@ def __init__( self, card_header=None, statusbar=None, options=[], initial_value=None, on_change=None, scroll_fix=False, icon=None, icon_color=CHOOSER_ICON, text=None, center=False, item_icon=lv.ICON_SMALL_CHECKMARK, - left_micron=microns.Cancel, right_micron=microns.Checkmark): + left_micron=None, right_micron=None): from views import ListItem, View + left_micron = left_micron or microns.Cancel + right_micron = right_micron or microns.Checkmark + super().__init__( card_header=card_header, statusbar=statusbar, diff --git a/ports/stm32/boards/Passport/modules/pages/yes_no_chooser_page.py b/ports/stm32/boards/Passport/modules/pages/yes_no_chooser_page.py index 30cab5224..3fd06d4dd 100644 --- a/ports/stm32/boards/Passport/modules/pages/yes_no_chooser_page.py +++ b/ports/stm32/boards/Passport/modules/pages/yes_no_chooser_page.py @@ -6,10 +6,18 @@ import lvgl as lv from pages import ChooserPage +import microns class YesNoChooserPage(ChooserPage): - def __init__(self, yes_text='Yes', no_text='No', icon=None, text=None, initial_value=True): + def __init__(self, + yes_text='Yes', + no_text='No', + icon=None, + text=None, + initial_value=True, + left_micron=None, + right_micron=None): options = [ {'label': yes_text, 'value': True}, {'label': no_text, 'value': False} @@ -23,4 +31,6 @@ def __init__(self, yes_text='Yes', no_text='No', icon=None, text=None, initial_v text=text, center=True, item_icon=None, - initial_value=options[0].get('value')) + initial_value=options[0].get('value'), + left_micron=left_micron, + right_micron=right_micron) From 1e4f3cafd0a4797c5f57cdd1add7d5d520ec8cd0 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 5 May 2023 16:51:59 -0500 Subject: [PATCH 078/187] SFT-1374: added newline to microsd bailout message --- ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 53a371663..f883c3c4f 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -35,7 +35,7 @@ async def scan_transaction(self): return if result == Error.PSBT_OVERSIZED: - text = "\nThis transaction is large and will take some time to scan. \ + text = "\nThis transaction is large and will take some time to scan.\n\ How would you like to proceed?" result = await YesNoChooserPage(text=text, yes_text='Continue with QR', From fa50c2445b67bb78c99e8504ca5765186189282b Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 8 May 2023 09:30:18 -0500 Subject: [PATCH 079/187] SFT-1374: iterated on text layout for microSD bailout --- .../stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index f883c3c4f..0a3725f6b 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -35,8 +35,8 @@ async def scan_transaction(self): return if result == Error.PSBT_OVERSIZED: - text = "\nThis transaction is large and will take some time to scan.\n\ -How would you like to proceed?" + text = "\nThis transaction is large and will take some time to scan. \ +How would you like to proceed?\n" result = await YesNoChooserPage(text=text, yes_text='Continue with QR', no_text='Sign with MicroSD', From a48217f029008f9c7157be18e06d67f276255405 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 11 May 2023 15:36:11 -0500 Subject: [PATCH 080/187] SFT-1374: removed print --- ports/stm32/boards/Passport/modules/pages/scan_qr_page.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py index 053ba91c3..24f235e1d 100644 --- a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py +++ b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py @@ -112,7 +112,6 @@ def update(self): num_frames = self.camera.num_frames() if self.max_frames is not None and num_frames > self.max_frames: - print("num_frames: {}, max_frames: {}".format(num_frames, self.max_frames)) self.set_result(QRScanResult(num_frames=num_frames, max_frames=self.max_frames)) return From 5ef7c9124d4b5eba291aab6365cbbe8c25e90638 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 5 May 2023 15:35:31 -0500 Subject: [PATCH 081/187] SFT-2016: added 2 pixels of padding to statusbar top --- ports/stm32/boards/Passport/modules/views/statusbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/views/statusbar.py b/ports/stm32/boards/Passport/modules/views/statusbar.py index 7cfd6aa2e..5f1fb2bc5 100644 --- a/ports/stm32/boards/Passport/modules/views/statusbar.py +++ b/ports/stm32/boards/Passport/modules/views/statusbar.py @@ -30,7 +30,7 @@ def __init__(self, title='', icon=None, fg_color=WHITE): if passport.IS_COLOR: top_pad = 0 else: - top_pad = 2 + top_pad = 4 default.pad(top=top_pad, bottom=0, left=10, right=10) default.pad_col(2) From 336b32dd0aeef2eb44243ac0ddc3c1abc41e099f Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 8 May 2023 11:21:25 -0500 Subject: [PATCH 082/187] SFT-2016: lowered statusbar further, shortened update firmware statusbar for mono --- .../boards/Passport/modules/flows/envoy_setup_flow.py | 6 ++++-- .../boards/Passport/modules/flows/manual_setup_flow.py | 6 ++++-- ports/stm32/boards/Passport/modules/menus.py | 8 +++++++- ports/stm32/boards/Passport/modules/views/statusbar.py | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py index 605712071..aeac93669 100644 --- a/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py @@ -71,6 +71,7 @@ async def set_initial_pin(self): async def update_firmware(self): from pages import ErrorPage, QuestionPage + import passport # Guards to ensure we can't get into a weird state if not self.ensure_pin_set(): @@ -78,10 +79,11 @@ async def update_firmware(self): await self.ensure_logged_in() # Intro page + title = 'UPDATE' + (' FIRMWARE' if passport.IS_COLOR else '') result = await QuestionPage( icon=lv.LARGE_ICON_FIRMWARE, text='Do you want to update Passport\'s firmware now?', - statusbar={'title': 'UPDATE FIRMWARE', 'icon': lv.ICON_FIRMWARE}).show() + statusbar={'title': title, 'icon': lv.ICON_FIRMWARE}).show() if not result: await ErrorPage(text='We recommend updating Passport\'s firmware at your earliest convenience.').show() self.goto(self.setup_seed) @@ -89,7 +91,7 @@ async def update_firmware(self): result = await UpdateFirmwareFlow( reset_after=False, - statusbar={'title': 'UPDATE FIRMWARE', 'icon': lv.ICON_FIRMWARE} + statusbar={'title': title, 'icon': lv.ICON_FIRMWARE} ).run() if result: import machine diff --git a/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py index 0e0392f46..89bd158a1 100644 --- a/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py @@ -65,6 +65,7 @@ async def set_initial_pin(self): async def update_firmware(self): from pages import ErrorPage, QuestionPage + import passport # Guards to ensure we can't get into a weird state if not self.ensure_pin_set(): @@ -72,10 +73,11 @@ async def update_firmware(self): await self.ensure_logged_in() # Intro page + title = 'UPDATE' + (' FIRMWARE' if passport.IS_COLOR else '') result = await QuestionPage( icon=lv.LARGE_ICON_FIRMWARE, text='Do you want to update Passport\'s firmware now?', - statusbar={'title': 'UPDATE FIRMWARE', 'icon': lv.ICON_FIRMWARE}).show() + statusbar={'title': title, 'icon': lv.ICON_FIRMWARE}).show() if not result: await ErrorPage(text='We recommend updating Passport\'s firmware at your earliest convenience.').show() self.goto(self.setup_seed) @@ -83,7 +85,7 @@ async def update_firmware(self): result = await UpdateFirmwareFlow( reset_after=False, - statusbar={'title': 'UPDATE FIRMWARE', 'icon': lv.ICON_FIRMWARE} + statusbar={'title': title, 'icon': lv.ICON_FIRMWARE} ).run() if result: import machine diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index d2d693511..8d88d7eb5 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -241,9 +241,15 @@ def security_menu(): def update_menu(): from flows import UpdateFirmwareFlow, ViewCurrentFirmwareFlow from utils import is_logged_in + import passport + title = 'UPDATE' + (' FIRMWARE' if passport.IS_COLOR else '') return [ - {'icon': lv.ICON_FIRMWARE, 'label': 'Update Firmware', 'flow': UpdateFirmwareFlow, 'is_visible': is_logged_in}, + {'icon': lv.ICON_FIRMWARE, + 'label': 'Update Firmware', + 'flow': UpdateFirmwareFlow, + 'is_visible': is_logged_in, + 'statusbar': {'title': title, 'icon': lv.ICON_FIRMWARE}}, {'icon': lv.ICON_INFO, 'label': 'Current Version', 'flow': ViewCurrentFirmwareFlow, 'statusbar': {}}, ] diff --git a/ports/stm32/boards/Passport/modules/views/statusbar.py b/ports/stm32/boards/Passport/modules/views/statusbar.py index 5f1fb2bc5..58c11c960 100644 --- a/ports/stm32/boards/Passport/modules/views/statusbar.py +++ b/ports/stm32/boards/Passport/modules/views/statusbar.py @@ -30,7 +30,7 @@ def __init__(self, title='', icon=None, fg_color=WHITE): if passport.IS_COLOR: top_pad = 0 else: - top_pad = 4 + top_pad = 6 default.pad(top=top_pad, bottom=0, left=10, right=10) default.pad_col(2) From bbee771851e44ade3f5ed149361ecb84a8662f9e Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 9 May 2023 15:44:03 -0500 Subject: [PATCH 083/187] SFT-2016: moved statusbar down 2 more pixels --- ports/stm32/boards/Passport/modules/views/statusbar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/views/statusbar.py b/ports/stm32/boards/Passport/modules/views/statusbar.py index 58c11c960..193f64a21 100644 --- a/ports/stm32/boards/Passport/modules/views/statusbar.py +++ b/ports/stm32/boards/Passport/modules/views/statusbar.py @@ -30,7 +30,7 @@ def __init__(self, title='', icon=None, fg_color=WHITE): if passport.IS_COLOR: top_pad = 0 else: - top_pad = 6 + top_pad = 8 default.pad(top=top_pad, bottom=0, left=10, right=10) default.pad_col(2) From 4648d2052453f1b09e37db9ef1bb59b318460d74 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 12 May 2023 12:11:27 -0500 Subject: [PATCH 084/187] SFT-938: added address 0 check --- .../modules/flows/verify_address_flow.py | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py b/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py index e9451e210..b99241024 100644 --- a/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py @@ -109,6 +109,11 @@ async def scan_address(self): self.goto(self.search_for_address) + def finalize(self, addr_idx, is_change): + self.found_addr_idx = addr_idx + self.found_is_change = is_change == 1 + self.goto(self.found) + async def search_for_address(self): from tasks import search_for_address_task from utils import get_prev_address_range, get_next_address_range, spinner_task @@ -123,6 +128,23 @@ async def search_for_address(self): addr_idx = -1 is_change = 0 + (addr_idx, path_info, error) = await spinner_task( + 'Searching Addresses', + search_for_address_task, + min_duration_ms=0, + args=[self.deriv_path, + 0, + self.address, + self.addr_type, + self.multisig_wallet, + is_change, + 1, + True]) + + if addr_idx >= 0: + self.finalize(addr_idx, is_change) + return + for is_change in range(0, 2): # print('CHECKING: low_range={} low_size={}'.format(self.low_range, self.low_size)) # Check downwards @@ -130,6 +152,7 @@ async def search_for_address(self): (addr_idx, path_info, error) = await spinner_task( 'Searching Addresses', search_for_address_task, + min_duration_ms=0, args=[self.deriv_path, self.low_range[is_change][0], self.address, @@ -148,6 +171,7 @@ async def search_for_address(self): (addr_idx, path_info, error) = await spinner_task( 'Searching Addresses', search_for_address_task, + min_duration_ms=0, args=[self.deriv_path, self.high_range[is_change][0], self.address, @@ -161,9 +185,7 @@ async def search_for_address(self): break if addr_idx >= 0: - self.found_addr_idx = addr_idx - self.found_is_change = is_change == 1 - self.goto(self.found) + self.finalize(addr_idx, is_change) else: self.goto(self.not_found) From 3f2a3b71f3e548dac6b30321b371e295f4a3672f Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 12 May 2023 11:42:10 -0500 Subject: [PATCH 085/187] SFT-1970: reordered just hash output --- ports/stm32/Justfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/stm32/Justfile b/ports/stm32/Justfile index 18c870bd7..542920155 100644 --- a/ports/stm32/Justfile +++ b/ports/stm32/Justfile @@ -345,12 +345,14 @@ hash filepath screen="mono" output_file="": build_hash=`cosign -t {{screen}} -p -f {{filepath}} | sed -rn 's/^FW Build Hash: (.*)$/\1/p'` echo "$build_hash" > ${directory}/${release_name}-build-hash - output="## RELEASE HASHES\n\nSHA256: \`$sha\`\nMD5: \`$md5\`\n\nYou can check these hashes with the following commands on most operating systems:\n\n" + output="## RELEASE HASHES\n\n" if [ -n "{{output_file}}" ]; then output+="### $filename:\n\n" fi + output+="SHA256: \`$sha\`\nMD5: \`$md5\`\n\nYou can check these hashes with the following commands on most operating systems:\n\n" + output+="SHA256: \`shasum -b -a 256 $filename\`\nMD5: \`md5 $filename\` or \`mdsum $filename\` or \`md5sum $filename\`\n\n" output+="### DEVELOPERS ONLY\n\nBuild Hash: \`$build_hash\`" From 40c26b8fdd24898676efc2ec9538d4111be0901b Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 12 May 2023 11:29:43 -0500 Subject: [PATCH 086/187] SFT-2078: removed sign_it --- ports/stm32/boards/Passport/modules/psbt.py | 136 -------------------- 1 file changed, 136 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/psbt.py b/ports/stm32/boards/Passport/modules/psbt.py index 5fa028242..f0c3a5fa0 100644 --- a/ports/stm32/boards/Passport/modules/psbt.py +++ b/ports/stm32/boards/Passport/modules/psbt.py @@ -1397,142 +1397,6 @@ def wr(*a): outp.serialize(out_fd, idx) out_fd.write(b'\0') - # def sign_it(self): - # # txn is approved. sign all inputs we can sign. add signatures - # # - hash the txn first - # # - sign all inputs we have the key for - # # - inputs might be p2sh, p2pkh and/or segwit style - # # - save partial inputs somewhere (append?) - # # - update our state with new partial sigs - - # with stash.SensitiveValues() as sv: - # # Double check the change outputs are right. This is slow, but critical because - # # it detects bad actors, not bugs or mistakes. - # # - equivilent check already done for p2sh outputs when we re-built the redeem script - # change_outs = [n for n, o in enumerate(self.outputs) if o.is_change] - # if change_outs: - - # for count, out_idx in enumerate(change_outs): - # # only expecting single case, but be general - - # oup = self.outputs[out_idx] - - # good = 0 - # for pubkey, subpath in oup.subpaths.items(): - # if subpath[0] != self.my_xfp and subpath[0] != swab32(self.my_xfp): - # # for multisig, will be N paths, and exactly one will - # # be our key. For single-signer, should always be my XFP - # continue - - # # derive actual pubkey from private - # skp = keypath_to_str(subpath) - # node = sv.derive_path(skp) - - # # check the pubkey of this BIP32 node - # if pubkey == node.public_key(): - # good += 1 - - # if not good: - # raise FraudulentChangeOutput(out_idx, - # "Deception regarding change output. " - # "BIP32 path doesn't match actual address.") - - # # Sign individual inputs - # sigs = 0 - # success = set() - # for in_idx, txi in self.input_iter(): - # inp = self.inputs[in_idx] - - # if not inp.has_utxo(): - # # maybe they didn't provide the UTXO - # continue - - # if not inp.required_key: - # # we don't know the key for this input - # continue - - # if inp.fully_signed: - # # for multisig, it's possible I need to add another sig - # # but in other cases, no more signatures are possible - # continue - - # txi.scriptSig = inp.scriptSig - # assert txi.scriptSig, "no scriptsig?" - - # if not inp.is_segwit: - # # Hash by serializing/blanking various subparts of the transaction - # digest = self.make_txn_sighash(in_idx, txi, inp.sighash) - # else: - # # Hash the inputs and such in totally new ways, based on BIP-143 - # digest = self.make_txn_segwit_sighash(in_idx, txi, - # inp.amount, inp.scriptCode, inp.sighash) - - # if inp.is_multisig: - # # need to consider a set of possible keys, since xfp may not be unique - # for which_key in inp.required_key: - # # get node required - # skp = keypath_to_str(inp.subpaths[which_key]) - # node = sv.derive_path(skp, register=False) - - # # expensive test, but works... and important - # pu = node.public_key() - # if pu == which_key: - # break - # else: - # raise AssertionError("Input #%d needs pubkey I dont have" % in_idx) - - # else: - # # single pubkey <=> single key - # which_key = inp.required_key - - # assert not inp.added_sig, "already done??" - # assert which_key in inp.subpaths, 'unk key' - - # if inp.subpaths[which_key][0] != self.my_xfp and - # inp.subpaths[which_key][0] != swab32(self.my_xfp): - # # we don't have the key for this subkey - # # (redundant, required_key wouldn't be set) - # continue - - # # get node required - # skp = keypath_to_str(inp.subpaths[which_key]) - # node = sv.derive_path(skp, register=False) - - # # expensive test, but works... and important - # pu = node.public_key() - # assert pu == which_key, "Path (%s) led to wrong pubkey for input #%d" % (skp, in_idx) - - # # The precious private key we need - # pk = node.private_key() - - # # print("privkey %s" % b2a_hex(pk).decode('ascii')) - # # print(" pubkey %s" % b2a_hex(which_key).decode('ascii')) - # # print(" digest %s" % b2a_hex(digest).decode('ascii')) - - # # Do the ACTUAL signature ... finally!!! - # result = trezorcrypto.secp256k1.sign(pk, digest) - - # # private key no longer required - # stash.blank_object(pk) - # stash.blank_object(node) - # del pk, node, pu, skp - - # # print("result %s" % b2a_hex(result).decode('ascii')) - - # # convert signature to DER format - # assert len(result) == 65 - # r = result[1:33] - # s = result[33:65] - - # inp.added_sig = (which_key, ser_sig_der(r, s, inp.sighash)) - - # success.add(in_idx) - - # # memory cleanup - # del result, r, s - - # gc.collect() - def make_txn_sighash(self, replace_idx, replacement, sighash_type): # calculate the hash value for one input of current transaction # - blank all script inputs From 0954637143028b055f0c212fc82dc5ebfacdd908 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 12 May 2023 11:26:58 -0500 Subject: [PATCH 087/187] SFT-2081: removed ScanPrivateKeyQRFLow --- ports/stm32/boards/Passport/manifest.py | 1 - .../boards/Passport/modules/flows/__init__.py | 1 - .../modules/flows/scan_private_key_qr_flow.py | 90 ------------------- 3 files changed, 92 deletions(-) delete mode 100644 ports/stm32/boards/Passport/modules/flows/scan_private_key_qr_flow.py diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index a177b34da..8795eba23 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -135,7 +135,6 @@ 'flows/reset_pin_flow.py', 'flows/restore_backup_flow.py', 'flows/restore_seed_flow.py', - 'flows/scan_private_key_qr_flow.py', 'flows/save_to_microsd_flow.py', 'flows/scv_flow.py', 'flows/seed_warning_flow.py', diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index 96572fd2b..d8690c2af 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -59,7 +59,6 @@ from .reset_pin_flow import * from .restore_backup_flow import * from .restore_seed_flow import * -from .scan_private_key_qr_flow import * from .scv_flow import * from .set_chain_flow import * from .set_initial_pin_flow import * diff --git a/ports/stm32/boards/Passport/modules/flows/scan_private_key_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_private_key_qr_flow.py deleted file mode 100644 index b27d6242e..000000000 --- a/ports/stm32/boards/Passport/modules/flows/scan_private_key_qr_flow.py +++ /dev/null @@ -1,90 +0,0 @@ -# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. -# SPDX-License-Identifier: GPL-3.0-or-later -# -# scan_private_key_qr_flow.py - Scan a QR code containing a private key - -from flows import Flow -from pages import ErrorPage, QuestionPage, SuccessPage -from tasks import new_seed_task, save_seed_task -from utils import has_secrets, spinner_task -from translations import t, T - - -class ScanPrivateKeyQRFlow(Flow): - def __init__(self, refresh_cards_when_done=False, autobackup=True, full_backup=False): - super().__init__(initial_state=self.confirm_scan, name='ScanPrivateKeyQRFlow') - self.refresh_cards_when_done = refresh_cards_when_done - self.autobackup = autobackup - self.full_backup = full_backup - - async def confirm_scan(self): - # Ensure we don't overwrite an existing seed - if has_secrets(): - await ErrorPage(text='Passport already has a seed!').show() - self.set_result(False) - return - - result = await QuestionPage(text='Scan a private key QR now? Make sure you trust the source.').show() - if result: - self.goto(self.scan_seed) - else: - self.set_result(False) - - async def scan_seed(self): - from pages import ScanQRPage, ErrorPage - from ubinascii import unhexlify as a2b_hex - - result = await ScanQRPage().show() - - if result is None: - self.set_result(False) - return - - try: - seed = a2b_hex(result.data) - except Exception as e: - self.error = "Not a valid seed" - self.goto(self.show_error) - return - - if len(seed) > 32: - self.error = "Seed too long" - self.goto(self.show_error) - return - - self.seed = seed - self.goto(self.save_seed) - - async def save_seed(self): - (error,) = await spinner_task('Saving Seed', save_seed_task, args=[self.seed]) - if error is None: - self.goto(self.show_seed_words) - else: - self.error = 'Unable to save seed.' - self.goto(self.show_error) - - async def show_seed_words(self): - from flows import ViewSeedWordsFlow - await ViewSeedWordsFlow().run() - self.goto(self.show_success) - - async def show_success(self): - import common - from flows import AutoBackupFlow, BackupFlow - - await SuccessPage(text='New seed saved.').show() - if self.full_backup: - await BackupFlow().run() - elif self.autobackup: - await AutoBackupFlow(offer=True).run() - - if self.refresh_cards_when_done: - common.ui.full_cards_refresh() - - await self.wait_to_die() - else: - self.set_result(True) - - async def show_error(self): - await ErrorPage(self.error).show() - self.set_result(False) From 76de1914ea9b4696bd79f1992a139c30897213af Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 12 May 2023 11:17:12 -0500 Subject: [PATCH 088/187] SFT-1899: used ScanQRFlow for address verification --- .../Passport/modules/flows/verify_address_flow.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py b/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py index b99241024..fb238dc26 100644 --- a/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py @@ -67,26 +67,23 @@ async def choose_sig_type(self): async def scan_address(self): import chains - from pages import ErrorPage, ScanQRPage + from pages import ErrorPage + from flows import ScanQRFlow from wallets.utils import get_addr_type_from_address, get_deriv_path_from_addr_type_and_acct from utils import is_valid_btc_address, get_next_addr + from data_codecs.qr_type import QRType - result = await ScanQRPage( - left_micron=microns.Back, - right_micron=None).show() + result = await ScanQRFlow(qr_types=[QRType.QR], + data_description='a Bitcoin address').run() if result is None: if not self.back(): self.set_result(False) return return - elif result.is_failure(): - await ErrorPage(text='Unable to scan QR code.').show() - self.set_result(False) - return # print('result={}'.format(result)) - self.address = result.data + self.address = result # Simple check on the data type first chain_name = chains.current_chain().name From 984e144a06ee258bc4d1c65fa564ce906fe9da49 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 12 May 2023 13:39:27 -0500 Subject: [PATCH 089/187] SFT-1846: back button now only hides symbol picker when it's out --- ports/stm32/boards/Passport/modules/pages/text_input_page.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/stm32/boards/Passport/modules/pages/text_input_page.py b/ports/stm32/boards/Passport/modules/pages/text_input_page.py index 062951e63..a1502360a 100644 --- a/ports/stm32/boards/Passport/modules/pages/text_input_page.py +++ b/ports/stm32/boards/Passport/modules/pages/text_input_page.py @@ -84,6 +84,7 @@ def left_action(self, is_pressed): if self.is_showing_symbols: self.is_showing_symbols = False self.update_symbol_picker() + return self.set_result(None) def attach(self, group): From 3ef5c1fe3f36a326e12b5906ff8114ed05ead39a Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 12 May 2023 15:32:17 -0500 Subject: [PATCH 090/187] SFT-1846: updated t9 to use correct mode after exiting symbol picker --- ports/stm32/boards/Passport/modules/pages/text_input_page.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/boards/Passport/modules/pages/text_input_page.py b/ports/stm32/boards/Passport/modules/pages/text_input_page.py index a1502360a..e5aa55528 100644 --- a/ports/stm32/boards/Passport/modules/pages/text_input_page.py +++ b/ports/stm32/boards/Passport/modules/pages/text_input_page.py @@ -84,6 +84,8 @@ def left_action(self, is_pressed): if self.is_showing_symbols: self.is_showing_symbols = False self.update_symbol_picker() + self.t9.set_mode(self.last_input_mode) + self.synchronize_with_t9() return self.set_result(None) From 8b6f122e2fd1fbc9a871115d6a956eeb4f0d7818 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 15 May 2023 15:20:33 -0500 Subject: [PATCH 091/187] SFT-2011: fixed SCV non-envoy flow --- ports/stm32/boards/Passport/modules/flows/scv_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index 7980af4ea..08195df01 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -75,7 +75,7 @@ async def scan_qr_challenge(self): try: scv_id = a2b_hex(parts[0]) - scv_signature = b2a_hex(parts[1]) + scv_signature = a2b_hex(parts[1]) except ValueError: await self.show_error('Security Check QR code is invalid.\n') return From 07bdb356328a8d21fe200645442da07e0d47da21 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 15 May 2023 16:34:53 -0500 Subject: [PATCH 092/187] SFT-2015: cancel transaction option cutoff --- .../boards/Passport/modules/flows/sign_psbt_common_flow.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_common_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_common_flow.py index 5aea21be4..5b84c08ee 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_common_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_common_flow.py @@ -148,11 +148,7 @@ async def sign_transaction(self): options = [{'label': 'Cancel', 'value': True}, {'label': 'Review Details', 'value': False}] - should_cancel = await ChooserPage( - text='Cancel this transaction?', - options=options, - icon=lv.LARGE_ICON_QUESTION, - initial_value=options[0].get('value')).show() + should_cancel = await QuestionPage(text='Cancel this transaction?').show() if should_cancel: self.set_result(None) else: From 66e2df545780ac7188e15a75d74bc64cf4a80d1f Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Tue, 16 May 2023 12:34:51 +0200 Subject: [PATCH 093/187] SFT-2102: Fix signed/unsigned comparisons Signed-off-by: Jean-Pierre De Jesus DIAZ --- extmod/foundation/modfoundation.c | 2 +- lib/lv_bindings/lvgl/src/extra/libs/qrcode/lv_qrcode.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extmod/foundation/modfoundation.c b/extmod/foundation/modfoundation.c index af2f4c918..80858c6dc 100644 --- a/extmod/foundation/modfoundation.c +++ b/extmod/foundation/modfoundation.c @@ -55,7 +55,7 @@ STATIC mp_obj_t mod_foundation_convert_rgb565_to_grayscale(size_t n_args, const mp_raise_ValueError(MP_ERROR_TEXT("invalid rgb565 buffer size")); return mp_const_none; } - if (grayscale_info.len != (hor_res * ver_res)) + if (grayscale_info.len != (size_t)(hor_res * ver_res)) { mp_raise_ValueError(MP_ERROR_TEXT("invalid grayscale buffer size")); return mp_const_none; diff --git a/lib/lv_bindings/lvgl/src/extra/libs/qrcode/lv_qrcode.c b/lib/lv_bindings/lvgl/src/extra/libs/qrcode/lv_qrcode.c index d901968c6..51460667f 100644 --- a/lib/lv_bindings/lvgl/src/extra/libs/qrcode/lv_qrcode.c +++ b/lib/lv_bindings/lvgl/src/extra/libs/qrcode/lv_qrcode.c @@ -122,7 +122,7 @@ lv_res_t lv_qrcode_update(lv_obj_t * obj, const void * data, uint32_t data_len, int32_t remain = res % qr_size; /* The qr version is incremented by four point */ - uint32_t version_extend = remain / (scale << 2); + int32_t version_extend = remain / (scale << 2); if(version_extend && qr_version < qrcodegen_VERSION_MAX) { qr_version = qr_version + version_extend > qrcode->max_version ? qrcode->max_version : qr_version + version_extend; From 3a42d51310fc77b9d8296aaff2a2d2a3974efbe0 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Thu, 4 May 2023 13:28:03 +0200 Subject: [PATCH 094/187] SFT-1961: Add rust-secp256k1 as a dependency Signed-off-by: Jean-Pierre De Jesus DIAZ --- extmod/foundation-rust/.cargo/config.toml | 4 + extmod/foundation-rust/Cargo.lock | 78 +++++++++++++++++++ extmod/foundation-rust/Cargo.toml | 15 +++- ports/stm32/boards/Passport/mpconfigboard.mk | 2 +- .../variant/simulator/mpconfigvariant.mk | 2 + 5 files changed, 99 insertions(+), 2 deletions(-) diff --git a/extmod/foundation-rust/.cargo/config.toml b/extmod/foundation-rust/.cargo/config.toml index 720ee44d2..36c3eb91b 100644 --- a/extmod/foundation-rust/.cargo/config.toml +++ b/extmod/foundation-rust/.cargo/config.toml @@ -5,4 +5,8 @@ rustflags = [ "--cfg", "dtcm", "--cfg", "sram4", + "--cfg", "rust_secp_no_symbol_renaming", ] + +[target.x86_64-unknown-none] +rustflags = ["--cfg", "rust_secp_no_symbol_renaming"] diff --git a/extmod/foundation-rust/Cargo.lock b/extmod/foundation-rust/Cargo.lock index 6febb1ac9..028a08349 100644 --- a/extmod/foundation-rust/Cargo.lock +++ b/extmod/foundation-rust/Cargo.lock @@ -29,6 +29,18 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "crc" version = "3.0.1" @@ -62,11 +74,25 @@ version = "0.1.0" dependencies = [ "heapless", "minicbor", + "rand", + "rand_core", + "secp256k1", "ur", "ur-foundation", "uuid", ] +[[package]] +name = "getrandom" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hash32" version = "0.3.1" @@ -103,6 +129,12 @@ dependencies = [ "either", ] +[[package]] +name = "libc" +version = "0.2.142" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" + [[package]] name = "lock_api" version = "0.4.9" @@ -175,6 +207,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" version = "1.0.52" @@ -199,6 +237,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -207,6 +257,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "rand_xoshiro" @@ -232,6 +285,25 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "rand", + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + [[package]] name = "semver" version = "1.0.17" @@ -308,3 +380,9 @@ name = "uuid" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/extmod/foundation-rust/Cargo.toml b/extmod/foundation-rust/Cargo.toml index 04029a556..e21a6f94b 100644 --- a/extmod/foundation-rust/Cargo.toml +++ b/extmod/foundation-rust/Cargo.toml @@ -34,9 +34,22 @@ git = "https://github.com/Foundation-Devices/rust-ur-foundation" branch = "dev-v0.1.0" default-features = false +[dependencies.secp256k1] +version = "0.27" +default-features = false +features = ["rand"] + +[dependencies.rand] +version = "0.8.5" +default-features = false + +[dependencies.rand_core] +version = "0.6.4" +default-features = false + [features] default = [] -std = [] +std = ["rand/std"] [lib] crate-type = ["lib", "staticlib"] diff --git a/ports/stm32/boards/Passport/mpconfigboard.mk b/ports/stm32/boards/Passport/mpconfigboard.mk index 359189800..997bce56f 100644 --- a/ports/stm32/boards/Passport/mpconfigboard.mk +++ b/ports/stm32/boards/Passport/mpconfigboard.mk @@ -95,4 +95,4 @@ ifeq ($(SCREEN_MODE), COLOR) endif RUST_TARGET := thumbv7em-none-eabihf -export RUSTFLAGS := --cfg dtcm --cfg sram4 +export RUSTFLAGS := --cfg dtcm --cfg sram4 --cfg rust_secp_no_symbol_renaming diff --git a/simulator/variant/simulator/mpconfigvariant.mk b/simulator/variant/simulator/mpconfigvariant.mk index 60ac1362a..374a65d36 100644 --- a/simulator/variant/simulator/mpconfigvariant.mk +++ b/simulator/variant/simulator/mpconfigvariant.mk @@ -11,3 +11,5 @@ CFLAGS_MOD += -DBL_FW_HDR_BASE=0 FROZEN_MANIFEST = FROZEN_MPY_DIR = + +export RUSTFLAGS := --cfg sram4 --cfg rust_secp_no_symbol_renaming From 0b2f5829141f19026ec3e252f6a7a2a4e902a930 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Thu, 4 May 2023 14:08:39 +0200 Subject: [PATCH 095/187] SFT-1961: Don't include Keccak on trezocrypto Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c | 8 ++++++++ extmod/trezor-firmware/crypto/bip32.c | 4 ++-- extmod/trezor-firmware/crypto/secp256k1.c | 2 ++ py/py.mk | 6 ++++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c index 6b07ada05..4f6380ea2 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -44,7 +44,9 @@ static void wrapped_ui_wait_callback(uint32_t current, uint32_t total) { #include "modtrezorcrypto-chacha20poly1305.h" #include "modtrezorcrypto-crc.h" #include "modtrezorcrypto-curve25519.h" +#if USE_KECCAK #include "modtrezorcrypto-ed25519.h" +#endif #include "modtrezorcrypto-groestl.h" #include "modtrezorcrypto-hmac.h" #include "modtrezorcrypto-nist256p1.h" @@ -54,8 +56,10 @@ static void wrapped_ui_wait_callback(uint32_t current, uint32_t total) { #include "modtrezorcrypto-secp256k1.h" #include "modtrezorcrypto-sha1.h" #include "modtrezorcrypto-sha256.h" +#if USE_KECCAK #include "modtrezorcrypto-sha3-256.h" #include "modtrezorcrypto-sha3-512.h" +#endif #include "modtrezorcrypto-sha512.h" #include "modtrezorcrypto-shamir.h" #include "modtrezorcrypto-slip39.h" @@ -83,8 +87,10 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_crc), MP_ROM_PTR(&mod_trezorcrypto_crc_module)}, {MP_ROM_QSTR(MP_QSTR_curve25519), MP_ROM_PTR(&mod_trezorcrypto_curve25519_module)}, +#if USE_KECCAK {MP_ROM_QSTR(MP_QSTR_ed25519), MP_ROM_PTR(&mod_trezorcrypto_ed25519_module)}, +#endif #if !BITCOIN_ONLY {MP_ROM_QSTR(MP_QSTR_monero), MP_ROM_PTR(&mod_trezorcrypto_monero_module)}, #endif @@ -106,10 +112,12 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&mod_trezorcrypto_Sha1_type)}, {MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&mod_trezorcrypto_Sha256_type)}, {MP_ROM_QSTR(MP_QSTR_sha512), MP_ROM_PTR(&mod_trezorcrypto_Sha512_type)}, +#if USE_KECCAK {MP_ROM_QSTR(MP_QSTR_sha3_256), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_type)}, {MP_ROM_QSTR(MP_QSTR_sha3_512), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_type)}, +#endif {MP_ROM_QSTR(MP_QSTR_shamir), MP_ROM_PTR(&mod_trezorcrypto_shamir_module)}, {MP_ROM_QSTR(MP_QSTR_slip39), MP_ROM_PTR(&mod_trezorcrypto_slip39_module)}, }; diff --git a/extmod/trezor-firmware/crypto/bip32.c b/extmod/trezor-firmware/crypto/bip32.c index 7811d66a4..d6d99eeb0 100644 --- a/extmod/trezor-firmware/crypto/bip32.c +++ b/extmod/trezor-firmware/crypto/bip32.c @@ -475,10 +475,8 @@ int hdnode_fill_public_key(HDNode *node) { ed25519_publickey(node->private_key, node->public_key + 1); } else if (node->curve == &ed25519_sha3_info) { ed25519_publickey_sha3(node->private_key, node->public_key + 1); -#if USE_KECCAK } else if (node->curve == &ed25519_keccak_info) { ed25519_publickey_keccak(node->private_key, node->public_key + 1); -#endif } else if (node->curve == &curve25519_info) { curve25519_scalarmult_basepoint(node->public_key + 1, node->private_key); #if USE_CARDANO @@ -793,9 +791,11 @@ const curve_info *get_curve_by_name(const char *curve_name) { if (strcmp(curve_name, SECP256K1_GROESTL_NAME) == 0) { return &secp256k1_groestl_info; } +#if USE_KECCAK if (strcmp(curve_name, SECP256K1_SMART_NAME) == 0) { return &secp256k1_smart_info; } +#endif if (strcmp(curve_name, NIST256P1_NAME) == 0) { return &nist256p1_info; } diff --git a/extmod/trezor-firmware/crypto/secp256k1.c b/extmod/trezor-firmware/crypto/secp256k1.c index 34ccaaacb..38c3fc0e2 100644 --- a/extmod/trezor-firmware/crypto/secp256k1.c +++ b/extmod/trezor-firmware/crypto/secp256k1.c @@ -84,6 +84,7 @@ const curve_info secp256k1_groestl_info = { .hasher_script = HASHER_SHA2, }; +#if USE_KECCAK const curve_info secp256k1_smart_info = { .bip32_name = "Bitcoin seed", .params = &secp256k1, @@ -92,3 +93,4 @@ const curve_info secp256k1_smart_info = { .hasher_pubkey = HASHER_SHA2_RIPEMD, .hasher_script = HASHER_SHA2, }; +#endif diff --git a/py/py.mk b/py/py.mk index 6fb46815b..7311969c0 100644 --- a/py/py.mk +++ b/py/py.mk @@ -104,6 +104,10 @@ $(LODEPNG_C): $(LODEPNG_DIR)/lodepng.cpp $(LODEPNG_DIR)/* SRC_MOD += $(subst $(TOP)/,,$(LODEPNG_C) $(MP_LODEPNG_C) $(LODEPNG_MODULE)) +# trezorcrypto +CFLAGS_MOD += -DUSE_BIP32_25519_CURVES=0 \ + -DUSE_KECCAK=0 \ + # External modules written in C. ifneq ($(USER_C_MODULES),) # pre-define USERMOD variables as expanded so that variables are immediate @@ -374,8 +378,6 @@ PY_EXTMOD_O_BASENAME = \ extmod/trezor-firmware/crypto/ed25519-donna/ed25519-donna-impl-base.o \ extmod/trezor-firmware/crypto/ed25519-donna/ed25519.o \ extmod/trezor-firmware/crypto/ed25519-donna/curve25519-donna-scalarmult-base.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519-keccak.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519-sha3.o \ extmod/trezor-firmware/crypto/chacha20poly1305/chacha20poly1305.o \ extmod/trezor-firmware/crypto/chacha20poly1305/chacha_merged.o \ extmod/trezor-firmware/crypto/chacha20poly1305/poly1305-donna.o \ From 67158fee6b28fcd62918cbc649761b1307041fe2 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Thu, 4 May 2023 14:39:15 +0200 Subject: [PATCH 096/187] SFT-1961: Remove unused include Signed-off-by: Jean-Pierre De Jesus DIAZ --- ports/stm32/boards/Passport/mpconfigboard.mk | 2 +- ports/unix/mpconfigport.mk | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/mpconfigboard.mk b/ports/stm32/boards/Passport/mpconfigboard.mk index 997bce56f..dae9063d3 100644 --- a/ports/stm32/boards/Passport/mpconfigboard.mk +++ b/ports/stm32/boards/Passport/mpconfigboard.mk @@ -52,7 +52,7 @@ build-Passport/boards/Passport/crypto/%.o: CFLAGS_MOD += \ -DUSE_BIP39_CACHE=0 -DBIP32_CACHE_SIZE=0 -DUSE_BIP32_CACHE=0 -DBIP32_CACHE_MAXDEPTH=0 \ -DRAND_PLATFORM_INDEPENDENT=1 -DUSE_BIP39_GENERATE=0 -DUSE_BIP32_25519_CURVES=0 -CFLAGS_MOD += -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core/embed/extmod/modtrezorcrypto -Iboards/$(BOARD)/trezor-firmware/core +CFLAGS_MOD += -Iboards/$(BOARD)/trezor-firmware/core # Bootloader CFLAGS CFLAGS_MOD += -DBL_NVROM_BASE=$(BL_NVROM_BASE) diff --git a/ports/unix/mpconfigport.mk b/ports/unix/mpconfigport.mk index 30374e1c4..f4bc2c3fe 100644 --- a/ports/unix/mpconfigport.mk +++ b/ports/unix/mpconfigport.mk @@ -54,7 +54,6 @@ CFLAGS_MOD += -I$(MICROPY_EXTMOD_DIR) \ -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/chacha20poly1305 \ -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/ed25519-donna \ -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core/embed/unix \ -I$(MICROPY_EXTMOD_DIR)/../ports/stm32/boards/Passport/include \ -I$(MICROPY_EXTMOD_DIR)/../ports/stm32/boards/Passport/common/micro-ecc # TODO: Move this the ports/stm32/boards/Passport include files? From 4accf5cc1f49a3d1e80fbc2e09095b9f456105b0 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Thu, 4 May 2023 14:44:53 +0200 Subject: [PATCH 097/187] SFT-1961: Remove duplicated include Signed-off-by: Jean-Pierre De Jesus DIAZ --- ports/stm32/boards/Passport/mpconfigboard.mk | 2 -- 1 file changed, 2 deletions(-) diff --git a/ports/stm32/boards/Passport/mpconfigboard.mk b/ports/stm32/boards/Passport/mpconfigboard.mk index dae9063d3..9ff2af891 100644 --- a/ports/stm32/boards/Passport/mpconfigboard.mk +++ b/ports/stm32/boards/Passport/mpconfigboard.mk @@ -52,8 +52,6 @@ build-Passport/boards/Passport/crypto/%.o: CFLAGS_MOD += \ -DUSE_BIP39_CACHE=0 -DBIP32_CACHE_SIZE=0 -DUSE_BIP32_CACHE=0 -DBIP32_CACHE_MAXDEPTH=0 \ -DRAND_PLATFORM_INDEPENDENT=1 -DUSE_BIP39_GENERATE=0 -DUSE_BIP32_25519_CURVES=0 -CFLAGS_MOD += -Iboards/$(BOARD)/trezor-firmware/core - # Bootloader CFLAGS CFLAGS_MOD += -DBL_NVROM_BASE=$(BL_NVROM_BASE) CFLAGS_MOD += -DBL_NVROM_SIZE=$(BL_NVROM_SIZE) From 178ec823510ba1f0d7cb6d4f2017b5db58502af0 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Thu, 4 May 2023 14:57:50 +0200 Subject: [PATCH 098/187] SFT-1961: Move trezorcrypto flags to py.mk Signed-off-by: Jean-Pierre De Jesus DIAZ --- mpy-cross/Makefile | 1 - ports/stm32/boards/Passport/mpconfigboard.mk | 9 +-------- ports/unix/mpconfigport.mk | 7 ------- py/py.mk | 11 ++++++++++- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile index d778539ef..74f5ea722 100644 --- a/mpy-cross/Makefile +++ b/mpy-cross/Makefile @@ -17,7 +17,6 @@ INC += -I$(BUILD) INC += -I$(TOP) INC += -I$(TOP)/extmod INC += -I$(TOP)/extmod/quirc -INC += -I$(TOP)/extmod/trezor-firmware/crypto INC += -I$(TOP)/ports/stm32/boards/Passport/include INC += -I$(TOP)/ports/stm32/boards/Passport/common/micro-ecc/ diff --git a/ports/stm32/boards/Passport/mpconfigboard.mk b/ports/stm32/boards/Passport/mpconfigboard.mk index 9ff2af891..338d5f7b0 100644 --- a/ports/stm32/boards/Passport/mpconfigboard.mk +++ b/ports/stm32/boards/Passport/mpconfigboard.mk @@ -38,14 +38,7 @@ FROZEN_MANIFEST ?= boards/Passport/manifest.py MICROPY_EXTMOD_DIR = ../../extmod CFLAGS_MOD += -I$(MICROPY_EXTMOD_DIR) \ -I$(MICROPY_EXTMOD_DIR)/foundation \ - -I$(MICROPY_EXTMOD_DIR)/quirc \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/aes \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/chacha20poly1305 \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/ed25519-donna \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core - -CFLAGS_MOD += -DBITCOIN_ONLY=1 -DAES_128=1 -DAES_192=1 + -I$(MICROPY_EXTMOD_DIR)/quirc # settings that apply only to crypto C-lang code build-Passport/boards/Passport/crypto/%.o: CFLAGS_MOD += \ diff --git a/ports/unix/mpconfigport.mk b/ports/unix/mpconfigport.mk index f4bc2c3fe..8e72b0aa5 100644 --- a/ports/unix/mpconfigport.mk +++ b/ports/unix/mpconfigport.mk @@ -42,18 +42,11 @@ MICROPY_PY_JNI = 0 # as submodules (currently affects only libffi). MICROPY_STANDALONE = 0 -CFLAGS_MOD += -DBITCOIN_ONLY=1 -DAES_128=1 -DAES_192=1 - MICROPY_EXTMOD_DIR = ../../extmod CFLAGS_MOD += -I$(MICROPY_EXTMOD_DIR) \ -I$(MICROPY_EXTMOD_DIR)/foundation \ -I$(MICROPY_EXTMOD_DIR)/quirc \ -I$(MICROPY_EXTMOD_DIR)/uasyncio \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/aes \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/chacha20poly1305 \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/ed25519-donna \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core \ -I$(MICROPY_EXTMOD_DIR)/../ports/stm32/boards/Passport/include \ -I$(MICROPY_EXTMOD_DIR)/../ports/stm32/boards/Passport/common/micro-ecc # TODO: Move this the ports/stm32/boards/Passport include files? diff --git a/py/py.mk b/py/py.mk index 7311969c0..1d60cd699 100644 --- a/py/py.mk +++ b/py/py.mk @@ -106,7 +106,16 @@ SRC_MOD += $(subst $(TOP)/,,$(LODEPNG_C) $(MP_LODEPNG_C) $(LODEPNG_MODULE)) # trezorcrypto CFLAGS_MOD += -DUSE_BIP32_25519_CURVES=0 \ - -DUSE_KECCAK=0 \ + -DUSE_KECCAK=0 \ + -DBITCOIN_ONLY=1 \ + -DAES_128=1 \ + -DAES_192=1 + +INC += -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto \ + -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/aes \ + -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/chacha20poly1305 \ + -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/ed25519-donna \ + -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core # External modules written in C. ifneq ($(USER_C_MODULES),) From 5f353c5334a53babf6e506a64a137d38cb4f427f Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Thu, 4 May 2023 15:00:02 +0200 Subject: [PATCH 099/187] SFT-1961: Use same trezorcrypto flags for simulator and firmware Signed-off-by: Jean-Pierre De Jesus DIAZ --- ports/stm32/boards/Passport/mpconfigboard.mk | 4 +--- py/py.mk | 7 ++++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ports/stm32/boards/Passport/mpconfigboard.mk b/ports/stm32/boards/Passport/mpconfigboard.mk index 338d5f7b0..1a3ac4a26 100644 --- a/ports/stm32/boards/Passport/mpconfigboard.mk +++ b/ports/stm32/boards/Passport/mpconfigboard.mk @@ -41,9 +41,7 @@ CFLAGS_MOD += -I$(MICROPY_EXTMOD_DIR) \ -I$(MICROPY_EXTMOD_DIR)/quirc # settings that apply only to crypto C-lang code -build-Passport/boards/Passport/crypto/%.o: CFLAGS_MOD += \ - -DUSE_BIP39_CACHE=0 -DBIP32_CACHE_SIZE=0 -DUSE_BIP32_CACHE=0 -DBIP32_CACHE_MAXDEPTH=0 \ - -DRAND_PLATFORM_INDEPENDENT=1 -DUSE_BIP39_GENERATE=0 -DUSE_BIP32_25519_CURVES=0 +build-Passport/boards/Passport/crypto/%.o: CFLAGS_MOD += -DRAND_PLATFORM_INDEPENDENT=1 # Bootloader CFLAGS CFLAGS_MOD += -DBL_NVROM_BASE=$(BL_NVROM_BASE) diff --git a/py/py.mk b/py/py.mk index 1d60cd699..013973fed 100644 --- a/py/py.mk +++ b/py/py.mk @@ -109,7 +109,12 @@ CFLAGS_MOD += -DUSE_BIP32_25519_CURVES=0 \ -DUSE_KECCAK=0 \ -DBITCOIN_ONLY=1 \ -DAES_128=1 \ - -DAES_192=1 + -DAES_192=1 \ + -DUSE_BIP39_CACHE=0 \ + -DUSE_BIP39_GENERATE=0 \ + -DUSE_BIP32_CACHE=0 \ + -DBIP32_CACHE_SIZE=0 \ + -DBIP32_CACHE_MAXDEPTH=0 INC += -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto \ -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/aes \ From df4e1bc93884c957c6f0e88c451e87ac618a3703 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Thu, 4 May 2023 16:26:45 +0200 Subject: [PATCH 100/187] SFT-1961: Disable unused trezorcrypto modules Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../extmod/modtrezorcrypto/modtrezorcrypto-bip32.h | 2 -- .../embed/extmod/modtrezorcrypto/modtrezorcrypto.c | 12 ++++++++++++ py/py.mk | 12 ------------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h index 2b96caf3d..288ebe3d0 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-bip32.h @@ -30,8 +30,6 @@ #include "nem.h" #endif -#define FOUNDATION_ADDITIONS - /// package: trezorcrypto.bip32 /// class HDNode: diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c index 4f6380ea2..221a95757 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -34,6 +34,8 @@ static void wrapped_ui_wait_callback(uint32_t current, uint32_t total) { } } +#define FOUNDATION_ADDITIONS + #include "modtrezorcrypto-aes.h" #include "modtrezorcrypto-bip32.h" #include "modtrezorcrypto-bip340.h" @@ -74,6 +76,7 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_aes), MP_ROM_PTR(&mod_trezorcrypto_AES_type)}, {MP_ROM_QSTR(MP_QSTR_bip32), MP_ROM_PTR(&mod_trezorcrypto_bip32_module)}, {MP_ROM_QSTR(MP_QSTR_bip39), MP_ROM_PTR(&mod_trezorcrypto_bip39_module)}, +#ifndef FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_blake256), MP_ROM_PTR(&mod_trezorcrypto_Blake256_type)}, {MP_ROM_QSTR(MP_QSTR_blake2b), MP_ROM_PTR(&mod_trezorcrypto_Blake2b_type)}, @@ -98,28 +101,37 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { MP_ROM_PTR(&mod_trezorcrypto_nist256p1_module)}, {MP_ROM_QSTR(MP_QSTR_groestl512), MP_ROM_PTR(&mod_trezorcrypto_Groestl512_type)}, +#endif // FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_hmac), MP_ROM_PTR(&mod_trezorcrypto_Hmac_type)}, +#ifndef FOUNDATION_ADDITIONS #if !BITCOIN_ONLY {MP_ROM_QSTR(MP_QSTR_nem), MP_ROM_PTR(&mod_trezorcrypto_nem_module)}, #endif {MP_ROM_QSTR(MP_QSTR_pbkdf2), MP_ROM_PTR(&mod_trezorcrypto_Pbkdf2_type)}, +#endif // FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_random), MP_ROM_PTR(&mod_trezorcrypto_random_module)}, {MP_ROM_QSTR(MP_QSTR_ripemd160), MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_type)}, {MP_ROM_QSTR(MP_QSTR_secp256k1), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_module)}, {MP_ROM_QSTR(MP_QSTR_bip340), MP_ROM_PTR(&mod_trezorcrypto_bip340_module)}, +#ifndef FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&mod_trezorcrypto_Sha1_type)}, +#endif // FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&mod_trezorcrypto_Sha256_type)}, +#ifndef FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_sha512), MP_ROM_PTR(&mod_trezorcrypto_Sha512_type)}, +#endif // FOUNDATION_ADDITIONS #if USE_KECCAK {MP_ROM_QSTR(MP_QSTR_sha3_256), MP_ROM_PTR(&mod_trezorcrypto_Sha3_256_type)}, {MP_ROM_QSTR(MP_QSTR_sha3_512), MP_ROM_PTR(&mod_trezorcrypto_Sha3_512_type)}, #endif +#ifndef FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_shamir), MP_ROM_PTR(&mod_trezorcrypto_shamir_module)}, {MP_ROM_QSTR(MP_QSTR_slip39), MP_ROM_PTR(&mod_trezorcrypto_slip39_module)}, +#endif // FOUNDATION_ADDITIONS }; STATIC MP_DEFINE_CONST_DICT(mp_module_trezorcrypto_globals, mp_module_trezorcrypto_globals_table); diff --git a/py/py.mk b/py/py.mk index 013973fed..aad21294a 100644 --- a/py/py.mk +++ b/py/py.mk @@ -384,18 +384,6 @@ PY_EXTMOD_O_BASENAME = \ extmod/trezor-firmware/crypto/aes/aeskey.o \ extmod/trezor-firmware/crypto/aes/aestab.o \ extmod/trezor-firmware/crypto/aes/aes_modes.o \ - extmod/trezor-firmware/crypto/ed25519-donna/curve25519-donna-32bit.o \ - extmod/trezor-firmware/crypto/ed25519-donna/curve25519-donna-helpers.o \ - extmod/trezor-firmware/crypto/ed25519-donna/modm-donna-32bit.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519-donna-basepoint-table.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519-donna-32bit-tables.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519-donna-impl-base.o \ - extmod/trezor-firmware/crypto/ed25519-donna/ed25519.o \ - extmod/trezor-firmware/crypto/ed25519-donna/curve25519-donna-scalarmult-base.o \ - extmod/trezor-firmware/crypto/chacha20poly1305/chacha20poly1305.o \ - extmod/trezor-firmware/crypto/chacha20poly1305/chacha_merged.o \ - extmod/trezor-firmware/crypto/chacha20poly1305/poly1305-donna.o \ - extmod/trezor-firmware/crypto/chacha20poly1305/rfc7539.o \ extmod/trezor-firmware/crypto/shamir.o \ extmod/trezor-firmware/crypto/groestl.o \ extmod/trezor-firmware/crypto/slip39.o \ From 5799e5d309e427189855deddcba15ed74f2a3c00 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Fri, 5 May 2023 17:19:29 +0200 Subject: [PATCH 101/187] SFT-1961: Add bindings for Schnorr sign Signed-off-by: Jean-Pierre De Jesus DIAZ --- extmod/foundation-rust/.cargo/config.toml | 4 - extmod/foundation-rust/Cargo.lock | 135 ++++++++++++++++-- extmod/foundation-rust/Cargo.toml | 15 +- extmod/foundation-rust/include/foundation.h | 11 ++ extmod/foundation-rust/src/lib.rs | 11 +- extmod/foundation-rust/src/rand.rs | 78 ++++++++++ extmod/foundation-rust/src/secp256k1.rs | 48 +++++++ extmod/foundation/modfoundation-secp56k1.h | 44 ++++++ extmod/foundation/modfoundation.c | 2 + .../extmod/modtrezorcrypto/modtrezorcrypto.c | 4 +- ports/stm32/boards/Passport/mpconfigboard.mk | 2 +- py/py.mk | 18 +-- .../variant/simulator/mpconfigvariant.mk | 2 +- 13 files changed, 339 insertions(+), 35 deletions(-) create mode 100644 extmod/foundation-rust/src/rand.rs create mode 100644 extmod/foundation-rust/src/secp256k1.rs create mode 100644 extmod/foundation/modfoundation-secp56k1.h diff --git a/extmod/foundation-rust/.cargo/config.toml b/extmod/foundation-rust/.cargo/config.toml index 36c3eb91b..720ee44d2 100644 --- a/extmod/foundation-rust/.cargo/config.toml +++ b/extmod/foundation-rust/.cargo/config.toml @@ -5,8 +5,4 @@ rustflags = [ "--cfg", "dtcm", "--cfg", "sram4", - "--cfg", "rust_secp_no_symbol_renaming", ] - -[target.x86_64-unknown-none] -rustflags = ["--cfg", "rust_secp_no_symbol_renaming"] diff --git a/extmod/foundation-rust/Cargo.lock b/extmod/foundation-rust/Cargo.lock index 028a08349..88a7e55f1 100644 --- a/extmod/foundation-rust/Cargo.lock +++ b/extmod/foundation-rust/Cargo.lock @@ -17,12 +17,27 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + [[package]] name = "bitcoin_hashes" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + [[package]] name = "byteorder" version = "1.4.3" @@ -41,6 +56,19 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield", + "critical-section", + "embedded-hal", + "volatile-register", +] + [[package]] name = "crc" version = "3.0.1" @@ -68,12 +96,25 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + [[package]] name = "foundation" version = "0.1.0" dependencies = [ + "cortex-m", + "critical-section", "heapless", "minicbor", + "once_cell", "rand", "rand_core", "secp256k1", @@ -109,7 +150,7 @@ source = "git+https://github.com/japaric/heapless#644653bf3b831c6bb4963be2de2480 dependencies = [ "atomic-polyfill", "hash32", - "rustc_version", + "rustc_version 0.4.0", "spin", "stable_deref_trait", ] @@ -131,9 +172,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.142" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "lock_api" @@ -165,6 +206,31 @@ dependencies = [ "syn", ] +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +dependencies = [ + "atomic-polyfill", + "critical-section", +] + [[package]] name = "phf" version = "0.11.1" @@ -215,18 +281,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.52" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.24" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50686e0021c4136d1d453b2dfe059902278681512a34d4248435dc34b6b5c8ec" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" dependencies = [ "proc-macro2", ] @@ -270,13 +336,22 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.17", ] [[package]] @@ -304,12 +379,27 @@ dependencies = [ "cc", ] +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "siphasher" version = "0.3.10" @@ -318,9 +408,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "spin" -version = "0.9.6" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5d6e0250b93c8427a177b849d144a96d5acc57006149479403d7861ab721e34" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ "lock_api", ] @@ -377,9 +467,30 @@ dependencies = [ [[package]] name = "uuid" -version = "1.3.0" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" + +[[package]] +name = "vcell" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" +dependencies = [ + "vcell", +] [[package]] name = "wasi" diff --git a/extmod/foundation-rust/Cargo.toml b/extmod/foundation-rust/Cargo.toml index e21a6f94b..341e07111 100644 --- a/extmod/foundation-rust/Cargo.toml +++ b/extmod/foundation-rust/Cargo.toml @@ -34,6 +34,18 @@ git = "https://github.com/Foundation-Devices/rust-ur-foundation" branch = "dev-v0.1.0" default-features = false +[target.'cfg(target_arch = "arm")'.dependencies.cortex-m] +version = "0.7" +features = ["cm7", "critical-section-single-core"] + +[dependencies.critical-section] +version = "1" + +[dependencies.once_cell] +version = "1" +default-features = false +features = ["critical-section"] + [dependencies.secp256k1] version = "0.27" default-features = false @@ -49,7 +61,7 @@ default-features = false [features] default = [] -std = ["rand/std"] +std = ["rand/std", "critical-section/std"] [lib] crate-type = ["lib", "staticlib"] @@ -59,3 +71,4 @@ lto = "fat" opt-level = "z" codegen-units = 1 strip = true +panic = "abort" diff --git a/extmod/foundation-rust/include/foundation.h b/extmod/foundation-rust/include/foundation.h index 2a74674b4..0a88e3b40 100644 --- a/extmod/foundation-rust/include/foundation.h +++ b/extmod/foundation-rust/include/foundation.h @@ -365,6 +365,17 @@ extern UR_Decoder UR_DECODER; extern UR_Encoder UR_ENCODER; +/** + * Computes a Schnorr signature over the message `data`. + * + * - `data` is the message hash. + * - `secret_key` is the secret key used to sign the message. + * - `signature` is the output of the resulting signature. + */ +void foundation_secp256k1_schnorr_sign(const uint8_t (*data)[32], + const uint8_t (*secret_key)[32], + uint8_t (*signature)[64]); + /** * Receive a Uniform Resource part. * diff --git a/extmod/foundation-rust/src/lib.rs b/extmod/foundation-rust/src/lib.rs index 837851b78..693c52679 100644 --- a/extmod/foundation-rust/src/lib.rs +++ b/extmod/foundation-rust/src/lib.rs @@ -4,14 +4,21 @@ #![cfg_attr(not(feature = "std"), no_std)] #![allow(non_camel_case_types)] +#[cfg(target_arch = "arm")] +use cortex_m as _; + +pub mod secp256k1; pub mod ur; /// cbindgen:ignore -#[cfg(not(feature = "std"))] +#[cfg(all(target_os = "none", target_arch = "arm"))] +mod rand; +/// cbindgen:ignore +#[cfg(target_os = "none")] mod stdout; +#[cfg(target_os = "none")] #[panic_handler] -#[cfg(all(not(feature = "std"), not(test)))] fn panic_handler(info: &core::panic::PanicInfo) -> ! { use core::fmt::Write; diff --git a/extmod/foundation-rust/src/rand.rs b/extmod/foundation-rust/src/rand.rs new file mode 100644 index 000000000..1aa0fa07d --- /dev/null +++ b/extmod/foundation-rust/src/rand.rs @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later + +//! Interface to Passport random number generator. + +use core::{ffi::c_void, num::NonZeroU32}; + +use rand::{CryptoRng, Error, RngCore}; + +const ERROR_CODE_FATAL: u32 = 1; + +/// Passport cryptographically secure random number generator. +/// +/// Uses the board's avalanche noise source, the MCU RNG and the +/// hardware RNG. +#[derive(Debug, Clone, Copy)] +pub struct PassportRng; + +impl RngCore for PassportRng { + fn next_u32(&mut self) -> u32 { + rand_core::impls::next_u32_via_fill(self) + } + + fn next_u64(&mut self) -> u64 { + rand_core::impls::next_u64_via_fill(self) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.try_fill_bytes(dest).expect("fatal Passport RNG error"); + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + const MIN_LEN: usize = 4; + + // 4 bytes at least are required to fill. + let mut tmp = [0; 4]; + let (buf, buf_len) = if dest.len() < MIN_LEN { + (tmp.as_mut_ptr() as *mut c_void, tmp.len()) + } else { + (dest.as_mut_ptr() as *mut c_void, dest.len()) + }; + + unsafe { noise_enable() }; + let succeed = + unsafe { noise_get_random_bytes(NOISE_ALL, buf, buf_len) }; + if !succeed { + unsafe { noise_disable() }; + return Err(Error::from( + NonZeroU32::new(ERROR_CODE_FATAL).unwrap(), + )); + } + unsafe { noise_disable() }; + + if dest.len() < MIN_LEN { + dest.copy_from_slice(&tmp[..dest.len()]); + } + + Ok(()) + } +} + +impl CryptoRng for PassportRng {} + +const NOISE_AVALANCHE_SOURCE: u8 = 1 << 0; +const NOISE_MCU_RNG_SOURCE: u8 = 1 << 1; +const NOISE_SE_RNG_SOURCE: u8 = 1 << 2; +const NOISE_ALL: u8 = + NOISE_AVALANCHE_SOURCE | NOISE_MCU_RNG_SOURCE | NOISE_SE_RNG_SOURCE; + +extern "C" { + fn noise_enable(); + fn noise_disable(); + fn noise_get_random_bytes( + sources: u8, + buf: *mut c_void, + buf_len: usize, + ) -> bool; +} diff --git a/extmod/foundation-rust/src/secp256k1.rs b/extmod/foundation-rust/src/secp256k1.rs new file mode 100644 index 000000000..857c2a2d2 --- /dev/null +++ b/extmod/foundation-rust/src/secp256k1.rs @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later + +use once_cell::sync::Lazy; +use secp256k1::{ + ffi::types::AlignedType, AllPreallocated, KeyPair, Message, Secp256k1, +}; + +/// cbindgen:ignore +static mut PRE_ALLOCATED_CTX_BUF: [AlignedType; 20] = [AlignedType::ZERO; 20]; + +/// cbindgen:ignore +static PRE_ALLOCATED_CTX: Lazy>> = + Lazy::new(|| { + let buf = unsafe { &mut PRE_ALLOCATED_CTX_BUF }; + Secp256k1::preallocated_new(buf) + .expect("the pre-allocated context buf should have enough space") + }); + +/// Computes a Schnorr signature over the message `data`. +/// +/// - `data` is the message hash. +/// - `secret_key` is the secret key used to sign the message. +/// - `signature` is the output of the resulting signature. +#[export_name = "foundation_secp256k1_schnorr_sign"] +pub extern "C" fn secp256k1_sign_schnorr( + data: &[u8; 32], + secret_key: &[u8; 32], + signature: &mut [u8; 64], +) { + let keypair = KeyPair::from_seckey_slice(&PRE_ALLOCATED_CTX, secret_key) + .expect("invalid secret key"); + + let msg = Message::from_slice(data).unwrap(); + let sig = + PRE_ALLOCATED_CTX.sign_schnorr_with_rng(&msg, &keypair, &mut rng()); + signature.copy_from_slice(sig.as_ref()); +} + +#[cfg(all(target_os = "none", target_arch = "arm"))] +fn rng() -> crate::rand::PassportRng { + crate::rand::PassportRng +} + +#[cfg(not(all(target_os = "none", target_arch = "arm")))] +fn rng() -> rand::rngs::OsRng { + rand::rngs::OsRng +} diff --git a/extmod/foundation/modfoundation-secp56k1.h b/extmod/foundation/modfoundation-secp56k1.h new file mode 100644 index 000000000..2ca47cf97 --- /dev/null +++ b/extmod/foundation/modfoundation-secp56k1.h @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "foundation.h" + +/// def sign_schnorr(data, secret_key) -> bytes: +/// """ +/// """ +STATIC mp_obj_t mod_foundation_secp256k1_sign_schnorr(mp_obj_t data_obj, + mp_obj_t secret_key_obj) +{ + mp_buffer_info_t data; + mp_buffer_info_t secret_key; + uint8_t signature[64]; + + mp_get_buffer_raise(data_obj, &data, MP_BUFFER_READ); + mp_get_buffer_raise(secret_key_obj, &secret_key, MP_BUFFER_READ); + + if (data.len != 32) { + mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("data should be 32 bytes")); + } + + if (secret_key.len != 32) { + mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("secret key should be 32 bytes")); + } + + foundation_secp256k1_schnorr_sign(data.buf, + secret_key.buf, + &signature); + + return mp_obj_new_bytes(signature, sizeof(signature)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_foundation_secp256k1_sign_schnorr_obj, + mod_foundation_secp256k1_sign_schnorr); + +STATIC const mp_rom_map_elem_t mod_foundation_secp256k1_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR_schnorr_sign), MP_ROM_PTR(&mod_foundation_secp256k1_sign_schnorr_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mod_foundation_secp256k1_globals, mod_foundation_secp256k1_globals_table); + +STATIC const mp_obj_module_t mod_foundation_secp256k1_module = { + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_foundation_secp256k1_globals, +}; diff --git a/extmod/foundation/modfoundation.c b/extmod/foundation/modfoundation.c index 80858c6dc..def4218b7 100644 --- a/extmod/foundation/modfoundation.c +++ b/extmod/foundation/modfoundation.c @@ -26,6 +26,7 @@ #include "modfoundation-bip39.h" #include "modfoundation-qr.h" +#include "modfoundation-secp56k1.h" #include "modfoundation-ur.h" /// package: foundation @@ -273,6 +274,7 @@ STATIC const mp_rom_map_elem_t foundation_module_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_FixedBytesIO), MP_ROM_PTR(&mp_type_fixedbytesio)}, {MP_ROM_QSTR(MP_QSTR_bip39), MP_ROM_PTR(&mod_foundation_bip39_module)}, {MP_ROM_QSTR(MP_QSTR_qr), MP_ROM_PTR(&mod_foundation_qr_module)}, + {MP_ROM_QSTR(MP_QSTR_secp256k1), MP_ROM_PTR(&mod_foundation_secp256k1_module)}, {MP_ROM_QSTR(MP_QSTR_ur), MP_ROM_PTR(&mod_foundation_ur_module)}, {MP_ROM_QSTR(MP_QSTR_convert_rgb565_to_grayscale), MP_ROM_PTR(&mod_foundation_convert_rgb565_to_grayscale_obj)}, {MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&mod_foundation_sha256_obj)}, diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c index 221a95757..82bfeea62 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -147,13 +147,13 @@ MP_REGISTER_MODULE(MP_QSTR_trezorcrypto, mp_module_trezorcrypto, #ifdef USE_SECP256K1_ZKP void secp256k1_default_illegal_callback_fn(const char *str, void *data) { (void)data; - mp_raise_ValueError(str); + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%s"), str); return; } void secp256k1_default_error_callback_fn(const char *str, void *data) { (void)data; - __fatal_error(NULL, str, __FILE__, __LINE__, __func__); + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%s"), str); return; } #endif diff --git a/ports/stm32/boards/Passport/mpconfigboard.mk b/ports/stm32/boards/Passport/mpconfigboard.mk index 1a3ac4a26..e4d928771 100644 --- a/ports/stm32/boards/Passport/mpconfigboard.mk +++ b/ports/stm32/boards/Passport/mpconfigboard.mk @@ -84,4 +84,4 @@ ifeq ($(SCREEN_MODE), COLOR) endif RUST_TARGET := thumbv7em-none-eabihf -export RUSTFLAGS := --cfg dtcm --cfg sram4 --cfg rust_secp_no_symbol_renaming +export RUSTFLAGS := --cfg dtcm --cfg sram4 diff --git a/py/py.mk b/py/py.mk index aad21294a..57a2a829d 100644 --- a/py/py.mk +++ b/py/py.mk @@ -110,6 +110,7 @@ CFLAGS_MOD += -DUSE_BIP32_25519_CURVES=0 \ -DBITCOIN_ONLY=1 \ -DAES_128=1 \ -DAES_192=1 \ + -DUSE_SECP256K1_ZKP=1 \ -DUSE_BIP39_CACHE=0 \ -DUSE_BIP39_GENERATE=0 \ -DUSE_BIP32_CACHE=0 \ @@ -155,17 +156,10 @@ endif ifeq ($(RUST_TARGET),) - UNAME_M ?= $(shell uname -m) - - ifeq ($(UNAME_M),x86_64) - RUST_ARCH ?= x86_64 - else ifeq ($(UNAME_M),arm) - RUST_ARCH ?= arm - else ifeq ($(UNAME_M),arm64) - RUST_ARCH ?= aarch64 - endif - - RUST_TARGET ?= $(RUST_ARCH)-unknown-none + RUST_TARGET ?= $(shell rustc --version --verbose | $(SED) -n 's/host: \(.*\)$$/\1/p') + RUST_FEATURES ?= --features std +else + RUST_FEATURES ?= endif FOUNDATION_RUST ?= $(TOP)/extmod/foundation-rust @@ -181,7 +175,7 @@ LDFLAGS_MOD += -L$(shell dirname $(FOUNDATION_RUST_LIB)) -lfoundation $(FOUNDATION_RUST_LIB): $(FOUNDATION_RUST_SRC) $(ECHO) "CARGO foundation-rust" - @cargo build --manifest-path $(FOUNDATION_RUST)/Cargo.toml --target $(RUST_TARGET) --release + cargo build --manifest-path $(FOUNDATION_RUST)/Cargo.toml --target $(RUST_TARGET) $(RUST_FEATURES) --release # FOUNDATION CHANGE: END diff --git a/simulator/variant/simulator/mpconfigvariant.mk b/simulator/variant/simulator/mpconfigvariant.mk index 374a65d36..1fdaa7bf2 100644 --- a/simulator/variant/simulator/mpconfigvariant.mk +++ b/simulator/variant/simulator/mpconfigvariant.mk @@ -12,4 +12,4 @@ CFLAGS_MOD += -DBL_FW_HDR_BASE=0 FROZEN_MANIFEST = FROZEN_MPY_DIR = -export RUSTFLAGS := --cfg sram4 --cfg rust_secp_no_symbol_renaming +export RUSTFLAGS := --cfg sram4 From 8a38f096d063b38bcc75a632ab23fa4acc4e3a4a Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Mon, 8 May 2023 18:33:47 +0200 Subject: [PATCH 102/187] SFT-1961: Fix compilation for simulator Signed-off-by: Jean-Pierre De Jesus DIAZ --- DEVELOPMENT.md | 2 -- Dockerfile | 4 +--- extmod/foundation-rust/Cargo.toml | 4 ++++ extmod/foundation-rust/src/lib.rs | 2 +- extmod/foundation-rust/src/secp256k1.rs | 8 ++++---- py/py.mk | 11 +++++------ 6 files changed, 15 insertions(+), 16 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index f2f2da782..ddc24c215 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -33,9 +33,7 @@ Several tools are required for building Passport. First install the `rustup` tool from [rustup.rs](https://rustup.rs/). rustup default 1.67.1 - rustup target add aarch64-unknown-none # For the simulator. Only if on macOS with an M1 CPU. rustup target add thumbv7em-none-eabihf - rustup target add x86_64-unknown-none cargo install cbindgen #### Cross-Compiler Toolchain diff --git a/Dockerfile b/Dockerfile index c289a41a1..f73b07c33 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,9 +40,7 @@ ENV PATH="/cargo/bin:${PATH}" # Finish installation of Rust toolchain. RUN rustup component add clippy && \ rustup component add rustfmt && \ - rustup target add aarch64-unknown-none && \ - rustup target add thumbv7em-none-eabihf && \ - rustup target add x86_64-unknown-none + rustup target add thumbv7em-none-eabihf # Install binaries using cargo. RUN cargo install cbindgen@^0.24 && \ diff --git a/extmod/foundation-rust/Cargo.toml b/extmod/foundation-rust/Cargo.toml index 341e07111..1a2d95eb7 100644 --- a/extmod/foundation-rust/Cargo.toml +++ b/extmod/foundation-rust/Cargo.toml @@ -55,6 +55,10 @@ features = ["rand"] version = "0.8.5" default-features = false +[target.'cfg(not(target_arch = "arm"))'.dependencies.rand] +version = "0.8.5" +features = ["std", "std_rng"] + [dependencies.rand_core] version = "0.6.4" default-features = false diff --git a/extmod/foundation-rust/src/lib.rs b/extmod/foundation-rust/src/lib.rs index 693c52679..c6b3751a7 100644 --- a/extmod/foundation-rust/src/lib.rs +++ b/extmod/foundation-rust/src/lib.rs @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2023 Foundation Devices, Inc. // SPDX-License-Identifier: GPL-3.0-or-later -#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(target_arch = "arm", no_std)] #![allow(non_camel_case_types)] #[cfg(target_arch = "arm")] diff --git a/extmod/foundation-rust/src/secp256k1.rs b/extmod/foundation-rust/src/secp256k1.rs index 857c2a2d2..d77f14bd9 100644 --- a/extmod/foundation-rust/src/secp256k1.rs +++ b/extmod/foundation-rust/src/secp256k1.rs @@ -37,12 +37,12 @@ pub extern "C" fn secp256k1_sign_schnorr( signature.copy_from_slice(sig.as_ref()); } -#[cfg(all(target_os = "none", target_arch = "arm"))] +#[cfg(target_arch = "arm")] fn rng() -> crate::rand::PassportRng { crate::rand::PassportRng } -#[cfg(not(all(target_os = "none", target_arch = "arm")))] -fn rng() -> rand::rngs::OsRng { - rand::rngs::OsRng +#[cfg(not(target_arch = "arm"))] +fn rng() -> rand::rngs::ThreadRng { + rand::thread_rng() } diff --git a/py/py.mk b/py/py.mk index 57a2a829d..c3180d3d1 100644 --- a/py/py.mk +++ b/py/py.mk @@ -117,11 +117,11 @@ CFLAGS_MOD += -DUSE_BIP32_25519_CURVES=0 \ -DBIP32_CACHE_SIZE=0 \ -DBIP32_CACHE_MAXDEPTH=0 -INC += -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/aes \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/chacha20poly1305 \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/crypto/ed25519-donna \ - -I$(MICROPY_EXTMOD_DIR)/trezor-firmware/core +INC += -I$(TOP)/extmod/trezor-firmware/crypto \ + -I$(TOP)/extmod/trezor-firmware/crypto/aes \ + -I$(TOP)/extmod/trezor-firmware/crypto/chacha20poly1305 \ + -I$(TOP)/extmod/trezor-firmware/crypto/ed25519-donna \ + -I$(TOP)/extmod/trezor-firmware/core # External modules written in C. ifneq ($(USER_C_MODULES),) @@ -154,7 +154,6 @@ ifeq ($(SCREEN_MODE),MONO) SRC_MOD += $(sort $(subst $(TOP)/,,$(shell find $(TOP)/ports/stm32/boards/Passport/images/mono -type f -name "*.c"))) endif - ifeq ($(RUST_TARGET),) RUST_TARGET ?= $(shell rustc --version --verbose | $(SED) -n 's/host: \(.*\)$$/\1/p') RUST_FEATURES ?= --features std From 72344be037d3cbc9d474dd99b4c963c6e316be4d Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Tue, 16 May 2023 12:36:44 +0200 Subject: [PATCH 103/187] SFT-1961: Remove bundled secp256k1 compilation support Signed-off-by: Jean-Pierre De Jesus DIAZ --- .../extmod/modtrezorcrypto/modtrezorcrypto.c | 4 +- ports/stm32/Makefile | 6 --- ports/unix/Makefile | 5 --- py/py.mk | 37 ++----------------- 4 files changed, 6 insertions(+), 46 deletions(-) diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c index 82bfeea62..816b951c3 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -63,7 +63,9 @@ static void wrapped_ui_wait_callback(uint32_t current, uint32_t total) { #include "modtrezorcrypto-sha3-512.h" #endif #include "modtrezorcrypto-sha512.h" +#ifndef FOUNDATION_ADDITIONS #include "modtrezorcrypto-shamir.h" +#endif #include "modtrezorcrypto-slip39.h" #if !BITCOIN_ONLY #include "modtrezorcrypto-cardano.h" @@ -114,8 +116,8 @@ STATIC const mp_rom_map_elem_t mp_module_trezorcrypto_globals_table[] = { MP_ROM_PTR(&mod_trezorcrypto_Ripemd160_type)}, {MP_ROM_QSTR(MP_QSTR_secp256k1), MP_ROM_PTR(&mod_trezorcrypto_secp256k1_module)}, - {MP_ROM_QSTR(MP_QSTR_bip340), MP_ROM_PTR(&mod_trezorcrypto_bip340_module)}, #ifndef FOUNDATION_ADDITIONS + {MP_ROM_QSTR(MP_QSTR_bip340), MP_ROM_PTR(&mod_trezorcrypto_bip340_module)}, {MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&mod_trezorcrypto_Sha1_type)}, #endif // FOUNDATION_ADDITIONS {MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&mod_trezorcrypto_Sha256_type)}, diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 4ebdb1fb2..509aee9c7 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -556,12 +556,6 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_O)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) OBJ += $(BUILD)/pins_$(BOARD).o -# secp256k1-zkp ARM assembly. -# NOTE: this is done here because the assembly and the flag from the Unix and -# STM32 ports differ. -OBJ += $(SECP256K1_DIR)/src/asm/field_10x26_arm.o -CFLAGS += -DUSE_EXTERNAL_ASM -DSECP256K1_CONTEXT_SIZE=184 - # For extmod/trezor-firmware/crypto/rand.c, we define a random32, random_reseed and random_buffer, # in our Passport board that uses our own noise source. CFLAGS += -DRAND_PLATFORM_INDEPENDENT diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 53ab1e150..756f05e9b 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -265,11 +265,6 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) -# secp256k1-zkp -# NOTE: this is done here because the flag from the Unix and STM32 ports -# differ. -CFLAGS += -DSECP256K1_CONTEXT_SIZE=208 -Wno-sign-compare - # List of sources for qstr extraction SRC_QSTR += $(SRC_C) $(SRC_CXX) $(LIB_SRC_C) $(EXTMOD_SRC_C) # Append any auto-generated sources that are needed by sources listed in diff --git a/py/py.mk b/py/py.mk index c3180d3d1..eab9361f0 100644 --- a/py/py.mk +++ b/py/py.mk @@ -54,33 +54,6 @@ SRC_MOD += $(sort $(subst $(TOP)/,,$(shell find $(LVGL_DIR)/src $(LVGL_GENERIC_D GIT_SUBMODULES += lib/lv_bindings - -# secp256k1 -SECP256K1_PATH = extmod/trezor-firmware/vendor/secp256k1-zkp -SECP256K1_DIR = $(TOP)/$(SECP256K1_PATH) -SECP256K1_ECMULT_STATIC_CONTEXT_H = $(SECP256K1_DIR)/src/ecmult_static_context.h -CFLAGS_MOD += -DUSE_NUM_NONE -DUSE_FIELD_INV_BUILTIN \ - -DUSE_FIELD_10X26 -DUSE_SCALAR_8X32 -DUSE_ECMULT_STATIC_PRECOMPUTATION \ - -DUSE_EXTERNAL_DEFAULT_CALLBACKS -DECMULT_GEN_PREC_BITS=4 \ - -DECMULT_WINDOW_SIZE=8 -DENABLE_MODULE_GENERATOR \ - -DENABLE_MODULE_RECOVERY -DENABLE_MODULE_SCHNORRSIG \ - -DENABLE_MODULE_EXTRAKEYS -I$(SECP256K1_DIR)/src -SECP256K1_MPY = $(BUILD)/secp256k1/secp256k1_mpy.c -INC += -I$(SECP256K1_DIR) -I$(SECP256K1_DIR)/include -HOST_CC = gcc -SRC_MOD += $(SECP256K1_PATH)/src/secp256k1.c $(SECP256K1_MPY) - -$(SECP256K1_ECMULT_STATIC_CONTEXT_H): - $(ECHO) "GEN-CONTEXT $@" - $(Q)$(HOST_CC) -O2 -DECMULT_GEN_PREC_BITS=4 -I$(SECP256K1_DIR)/src $(SECP256K1_DIR)/src/gen_context.c -o $(SECP256K1_DIR)/gen_context - $(Q)cd $(SECP256K1_DIR) && ./gen_context - -# NOTE: generates a dummy file in order to have ecmult_static_context.h as a dependency. -$(SECP256K1_MPY): $(SECP256K1_ECMULT_STATIC_CONTEXT_H) - $(ECHO) "GEN $@" - $(Q)mkdir -p $(dir $@) - $(Q)touch $@ - #lodepng LODEPNG_DIR = $(TOP)/lib/lv_bindings/driver/png/lodepng MP_LODEPNG_C = $(TOP)/lib/lv_bindings/driver/png/mp_lodepng.c @@ -110,7 +83,6 @@ CFLAGS_MOD += -DUSE_BIP32_25519_CURVES=0 \ -DBITCOIN_ONLY=1 \ -DAES_128=1 \ -DAES_192=1 \ - -DUSE_SECP256K1_ZKP=1 \ -DUSE_BIP39_CACHE=0 \ -DUSE_BIP39_GENERATE=0 \ -DUSE_BIP32_CACHE=0 \ @@ -383,10 +355,8 @@ PY_EXTMOD_O_BASENAME = \ extmod/trezor-firmware/crypto/rand.o \ extmod/trezor-firmware/crypto/rfc6979.o \ extmod/trezor-firmware/crypto/hmac_drbg.o \ - extmod/trezor-firmware/crypto/zkp_bip340.o \ extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.o \ - extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/crc.o \ - extmod/trezor-firmware/core/vendor/trezor-crypto/zkp_context.o + extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/crc.o # prepend the build destination prefix to the py object files PY_CORE_O = $(addprefix $(BUILD)/, $(PY_CORE_O_BASENAME)) @@ -412,9 +382,8 @@ endif # Sources that may contain qstrings SRC_QSTR_IGNORE = py/nlr% -SRC_MOD_QSTR_IGNORE = $(SECP256K1_PATH)/src/secp256k1.c extmod/trezor-firmware/crypto/zkp_bip340.c -SRC_EXTMOD_QSTR_IGNORE = extmod/trezor-firmware/crypto/zkp_bip340.c \ - extmod/trezor-firmware/core/vendor/trezor-crypto/zkp_context.c +SRC_MOD_QSTR_IGNORE = +SRC_EXTMOD_QSTR_IGNORE = SRC_QSTR += $(filter-out $(SRC_MOD_QSTR_IGNORE),$(SRC_MOD)) \ $(filter-out $(SRC_QSTR_IGNORE),$(PY_CORE_O_BASENAME:.o=.c)) \ $(filter-out $(SRC_EXTMOD_QSTR_IGNORE),$(PY_EXTMOD_O_BASENAME:.o=.c)) From ae60eb3f6e41ba219c1c6bfda17ffeaa5ac7c4b0 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 23 May 2023 13:51:12 -0500 Subject: [PATCH 104/187] SFT-2123: fixed signed UR encoding --- .../stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 0a3725f6b..8c9667e08 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -135,9 +135,9 @@ async def show_signed_transaction(self): else: qr_type = QRType.UR2 if self.ur_type == ur.Value.CRYPTO_PSBT: - qr_data = ur.new_bytes(self.signed_bytes) - elif self.ur_type == ur.Value.BYTES: qr_data = ur.new_crypto_psbt(self.signed_bytes) + elif self.ur_type == ur.Value.BYTES: + qr_data = ur.new_bytes(self.signed_bytes) else: raise RuntimeError('Unknown UR type: {}'.format(self.ur_type)) From 4f197ef7b319e24869d2215296285eabb950286b Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 15 May 2023 16:21:15 -0500 Subject: [PATCH 105/187] SFT-2019: added backup options to restore seed flow --- .../modules/flows/initial_seed_setup_flow.py | 2 +- .../Passport/modules/flows/restore_seed_flow.py | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py index f02fb032a..1ece25722 100644 --- a/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py @@ -45,7 +45,7 @@ async def show_seed_setup_menu(self): options = [{'label': 'Create New Seed', 'value': lambda: NewSeedFlow(show_words=not self.is_envoy, full_backup=True)}, - {'label': 'Restore Seed', 'value': lambda: RestoreSeedFlow()}, + {'label': 'Restore Seed', 'value': lambda: RestoreSeedFlow(full_backup=True)}, {'label': 'Restore Backup', 'value': lambda: RestoreBackupFlow()}] flow = await ChooserPage( diff --git a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py index 8dbd11290..538d06319 100644 --- a/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/restore_seed_flow.py @@ -13,13 +13,15 @@ class RestoreSeedFlow(Flow): - def __init__(self, refresh_cards_when_done=False): + def __init__(self, refresh_cards_when_done=False, autobackup=True, full_backup=False): super().__init__(initial_state=self.choose_restore_method, name='RestoreSeedFlow') self.refresh_cards_when_done = refresh_cards_when_done self.seed_format = None self.seed_length = None self.validate_text = None self.seed_words = [] + self.full_backup = full_backup + self.autobackup = autobackup async def choose_restore_method(self): from pages import ChooserPage @@ -130,6 +132,7 @@ async def invalid_seed(self): async def valid_seed(self): from foundation import bip39 + from flows import AutoBackupFlow, BackupFlow entropy = bytearray(33) # Includes an extra byte for the checksum bits @@ -146,7 +149,12 @@ async def valid_seed(self): (error,) = await spinner_task('Saving seed', save_seed_task, args=[entropy]) if error is None: import common + await SuccessPage(text='New seed restored and saved.').show() + if self.full_backup: + await BackupFlow().run() + elif self.autobackup: + await AutoBackupFlow(offer=True).run() if self.refresh_cards_when_done: common.ui.full_cards_refresh() @@ -155,5 +163,5 @@ async def valid_seed(self): else: self.set_result(True) else: - # WIP: This is not complete - offer backup? await ErrorPage('Unable to save seed.').show() + self.set_result(False) From e443030f7354250d114cb9bc3e4ab7f00e08eb89 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 23 May 2023 16:34:31 -0500 Subject: [PATCH 106/187] SFT-2019: added backup to restore from backup flow --- .../modules/flows/initial_seed_setup_flow.py | 2 +- .../Passport/modules/flows/restore_backup_flow.py | 12 +++++++++++- .../Passport/modules/tasks/restore_backup_task.py | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py index 1ece25722..5c187e00a 100644 --- a/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py @@ -46,7 +46,7 @@ async def show_seed_setup_menu(self): options = [{'label': 'Create New Seed', 'value': lambda: NewSeedFlow(show_words=not self.is_envoy, full_backup=True)}, {'label': 'Restore Seed', 'value': lambda: RestoreSeedFlow(full_backup=True)}, - {'label': 'Restore Backup', 'value': lambda: RestoreBackupFlow()}] + {'label': 'Restore Backup', 'value': lambda: RestoreBackupFlow(full_backup=True)}] flow = await ChooserPage( text=None, diff --git a/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py b/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py index 8d65d04c3..31c9f9a67 100644 --- a/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py @@ -24,12 +24,14 @@ class RestoreBackupFlow(Flow): - def __init__(self, refresh_cards_when_done=False): + def __init__(self, refresh_cards_when_done=False, autobackup=True, full_backup=False): super().__init__(initial_state=self.check_if_erased, name='RestoreBackupFlow') self.refresh_cards_when_done = refresh_cards_when_done self.backup_code = [None] * TOTAL_BACKUP_CODE_DIGITS self.backup_password_words = [] self.backup_password_prefixes = [] + self.full_backup = full_backup + self.autobackup = autobackup async def check_if_erased(self): from common import pa @@ -102,6 +104,8 @@ async def enter_backup_code(self): async def do_restore(self): from utils import start_task + from flows import AutoBackupFlow, BackupFlow + from pages import InfoPage # TODO: Change from spinner to ProgressPage and pass on_progress instead of None below. (error,) = await spinner_task( @@ -113,6 +117,12 @@ async def do_restore(self): await SuccessPage(text='Restore Complete!').show() self.set_result(True) + if self.full_backup: + await InfoPage("You will receive a new backup code to use with your new Passport.").show() + await BackupFlow().run() + elif self.autobackup: + await AutoBackupFlow(offer=True).run() + if self.refresh_cards_when_done: common.ui.update_cards(is_init=True) diff --git a/ports/stm32/boards/Passport/modules/tasks/restore_backup_task.py b/ports/stm32/boards/Passport/modules/tasks/restore_backup_task.py index 73ce63f29..f2a6afc10 100644 --- a/ports/stm32/boards/Passport/modules/tasks/restore_backup_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/restore_backup_task.py @@ -123,5 +123,8 @@ async def restore_backup_task(on_done, decryption_password, backup_file_path): settings.set(k[8:], vals[k]) + # This would be true in the old backup, but false for this new device + settings.set('backup_quiz', False) + # Success! await on_done(None) From 7c47f695b921793e5073f2da6d6d059ce40c9ec2 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 15 May 2023 12:07:51 -0500 Subject: [PATCH 107/187] SFT-2018: renamed multisigs forlder to multisig_configs --- ports/stm32/boards/Passport/modules/public_constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/public_constants.py b/ports/stm32/boards/Passport/modules/public_constants.py index 66420ec0e..13f983a7d 100644 --- a/ports/stm32/boards/Passport/modules/public_constants.py +++ b/ports/stm32/boards/Passport/modules/public_constants.py @@ -100,7 +100,7 @@ # Default Directories DIR_BACKUPS = 'backups' DIR_KEY_MNGR = 'key_manager' -DIR_MULTISIGS = 'multisigs' +DIR_MULTISIGS = 'multisig_configs' DIR_WALLET_CONFIGS = 'wallet_configs' DIR_TRANSACTIONS = 'transactions' DIR_HEALTH_CHECKS = 'health_checks' From 3960ad7c267436123f87aa27853ffb1b149cc6ab Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 15 May 2023 15:27:59 -0500 Subject: [PATCH 108/187] SFT-2018: removed underscores from directory names --- ports/stm32/boards/Passport/modules/public_constants.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/public_constants.py b/ports/stm32/boards/Passport/modules/public_constants.py index 13f983a7d..549e2751e 100644 --- a/ports/stm32/boards/Passport/modules/public_constants.py +++ b/ports/stm32/boards/Passport/modules/public_constants.py @@ -99,11 +99,11 @@ # Default Directories DIR_BACKUPS = 'backups' -DIR_KEY_MNGR = 'key_manager' -DIR_MULTISIGS = 'multisig_configs' -DIR_WALLET_CONFIGS = 'wallet_configs' +DIR_KEY_MNGR = 'key manager' +DIR_MULTISIGS = 'multisig configs' +DIR_WALLET_CONFIGS = 'wallet configs' DIR_TRANSACTIONS = 'transactions' -DIR_HEALTH_CHECKS = 'health_checks' +DIR_HEALTH_CHECKS = 'health checks' RFC_SIGNATURE_TEMPLATE = '''\ -----BEGIN {blockchain} SIGNED MESSAGE----- From d42bb0b4cbc7bb9ef9e184359b53deb99ec2d440 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 23 May 2023 17:02:09 -0500 Subject: [PATCH 109/187] SFT-2018: returned to using underscores --- ports/stm32/boards/Passport/modules/public_constants.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/public_constants.py b/ports/stm32/boards/Passport/modules/public_constants.py index 549e2751e..9adf2172d 100644 --- a/ports/stm32/boards/Passport/modules/public_constants.py +++ b/ports/stm32/boards/Passport/modules/public_constants.py @@ -100,10 +100,10 @@ # Default Directories DIR_BACKUPS = 'backups' DIR_KEY_MNGR = 'key manager' -DIR_MULTISIGS = 'multisig configs' -DIR_WALLET_CONFIGS = 'wallet configs' +DIR_MULTISIGS = 'multisig_configs' +DIR_WALLET_CONFIGS = 'wallet_configs' DIR_TRANSACTIONS = 'transactions' -DIR_HEALTH_CHECKS = 'health checks' +DIR_HEALTH_CHECKS = 'health_checks' RFC_SIGNATURE_TEMPLATE = '''\ -----BEGIN {blockchain} SIGNED MESSAGE----- From c0bef488dbaa10d36c7f520a50b2bed0507f2600 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 23 May 2023 17:02:50 -0500 Subject: [PATCH 110/187] SFT-2018: used underscore in key_manager directory --- ports/stm32/boards/Passport/modules/public_constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/public_constants.py b/ports/stm32/boards/Passport/modules/public_constants.py index 9adf2172d..13f983a7d 100644 --- a/ports/stm32/boards/Passport/modules/public_constants.py +++ b/ports/stm32/boards/Passport/modules/public_constants.py @@ -99,7 +99,7 @@ # Default Directories DIR_BACKUPS = 'backups' -DIR_KEY_MNGR = 'key manager' +DIR_KEY_MNGR = 'key_manager' DIR_MULTISIGS = 'multisig_configs' DIR_WALLET_CONFIGS = 'wallet_configs' DIR_TRANSACTIONS = 'transactions' From f100796a0661b03b318c307d0fa1ac28ab3a05e5 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 23 May 2023 14:28:21 -0500 Subject: [PATCH 111/187] SFT-2106: fixed seed words flow control --- .../Passport/modules/flows/view_seed_words_flow.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py index f577a2fff..02b271d49 100644 --- a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py @@ -132,16 +132,16 @@ async def show_seed_words(self): result = await SeedWarningFlow(mention_passphrase=self.mention_passphrase).run() if not result: - self.back() + self.set_result(False) return - result = await SeedWordsListPage(words=self.words, - left_micron=self.seed_micron).show() - - if not result: - if self.qr_type: + result = False + while not result: + result = await SeedWordsListPage(words=self.words, + left_micron=self.seed_micron).show() + if not result and self.qr_type: self.back() - return + return self.goto(self.show_passphrase) From f17649b273306dfb066043aa7830483f0b59c40f Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 12 May 2023 12:44:15 -0500 Subject: [PATCH 112/187] SFT-938: fixed cutoff shield page --- ports/stm32/boards/Passport/manifest.py | 1 - .../boards/Passport/modules/flows/scv_flow.py | 23 ++++++++++----- .../boards/Passport/modules/pages/__init__.py | 1 - .../Passport/modules/pages/shield_page.py | 29 ------------------- 4 files changed, 15 insertions(+), 39 deletions(-) delete mode 100644 ports/stm32/boards/Passport/modules/pages/shield_page.py diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index 8795eba23..9433d83a2 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -183,7 +183,6 @@ 'pages/question_page.py', 'pages/seed_words_list_page.py', 'pages/scan_qr_page.py', - 'pages/shield_page.py', 'pages/show_qr_page.py', 'pages/shutdown_page.py', 'pages/spinner_page.py', diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index 08195df01..d708c0a9c 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -6,7 +6,7 @@ import lvgl as lv from flows import Flow, ScanQRFlow from pages import ShowQRPage, QuestionPage, ChooserPage -from styles.colors import HIGHLIGHT_TEXT_HEX +from styles.colors import HIGHLIGHT_TEXT_HEX, DEFAULT_LARGE_ICON_COLOR from data_codecs.qr_type import QRType from utils import a2b_hex, recolor from ubinascii import hexlify as b2a_hex @@ -33,7 +33,7 @@ def __init__(self, envoy=True, ask_to_skip=True): self.uuid = None async def show_intro(self): - from pages import ShieldPage + from pages import LongTextPage if self.envoy: text = 'On the next screen, scan the QR code shown in Envoy.' @@ -42,9 +42,12 @@ async def show_intro(self): 'On the next screen, scan the Security Check ' \ 'QR code from validate.foundationdevices.com.' - result = await ShieldPage(text=text, - left_micron=microns.Back, - right_micron=microns.Forward).show() + result = await LongTextPage(text=text, + centered=True, + icon=lv.LARGE_ICON_SHIELD, + icon_color=DEFAULT_LARGE_ICON_COLOR, + left_micron=microns.Back, + right_micron=microns.Forward).show() if result: self.goto(self.scan_qr_challenge) else: @@ -130,13 +133,17 @@ async def show_envoy_response(self): self.goto(self.ask_if_valid) async def show_manual_response(self): - from pages import ShieldPage + from pages import StatusPage lines = ['{}. {}\n'.format(idx + 1, word) for idx, word in enumerate(self.words)] words = ''.join(lines) - result = await ShieldPage(text=words, card_header={'title': 'Security Check'}, - left_micron=microns.Retry, right_micron=microns.Forward).show() + result = await StatusPage(text=words, + card_header={'title': 'Security Check'}, + icon=lv.LARGE_ICON_SHIELD, + icon_color=DEFAULT_LARGE_ICON_COLOR, + left_micron=microns.Retry, + right_micron=microns.Forward).show() if not result: self.back() else: diff --git a/ports/stm32/boards/Passport/modules/pages/__init__.py b/ports/stm32/boards/Passport/modules/pages/__init__.py index 10a6f3fab..fde5ef190 100644 --- a/ports/stm32/boards/Passport/modules/pages/__init__.py +++ b/ports/stm32/boards/Passport/modules/pages/__init__.py @@ -33,7 +33,6 @@ from .scan_qr_page import * from .seed_words_list_page import * from .setup_mode_chooser_page import * -from .shield_page import * from .show_security_words_setting_page import * from .show_qr_page import * from .shutdown_page import * diff --git a/ports/stm32/boards/Passport/modules/pages/shield_page.py b/ports/stm32/boards/Passport/modules/pages/shield_page.py deleted file mode 100644 index dda274925..000000000 --- a/ports/stm32/boards/Passport/modules/pages/shield_page.py +++ /dev/null @@ -1,29 +0,0 @@ -# SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -# SPDX-License-Identifier: GPL-3.0-or-later -# -# info_page.py - -import lvgl as lv -from pages import StatusPage -from styles.colors import DEFAULT_LARGE_ICON_COLOR -import microns - - -class ShieldPage(StatusPage): - def __init__( - self, - text=None, - centered=True, - card_header=None, - statusbar=None, - left_micron=microns.Cancel, - right_micron=microns.Checkmark): - super().__init__( - text=text, - icon=lv.LARGE_ICON_SHIELD, - icon_color=DEFAULT_LARGE_ICON_COLOR, - centered=centered, - card_header=card_header, - statusbar=statusbar, - left_micron=left_micron, - right_micron=right_micron) From 894992cd00fd3412c85b67c4498fd99f7e691e97 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 23 May 2023 16:59:13 -0500 Subject: [PATCH 113/187] SFT-2051: split Supply Chain Flow text into 2 pages --- .../boards/Passport/modules/flows/scv_flow.py | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index d708c0a9c..ca4ce88fe 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -33,21 +33,34 @@ def __init__(self, envoy=True, ask_to_skip=True): self.uuid = None async def show_intro(self): - from pages import LongTextPage + from pages import StatusPage if self.envoy: - text = 'On the next screen, scan the QR code shown in Envoy.' + messages = ['On the next screen, scan the QR code shown in Envoy.'] else: - text = 'Let\'s confirm Passport was not tampered with during shipping. ' \ - 'On the next screen, scan the Security Check ' \ - 'QR code from validate.foundationdevices.com.' - - result = await LongTextPage(text=text, - centered=True, - icon=lv.LARGE_ICON_SHIELD, - icon_color=DEFAULT_LARGE_ICON_COLOR, - left_micron=microns.Back, - right_micron=microns.Forward).show() + messages = ['Let\'s confirm Passport was not tampered with during shipping. ', + 'Next, scan the Security Check ' + 'QR code from validate.foundationdevices.com.'] + + # for text in messages: + # result = await ShieldPage(text=text, + # left_micron=microns.Back, + # right_micron=microns.Forward).show() + message_index = 0 + while message_index < len(messages): + result = await StatusPage(text=messages[message_index], + card_header={'title': 'Security Check'}, + icon=lv.LARGE_ICON_SHIELD, + icon_color=DEFAULT_LARGE_ICON_COLOR, + left_micron=microns.Back, + right_micron=microns.Forward).show() + if result: + message_index += 1 + elif message_index > 0: + message_index -= 1 + else: + break + if result: self.goto(self.scan_qr_challenge) else: From 0edd391ecc34fe4ed0485bbc496cb3a5d6f54b43 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 24 May 2023 11:13:00 -0500 Subject: [PATCH 114/187] SFT-2051: restored ShieldPage, made SeriesOfPagesFlow to show a series of the same type of page --- ports/stm32/boards/Passport/manifest.py | 2 + .../boards/Passport/modules/flows/__init__.py | 1 + .../boards/Passport/modules/flows/scv_flow.py | 51 ++++++++----------- .../modules/flows/series_of_pages_flow.py | 30 +++++++++++ .../boards/Passport/modules/pages/__init__.py | 1 + .../Passport/modules/pages/shield_page.py | 29 +++++++++++ 6 files changed, 83 insertions(+), 31 deletions(-) create mode 100644 ports/stm32/boards/Passport/modules/flows/series_of_pages_flow.py create mode 100644 ports/stm32/boards/Passport/modules/pages/shield_page.py diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index 9433d83a2..3d9eb8e81 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -114,6 +114,7 @@ 'flows/magic_scan_validate_address_flow.py', 'flows/scan_qr_flow.py', + 'flows/series_of_pages_flow.py', 'flows/system_test_flow.py', 'flows/system_test_camera_flow.py', @@ -183,6 +184,7 @@ 'pages/question_page.py', 'pages/seed_words_list_page.py', 'pages/scan_qr_page.py', + 'pages/shield_page.py', 'pages/show_qr_page.py', 'pages/shutdown_page.py', 'pages/spinner_page.py', diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index d8690c2af..72719015f 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -14,6 +14,7 @@ from .scan_qr_flow import * from .backup_common_flow import * from .seed_warning_flow import * +from .series_of_pages_flow import * # QR Magic Scan flows from .magic_scan_import_multisig_flow import * diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index ca4ce88fe..01dfd2663 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -33,33 +33,26 @@ def __init__(self, envoy=True, ask_to_skip=True): self.uuid = None async def show_intro(self): - from pages import StatusPage + from pages import ShieldPage + from flows import SeriesOfPagesFlow if self.envoy: - messages = ['On the next screen, scan the QR code shown in Envoy.'] + messages = [{'text': 'On the next screen, scan the QR code shown in Envoy.'}] else: - messages = ['Let\'s confirm Passport was not tampered with during shipping. ', - 'Next, scan the Security Check ' - 'QR code from validate.foundationdevices.com.'] - - # for text in messages: - # result = await ShieldPage(text=text, - # left_micron=microns.Back, - # right_micron=microns.Forward).show() - message_index = 0 - while message_index < len(messages): - result = await StatusPage(text=messages[message_index], - card_header={'title': 'Security Check'}, - icon=lv.LARGE_ICON_SHIELD, - icon_color=DEFAULT_LARGE_ICON_COLOR, - left_micron=microns.Back, - right_micron=microns.Forward).show() - if result: - message_index += 1 - elif message_index > 0: - message_index -= 1 - else: - break + messages = [{'text': 'Let\'s confirm Passport was not tampered with during shipping.'}, + {'text': 'Next, scan the Security Check ' + 'QR code from validate.foundationdevices.com.'}] + + # message_index = 0 + # while message_index < len(messages): + # result = await ShieldPage(text=messages[message_index], left_micron=microns.Back).show() + # if result: + # message_index += 1 + # elif message_index > 0: + # message_index -= 1 + # else: + # break + result = await SeriesOfPagesFlow(ShieldPage, messages).run() if result: self.goto(self.scan_qr_challenge) @@ -146,17 +139,13 @@ async def show_envoy_response(self): self.goto(self.ask_if_valid) async def show_manual_response(self): - from pages import StatusPage + from pages import ShieldPage lines = ['{}. {}\n'.format(idx + 1, word) for idx, word in enumerate(self.words)] words = ''.join(lines) - result = await StatusPage(text=words, - card_header={'title': 'Security Check'}, - icon=lv.LARGE_ICON_SHIELD, - icon_color=DEFAULT_LARGE_ICON_COLOR, - left_micron=microns.Retry, - right_micron=microns.Forward).show() + result = await ShieldPage(text=words, + left_micron=microns.Retry).show() if not result: self.back() else: diff --git a/ports/stm32/boards/Passport/modules/flows/series_of_pages_flow.py b/ports/stm32/boards/Passport/modules/flows/series_of_pages_flow.py new file mode 100644 index 000000000..ec7ef937e --- /dev/null +++ b/ports/stm32/boards/Passport/modules/flows/series_of_pages_flow.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# series_of_pages_flow.py - Display a series of pages + +from flows import Flow +from foundation import ur + + +class SeriesOfPagesFlow(Flow): + def __init__(self, page_class, page_args): + super().__init__(initial_state=self.display_pages, name='SeriesOfPagesFlow') + + self.page_class = page_class + self.page_args = page_args + + async def display_pages(self): + page_index = 0 + result = None + while page_index < len(self.page_args): + result = await self.page_class(**self.page_args[page_index]).show() + + if result: + page_index += 1 + elif page_index > 0: + page_index -= 1 + else: + break + + self.set_result(result) diff --git a/ports/stm32/boards/Passport/modules/pages/__init__.py b/ports/stm32/boards/Passport/modules/pages/__init__.py index fde5ef190..10a6f3fab 100644 --- a/ports/stm32/boards/Passport/modules/pages/__init__.py +++ b/ports/stm32/boards/Passport/modules/pages/__init__.py @@ -33,6 +33,7 @@ from .scan_qr_page import * from .seed_words_list_page import * from .setup_mode_chooser_page import * +from .shield_page import * from .show_security_words_setting_page import * from .show_qr_page import * from .shutdown_page import * diff --git a/ports/stm32/boards/Passport/modules/pages/shield_page.py b/ports/stm32/boards/Passport/modules/pages/shield_page.py new file mode 100644 index 000000000..4024203c6 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/pages/shield_page.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# info_page.py + +import lvgl as lv +from pages import StatusPage +from styles.colors import DEFAULT_LARGE_ICON_COLOR +import microns + + +class ShieldPage(StatusPage): + def __init__( + self, + text=None, + centered=True, + card_header={'title': 'Security Check'}, + statusbar=None, + left_micron=microns.Back, + right_micron=microns.Forward): + super().__init__( + text=text, + icon=lv.LARGE_ICON_SHIELD, + icon_color=DEFAULT_LARGE_ICON_COLOR, + centered=centered, + card_header=card_header, + statusbar=statusbar, + left_micron=left_micron, + right_micron=right_micron) From 56336375ff3b42f3d314a33f2a952d38e854aee5 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 24 May 2023 11:19:14 -0500 Subject: [PATCH 115/187] SFT-2051: reduced diff --- ports/stm32/boards/Passport/modules/flows/scv_flow.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index 01dfd2663..3eeaa8398 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -6,7 +6,7 @@ import lvgl as lv from flows import Flow, ScanQRFlow from pages import ShowQRPage, QuestionPage, ChooserPage -from styles.colors import HIGHLIGHT_TEXT_HEX, DEFAULT_LARGE_ICON_COLOR +from styles.colors import HIGHLIGHT_TEXT_HEX from data_codecs.qr_type import QRType from utils import a2b_hex, recolor from ubinascii import hexlify as b2a_hex @@ -43,15 +43,6 @@ async def show_intro(self): {'text': 'Next, scan the Security Check ' 'QR code from validate.foundationdevices.com.'}] - # message_index = 0 - # while message_index < len(messages): - # result = await ShieldPage(text=messages[message_index], left_micron=microns.Back).show() - # if result: - # message_index += 1 - # elif message_index > 0: - # message_index -= 1 - # else: - # break result = await SeriesOfPagesFlow(ShieldPage, messages).run() if result: From bc7fdb0a70442911c5e504b0a1c6131aea3bdccd Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 5 Apr 2023 23:14:44 -0500 Subject: [PATCH 116/187] SFT-1434: laid groundwork for additional actions for key manager keys --- ports/stm32/boards/Passport/manifest.py | 1 + .../boards/Passport/modules/derived_key.py | 4 +- .../boards/Passport/modules/flows/__init__.py | 1 + .../Passport/modules/flows/menu_flow.py | 6 +- .../modules/flows/nostr_delegation_flow.py | 137 ++++++++++++++++++ ports/stm32/boards/Passport/modules/menus.py | 8 +- 6 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index 3d9eb8e81..f47ecabb1 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -126,6 +126,7 @@ 'flows/new_account_flow.py', 'flows/new_derived_key_flow.py', 'flows/new_seed_flow.py', + 'flows/nostr_delegation_flow.py', 'flows/connect_wallet_flow.py', 'flows/page_flow.py', 'flows/read_file_flow.py', diff --git a/ports/stm32/boards/Passport/modules/derived_key.py b/ports/stm32/boards/Passport/modules/derived_key.py index 454960910..dfb3eedcd 100644 --- a/ports/stm32/boards/Passport/modules/derived_key.py +++ b/ports/stm32/boards/Passport/modules/derived_key.py @@ -5,6 +5,7 @@ import lvgl as lv from tasks import bip85_24_word_seed_task, bip85_12_word_seed_task, nostr_key_task +from menus import nostr_menu # Each key generation task must take index as args, whether or not they use it. # tn stands for Type Number @@ -27,7 +28,8 @@ 'indexed': True, 'words': False, 'task': nostr_key_task, - 'continue_text': 'post on your behalf'}, + 'continue_text': 'post on your behalf', + 'menu': nostr_menu}, ] diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index 72719015f..baddb7e4b 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -51,6 +51,7 @@ from .new_account_flow import * from .new_derived_key_flow import * from .new_seed_flow import * +from .nostr_delegation_flow import * from .connect_wallet_flow import * from .read_file_flow import * from .remove_dev_pubkey_flow import * diff --git a/ports/stm32/boards/Passport/modules/flows/menu_flow.py b/ports/stm32/boards/Passport/modules/flows/menu_flow.py index d0e052153..656695823 100644 --- a/ports/stm32/boards/Passport/modules/flows/menu_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/menu_flow.py @@ -14,7 +14,7 @@ class MenuFlow(Flow): latest_menu = None def __init__(self, menu, initial_selected_index=0, is_top_level=None, context=None, - card_header=None, statusbar=None): + card_header=None, statusbar=None, dynamic=None): self.menu = menu super().__init__(initial_state=self.show_menu, name='MenuFlow') @@ -24,6 +24,7 @@ def __init__(self, menu, initial_selected_index=0, is_top_level=None, context=No self.context = context self.card_header = card_header self.statusbar = statusbar + self.dynamic = dynamic MenuFlow.latest_menu = self async def show_menu(self): @@ -34,6 +35,9 @@ async def show_menu(self): # This allows them to update if any state has changed since last running. assert(callable(self.menu)) self.items = self.menu() + if self.dynamic: + assert(callable(self.dynamic)) + self.items.extend(self.dynamic()) self.prev_statusbar = None self.prev_card_header = None diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py new file mode 100644 index 000000000..193222c79 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -0,0 +1,137 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# nostr_delegation_flow.py - Sign a nostr delegation token + +from flows import Flow +from foundation import FixedBytesIO, ur +from passport import mem +from pages import ErrorPage + + +class NostrDelegationFlow(Flow): + def __init__(self, context=None): + from derived_key import get_key_type_from_tn + + self.key = context + self.key_type = get_key_type_from_tn(self.key['tn']) + super().__init__(initial_state=self.here, name='NostrDelegationFlow') + + async def here(self): + from pages import SuccessPage + await SuccessPage("{} {}".format(self.key_type['title'], self.key['index'])).show() + self.set_result(True) + + # async def scan_transaction(self): + # from pages import ScanQRPage, ErrorPage + # import microns + + # # TODO: May need to set statusbar content here and restore it after + # result = await ScanQRPage(right_micron=microns.Checkmark).show() + # if result is None: + # # User canceled the scan + # self.set_result(False) + # else: + # # Got a scan result (aka QRScanResult). + # if result.is_failure(): + # # Unable to scan QR code - show error? + # await ErrorPage(text='Unable to scan QR code.\n\n{}'.format(result.error)).show() + # self.set_result(False) + # else: + # # TODO: handle hex not only UR. Wasn't handled before the UR + # # rework too. + # if isinstance(result.data, ur.Value): + # self.qr_type = result.qr_type + # self.ur_type = result.data.ur_type() + + # if self.ur_type == ur.Value.BYTES: + # self.raw_psbt = result.data.unwrap_bytes() + # elif self.ur_type == ur.Value.CRYPTO_PSBT: + # self.raw_psbt = result.data.unwrap_crypto_psbt() + # else: + # await ErrorPage(text='The QR code does not contain a transaction.').show() + # self.set_result(False) + # return + + # self.goto(self.copy_to_flash) + # else: + # await ErrorPage(text='The QR code does not contain a transaction.').show() + # self.set_result(False) + + # async def copy_to_flash(self): + # import gc + # from utils import spinner_task + # from tasks import copy_psbt_to_external_flash_task + # from pages import ErrorPage + # from public_constants import TXN_INPUT_OFFSET + # from errors import Error + + # gc.collect() # Try to avoid excessive fragmentation + + # # TODO: Pass on_progress function as the first argument if we want progress or remove it + # (self.psbt_len, self.output_encoder, error) = await spinner_task( + # 'Parsing transaction', copy_psbt_to_external_flash_task, args=[None, self.raw_psbt, TXN_INPUT_OFFSET]) + # if error is not None: + # if error == Error.PSBT_TOO_LARGE: + # await ErrorPage(text='PSBT too large').show() + # else: + # await ErrorPage(text='Invalid PSBT (copying QR)').show() + # self.set_result(False) + # return + + # gc.collect() # Try to avoid excessive fragmentation + + # # PSBT was copied to external flash + # self.goto(self.common_flow) + + # async def common_flow(self): + # from flows import SignPsbtCommonFlow + + # # This flow validates and signs if all goes well, and returns the signed psbt + # self.psbt = await SignPsbtCommonFlow(self.psbt_len).run() + + # if self.psbt is None: + # self.set_result(False) + # else: + # self.goto(self.show_signed_transaction) + + # async def show_signed_transaction(self): + # import gc + # from pages import ShowQRPage + # from data_codecs.qr_type import QRType + # from ubinascii import hexlify as b2a_hex + # import microns + + # # Copy signed txn into a bytearray and show the data as a UR + # # try: + # signed_bytes = None + # try: + # with FixedBytesIO(mem.psbt_output) as bfd: + # with self.output_encoder(bfd) as fd: + # # Always serialize back to PSBT for QR codes + # self.psbt.serialize(fd) + # bfd.seek(0) + # signed_bytes = bfd.getvalue() + # # print('len(signed_bytes)={}'.format(len(signed_bytes))) + # # print('signed_bytes={}'.format(signed_bytes)) + # except MemoryError as e: + # await ErrorPage(text='Transaction is too complex: {}'.format(e)).show() + # self.set_result(False) + # return + + # self.psbt = None + # gc.collect() + + # if self.qr_type == QRType.QR: + # qr_data = b2a_hex(signed_bytes) + # elif self.qr_type == QRType.UR2 and self.ur_type == ur.Value.BYTES: + # qr_data = ur.new_bytes(signed_bytes) + # elif self.qr_type == QRType.UR2 and self.ur_type == ur.Value.CRYPTO_PSBT: + # qr_data = ur.new_crypto_psbt(signed_bytes) + # else: + # raise RuntimeException("Unsupported output format") + + # await ShowQRPage(qr_type=self.qr_type, + # qr_data=qr_data, + # right_micron=microns.Checkmark).show() + # self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 8d88d7eb5..8ff60e6ab 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -178,6 +178,12 @@ def manage_keys(): ] +def nostr_menu(): + from flows import NostrDelegationFlow + + return [{'icon': lv.ICON_SIGN, 'label': 'Delegate', 'flow': NostrDelegationFlow}] + + def key_manager_menu(): from utils import get_derived_keys, are_hidden_keys_showing from derived_key import get_key_type_from_tn @@ -204,7 +210,7 @@ def key_manager_menu(): 'card_header': {'title': title, 'right_icon': key_type['icon']}, 'statusbar': {'title': 'KEY MANAGER'}, - 'args': {'context': key}, + 'args': {'context': key, 'dynamic': key_type.get('menu', None)}, 'auto_card_header': False}) result.append({'icon': lv.ICON_ONE_KEY, 'label': 'New Key', 'submenu': new_key_menu}) From a339562f035848314532966993b08f3f806a46bd Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 6 Apr 2023 01:23:00 -0500 Subject: [PATCH 117/187] SFT-1434: generated npub, waiting for delegation string --- .../boards/Passport/modules/derived_key.py | 1 + .../modules/flows/export_derived_key_flow.py | 7 +- .../modules/flows/nostr_delegation_flow.py | 145 ++++-------------- .../Passport/modules/tasks/bip85_seed_task.py | 2 +- .../Passport/modules/tasks/nostr_key_task.py | 7 +- 5 files changed, 43 insertions(+), 119 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/derived_key.py b/ports/stm32/boards/Passport/modules/derived_key.py index dfb3eedcd..8969ff97f 100644 --- a/ports/stm32/boards/Passport/modules/derived_key.py +++ b/ports/stm32/boards/Passport/modules/derived_key.py @@ -8,6 +8,7 @@ from menus import nostr_menu # Each key generation task must take index as args, whether or not they use it. +# Each task must return ({'priv', , etc.}, None) # tn stands for Type Number key_types = [ {'tn': 0, diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index aa693c0a7..f1c881cc4 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -30,9 +30,10 @@ async def generate_key(self): self.set_result(False) return - (self.pk, error) = await spinner_task(text='Generating Key', - task=self.key_type['task'], - args=[self.key['index']]) + (vals, error) = await spinner_task(text='Generating Key', + task=self.key_type['task'], + args=[self.key['index']]) + self.pk = vals['priv'] if error is not None: await ErrorPage(error).show() self.set_result(False) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 193222c79..a66416e29 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -4,9 +4,6 @@ # nostr_delegation_flow.py - Sign a nostr delegation token from flows import Flow -from foundation import FixedBytesIO, ur -from passport import mem -from pages import ErrorPage class NostrDelegationFlow(Flow): @@ -15,123 +12,45 @@ def __init__(self, context=None): self.key = context self.key_type = get_key_type_from_tn(self.key['tn']) - super().__init__(initial_state=self.here, name='NostrDelegationFlow') + self.nsec = None + self.npub = None + self.delegation_string = None + super().__init__(initial_state=self.export_npub, name='NostrDelegationFlow') - async def here(self): - from pages import SuccessPage - await SuccessPage("{} {}".format(self.key_type['title'], self.key['index'])).show() - self.set_result(True) - - # async def scan_transaction(self): - # from pages import ScanQRPage, ErrorPage - # import microns - - # # TODO: May need to set statusbar content here and restore it after - # result = await ScanQRPage(right_micron=microns.Checkmark).show() - # if result is None: - # # User canceled the scan - # self.set_result(False) - # else: - # # Got a scan result (aka QRScanResult). - # if result.is_failure(): - # # Unable to scan QR code - show error? - # await ErrorPage(text='Unable to scan QR code.\n\n{}'.format(result.error)).show() - # self.set_result(False) - # else: - # # TODO: handle hex not only UR. Wasn't handled before the UR - # # rework too. - # if isinstance(result.data, ur.Value): - # self.qr_type = result.qr_type - # self.ur_type = result.data.ur_type() - - # if self.ur_type == ur.Value.BYTES: - # self.raw_psbt = result.data.unwrap_bytes() - # elif self.ur_type == ur.Value.CRYPTO_PSBT: - # self.raw_psbt = result.data.unwrap_crypto_psbt() - # else: - # await ErrorPage(text='The QR code does not contain a transaction.').show() - # self.set_result(False) - # return - - # self.goto(self.copy_to_flash) - # else: - # await ErrorPage(text='The QR code does not contain a transaction.').show() - # self.set_result(False) + async def export_npub(self): + from utils import spinner_task + from pages import ShowQRPage, ErrorPage - # async def copy_to_flash(self): - # import gc - # from utils import spinner_task - # from tasks import copy_psbt_to_external_flash_task - # from pages import ErrorPage - # from public_constants import TXN_INPUT_OFFSET - # from errors import Error + (vals, error) = await spinner_task(text='Generating npub', + task=self.key_type['task'], + args=[self.key['index']]) + self.nsec = vals['priv'] + self.npub = vals['pub'] - # gc.collect() # Try to avoid excessive fragmentation + if not self.nsec or not self.npub: + await ErrorPage("Failed to generate npub and nsec").show() + self.set_result(False) + return - # # TODO: Pass on_progress function as the first argument if we want progress or remove it - # (self.psbt_len, self.output_encoder, error) = await spinner_task( - # 'Parsing transaction', copy_psbt_to_external_flash_task, args=[None, self.raw_psbt, TXN_INPUT_OFFSET]) - # if error is not None: - # if error == Error.PSBT_TOO_LARGE: - # await ErrorPage(text='PSBT too large').show() - # else: - # await ErrorPage(text='Invalid PSBT (copying QR)').show() - # self.set_result(False) - # return + await ShowQRPage(qr_data=self.npub).show() + self.goto(self.scan_delegation_string) - # gc.collect() # Try to avoid excessive fragmentation + async def scan_delegation_string(self): + from pages import ScanQRPage, ErrorPage - # # PSBT was copied to external flash - # self.goto(self.common_flow) + # TODO: replace with ScanQRFlow + result = await ScanQRPage().show() - # async def common_flow(self): - # from flows import SignPsbtCommonFlow + if not result: + self.set_result(False) + return - # # This flow validates and signs if all goes well, and returns the signed psbt - # self.psbt = await SignPsbtCommonFlow(self.psbt_len).run() + if result.is_failure(): + await ErrorPage(text='Unable to scan QR code.').show() + self.set_result(False) + return - # if self.psbt is None: - # self.set_result(False) - # else: - # self.goto(self.show_signed_transaction) + self.delegation_string = result.data - # async def show_signed_transaction(self): - # import gc - # from pages import ShowQRPage - # from data_codecs.qr_type import QRType - # from ubinascii import hexlify as b2a_hex - # import microns - - # # Copy signed txn into a bytearray and show the data as a UR - # # try: - # signed_bytes = None - # try: - # with FixedBytesIO(mem.psbt_output) as bfd: - # with self.output_encoder(bfd) as fd: - # # Always serialize back to PSBT for QR codes - # self.psbt.serialize(fd) - # bfd.seek(0) - # signed_bytes = bfd.getvalue() - # # print('len(signed_bytes)={}'.format(len(signed_bytes))) - # # print('signed_bytes={}'.format(signed_bytes)) - # except MemoryError as e: - # await ErrorPage(text='Transaction is too complex: {}'.format(e)).show() - # self.set_result(False) - # return - - # self.psbt = None - # gc.collect() - - # if self.qr_type == QRType.QR: - # qr_data = b2a_hex(signed_bytes) - # elif self.qr_type == QRType.UR2 and self.ur_type == ur.Value.BYTES: - # qr_data = ur.new_bytes(signed_bytes) - # elif self.qr_type == QRType.UR2 and self.ur_type == ur.Value.CRYPTO_PSBT: - # qr_data = ur.new_crypto_psbt(signed_bytes) - # else: - # raise RuntimeException("Unsupported output format") - - # await ShowQRPage(qr_type=self.qr_type, - # qr_data=qr_data, - # right_micron=microns.Checkmark).show() - # self.set_result(True) + # TODO: parse delegation string, go to display info + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/tasks/bip85_seed_task.py b/ports/stm32/boards/Passport/modules/tasks/bip85_seed_task.py index 0dfc03c2a..67dd0bc4f 100644 --- a/ports/stm32/boards/Passport/modules/tasks/bip85_seed_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/bip85_seed_task.py @@ -23,4 +23,4 @@ async def bip85_seed_task(on_done, num_words, index): node = sv.derive_path(path) entropy = hmac(512, 'bip-entropy-from-k', node.private_key()).digest() seed = entropy[0:width] - await on_done(seed, None) + await on_done({'priv': seed}, None) diff --git a/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py b/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py index 218ce7980..43403ee0c 100644 --- a/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py @@ -7,10 +7,13 @@ async def nostr_key_task(on_done, index): import stash import tcc + from trezorcrypto import secp256k1 path = "m/44'/1237'/{}'/0/0".format(index) with stash.SensitiveValues() as sv: node = sv.derive_path(path) key = node.private_key() - key = tcc.codecs.bech32_plain_encode("nsec", key) - await on_done(key, None) + pub = secp256k1.publickey(key, True)[1:] + nsec = tcc.codecs.bech32_plain_encode("nsec", key) + npub = tcc.codecs.bech32_plain_encode("npub", pub) + await on_done({'priv': nsec, 'pub': npub}, None) From 4403185154beed63c133d01a6afc97d1c999ddf1 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 6 Apr 2023 13:44:10 -0500 Subject: [PATCH 118/187] SFT-1434: first pass (untested) nip26 implementation, added timezones to support nip26 --- ports/stm32/boards/Passport/manifest.py | 1 + .../boards/Passport/modules/flows/__init__.py | 1 + .../modules/flows/choose_timezone_flow.py | 46 ++++ .../modules/flows/nostr_delegation_flow.py | 215 +++++++++++++++++- ports/stm32/boards/Passport/modules/menus.py | 3 +- .../Passport/modules/tasks/nostr_key_task.py | 16 +- ports/stm32/boards/Passport/modules/utils.py | 16 ++ 7 files changed, 285 insertions(+), 13 deletions(-) create mode 100644 ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index f47ecabb1..e5df88703 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -85,6 +85,7 @@ 'flows/casa_health_check_microsd_flow.py', 'flows/casa_health_check_qr_flow.py', 'flows/change_pin_flow.py', + 'flows/choose_timezone_flow.py', 'flows/delete_account_flow.py', 'flows/delete_multisig_flow.py', 'flows/envoy_setup_flow.py', diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index baddb7e4b..66e4b12e2 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -31,6 +31,7 @@ from .casa_health_check_microsd_flow import * from .casa_health_check_qr_flow import * from .change_pin_flow import * +from .choose_timezone_flow import * from .delete_account_flow import * from .delete_multisig_flow import * from .erase_passport_flow import * diff --git a/ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py b/ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py new file mode 100644 index 000000000..107c7e983 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# choose_timezone_flow.py - Choose a timezone + +from flows import Flow + + +class ChooseTimezoneFlow(Flow): + def __init__(self, context=None): + super().__init__(initial_state=self.enter_timezone, name='ChooseTimezoneFlow') + + async def enter_timezone(self): + from pages import TextInputPage, SuccessPage, ErrorPage + from common import settings + from utils import InputMode + import microns + # from flows import AutoBackupFlow + + timezone = settings.get('timezone', None) + result = await TextInputPage(card_header={'title': 'GMT Offset'}, + numeric_only=False, + initial_text='-' if timezone is None else str(timezone), + initial_mode=InputMode.NUMERIC, + max_length=3, + left_micron=microns.Back, + right_micron=microns.Checkmark).show() + if result is None: + self.set_result(False) + return + + try: + tz = int(result) + except Exception as e: + await ErrorPage('Timezone offset must be a number from -12 to 12.').show() + return + + if tz < -12 or tz > 12: + await ErrorPage('Timezones range from GMT-12 to GMT+12.').show() + return + + await SuccessPage(text='Time Zone Saved').show() + # TODO: auto backup? + # await AutoBackupFlow().run() + settings.set('timezone', tz) + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index a66416e29..75482df47 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -6,13 +6,174 @@ from flows import Flow +def created_at_helper(carrot, created_at, timezone): + from datetime import datetime + created = [c for c in created_at if c.count(carrot)] + assert len(created) <= 1, 'There must only be 1 "created {}" condition.'.format( + 'before' if carrot == '<' else 'after') + + if len(created) == 0: + return None + + created = int(created[0].split(carrot)[1]) + + # TODO: this could be a util + if timezone is not None: + datetime.timezone(datetime.timedelta(hours=int(timezone))) + created = datetime.fromtimestamp(created).strftime('%Y-%m-%d %H:%M') + + # Ensure timezone string exists, prepend + if positive + # TODO: this could be a util + if timezone is None: + timezone = "+0" + elif int(timezone) >= 0: + timezone = "+" + timezone + + return created + " GMT" + timezone + + +event_kind = { + 0: 'Metadata', + 1: 'Short Text Notes', + 2: 'Recommend Relays', + 3: 'Contacts', + 4: 'Encrypted Direct Messages', + 5: 'Event Deletion', + 6: 'Reposts', + 7: 'Reactions', + 8: 'Badge Awards', + 40: 'Channel Creation', + 41: 'Channel Metadata', + 42: 'Channel Messages', + 43: 'Channel Hide Messages', + 44: 'Channel Mute Users', + 1984: 'Reporting', + 9731: 'Zap Requests', + 9735: 'Zaps', + 10000: 'Mute Lists', + 10001: 'Pin Lists', + 10002: 'Relay List Metadata', + 24133: 'Nostr Connect', + 30000: 'Categorized People Lists', + 30001: 'Categorized Bookmark Lists', + 30008: 'Profile Badges', + 30009: 'Badge Definitions', + 30023: 'Long-Form Content', + 30078: 'Application-Specific Data', +} + + +def parse_delegation_string(delegation_string): + from ubinascii import unhexlify as a2b_hex + from utils import nostr_nip19_from_key + import uio + import re + from common import settings + from styles.colors import HIGHLIGHT_TEXT_HEX + + fields = delegation_string.split(':') + num_fields = len(fields) + assert num_fields == 4, \ + 'Invalid delegation string: must have 4 fields, found {}'.format(num_fields) + assert field[0] == 'nostr' and field[1] == 'delegation', \ + 'First 2 fields of delegation string must be "nostr:delegation:"' + + # exceptions handled by caller + delegatee = a2b_hex(field[2]) + + # TODO: check length before converting to npub + + delegatee_npub = nostr_nip19_from_key(delegatee, "npub") + + conditions = fields[3].split('&') + num_conditions = len(conditions) + assert num_conditions > 0, \ + 'Delegation conditions are required, found {}'.format(num_conditions) + + # TODO: what are the condition parsing rules? Can multiple kinds be given different + # created_at rules within 1 delegation? I assume not for now. This means + # all 'kind' conditions must come before all 'created_at' conditions. + + kind_pattern = re.compile('^kind=\\d+$') + created_at_pattern = re.compile('^created_at[\\<\\>]\\d+$') + kinds = [] + created_at = [] + + # Get all kinds + for c in conditions: + if kind_pattern.search(c): + kinds.append(c) + else: + break + + # Get all created_at + for c in conditions: + if created_at_pattern.search(c): + created_at.append(c) + else: + assert not kind_pattern.search(c), \ + 'All "kinds" must come before all "created_at" conditions.' + break + + assert len(created_at) <= 2, 'There must be at most 2 "created_at" conditions.' + + timezone = settings.get('timezone', None) + created_before = created_at_helper('<', created_at, timezone) + created_after = created_at_helper('>', created_at, timezone) + + # len(kinds) + len(created_at) == len(conditions) iff all conditions are valid and + # all 'kinds' come before all 'created_at' + assert len(kinds) + len(created_at) == len(condtions), 'Invalid conditions found' + + # temp = [] + # for k in kinds: + # temp.append(int(k.split('=')[1])) + # kinds = temp + kinds = list(map(lambda k: int(k.split('=')[1]), kinds)) + + # All inputs checked, format description and warnings + + details = uio.StringIO() + details.write("\n{}\n{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Delegating To:'), + delegatee_npub)) + + if created_after: + details.write("\n{}\n{}\n{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Delegation Start Date:'), + created_after, + "Make sure this time isn't in the past!")) + else: + details.write("\n{}\n{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Warning:'), + "No start date, use caution!")) + + if created_before: + details.write("\n{}\n{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Delegation End Date:'), + created_before)) + else: + details.write("\n{}\n{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Warning:'), + "No end date, use caution!")) + + details.write("\n{}".format( + recolor(HIGHLIGHT_TEXT_HEX, 'Event Types:'))) + + for k in kinds: + details.write("\n{}: {}".format( + k, event_kind.get(k, "Unknown event, use caution!"))) + + return details.getvalue() + + class NostrDelegationFlow(Flow): def __init__(self, context=None): from derived_key import get_key_type_from_tn self.key = context self.key_type = get_key_type_from_tn(self.key['tn']) - self.nsec = None + self.pk = None self.npub = None self.delegation_string = None super().__init__(initial_state=self.export_npub, name='NostrDelegationFlow') @@ -24,10 +185,10 @@ async def export_npub(self): (vals, error) = await spinner_task(text='Generating npub', task=self.key_type['task'], args=[self.key['index']]) - self.nsec = vals['priv'] - self.npub = vals['pub'] + self.pk = vals['pk'] + self.npub = vals['npub'] - if not self.nsec or not self.npub: + if not self.pk or not self.npub: await ErrorPage("Failed to generate npub and nsec").show() self.set_result(False) return @@ -46,11 +207,53 @@ async def scan_delegation_string(self): return if result.is_failure(): - await ErrorPage(text='Unable to scan QR code.').show() + await ErrorPage('Unable to scan QR code.').show() self.set_result(False) return self.delegation_string = result.data + self.goto(self.display_details) + + async def display_details(self): + from pages import ErrorPage, InfoPage, LongTextPage + from common import settings + from flows import ChooseTimezoneFlow + import microns + + if not settings.get('timezone', None): + result = await InfoPage('Nostr delegation is time-sensitive. Please enter your timezone.', + left_micron=microns.Back, + right_micron=microns.Forward).show() + if not result: + self.back() + return + await ChooseTimezoneFlow().run() + + try: + details = parse_delegation_string(self.delegation_string) + except Exception as e: + await ErrorPage('{}'.format(e)).show() + self.set_result(False) + return + + result = await LongTextPage(text=details, + centered=True, + card_header={'title': 'Delegation Details'}).show() + if not result: + self.set_result(False) + return + + self.goto(self.sign_delegation) + return + + async def sign_delegation(self): + from serializations import sha256 + from utils import nostr_sign + from pages import ShowQRPage + from ubinascii import hexlify as b2a_hex + + sha = sha256(self.delegation_string) + sig = nostr_sign(self.pk, sha) - # TODO: parse delegation string, go to display info + await ShowQRPage(qr_data=b2a_hex(sig)).show() self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 8ff60e6ab..9500ff991 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -110,7 +110,7 @@ def plus_menu(): def device_menu(): - from flows import AboutFlow, ChangePINFlow + from flows import AboutFlow, ChangePINFlow, ChooseTimezoneFlow from pages import AutoShutdownSettingPage, BrightnessSettingPage from utils import is_logged_in @@ -118,6 +118,7 @@ def device_menu(): {'icon': lv.ICON_BRIGHTNESS, 'label': 'Screen Brightness', 'page': BrightnessSettingPage}, {'icon': lv.ICON_COUNTDOWN, 'label': 'Auto-Shutdown', 'page': AutoShutdownSettingPage}, {'icon': lv.ICON_PIN, 'label': 'Change PIN', 'flow': ChangePINFlow, 'is_visible': is_logged_in}, + {'icon': lv.ICON_CLOCK, 'label': 'Change Timezone', 'flow': ChooseTimezoneFlow}, {'icon': lv.ICON_INFO, 'label': 'About', 'flow': AboutFlow}, ] diff --git a/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py b/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py index 43403ee0c..9db0c7633 100644 --- a/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py @@ -6,14 +6,18 @@ async def nostr_key_task(on_done, index): import stash - import tcc - from trezorcrypto import secp256k1 + # import tcc + # from trezorcrypto import secp256k1 + from utils import nostr_pubkey_from_pk, nostr_nip19_from_key path = "m/44'/1237'/{}'/0/0".format(index) with stash.SensitiveValues() as sv: node = sv.derive_path(path) key = node.private_key() - pub = secp256k1.publickey(key, True)[1:] - nsec = tcc.codecs.bech32_plain_encode("nsec", key) - npub = tcc.codecs.bech32_plain_encode("npub", pub) - await on_done({'priv': nsec, 'pub': npub}, None) + # pub = secp256k1.publickey(key, True)[1:] + pub = nostr_pubkey_from_pk(key) + # nsec = tcc.codecs.bech32_plain_encode("nsec", key) + # npub = tcc.codecs.bech32_plain_encode("npub", pub) + nsec = nostr_nip19_from_key(key, "nsec") + npub = nostr_nip19_from_key(pub, "npub") + await on_done({'priv': nsec, 'npub': npub, 'pk': key, 'pub': pub}, None) diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index c57e48aea..05bd05c20 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1330,4 +1330,20 @@ def get_words_from_seed(seed): except Exception as e: return (None, '{}'.format(e)) + +def nostr_pubkey_from_pk(pk): + from trezorcrypto import secp256k1 + return secp256k1.publickey(pk, True)[1:] + + +def nostr_nip19_from_key(key, key_type): # generate nsec/npub + import tcc + return tcc.codecs.bech32_plain_encode(key_type, key) + + +def nostr_sign(key, message): + from trezorcrypto import secp256k1 + return secp256k1.sign(key, message) + + # EOF From e5b85c0c87f437ed403bda36266f3ce92c8817e1 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 6 Apr 2023 16:44:20 -0500 Subject: [PATCH 119/187] SFT-1434: second pass nip26 delegation, just missing correct signatures and some quality of life problems --- .../modtrezorcrypto/modtrezorcrypto-schnorr.h | 66 +++++++++++++++++++ .../extmod/modtrezorcrypto/modtrezorcrypto.c | 1 + .../modules/flows/nostr_delegation_flow.py | 62 ++++++++++++----- ports/stm32/boards/Passport/modules/utils.py | 5 +- py/py.mk | 1 + 5 files changed, 116 insertions(+), 19 deletions(-) create mode 100644 extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h new file mode 100644 index 000000000..9545cbf0b --- /dev/null +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h @@ -0,0 +1,66 @@ +/* + * This file is part of the TREZOR project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "py/obj.h" +#include "py/objstr.h" +#include "py/runtime.h" + +#include "schnorr.h" +#include "secp256k1.h" + +/// package: trezorcrypto.schnorr + +/// def sign(pk: bytes, digest: bytes) -> bytes: +/// """ +/// Schnorr signatures +/// """ +STATIC mp_obj_t mod_trezorcrypto_schnorr_sign(mp_obj_t pk_obj, mp_obj_t digest_obj) { + mp_buffer_info_t pk, digest; + mp_get_buffer_raise(pk_obj, &pk, MP_BUFFER_READ); + mp_get_buffer_raise(digest_obj, &digest, MP_BUFFER_READ); + + vstr_t signature; + vstr_init_len(&signature, SCHNORR_SIG_LENGTH); + + int rv = schnorr_sign_digest(&secp256k1, pk.buf, digest.buf, (uint8_t *)signature.buf); + if (rv != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("schnorr signature failed")); + } + signature.len = strlen(signature.buf); + + return mp_obj_new_str_from_vstr(&mp_type_str, &signature); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2( + mod_trezorcrypto_schnorr_sign_obj, + mod_trezorcrypto_schnorr_sign); + +STATIC const mp_rom_map_elem_t mod_trezorcrypto_schnorr_globals_table[] = { + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_schnorr)}, + {MP_ROM_QSTR(MP_QSTR_sign), + MP_ROM_PTR(&mod_trezorcrypto_schnorr_sign_obj)}, +}; +STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_schnorr_globals, + mod_trezorcrypto_schnorr_globals_table); + +STATIC const mp_obj_module_t mod_trezorcrypto_schnorr_module = { + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&mod_trezorcrypto_schnorr_globals, +}; diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c index 816b951c3..9f16b0924 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -56,6 +56,7 @@ static void wrapped_ui_wait_callback(uint32_t current, uint32_t total) { #include "modtrezorcrypto-random.h" #include "modtrezorcrypto-ripemd160.h" #include "modtrezorcrypto-secp256k1.h" +#include "modtrezorcrypto-schnorr.h" #include "modtrezorcrypto-sha1.h" #include "modtrezorcrypto-sha256.h" #if USE_KECCAK diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 75482df47..063b18949 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -7,7 +7,7 @@ def created_at_helper(carrot, created_at, timezone): - from datetime import datetime + import utime created = [c for c in created_at if c.count(carrot)] assert len(created) <= 1, 'There must only be 1 "created {}" condition.'.format( 'before' if carrot == '<' else 'after') @@ -19,15 +19,27 @@ def created_at_helper(carrot, created_at, timezone): # TODO: this could be a util if timezone is not None: - datetime.timezone(datetime.timedelta(hours=int(timezone))) - created = datetime.fromtimestamp(created).strftime('%Y-%m-%d %H:%M') + # utime.timezone(int(timezone) * 3600) # stored in hours, need seconds + created += int(timezone) * 3600 + # TODO: time string is broken + time_tup = utime.gmtime(created) + created = "{}-{}-{} {}:{}".format(time_tup[3], # Day + time_tup[2], # Month + time_tup[1], # Year + time_tup[4], # Hour + time_tup[5], # Minute + ) + + # created = utime.fromtimestamp(created).strftime('%Y-%m-%d %H:%M') # Ensure timezone string exists, prepend + if positive # TODO: this could be a util if timezone is None: timezone = "+0" elif int(timezone) >= 0: - timezone = "+" + timezone + timezone = "+" + str(timezone) + else: + timezone = str(timezone) return created + " GMT" + timezone @@ -65,7 +77,7 @@ def created_at_helper(carrot, created_at, timezone): def parse_delegation_string(delegation_string): from ubinascii import unhexlify as a2b_hex - from utils import nostr_nip19_from_key + from utils import nostr_nip19_from_key, recolor import uio import re from common import settings @@ -75,11 +87,12 @@ def parse_delegation_string(delegation_string): num_fields = len(fields) assert num_fields == 4, \ 'Invalid delegation string: must have 4 fields, found {}'.format(num_fields) - assert field[0] == 'nostr' and field[1] == 'delegation', \ + assert fields[0] == 'nostr' and fields[1] == 'delegation', \ 'First 2 fields of delegation string must be "nostr:delegation:"' # exceptions handled by caller - delegatee = a2b_hex(field[2]) + # TODO: make these exceptions prettier + delegatee = a2b_hex(fields[2]) # TODO: check length before converting to npub @@ -90,6 +103,8 @@ def parse_delegation_string(delegation_string): assert num_conditions > 0, \ 'Delegation conditions are required, found {}'.format(num_conditions) + assert len(set(conditions)) == len(conditions), "Duplicate conditions found" + # TODO: what are the condition parsing rules? Can multiple kinds be given different # created_at rules within 1 delegation? I assume not for now. This means # all 'kind' conditions must come before all 'created_at' conditions. @@ -106,6 +121,9 @@ def parse_delegation_string(delegation_string): else: break + # remove all found kinds from conditions before continuing + conditions = list(set(conditions) - set(kinds)) + # Get all created_at for c in conditions: if created_at_pattern.search(c): @@ -122,8 +140,8 @@ def parse_delegation_string(delegation_string): created_after = created_at_helper('>', created_at, timezone) # len(kinds) + len(created_at) == len(conditions) iff all conditions are valid and - # all 'kinds' come before all 'created_at' - assert len(kinds) + len(created_at) == len(condtions), 'Invalid conditions found' + # all 'kinds' come before all 'created_at', but we already removed 'kinds' + assert len(created_at) == len(conditions), 'Invalid conditions found' # temp = [] # for k in kinds: @@ -138,26 +156,32 @@ def parse_delegation_string(delegation_string): recolor(HIGHLIGHT_TEXT_HEX, 'Delegating To:'), delegatee_npub)) + details.write("\n\n") + if created_after: - details.write("\n{}\n{}\n{}".format( + details.write("{}\n{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Delegation Start Date:'), created_after, "Make sure this time isn't in the past!")) else: - details.write("\n{}\n{}".format( + details.write("{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Warning:'), "No start date, use caution!")) + details.write("\n\n") + if created_before: - details.write("\n{}\n{}".format( + details.write("{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Delegation End Date:'), created_before)) else: - details.write("\n{}\n{}".format( + details.write("{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Warning:'), "No end date, use caution!")) - details.write("\n{}".format( + details.write("\n\n") + + details.write("{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Event Types:'))) for k in kinds: @@ -181,11 +205,13 @@ def __init__(self, context=None): async def export_npub(self): from utils import spinner_task from pages import ShowQRPage, ErrorPage + from ubinascii import unhexlify as a2b_hex (vals, error) = await spinner_task(text='Generating npub', task=self.key_type['task'], args=[self.key['index']]) self.pk = vals['pk'] + # self.pk = a2b_hex("ee35e8bb71131c02c1d7e73231daa48e9953d329a4b701f7133c8f46dd21139c") self.npub = vals['npub'] if not self.pk or not self.npub: @@ -248,12 +274,14 @@ async def display_details(self): async def sign_delegation(self): from serializations import sha256 - from utils import nostr_sign + from utils import nostr_sign, B2A from pages import ShowQRPage - from ubinascii import hexlify as b2a_hex + print("pk: {}".format(B2A(self.pk))) sha = sha256(self.delegation_string) + print("sha: {}".format(B2A(sha))) sig = nostr_sign(self.pk, sha) + print("sig: {}".format(B2A(sig))) - await ShowQRPage(qr_data=b2a_hex(sig)).show() + await ShowQRPage(qr_data=B2A(sig)).show() self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index 05bd05c20..b821587f7 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1342,8 +1342,9 @@ def nostr_nip19_from_key(key, key_type): # generate nsec/npub def nostr_sign(key, message): - from trezorcrypto import secp256k1 - return secp256k1.sign(key, message) + from trezorcrypto import schnorr + from serializations import sha256 + return sha256(schnorr.sign(key, message)) # EOF diff --git a/py/py.mk b/py/py.mk index eab9361f0..a1f3c7ad2 100644 --- a/py/py.mk +++ b/py/py.mk @@ -352,6 +352,7 @@ PY_EXTMOD_O_BASENAME = \ extmod/trezor-firmware/crypto/shamir.o \ extmod/trezor-firmware/crypto/groestl.o \ extmod/trezor-firmware/crypto/slip39.o \ + extmod/trezor-firmware/crypto/schnorr.o \ extmod/trezor-firmware/crypto/rand.o \ extmod/trezor-firmware/crypto/rfc6979.o \ extmod/trezor-firmware/crypto/hmac_drbg.o \ From 51b5c2356ce8caccb15675918c16814b516459b7 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 7 Apr 2023 11:24:16 -0500 Subject: [PATCH 120/187] SFT-1434: signature is now correct length, but still wrong --- .../embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h | 5 ++--- ports/stm32/boards/Passport/modules/utils.py | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h index 9545cbf0b..1698fa452 100644 --- a/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h +++ b/extmod/trezor-firmware/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-schnorr.h @@ -37,16 +37,15 @@ STATIC mp_obj_t mod_trezorcrypto_schnorr_sign(mp_obj_t pk_obj, mp_obj_t digest_o mp_get_buffer_raise(pk_obj, &pk, MP_BUFFER_READ); mp_get_buffer_raise(digest_obj, &digest, MP_BUFFER_READ); - vstr_t signature; + vstr_t signature = {0}; vstr_init_len(&signature, SCHNORR_SIG_LENGTH); int rv = schnorr_sign_digest(&secp256k1, pk.buf, digest.buf, (uint8_t *)signature.buf); if (rv != 0) { mp_raise_ValueError(MP_ERROR_TEXT("schnorr signature failed")); } - signature.len = strlen(signature.buf); - return mp_obj_new_str_from_vstr(&mp_type_str, &signature); + return mp_obj_new_str_from_vstr(&mp_type_bytes, &signature); } STATIC MP_DEFINE_CONST_FUN_OBJ_2( mod_trezorcrypto_schnorr_sign_obj, diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index b821587f7..1e4194b86 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1343,8 +1343,7 @@ def nostr_nip19_from_key(key, key_type): # generate nsec/npub def nostr_sign(key, message): from trezorcrypto import schnorr - from serializations import sha256 - return sha256(schnorr.sign(key, message)) + return schnorr.sign(key, message) # EOF From 4ed36ebdeb62f421ed0553130d28645bfb66eb66 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 7 Apr 2023 12:26:11 -0500 Subject: [PATCH 121/187] SFT-1434: improved date formatting --- .../modules/flows/nostr_delegation_flow.py | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 063b18949..b9c7ca6d3 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -5,6 +5,21 @@ from flows import Flow +months = { + 1: 'January', + 2: 'February', + 3: 'March', + 4: 'April', + 5: 'May', + 6: 'June', + 7: 'July', + 8: 'Aug', + 9: 'September', + 10: 'October', + 11: 'November', + 12: 'December', +} + def created_at_helper(carrot, created_at, timezone): import utime @@ -16,24 +31,23 @@ def created_at_helper(carrot, created_at, timezone): return None created = int(created[0].split(carrot)[1]) + print(created) # TODO: this could be a util if timezone is not None: # utime.timezone(int(timezone) * 3600) # stored in hours, need seconds created += int(timezone) * 3600 - # TODO: time string is broken - time_tup = utime.gmtime(created) - created = "{}-{}-{} {}:{}".format(time_tup[3], # Day - time_tup[2], # Month - time_tup[1], # Year - time_tup[4], # Hour - time_tup[5], # Minute - ) + print(created) - # created = utime.fromtimestamp(created).strftime('%Y-%m-%d %H:%M') + time_tup = utime.gmtime(created) + created = "{} {}, {}\n{}:{}".format(months[time_tup[1]], # Month + time_tup[2], # Day + time_tup[0], # Year + time_tup[3], # Hour + time_tup[4], # Minute + ) # Ensure timezone string exists, prepend + if positive - # TODO: this could be a util if timezone is None: timezone = "+0" elif int(timezone) >= 0: @@ -246,7 +260,7 @@ async def display_details(self): from flows import ChooseTimezoneFlow import microns - if not settings.get('timezone', None): + if settings.get('timezone', None) is None: result = await InfoPage('Nostr delegation is time-sensitive. Please enter your timezone.', left_micron=microns.Back, right_micron=microns.Forward).show() From 618844191bd08311865b5ef9762cdf3b6fcbbc02 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 7 Apr 2023 13:23:52 -0500 Subject: [PATCH 122/187] SFT-1434: moved time formatting to utils --- .../modules/flows/nostr_delegation_flow.py | 59 +++---------------- ports/stm32/boards/Passport/modules/utils.py | 43 ++++++++++++++ 2 files changed, 50 insertions(+), 52 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index b9c7ca6d3..271d4f523 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -5,24 +5,9 @@ from flows import Flow -months = { - 1: 'January', - 2: 'February', - 3: 'March', - 4: 'April', - 5: 'May', - 6: 'June', - 7: 'July', - 8: 'Aug', - 9: 'September', - 10: 'October', - 11: 'November', - 12: 'December', -} - -def created_at_helper(carrot, created_at, timezone): - import utime +def created_at_helper(carrot, created_at): + from utils import timestamp_to_str created = [c for c in created_at if c.count(carrot)] assert len(created) <= 1, 'There must only be 1 "created {}" condition.'.format( 'before' if carrot == '<' else 'after') @@ -31,31 +16,7 @@ def created_at_helper(carrot, created_at, timezone): return None created = int(created[0].split(carrot)[1]) - print(created) - - # TODO: this could be a util - if timezone is not None: - # utime.timezone(int(timezone) * 3600) # stored in hours, need seconds - created += int(timezone) * 3600 - print(created) - - time_tup = utime.gmtime(created) - created = "{} {}, {}\n{}:{}".format(months[time_tup[1]], # Month - time_tup[2], # Day - time_tup[0], # Year - time_tup[3], # Hour - time_tup[4], # Minute - ) - - # Ensure timezone string exists, prepend + if positive - if timezone is None: - timezone = "+0" - elif int(timezone) >= 0: - timezone = "+" + str(timezone) - else: - timezone = str(timezone) - - return created + " GMT" + timezone + return timestamp_to_str(created) event_kind = { @@ -94,7 +55,6 @@ def parse_delegation_string(delegation_string): from utils import nostr_nip19_from_key, recolor import uio import re - from common import settings from styles.colors import HIGHLIGHT_TEXT_HEX fields = delegation_string.split(':') @@ -149,18 +109,13 @@ def parse_delegation_string(delegation_string): assert len(created_at) <= 2, 'There must be at most 2 "created_at" conditions.' - timezone = settings.get('timezone', None) - created_before = created_at_helper('<', created_at, timezone) - created_after = created_at_helper('>', created_at, timezone) + created_before = created_at_helper('<', created_at) + created_after = created_at_helper('>', created_at) # len(kinds) + len(created_at) == len(conditions) iff all conditions are valid and # all 'kinds' come before all 'created_at', but we already removed 'kinds' assert len(created_at) == len(conditions), 'Invalid conditions found' - # temp = [] - # for k in kinds: - # temp.append(int(k.split('=')[1])) - # kinds = temp kinds = list(map(lambda k: int(k.split('=')[1]), kinds)) # All inputs checked, format description and warnings @@ -172,7 +127,7 @@ def parse_delegation_string(delegation_string): details.write("\n\n") - if created_after: + if created_after is not None: details.write("{}\n{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Delegation Start Date:'), created_after, @@ -184,7 +139,7 @@ def parse_delegation_string(delegation_string): details.write("\n\n") - if created_before: + if created_before is not None: details.write("{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Delegation End Date:'), created_before)) diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index 1e4194b86..cb7ff5e43 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1346,4 +1346,47 @@ def nostr_sign(key, message): return schnorr.sign(key, message) +months = { + 1: 'January', + 2: 'February', + 3: 'March', + 4: 'April', + 5: 'May', + 6: 'June', + 7: 'July', + 8: 'Aug', + 9: 'September', + 10: 'October', + 11: 'November', + 12: 'December', +} + + +def timestamp_to_str(time): + import utime + from common import settings + + timezone = settings.get('timezone', None) + if timezone is not None: + time += int(timezone) * 3600 + + time_tup = utime.gmtime(time) + time = "{} {}, {}\n{}:{}".format(months[time_tup[1]], # Month + time_tup[2], # Day + time_tup[0], # Year + time_tup[3], # Hour + time_tup[4], # Minute + ) + + # Ensure timezone string exists, prepend + if positive + if timezone is None: + timezone = "+0" + elif int(timezone) >= 0: + timezone = "+" + str(timezone) + else: + timezone = str(timezone) + + return time + " GMT" + timezone + + # EOF From 4b68d443f0bf1f67f1c379d166554af30a906755 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 7 Apr 2023 16:31:35 -0500 Subject: [PATCH 123/187] SFT-1434: refined time formatting and validated delegation string parsing and formatting --- .../color/ICON_CLOCK__CF_INDEXED_2_BIT.png | Bin 7114 -> 423 bytes .../modules/flows/choose_timezone_flow.py | 7 +- .../modules/flows/nostr_delegation_flow.py | 110 +++++++++++------- ports/stm32/boards/Passport/modules/menus.py | 1 - ports/stm32/boards/Passport/modules/utils.py | 12 +- 5 files changed, 81 insertions(+), 49 deletions(-) diff --git a/ports/stm32/boards/Passport/images/color/ICON_CLOCK__CF_INDEXED_2_BIT.png b/ports/stm32/boards/Passport/images/color/ICON_CLOCK__CF_INDEXED_2_BIT.png index 8d9c41e24de5dee65ad8d914e28d3726d5734a59..4e2e5bf40aaff7dbf780cc7dd6bf06ad28c902ff 100644 GIT binary patch delta 398 zcmV;90dfAyH>U%TBYyx1a7bBm000XU000XU0RWnu7ytkO0drDELIAGL9O(c600d`2 zO+f$vv5yP*x5BRPWt$E7_M*EGdR6#>`e0tAEeNm^1A)kbej|!N_Zy1g*fO&YA?- zL6%-sLCqle)9|z4Mc@R#f)7!AqJpwcRV+|Z*awBP?(IsOSU0*T_6bBj7myw(6P#1; z#>WzVr`arec`J1-rPU`1qqE1*Ipq%22sI9cBYrn36*u=okK32v6MFfPV)g^}axS>k3$3V$>Tw@!eby8`NjLW5kQ44W`8Jkq^qJ&~Yr4P2~aW zlGC((fw~=J`G!FIaHjPtWckd3)Mu^_hh^0vlpbHLESMmUuJwib^hN(9z##CW?M=ql sKpWF(wIyR4H4~dUYc`PY`ULy~>v6mlXKJEb00000Ne4wvM6N<$g8q1|LI3~& literal 7114 zcmeHKc{G&m`yU~)rA6_kjG?5AS(q^nJCGwlCmZx zOZK(wL}}6T7NPX!_fT(d@A-bu`JMNi-|xS7&Uxm!pKJNt*Y&xs`#$#_Wnq3$T;w+q z2m~T-Y@}}mzBjKt!fV0**r@H|5Xidc0oFve6^RRFFzN0T9{|ce&H$i*KgAsa@gEvZ zvu7&olh9wTj6O#Au#Tx2XgIRH?c(Z}*;n+_9kmZUn=WM#u z{7|RC*z$IP_p!}p??>hyJJ+0eAIIku!uyaE^RW8UWYu1V-~-UF{H&EpQB` zCSz`G(u<^^pz)f6dn-;vhrD<;C+j?>fvq(Js=wv(^lGn<3@>Rr{Xv}TSo%`^xY;{1 z?MUA_2B&KMCtORds}ost6u-^XB<1&Q#|ZO*(#GuBT`_;K{Ke~MhZJw6KI|CHlQgP=> z2F?PtOA)vG${#y@ezo@v)0`J86P;13Ca(XciuYUjDY@$ly3vI~_w$?{Z&t?L;qA05 z(@m|TXK8Ozm@?kFcghK}^(N<`^hYSs;+D>k8^YJTs3AcnbkDVYat{1_+p@PwzdE_F z&Zo4u_;d7tcE3RrwLYj>Oc5rdiXut*a2K|y|#9_EX*>sjSPZ8smL2Z|_POH@== zw)wE}tiCbqe2!7O&KX%&%XyY+2gteDCl7nbihQlFYBTu65}U5S_dtDcNO?sxB43ugr`dJSux^!*)Z% z1|Ond7XhSOV3u|@`5yGMpTJ=zL!7e^auw()=?svj5RY};VqvT^Cqjmc79rWso- zX%iAU?5hSc1NmR(8FDvly{IgS|}OEt^|*(L+wi|vhe5xYASM93wERa=#N2`~K4 zrWquQh7Uz@=22Ta{6^R%&r4d|N}cq46m@+f?fRy6v`S27VuYl1cI?^4uGE!jSCY$c?5*JP>_XCqa)w*Rk|P`B%;H{6 z2WCt+iq8~RRTh;?xG46q>_%gUY-u;bZSGB6bcV-mct|w)wx~mJLLRD(4D$O8)v9

rr?CI=oy*g&(aajes#}06Ge7Usx{?b5W4o7&&b;1%x0U8C5i6qXHv;3uhiG(N@Z@%F*UFD6WVyQ#jrTBLhRY@jn4C<+YZaCG@B8) z(>ZCvgAPq$;~z3Vw}n}Bm0dOx$}^ZlH$*ii(NI%yoRfFWazBS)vgKdc4{fTF-D7p@ z%i!piyq+EAH)z7G@6#@(1r)?~RbOFy^gvG{^6#=d{f}L}k{?8;#HpXSP~mODzCjCv z`h-H!0@i1C@2g?X-#b0DTu-zWQb1n@udMxM-@ucGkU@sF~W{R0~3?|>nO^1Kd%L&G$JDU+dH^JL^2YFoi){E%O7`0f3Ck~EW z9(Uf1cU@KX=I=*8U>72k)NEs<@fB5H>~ zMCS}D>OSX(2R;ySwwp_OwL2qI(P%WQ=0n6_$3RJFTP<68Z`_lC)bW_|>j!7|<>{4p zJ*$66g?`T8rE@^zedm{{yn7K}SnBT(x5xQKXC=;d)_;s@m^qb>s9Sv79k?8G-TTt# zquonI({HW5syuADI#TYi<*;nVr1 zU*?*yz7l@8{Y}yXjY2miPC#Cns^Bfhyk?}U5dZ%@M==7l{Jy6y5kbM{2V0njCV zt=aD3!pbrG`#0Mr6R%vm za?aJD#!27wAkiZ$>#U7!$$&oI;O_QtEkc2J(`L_bZj=6C>2#Ut@p99F^rN%6zH3Eh6d7ZU&H8ipL%e4(g({$yx8*u zQ`V#xTpc`h^C{AVk7A%eI3|pg@I36ur2<^(L%`?;jy=#Bh!;rWxR(nTyr!Au*3};2 z+}onll6?ML@EKLkZ(y_!FtfTYqD?rbxB(;NKe;5}k{-ht}I+IOeB*9l|N&sCH95@VnD zobJAF_gb4OqwC)p_^!6|?$%~e^!!|Fb$AD@$Vw&6(rO01?U`)z@=3W9vQiTJ%ghp` z@7@#fj24+x$8WZ;SR-XFceS&iAesEA5WVQ%IOktC*9W~WhfI?bdG>rZXMD%K{nYob zd-2swQ^-JK>z!cwi9=nU7YF*j;NqGu{Nb;1SgOi-&!+?o(Ney(x6f0y43fY~a|~@J zmK`HJY4Gkiw}!fylu&ovc$5<_K~`;GIXHQz?xGGmm{Yo%fP=7e>6#PeM$c!yoZE8; zKbPR{S3g+1#wAqRUQF3aq3E_a1~xXVlWj9@k>B@r?ul_ud812z>@DVXSHrTGy`}LH z9S+Nch`!U^8M&r!ayY-+Vm|UDjxR?(dKt3g^f&vNkatTuS&MncjzJ)N5fnW=3u8UK zKM#E1F)t%1LEET)ziflEZW&DKz`jVFTb_jL0qd*THkXB^2*q6mryk|V5iXooY-q4# zz;TN=i5!OS5)n!KAd^jdoj7= zcqZ<_q4R`5b1nBS!6>;()#|T}l`n5(dKjKH4T!@LR5lM2X=EF;^`!D--W9LJ_nlQm zjIqh0^oMsP^JCw%d*8el%I{>}?Y8$w0Z-=s6z~L2G&9AM=~Pvc8{HL9^`|nx6FLN< zrR&cik-Y&n)D`fc(6nLitM9>}6gO>{EyfIK#?S*iDMkTI;7EYEH95eWtmy{R)e+J1 z$AbV=fK7t>Q+;SGyuUVV6&DYVSHuVybk&6ItqmiZSwQvZOaQ8`s;-KJ8~9WF&@del zs20=B9dD&?_yYp`(uR4m*$g}a!R2yQxoWC(rUwG0si}!Tq7i5`9JGM5j?>sAe>jb$ zumbTNLmyy~nG^<_LZ?AjFiEa-4qF=r1NG29ubYS=Eu9y$rLyI>d+mDBx3R1vAu8DIa!PQA9G-gFf(!{JnxsmaP zbS9MqmXksyc>o9o&0|%uLOA|_g|Rjat&03hV&Ow#yMqqeFjESRdQ5=C zrZcVSbRTWlN=VQZ&!1{Da5=e=*d%=t8vsF(Xfz&)#iKN=!2t?|N2-Cg+(}%LUl%UYnMS&-gzo)<=`2lXLae`Ri zRb)>R%>w{;k00&&r=0R%S^>bI)WCva;F|6@6kMGQVBt6{T4SXZ)HSgvl%_iQdpG?= zXVKl+ToMyF-~sXoas{^MDp%0mtA$ejdn{Z}V5JHmVQ?fC{-1;)ek6=o*)#skSPStV zoM^2Y{Ibb_e&1!_<^}GBh@YF`56-}N|37~}YVrR$1r+-4B>#xtf9d*{u7AY9KQjKe zyZ)u?A2INcjQ{Pf|1-Ko{<=;9H1HI}1ush~)bU*KqP5o5`A21?d3 zjE=D&5YbI54<95wLmCtcv5n0Pgr?VS6cptbyw2PJfvmAK)<0m4Yvm-in^;>)H-@}m zdN8^u^4W2zF-Srllp$Ys!yx9Eex~H+Vmsm6FP$mFXki#PKPJy0Q?lh z9HyL}JzMrN?J48#4qVKM&Ly4qPiAYvG8B{rMfS@fMXdSw_U_*_u*Q!d{I-bR3=zx{ z!U;M+c7+{)-hLFvm&tdlj=4o$6bEsbEr#fZUAMGRs9PsQfy9TVNj}I73O(OaN1a%E zV{IFssNYCTsVwp(z~2d32)iwL67Ldqm0~QX*nSBA0%G(!h22^{z8s*~?^C_|Roqo8 zF+bBDQRBnZRKv7*;{ewe3Lhq97b~xppEox-v?)v2f%zpq?1_B%XvOXQ!$;oVX~xn= z(nT0Mb}Q~*mse?PA|Fou7(Z|MY#F<HwAB;d?&Xvyk;W-g2J~Jf-lN#%?8iiXv5L;ykSRW)%@D4bIk9E;QqU7wL5tUDuA?7a zVuC*VMu8!fiXPbYdrO#M(Uqjli%%1q!sJ~vdl$8{RA1$cPrv!vzU$~j1u8w?BtXc4 zZ^F$9fw_JO!R6%t0K2=9{{R30 diff --git a/ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py b/ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py index 107c7e983..cffc8dcff 100644 --- a/ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py @@ -39,8 +39,9 @@ async def enter_timezone(self): await ErrorPage('Timezones range from GMT-12 to GMT+12.').show() return - await SuccessPage(text='Time Zone Saved').show() - # TODO: auto backup? - # await AutoBackupFlow().run() settings.set('timezone', tz) + + if tz != timezone: + await SuccessPage(text='Time Zone Saved').show() + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 271d4f523..8e98fc79d 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -7,7 +7,6 @@ def created_at_helper(carrot, created_at): - from utils import timestamp_to_str created = [c for c in created_at if c.count(carrot)] assert len(created) <= 1, 'There must only be 1 "created {}" condition.'.format( 'before' if carrot == '<' else 'after') @@ -15,8 +14,7 @@ def created_at_helper(carrot, created_at): if len(created) == 0: return None - created = int(created[0].split(carrot)[1]) - return timestamp_to_str(created) + return int(created[0].split(carrot)[1]) event_kind = { @@ -52,10 +50,8 @@ def created_at_helper(carrot, created_at): def parse_delegation_string(delegation_string): from ubinascii import unhexlify as a2b_hex - from utils import nostr_nip19_from_key, recolor - import uio + from utils import nostr_nip19_from_key import re - from styles.colors import HIGHLIGHT_TEXT_HEX fields = delegation_string.split(':') num_fields = len(fields) @@ -64,20 +60,20 @@ def parse_delegation_string(delegation_string): assert fields[0] == 'nostr' and fields[1] == 'delegation', \ 'First 2 fields of delegation string must be "nostr:delegation:"' - # exceptions handled by caller - # TODO: make these exceptions prettier - delegatee = a2b_hex(fields[2]) - - # TODO: check length before converting to npub + try: + delegatee = a2b_hex(fields[2]) + except Exception as e: + raise Exception('Invalid delegatee format') + assert len(delegatee) == 32, 'Invalid delegatee length' delegatee_npub = nostr_nip19_from_key(delegatee, "npub") + assert len(fields[3]) > 0, \ + 'Delegation conditions are required, found none' + conditions = fields[3].split('&') - num_conditions = len(conditions) - assert num_conditions > 0, \ - 'Delegation conditions are required, found {}'.format(num_conditions) - assert len(set(conditions)) == len(conditions), "Duplicate conditions found" + assert len(set(conditions)) == len(conditions), 'Duplicate conditions found' # TODO: what are the condition parsing rules? Can multiple kinds be given different # created_at rules within 1 delegation? I assume not for now. This means @@ -96,7 +92,8 @@ def parse_delegation_string(delegation_string): break # remove all found kinds from conditions before continuing - conditions = list(set(conditions) - set(kinds)) + for k in kinds: + conditions.remove(k) # Get all created_at for c in conditions: @@ -107,18 +104,32 @@ def parse_delegation_string(delegation_string): 'All "kinds" must come before all "created_at" conditions.' break - assert len(created_at) <= 2, 'There must be at most 2 "created_at" conditions.' - + # This throws an assertion if there are multiple of either condition created_before = created_at_helper('<', created_at) created_after = created_at_helper('>', created_at) - # len(kinds) + len(created_at) == len(conditions) iff all conditions are valid and - # all 'kinds' come before all 'created_at', but we already removed 'kinds' - assert len(created_at) == len(conditions), 'Invalid conditions found' + if created_before is not None and created_after is not None: + assert created_after < created_before, 'Start date must be before end date.' + + # remove all created at to leave invalid condition and any following conditions + for c in created_at: + conditions.remove(c) + + # any remaining conditions didn't match + conditions = list(set(conditions) - set(created_at)) + assert len(conditions) == 0, \ + 'Invalid condition found:\n{}'.format(conditions[0]) kinds = list(map(lambda k: int(k.split('=')[1]), kinds)) - # All inputs checked, format description and warnings + # All inputs checked + return delegatee_npub, created_before, created_after, kinds + + +def format_delegation_string(delegatee_npub, created_before, created_after, kinds): + from utils import timestamp_to_str, recolor + import uio + from styles.colors import HIGHLIGHT_TEXT_HEX details = uio.StringIO() details.write("\n{}\n{}".format( @@ -130,7 +141,7 @@ def parse_delegation_string(delegation_string): if created_after is not None: details.write("{}\n{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Delegation Start Date:'), - created_after, + timestamp_to_str(created_after), "Make sure this time isn't in the past!")) else: details.write("{}\n{}".format( @@ -142,7 +153,7 @@ def parse_delegation_string(delegation_string): if created_before is not None: details.write("{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Delegation End Date:'), - created_before)) + timestamp_to_str(created_before))) else: details.write("{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Warning:'), @@ -169,6 +180,10 @@ def __init__(self, context=None): self.pk = None self.npub = None self.delegation_string = None + self.delegatee_npub = None + self.created_before = None + self.created_after = None + self.kinds = None super().__init__(initial_state=self.export_npub, name='NostrDelegationFlow') async def export_npub(self): @@ -207,6 +222,15 @@ async def scan_delegation_string(self): return self.delegation_string = result.data + + try: + self.delegatee_npub, self.created_before, self.created_after, self.kinds = \ + parse_delegation_string(self.delegation_string) + except Exception as e: + await ErrorPage('{}'.format(e)).show() + self.set_result(False) + return + self.goto(self.display_details) async def display_details(self): @@ -215,25 +239,28 @@ async def display_details(self): from flows import ChooseTimezoneFlow import microns - if settings.get('timezone', None) is None: - result = await InfoPage('Nostr delegation is time-sensitive. Please enter your timezone.', - left_micron=microns.Back, - right_micron=microns.Forward).show() - if not result: - self.back() - return - await ChooseTimezoneFlow().run() - - try: - details = parse_delegation_string(self.delegation_string) - except Exception as e: - await ErrorPage('{}'.format(e)).show() + result = await InfoPage('Nostr delegation is time-sensitive. Please enter your timezone.', + left_micron=microns.Cancel, + right_micron=microns.Forward).show() + if not result: self.set_result(False) return + result = await ChooseTimezoneFlow().run() + + if not result: + return # Go back to previous page + + details = format_delegation_string(self.delegatee_npub, + self.created_before, + self.created_after, + self.kinds) + result = await LongTextPage(text=details, centered=True, - card_header={'title': 'Delegation Details'}).show() + card_header={'title': 'Delegation Details'}, + left_micron=microns.Cancel, + right_micron=microns.Checkmark).show() if not result: self.set_result(False) return @@ -252,5 +279,10 @@ async def sign_delegation(self): sig = nostr_sign(self.pk, sha) print("sig: {}".format(B2A(sig))) - await ShowQRPage(qr_data=B2A(sig)).show() + result = await ShowQRPage(qr_data=B2A(sig)).show() + + if not result: + self.back() + return + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 9500ff991..29ea3bd1c 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -118,7 +118,6 @@ def device_menu(): {'icon': lv.ICON_BRIGHTNESS, 'label': 'Screen Brightness', 'page': BrightnessSettingPage}, {'icon': lv.ICON_COUNTDOWN, 'label': 'Auto-Shutdown', 'page': AutoShutdownSettingPage}, {'icon': lv.ICON_PIN, 'label': 'Change PIN', 'flow': ChangePINFlow, 'is_visible': is_logged_in}, - {'icon': lv.ICON_CLOCK, 'label': 'Change Timezone', 'flow': ChooseTimezoneFlow}, {'icon': lv.ICON_INFO, 'label': 'About', 'flow': AboutFlow}, ] diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index cb7ff5e43..32715560a 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1371,12 +1371,12 @@ def timestamp_to_str(time): time += int(timezone) * 3600 time_tup = utime.gmtime(time) - time = "{} {}, {}\n{}:{}".format(months[time_tup[1]], # Month - time_tup[2], # Day - time_tup[0], # Year - time_tup[3], # Hour - time_tup[4], # Minute - ) + time = "{} {}, {}\n{}:{:02d}".format(months[time_tup[1]], # Month + time_tup[2], # Day + time_tup[0], # Year + time_tup[3], # Hour + time_tup[4], # Minute + ) # Ensure timezone string exists, prepend + if positive if timezone is None: From e481c3300780ef8dc2106f32fcc73337632940c8 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 7 Apr 2023 16:42:24 -0500 Subject: [PATCH 124/187] SFT-1434: asserted 1 or more event kinds --- .../boards/Passport/modules/flows/nostr_delegation_flow.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 8e98fc79d..6c5a8609e 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -91,6 +91,8 @@ def parse_delegation_string(delegation_string): else: break + assert len(kinds) > 0, 'Event kinds are required.' + # remove all found kinds from conditions before continuing for k in kinds: conditions.remove(k) From 80fd7c5a8a847b852e5fc75567b0ca596e003741 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Sun, 9 Apr 2023 11:42:44 -0500 Subject: [PATCH 125/187] SFT-1434: moved dynamic submenu items to top --- ports/stm32/boards/Passport/modules/flows/menu_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/menu_flow.py b/ports/stm32/boards/Passport/modules/flows/menu_flow.py index 656695823..608b770b7 100644 --- a/ports/stm32/boards/Passport/modules/flows/menu_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/menu_flow.py @@ -37,7 +37,7 @@ async def show_menu(self): self.items = self.menu() if self.dynamic: assert(callable(self.dynamic)) - self.items.extend(self.dynamic()) + self.items[:0] = self.dynamic() self.prev_statusbar = None self.prev_card_header = None From 5348ad21564b67d82efb1544402e381ff418fd78 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 10 Apr 2023 17:35:45 -0500 Subject: [PATCH 126/187] SFT-1434: improved NIP26 UI flow --- .../modules/flows/nostr_delegation_flow.py | 63 ++++++++++++++----- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 6c5a8609e..ded0d191c 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -186,12 +186,25 @@ def __init__(self, context=None): self.created_before = None self.created_after = None self.kinds = None - super().__init__(initial_state=self.export_npub, name='NostrDelegationFlow') + super().__init__(initial_state=self.show_warning, name='NostrDelegationFlow') + + async def show_warning(self): + from flows import SeedWarningFlow + + result = await SeedWarningFlow(action_text="sign a Nostr delegation" + .format(self.key_type['title']), + funds_text="post on your behalf").run() + if not result: + self.set_result(False) + return + + self.goto(self.export_npub) async def export_npub(self): from utils import spinner_task - from pages import ShowQRPage, ErrorPage + from pages import ShowQRPage, ErrorPage, InfoPage from ubinascii import unhexlify as a2b_hex + import microns (vals, error) = await spinner_task(text='Generating npub', task=self.key_type['task'], @@ -205,23 +218,35 @@ async def export_npub(self): self.set_result(False) return - await ShowQRPage(qr_data=self.npub).show() + result = await ShowQRPage(qr_data=self.npub, + left_micron=microns.Cancel, + caption='Scan this npub QR code with your Nostr client.').show() + if not result: + self.set_result(False) + return + self.goto(self.scan_delegation_string) async def scan_delegation_string(self): - from pages import ScanQRPage, ErrorPage + from pages import ScanQRPage, ErrorPage, InfoPage + import microns - # TODO: replace with ScanQRFlow - result = await ScanQRPage().show() + result = await InfoPage('On the next screen, scan the delegation details QR from your Nostr client.', + left_micron=microns.Cancel).show() if not result: self.set_result(False) return + # TODO: replace with ScanQRFlow + result = await ScanQRPage().show() + + if not result: + return # return to InfoPage + if result.is_failure(): await ErrorPage('Unable to scan QR code.').show() - self.set_result(False) - return + return # return to InfoPage self.delegation_string = result.data @@ -230,14 +255,12 @@ async def scan_delegation_string(self): parse_delegation_string(self.delegation_string) except Exception as e: await ErrorPage('{}'.format(e)).show() - self.set_result(False) - return + return # return to InfoPage - self.goto(self.display_details) + self.goto(self.request_tz) - async def display_details(self): - from pages import ErrorPage, InfoPage, LongTextPage - from common import settings + async def request_tz(self): + from pages import InfoPage from flows import ChooseTimezoneFlow import microns @@ -253,6 +276,12 @@ async def display_details(self): if not result: return # Go back to previous page + self.goto(self.display_details) + + async def display_details(self): + from pages import LongTextPage + import microns + details = format_delegation_string(self.delegatee_npub, self.created_before, self.created_after, @@ -268,12 +297,12 @@ async def display_details(self): return self.goto(self.sign_delegation) - return async def sign_delegation(self): from serializations import sha256 from utils import nostr_sign, B2A from pages import ShowQRPage + import microns print("pk: {}".format(B2A(self.pk))) sha = sha256(self.delegation_string) @@ -281,7 +310,9 @@ async def sign_delegation(self): sig = nostr_sign(self.pk, sha) print("sig: {}".format(B2A(sig))) - result = await ShowQRPage(qr_data=B2A(sig)).show() + result = await ShowQRPage(qr_data=B2A(sig), + right_micron=microns.Checkmark, + caption='Scan this final QR code with your Nostr client.').show() if not result: self.back() From 1ceee4a5651a3452f8f8f8ae0686945e0ddd79be Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 11 Apr 2023 10:39:57 -0500 Subject: [PATCH 127/187] SFT-1434: added SD option for delegation --- .../modules/flows/nostr_delegation_flow.py | 111 ++++++++++++++---- 1 file changed, 89 insertions(+), 22 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index ded0d191c..ac4fcba41 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -186,6 +186,7 @@ def __init__(self, context=None): self.created_before = None self.created_after = None self.kinds = None + self.use_qr = None super().__init__(initial_state=self.show_warning, name='NostrDelegationFlow') async def show_warning(self): @@ -198,11 +199,27 @@ async def show_warning(self): self.set_result(False) return + self.goto(self.choose_mode) + + async def choose_mode(self): + from pages import ChooserPage + + options = [{'label': 'Delegate via QR', 'value': True}, + {'label': 'Delegate via microSD', 'value': False}] + + mode = await ChooserPage(card_header={'title': 'Export Mode'}, options=options).show() + + if mode is None: + self.set_result(False) + return + + self.use_qr = mode self.goto(self.export_npub) async def export_npub(self): from utils import spinner_task from pages import ShowQRPage, ErrorPage, InfoPage + from flows import SaveToMicroSDFlow from ubinascii import unhexlify as a2b_hex import microns @@ -218,9 +235,23 @@ async def export_npub(self): self.set_result(False) return - result = await ShowQRPage(qr_data=self.npub, - left_micron=microns.Cancel, - caption='Scan this npub QR code with your Nostr client.').show() + if self.use_qr: + result = await ShowQRPage(caption='Scan this npub QR code with your Nostr client.', + qr_data=self.npub, + left_micron=microns.Cancel).show() + else: + result = await InfoPage('Copy the following npub into your Nostr client.', + left_micron=microns.Cancel).show() + + if not result: + self.set_result(False) + return + + filename = '{}-{}-npub.txt'.format(self.key_type['title'], self.key['name']) + result = await SaveToMicroSDFlow(filename=filename, + data=self.npub, + success_text="Nostr npub").run() + if not result: self.set_result(False) return @@ -230,25 +261,48 @@ async def export_npub(self): async def scan_delegation_string(self): from pages import ScanQRPage, ErrorPage, InfoPage import microns + from flows import FilePickerFlow + from utils import spinner_task + from tasks import read_file_task - result = await InfoPage('On the next screen, scan the delegation details QR from your Nostr client.', - left_micron=microns.Cancel).show() + if self.use_qr: + info_text = 'On the next screen, scan the delegation details QR from your Nostr client.' + else: + info_text = 'Next, select the delegation details file from your SD card.' + result = await InfoPage(text=info_text, left_micron=microns.Cancel).show() if not result: self.set_result(False) return - # TODO: replace with ScanQRFlow - result = await ScanQRPage().show() + if self.use_qr: + result = await ScanQRPage().show() - if not result: - return # return to InfoPage + if not result: + return # return to InfoPage - if result.is_failure(): - await ErrorPage('Unable to scan QR code.').show() - return # return to InfoPage + if result.is_failure(): + await ErrorPage('Unable to scan QR code.').show() + return # return to InfoPage + + self.delegation_string = result.data + else: + result = await FilePickerFlow(show_folders=True).run() - self.delegation_string = result.data + if result is None: + return # return to InfoPage + + # TODO: replace with read file flow + filename, full_path, is_folder = result + (data, error) = await spinner_task('Reading File', + read_file_task, + args=[full_path, False]) + + if error or data is None: + await ErrorPage('Unable to read file.').show() + return # return to InfoPage + + self.delegation_string = data.strip() try: self.delegatee_npub, self.created_before, self.created_after, self.kinds = \ @@ -301,21 +355,34 @@ async def display_details(self): async def sign_delegation(self): from serializations import sha256 from utils import nostr_sign, B2A - from pages import ShowQRPage + from pages import ShowQRPage, InfoPage import microns + from flows import SaveToMicroSDFlow print("pk: {}".format(B2A(self.pk))) sha = sha256(self.delegation_string) print("sha: {}".format(B2A(sha))) - sig = nostr_sign(self.pk, sha) - print("sig: {}".format(B2A(sig))) + sig = B2A(nostr_sign(self.pk, sha)) + print("sig: {}".format(sig)) + + if self.use_qr: + result = await ShowQRPage(caption='Scan this final QR code with your Nostr client.', + qr_data=sig, + right_micron=microns.Checkmark).show() + if not result: + self.back() + return + else: + result = await InfoPage('Copy the following delegation code into your Nostr client.', + left_micron=microns.Back).show() - result = await ShowQRPage(qr_data=B2A(sig), - right_micron=microns.Checkmark, - caption='Scan this final QR code with your Nostr client.').show() + if not result: + self.back() + return - if not result: - self.back() - return + filename = '{}-{}-delegation.txt'.format(self.key_type['title'], self.key['name']) + result = await SaveToMicroSDFlow(filename=filename, + data=sig, + success_text="Nostr delegation").run() self.set_result(True) From edf60c56e84ab916fd91a4402afc27c45e1bf2d8 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 12 Apr 2023 17:25:07 -0500 Subject: [PATCH 128/187] SFT-1434: integrated ReadFileFlow --- .../Passport/modules/flows/nostr_delegation_flow.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index ac4fcba41..41b600a61 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -261,9 +261,7 @@ async def export_npub(self): async def scan_delegation_string(self): from pages import ScanQRPage, ErrorPage, InfoPage import microns - from flows import FilePickerFlow - from utils import spinner_task - from tasks import read_file_task + from flows import FilePickerFlow, ReadFileFlow if self.use_qr: info_text = 'On the next screen, scan the delegation details QR from your Nostr client.' @@ -292,14 +290,10 @@ async def scan_delegation_string(self): if result is None: return # return to InfoPage - # TODO: replace with read file flow filename, full_path, is_folder = result - (data, error) = await spinner_task('Reading File', - read_file_task, - args=[full_path, False]) + data = await ReadFileFlow(file_path=full_path, binary=False).run() - if error or data is None: - await ErrorPage('Unable to read file.').show() + if data is None: return # return to InfoPage self.delegation_string = data.strip() From fc9c962bd4e3d3902d7aa42a508bf9da782987a5 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 19 Apr 2023 12:10:51 -0500 Subject: [PATCH 129/187] SFT-1434: removed timezones --- .../modules/flows/nostr_delegation_flow.py | 23 ++----------------- ports/stm32/boards/Passport/modules/utils.py | 17 +------------- 2 files changed, 3 insertions(+), 37 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 41b600a61..052745289 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -141,7 +141,7 @@ def format_delegation_string(delegatee_npub, created_before, created_after, kind details.write("\n\n") if created_after is not None: - details.write("{}\n{}\n{}".format( + details.write("{}\n{} UTC\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Delegation Start Date:'), timestamp_to_str(created_after), "Make sure this time isn't in the past!")) @@ -153,7 +153,7 @@ def format_delegation_string(delegatee_npub, created_before, created_after, kind details.write("\n\n") if created_before is not None: - details.write("{}\n{}".format( + details.write("{}\n{} UTC".format( recolor(HIGHLIGHT_TEXT_HEX, 'Delegation End Date:'), timestamp_to_str(created_before))) else: @@ -305,25 +305,6 @@ async def scan_delegation_string(self): await ErrorPage('{}'.format(e)).show() return # return to InfoPage - self.goto(self.request_tz) - - async def request_tz(self): - from pages import InfoPage - from flows import ChooseTimezoneFlow - import microns - - result = await InfoPage('Nostr delegation is time-sensitive. Please enter your timezone.', - left_micron=microns.Cancel, - right_micron=microns.Forward).show() - if not result: - self.set_result(False) - return - - result = await ChooseTimezoneFlow().run() - - if not result: - return # Go back to previous page - self.goto(self.display_details) async def display_details(self): diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index 32715560a..ead0d476e 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1364,29 +1364,14 @@ def nostr_sign(key, message): def timestamp_to_str(time): import utime - from common import settings - - timezone = settings.get('timezone', None) - if timezone is not None: - time += int(timezone) * 3600 time_tup = utime.gmtime(time) - time = "{} {}, {}\n{}:{:02d}".format(months[time_tup[1]], # Month + return "{} {}, {}\n{}:{:02d}".format(months[time_tup[1]], # Month time_tup[2], # Day time_tup[0], # Year time_tup[3], # Hour time_tup[4], # Minute ) - # Ensure timezone string exists, prepend + if positive - if timezone is None: - timezone = "+0" - elif int(timezone) >= 0: - timezone = "+" + str(timezone) - else: - timezone = str(timezone) - - return time + " GMT" + timezone - # EOF From f5df72f1e39dab41c50077d549d70eec18edaa4d Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 11 May 2023 15:24:17 -0500 Subject: [PATCH 130/187] SFT-1434: removed timezone flows, fixed rebase errors --- ports/stm32/boards/Passport/manifest.py | 1 - .../boards/Passport/modules/flows/__init__.py | 1 - .../modules/flows/choose_timezone_flow.py | 47 ------------------- .../modules/flows/export_derived_key_flow.py | 4 +- .../modules/flows/nostr_delegation_flow.py | 2 +- ports/stm32/boards/Passport/modules/menus.py | 2 +- 6 files changed, 4 insertions(+), 53 deletions(-) delete mode 100644 ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index e5df88703..f47ecabb1 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -85,7 +85,6 @@ 'flows/casa_health_check_microsd_flow.py', 'flows/casa_health_check_qr_flow.py', 'flows/change_pin_flow.py', - 'flows/choose_timezone_flow.py', 'flows/delete_account_flow.py', 'flows/delete_multisig_flow.py', 'flows/envoy_setup_flow.py', diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index 66e4b12e2..baddb7e4b 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -31,7 +31,6 @@ from .casa_health_check_microsd_flow import * from .casa_health_check_qr_flow import * from .change_pin_flow import * -from .choose_timezone_flow import * from .delete_account_flow import * from .delete_multisig_flow import * from .erase_passport_flow import * diff --git a/ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py b/ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py deleted file mode 100644 index cffc8dcff..000000000 --- a/ports/stm32/boards/Passport/modules/flows/choose_timezone_flow.py +++ /dev/null @@ -1,47 +0,0 @@ -# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. -# SPDX-License-Identifier: GPL-3.0-or-later -# -# choose_timezone_flow.py - Choose a timezone - -from flows import Flow - - -class ChooseTimezoneFlow(Flow): - def __init__(self, context=None): - super().__init__(initial_state=self.enter_timezone, name='ChooseTimezoneFlow') - - async def enter_timezone(self): - from pages import TextInputPage, SuccessPage, ErrorPage - from common import settings - from utils import InputMode - import microns - # from flows import AutoBackupFlow - - timezone = settings.get('timezone', None) - result = await TextInputPage(card_header={'title': 'GMT Offset'}, - numeric_only=False, - initial_text='-' if timezone is None else str(timezone), - initial_mode=InputMode.NUMERIC, - max_length=3, - left_micron=microns.Back, - right_micron=microns.Checkmark).show() - if result is None: - self.set_result(False) - return - - try: - tz = int(result) - except Exception as e: - await ErrorPage('Timezone offset must be a number from -12 to 12.').show() - return - - if tz < -12 or tz > 12: - await ErrorPage('Timezones range from GMT-12 to GMT+12.').show() - return - - settings.set('timezone', tz) - - if tz != timezone: - await SuccessPage(text='Time Zone Saved').show() - - self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index f1c881cc4..932ef9b70 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -31,8 +31,8 @@ async def generate_key(self): return (vals, error) = await spinner_task(text='Generating Key', - task=self.key_type['task'], - args=[self.key['index']]) + task=self.key_type['task'], + args=[self.key['index']]) self.pk = vals['priv'] if error is not None: await ErrorPage(error).show() diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 052745289..ee6729c56 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -194,7 +194,7 @@ async def show_warning(self): result = await SeedWarningFlow(action_text="sign a Nostr delegation" .format(self.key_type['title']), - funds_text="post on your behalf").run() + continue_text="post on your behalf").run() if not result: self.set_result(False) return diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 29ea3bd1c..8ff60e6ab 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -110,7 +110,7 @@ def plus_menu(): def device_menu(): - from flows import AboutFlow, ChangePINFlow, ChooseTimezoneFlow + from flows import AboutFlow, ChangePINFlow from pages import AutoShutdownSettingPage, BrightnessSettingPage from utils import is_logged_in From b3ab808a29c6a6f3c870a3d2b30a721057cfb497 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 15 May 2023 08:58:46 -0500 Subject: [PATCH 131/187] SFT-1434: using foundation schnorr, not working --- .../Passport/modules/flows/nostr_delegation_flow.py | 2 ++ ports/stm32/boards/Passport/modules/utils.py | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index ee6729c56..97c09419e 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -248,6 +248,7 @@ async def export_npub(self): return filename = '{}-{}-npub.txt'.format(self.key_type['title'], self.key['name']) + # TODO: use the key manager path result = await SaveToMicroSDFlow(filename=filename, data=self.npub, success_text="Nostr npub").run() @@ -356,6 +357,7 @@ async def sign_delegation(self): return filename = '{}-{}-delegation.txt'.format(self.key_type['title'], self.key['name']) + # TODO: use the key manager path result = await SaveToMicroSDFlow(filename=filename, data=sig, success_text="Nostr delegation").run() diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index ead0d476e..b5ec9dfbd 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1342,8 +1342,12 @@ def nostr_nip19_from_key(key, key_type): # generate nsec/npub def nostr_sign(key, message): - from trezorcrypto import schnorr - return schnorr.sign(key, message) + # from trezorcrypto import schnorr + # return schnorr.sign(key, message) + import foundation + + ctx = foundation.secp256k1.Secp256k1() + return ctx.schnorr_sign(message, key) months = { From 93aa26cb47a3965ed6caa5b853c1d2e8ae90cb20 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 15 May 2023 09:53:52 -0500 Subject: [PATCH 132/187] SFT-1434: improved file naming --- .../modules/flows/nostr_delegation_flow.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 97c09419e..4eadcb3fa 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -187,6 +187,8 @@ def __init__(self, context=None): self.created_after = None self.kinds = None self.use_qr = None + self.orig_path = None + self.basename = None super().__init__(initial_state=self.show_warning, name='NostrDelegationFlow') async def show_warning(self): @@ -217,11 +219,12 @@ async def choose_mode(self): self.goto(self.export_npub) async def export_npub(self): - from utils import spinner_task + from utils import spinner_task, get_folder_path from pages import ShowQRPage, ErrorPage, InfoPage from flows import SaveToMicroSDFlow from ubinascii import unhexlify as a2b_hex import microns + from public_constants import DIR_KEY_MNGR (vals, error) = await spinner_task(text='Generating npub', task=self.key_type['task'], @@ -248,9 +251,9 @@ async def export_npub(self): return filename = '{}-{}-npub.txt'.format(self.key_type['title'], self.key['name']) - # TODO: use the key manager path result = await SaveToMicroSDFlow(filename=filename, data=self.npub, + path=get_folder_path(DIR_KEY_MNGR), success_text="Nostr npub").run() if not result: @@ -275,6 +278,7 @@ async def scan_delegation_string(self): return if self.use_qr: + # TODO: Use ScanQRFlow result = await ScanQRPage().show() if not result: @@ -297,6 +301,7 @@ async def scan_delegation_string(self): if data is None: return # return to InfoPage + self.orig_path, self.basename = full_path.rsplit('/', 1) self.delegation_string = data.strip() try: @@ -356,10 +361,11 @@ async def sign_delegation(self): self.back() return - filename = '{}-{}-delegation.txt'.format(self.key_type['title'], self.key['name']) - # TODO: use the key manager path - result = await SaveToMicroSDFlow(filename=filename, + # Name resulting file after original file + target_fname = self.basename.rsplit('.', 1)[0] + '-signed.txt' + result = await SaveToMicroSDFlow(filename=target_fname, data=sig, + path=self.orig_path, success_text="Nostr delegation").run() self.set_result(True) From b05383c35121a20e509e413a7d5cb322521f6f2b Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 15 May 2023 10:12:46 -0500 Subject: [PATCH 133/187] SFT-1434: used ScanQRFlow for nostr delegation --- .../modules/flows/nostr_delegation_flow.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 4eadcb3fa..1fc326c2e 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -263,9 +263,9 @@ async def export_npub(self): self.goto(self.scan_delegation_string) async def scan_delegation_string(self): - from pages import ScanQRPage, ErrorPage, InfoPage + from pages import ErrorPage, InfoPage import microns - from flows import FilePickerFlow, ReadFileFlow + from flows import FilePickerFlow, ReadFileFlow, ScanQRFlow if self.use_qr: info_text = 'On the next screen, scan the delegation details QR from your Nostr client.' @@ -278,17 +278,12 @@ async def scan_delegation_string(self): return if self.use_qr: - # TODO: Use ScanQRFlow - result = await ScanQRPage().show() + result = await ScanQRFlow(data_description='a Nostr delegation description').run() - if not result: - return # return to InfoPage - - if result.is_failure(): - await ErrorPage('Unable to scan QR code.').show() + if result is None: return # return to InfoPage - self.delegation_string = result.data + self.delegation_string = result else: result = await FilePickerFlow(show_folders=True).run() From 01be8c690f3c8705160cda7df4e7c7f39f7518cb Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 15 May 2023 17:06:03 -0500 Subject: [PATCH 134/187] SFT-1434: lowercased "Reading file" --- ports/stm32/boards/Passport/modules/flows/read_file_flow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py index a68922c2c..822c6e013 100644 --- a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py @@ -22,7 +22,7 @@ async def read_file(self): from errors import Error from pages import ErrorPage - (data, error) = await spinner_task('Reading File', + (data, error) = await spinner_task('Reading file', read_file_task, args=[self.file_path, self.binary, self.read_fn]) From 0bd4f056a25731543aca4b9129ad963d93e4e278 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 16 May 2023 10:00:32 -0500 Subject: [PATCH 135/187] SFT-1434: called schnorr_sign correctly --- ports/stm32/boards/Passport/modules/utils.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index b5ec9dfbd..a6d777486 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1342,12 +1342,8 @@ def nostr_nip19_from_key(key, key_type): # generate nsec/npub def nostr_sign(key, message): - # from trezorcrypto import schnorr - # return schnorr.sign(key, message) - import foundation - - ctx = foundation.secp256k1.Secp256k1() - return ctx.schnorr_sign(message, key) + from foundation import secp256k1 + return secp256k1.schnorr_sign(message, key) months = { From 5aacbeadbc603726e3bb7f1006112fdfcc40e2cc Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 16 May 2023 15:28:11 -0500 Subject: [PATCH 136/187] SFT-1434: removed periods from relevant messages --- .../Passport/modules/flows/nostr_delegation_flow.py | 12 ++++++------ .../Passport/modules/flows/seed_warning_flow.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 1fc326c2e..a12e97f1d 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -239,11 +239,11 @@ async def export_npub(self): return if self.use_qr: - result = await ShowQRPage(caption='Scan this npub QR code with your Nostr client.', + result = await ShowQRPage(caption='Scan this npub QR code with your Nostr client', qr_data=self.npub, left_micron=microns.Cancel).show() else: - result = await InfoPage('Copy the following npub into your Nostr client.', + result = await InfoPage('Copy the following npub into your Nostr client', left_micron=microns.Cancel).show() if not result: @@ -268,9 +268,9 @@ async def scan_delegation_string(self): from flows import FilePickerFlow, ReadFileFlow, ScanQRFlow if self.use_qr: - info_text = 'On the next screen, scan the delegation details QR from your Nostr client.' + info_text = 'On the next screen, scan the delegation details QR from your Nostr client' else: - info_text = 'Next, select the delegation details file from your SD card.' + info_text = 'Next, select the delegation details file from your SD card' result = await InfoPage(text=info_text, left_micron=microns.Cancel).show() if not result: @@ -342,14 +342,14 @@ async def sign_delegation(self): print("sig: {}".format(sig)) if self.use_qr: - result = await ShowQRPage(caption='Scan this final QR code with your Nostr client.', + result = await ShowQRPage(caption='Scan this final QR code with your Nostr client', qr_data=sig, right_micron=microns.Checkmark).show() if not result: self.back() return else: - result = await InfoPage('Copy the following delegation code into your Nostr client.', + result = await InfoPage('Copy the following delegation code into your Nostr client', left_micron=microns.Back).show() if not result: diff --git a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py index 4ca63116e..327a0e2be 100644 --- a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py @@ -22,9 +22,9 @@ async def show_intro(self): import stash if not self.mention_passphrase or not stash.bip39_passphrase: - text = 'Passport is about to {}.'.format(self.action_text) + text = 'Passport is about to {}'.format(self.action_text) else: - text = 'Passport is about to {} and passphrase.'.format(self.action_text) + text = 'Passport is about to {} and passphrase'.format(self.action_text) result = await InfoPage( icon=lv.LARGE_ICON_SEED, text=text, left_micron=microns.Back, right_micron=microns.Forward).show() From bf05612cd75a930e50af1b80e2ce7882ec82bc1e Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 16 May 2023 15:29:12 -0500 Subject: [PATCH 137/187] SFT-1434: removed prints --- .../boards/Passport/modules/flows/nostr_delegation_flow.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index a12e97f1d..41797cb0e 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -335,11 +335,8 @@ async def sign_delegation(self): import microns from flows import SaveToMicroSDFlow - print("pk: {}".format(B2A(self.pk))) sha = sha256(self.delegation_string) - print("sha: {}".format(B2A(sha))) sig = B2A(nostr_sign(self.pk, sha)) - print("sig: {}".format(sig)) if self.use_qr: result = await ShowQRPage(caption='Scan this final QR code with your Nostr client', From 45f125aa3263cdddb32eca4c941330548c90b231 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 24 May 2023 11:26:54 -0500 Subject: [PATCH 138/187] SFT-1434: flipped passphrase text to make for better reading --- .../boards/Passport/modules/flows/seed_warning_flow.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py index 327a0e2be..4c54dc9e5 100644 --- a/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/seed_warning_flow.py @@ -21,10 +21,11 @@ async def show_intro(self): from pages import InfoPage import stash - if not self.mention_passphrase or not stash.bip39_passphrase: - text = 'Passport is about to {}'.format(self.action_text) - else: + if self.mention_passphrase and stash.bip39_passphrase: text = 'Passport is about to {} and passphrase'.format(self.action_text) + else: + text = 'Passport is about to {}'.format(self.action_text) + result = await InfoPage( icon=lv.LARGE_ICON_SEED, text=text, left_micron=microns.Back, right_micron=microns.Forward).show() From 6fdc95c4a5811c3f29893e15aa9a676986fc407f Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 24 May 2023 11:38:22 -0500 Subject: [PATCH 139/187] SFT-1434: removed dead code, adding success page to delegation --- .../modules/flows/nostr_delegation_flow.py | 15 ++++++++++++++- .../Passport/modules/tasks/nostr_key_task.py | 5 ----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index 41797cb0e..e390fdbbf 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -339,7 +339,7 @@ async def sign_delegation(self): sig = B2A(nostr_sign(self.pk, sha)) if self.use_qr: - result = await ShowQRPage(caption='Scan this final QR code with your Nostr client', + result = await ShowQRPage(caption='Scan this QR code with your Nostr client', qr_data=sig, right_micron=microns.Checkmark).show() if not result: @@ -360,4 +360,17 @@ async def sign_delegation(self): path=self.orig_path, success_text="Nostr delegation").run() + self.goto(self.show_success) + + async def show_success(self): + from pages import SuccessPage + import microns + + result = await SuccessPage(text='Delegation complete', + left_micron=microns.Back).show() + + if not result: + self.back() + return + self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py b/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py index 9db0c7633..971fa4c96 100644 --- a/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py +++ b/ports/stm32/boards/Passport/modules/tasks/nostr_key_task.py @@ -6,18 +6,13 @@ async def nostr_key_task(on_done, index): import stash - # import tcc - # from trezorcrypto import secp256k1 from utils import nostr_pubkey_from_pk, nostr_nip19_from_key path = "m/44'/1237'/{}'/0/0".format(index) with stash.SensitiveValues() as sv: node = sv.derive_path(path) key = node.private_key() - # pub = secp256k1.publickey(key, True)[1:] pub = nostr_pubkey_from_pk(key) - # nsec = tcc.codecs.bech32_plain_encode("nsec", key) - # npub = tcc.codecs.bech32_plain_encode("npub", pub) nsec = nostr_nip19_from_key(key, "nsec") npub = nostr_nip19_from_key(pub, "npub") await on_done({'priv': nsec, 'npub': npub, 'pk': key, 'pub': pub}, None) From 34dd87253cab375e66d9939593e5a36ae4f4ddf1 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 24 May 2023 11:46:17 -0500 Subject: [PATCH 140/187] SFT-1434: removed exclamation points --- .../Passport/modules/flows/nostr_delegation_flow.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py index e390fdbbf..073282e26 100644 --- a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py @@ -144,11 +144,11 @@ def format_delegation_string(delegatee_npub, created_before, created_after, kind details.write("{}\n{} UTC\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Delegation Start Date:'), timestamp_to_str(created_after), - "Make sure this time isn't in the past!")) + "Make sure this time isn't in the past.")) else: details.write("{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Warning:'), - "No start date, use caution!")) + "No start date, use caution.")) details.write("\n\n") @@ -159,7 +159,7 @@ def format_delegation_string(delegatee_npub, created_before, created_after, kind else: details.write("{}\n{}".format( recolor(HIGHLIGHT_TEXT_HEX, 'Warning:'), - "No end date, use caution!")) + "No end date, use caution.")) details.write("\n\n") @@ -168,7 +168,7 @@ def format_delegation_string(delegatee_npub, created_before, created_after, kind for k in kinds: details.write("\n{}: {}".format( - k, event_kind.get(k, "Unknown event, use caution!"))) + k, event_kind.get(k, "Unknown event, use caution."))) return details.getvalue() From 9bdaef3ccce02d58956b4e2427a04eb31f67d421 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 25 May 2023 10:48:16 -0500 Subject: [PATCH 141/187] SFT-1938: undid file renaming --- ports/stm32/boards/Passport/modules/files.py | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/files.py b/ports/stm32/boards/Passport/modules/files.py index f7e3726aa..6fed3ed02 100644 --- a/ports/stm32/boards/Passport/modules/files.py +++ b/ports/stm32/boards/Passport/modules/files.py @@ -168,15 +168,6 @@ def pick_filename(self, pattern, path=None): basename, ext = pattern.rsplit('.', 1) ext = '.' + ext - # rename numberless first - numberless_fname = path + '/' + basename + ext - fname = path + '/' + basename + '-001' + ext - try: - os.stat(numberless_fname) - uos.rename(numberless_fname, fname) - except OSError as e: - pass # file doesn't exist, move on - # look for existing numbered files, even if some are deleted, and pick next # highest filename highest = 0 @@ -187,14 +178,7 @@ def pick_filename(self, pattern, path=None): m = pat.match(fn) if not m: continue - - # Rename older files to fit 3 digit numbering scheme - old_num = int(m.group(1)) - new_fn = basename + ('-%03d' % old_num) + ext - if fn != new_fn: - uos.rename(path + '/' + fn, path + '/' + new_fn) - - highest = max(highest, old_num) + highest = max(highest, int(m.group(1))) fname = path + '/' + basename + ('-%03d' % (highest + 1)) + ext From 9dcf66f33ddf9eb4326e48dd2bbf413a8cba99ff Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 31 May 2023 17:10:04 -0500 Subject: [PATCH 142/187] SFT-2043: first pass at new mono brandmark icon --- .../images/mono/LARGE_ICON_BRANDMARK.c | 126 +++++++++--------- ...LARGE_ICON_BRANDMARK__CF_INDEXED_1_BIT.png | Bin 5310 -> 1553 bytes 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c b/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c index 28061f41f..b1d140ff1 100644 --- a/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c +++ b/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. // SPDX-License-Identifier: GPL-3.0-or-later // @@ -18,69 +18,69 @@ #endif const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_LARGE_ICON_BRANDMARK uint8_t LARGE_ICON_BRANDMARK_map[] = { - 0x07, 0x07, 0x0a, 0x07, /*Color of index 0*/ - 0x8a, 0x98, 0xcf, 0xef, /*Color of index 1*/ + 0xfe, 0xfe, 0xfe, 0xff, /*Color of index 0*/ + 0x1a, 0x1a, 0x1a, 0xff, /*Color of index 1*/ - 0x00, 0x00, 0x02, 0xf0, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xe0, 0xff, 0xc0, 0x00, 0x00, - 0x00, 0x01, 0xff, 0xe0, 0x7f, 0xf0, 0x00, 0x00, - 0x00, 0x03, 0xff, 0xc0, 0x7f, 0xfc, 0x00, 0x00, - 0x00, 0x0f, 0xff, 0xc0, 0x3f, 0xff, 0x00, 0x00, - 0x00, 0x1f, 0xff, 0x80, 0x3f, 0xff, 0x80, 0x00, - 0x00, 0x3f, 0xff, 0x80, 0x1f, 0xff, 0xc0, 0x00, - 0x00, 0x7f, 0xff, 0x00, 0x0f, 0xff, 0xe0, 0x00, - 0x00, 0xff, 0xff, 0x00, 0x0f, 0xff, 0xf0, 0x00, - 0x01, 0xff, 0xfe, 0x00, 0x07, 0xff, 0xf8, 0x00, - 0x03, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xfc, 0x00, - 0x07, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xfc, 0x00, - 0x07, 0xff, 0xf8, 0x00, 0x01, 0xff, 0xfe, 0x00, - 0x0f, 0xff, 0xf8, 0x00, 0x01, 0xff, 0xff, 0x00, - 0x0f, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0x00, - 0x1f, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0x80, - 0x1f, 0xff, 0xe0, 0x00, 0x00, 0x7f, 0xff, 0x80, - 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x7f, 0xff, 0xc0, - 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x3f, 0xff, 0xc0, - 0x7f, 0xff, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xe0, - 0x7f, 0xff, 0x80, 0x00, 0x00, 0x1f, 0xff, 0xe0, - 0x7f, 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, - 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, - 0xff, 0xfe, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, - 0xff, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, - 0xff, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, - 0xff, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, - 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, - 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, - 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, - 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, - 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0, - 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf0, - 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, - 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, - 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, - 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, - 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, - 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, - 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, - 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, - 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, - 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x03, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, - 0x00, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xff, 0xff, 0xe0, 0x00, 0x00, - 0x00, 0x00, 0x0f, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0xf0, 0xff, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xe2, 0x7f, 0xf0, 0x00, 0x00, + 0x00, 0x03, 0xff, 0xc0, 0x3f, 0xfc, 0x00, 0x00, + 0x00, 0x07, 0xfe, 0xc2, 0x37, 0xfe, 0x00, 0x00, + 0x00, 0x1f, 0xfd, 0x81, 0x1b, 0xff, 0x80, 0x00, + 0x00, 0x3f, 0xfb, 0x00, 0x8d, 0xff, 0xc0, 0x00, + 0x00, 0x7f, 0xeb, 0x02, 0x0d, 0x7f, 0xe0, 0x00, + 0x00, 0xff, 0xb6, 0x01, 0x46, 0xdf, 0xf0, 0x00, + 0x01, 0xff, 0xea, 0x00, 0x05, 0x7f, 0xf8, 0x00, + 0x03, 0xff, 0x2c, 0x02, 0xa3, 0x4f, 0xfc, 0x00, + 0x03, 0xfd, 0xd8, 0x00, 0x11, 0xbb, 0xfc, 0x00, + 0x07, 0xff, 0x28, 0x02, 0x81, 0x4f, 0xfe, 0x00, + 0x0f, 0xfa, 0xd0, 0x00, 0x50, 0xb5, 0xff, 0x00, + 0x0f, 0xf6, 0x90, 0x02, 0x04, 0x96, 0xff, 0x00, + 0x1f, 0xfd, 0x60, 0x00, 0xa0, 0x6b, 0xff, 0x80, + 0x1f, 0xd2, 0x40, 0x01, 0x08, 0x24, 0xbf, 0x80, + 0x3f, 0xf6, 0xc0, 0x00, 0x22, 0x36, 0xff, 0xc0, + 0x3f, 0xd4, 0x80, 0x02, 0x80, 0x12, 0xbf, 0xc0, + 0x3e, 0xea, 0x80, 0x00, 0x14, 0x15, 0x6f, 0xc0, + 0x7f, 0xd5, 0x00, 0x01, 0x01, 0x0a, 0xbf, 0xe0, + 0x7f, 0xaa, 0x00, 0x00, 0x44, 0x05, 0x5f, 0xe0, + 0x7e, 0xda, 0x00, 0x02, 0x10, 0x45, 0xb7, 0xe0, + 0x7f, 0x52, 0x00, 0x00, 0x41, 0x04, 0xaf, 0xe0, + 0xff, 0xd4, 0x00, 0x01, 0x00, 0x02, 0xbf, 0xf0, + 0xfb, 0x28, 0x00, 0x00, 0x08, 0x41, 0x4d, 0xf0, + 0xff, 0xd8, 0x00, 0x00, 0x41, 0x01, 0xbf, 0xf0, + 0xfe, 0x90, 0x00, 0x02, 0x04, 0x08, 0x97, 0xf0, + 0xfd, 0xb0, 0x00, 0x00, 0x10, 0x00, 0xdb, 0xf0, + 0xfe, 0xa0, 0x00, 0x00, 0x80, 0x20, 0x57, 0xf0, + 0xf7, 0x40, 0x00, 0x02, 0x00, 0x80, 0x2e, 0xf0, + 0xfe, 0xc0, 0x00, 0x00, 0x04, 0x02, 0x37, 0xf0, + 0xfe, 0xc0, 0x00, 0x00, 0x20, 0x00, 0x37, 0xf0, + 0x76, 0x80, 0x00, 0x00, 0x80, 0x08, 0x16, 0xe0, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x20, 0x8f, 0xe0, + 0x7d, 0x00, 0x00, 0x02, 0x02, 0x00, 0x0b, 0xe0, + 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xe0, + 0x3e, 0x00, 0x00, 0x00, 0x10, 0x02, 0x07, 0xc0, + 0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x23, 0xc0, + 0x3c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0xc0, + 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x80, + 0x18, 0x00, 0x00, 0x00, 0x08, 0x21, 0x09, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x03, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xcc, 0x00, + 0x00, 0xd7, 0xff, 0xff, 0xff, 0xfe, 0xb0, 0x00, + 0x00, 0x2d, 0xff, 0xff, 0xff, 0xfb, 0x40, 0x00, + 0x00, 0x52, 0xbf, 0xff, 0xff, 0xd4, 0xa0, 0x00, + 0x00, 0x36, 0xd7, 0xff, 0xfe, 0xb6, 0xc0, 0x00, + 0x00, 0x04, 0xad, 0x6f, 0x6b, 0x52, 0x00, 0x00, + 0x00, 0x05, 0x5a, 0xd9, 0xb5, 0xaa, 0x00, 0x00, + 0x00, 0x01, 0x22, 0xa9, 0x54, 0x48, 0x00, 0x00, + 0x00, 0x00, 0xad, 0x56, 0xab, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xa9, 0x51, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x0b, 0x26, 0x4d, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xa9, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, }; const lv_img_dsc_t LARGE_ICON_BRANDMARK = { diff --git a/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK__CF_INDEXED_1_BIT.png index 9a5137682ac86a463958b2b6ef8e14aa70f0356e..211233bf5a7d7e2ba9b79c923b85866ababd8f74 100644 GIT binary patch delta 1486 zcmV;<1u^=*DUl42ReuGhNklIRL8E`q*xr^MVa*3ZcZ~o@Z`GG)J@|b`M}LHygg}>;HC!RNK^woH z)#vxpDY>|BtYxI8!*h&X-|z4l&(hsL??-j5YbuLBJL9r*yrR0Hwv1?FOSbzdBY}P& zF*ch7%C}@}<8nyvIi|mh6Y1=5>oPrn`~9RT@fGr+KagxX(UzRGxhXmg<#zAuwoTq5 z9O=e*w#8AiqJMAEhO0ZOVDg2RA6#EbA)&3& z>3XIGSl4=L;~Ni&WKO3yVJw{lbK=HodcYE72#fAvNFE5U1CN5nG;q>*lbdev8C}I$ zxEpKtDt{Wf$$}vXujO_4{T7D?<-O-ltW?2HE|cHD3=6 zvRy{w5Vb*FmguB0%%*jmRhwcKkMp>M^oeR*9e;|rW6L8KVl0-moU9t$lAgJ!h8g1{ zlmA+Vgnt99=t)_XHB8No2lX5%R1sK;Bt4#?TALC#uWL`9fVMo)O+p~NTo2x`I8MP$ zXof{>nIv*_p=V>55IH+)wi&h7GB9iWF59Q86%>bcxlo)%Z$@boKZ=Tz6PrVlLAlEWBM)gxfdJrCN zv>x2^`odnCQo1rjx4;w45j@iJ6bN#j>_?fi6V@x`wzkiE}k^TWahHS$mr)B(=$WP(YQkV6~Q%X@K z+uUsFCyl)VZ61L{VtXU#ooK$YrDhb;UJ+emJ>W@ec!&@^ChGSYhnSkdK zDL-qz3ATUELiruNb=(nB`z9#ZAbMWH?Kus9&w$TTKsR9=;lC`+p6a z*QPv^H=~RrbP%tnK{+gW2eEOSjWUi&QfBQ%z5X1RY|Nm@ep}KbL9-_q;h#X(69{61 zHmmQ?BA-8?R^Ry&@7EysT4%#Qj4(#~kc?mD|A_Dfd|8FzH96!mOE9P;C}yUz-X{-u z=k=T6ooxdYgZnJ7DcJ7nYQ5IbU4I|$0In=A#fkrN?5gOi8Kx!rHElUxTrERmS0EX5 z#UX(41a;@Mq8ESGj6Jyw6F%zsX6MvEAc7WrCIPpF&!K^nbapLaiZtk*U>5W>0L@VD z;>_H#+?)K9N)DDDT7tVrE6YCMzQ561hOva@sz9o)^4apfyIR1REj1C376B$-=2!uyXCneSX}e65mD*Q13Ibp9$ku0fDc>E|zysQj$9fAX zmL2P=^yb0kC<&OZGNE^c2S>WQK87EfT03+>y6V<)`%p!65Oo}WuzwdcNc3M_XWy;W oqa6Py%HhCSXk6P=Y1%gY0gU%F)Yniyd;kCd07*qoM6N<$f(7;GI{*Lx delta 5273 zcmV;K6lUv@48AFlReuyyNklYEw1drKtH+m31rfAqBA}Aw)#2A<8dOv1`u}=PM;k8`|r-E z%TPkKe#Jcg<&W<)Dmaux;ays*fh0hu+S>gfm31%(104jBN|H!b zl0?N(=)y1nSj{rk^XN6GjVO$#K>d-xIi<5eYlC}R9gWk?O{ET0baLPaU)o=9=lO#N zzxjh>cqUVqP_$ZODS=w0$8zfi0Y=4OvXaEAR!N)(8-ME{ij>h{SF6*%_r zQUBxQL*p1AeG)eeTbrv+r=uX&YQEJ{v(1*8Z?{z^%anHD-l;QL2H@ZM;Uj8|WlexF z;yayIQ(10@!Gtpq*EEh*wUX%mO6n?Us$-mo02_o6*;QG)eZz;o@Ykn$Uh{`h6g2_x zg_pnicYpWjC_Jw4GKjOvvW{yuo4N_m=jRE$sahC_JhvD;h^0~WU;NLTyT||eng3L) zEUN-cRx5e`k<7XKJNUT6HHvGRB)V2fRe!aj`qI?JI1l4QkzL5BQr1pwJveq~(d%w1 zj=x0x-(O5kPHSU!f@PfpT-I)>cB`%C0QUSm>wi4jZI$I2rA0;fgYQ3Z;Niz7@Vr$k zEGyRGC&vD4IO~K@H@Svk?WF6IMHFe%@x%v5dJvTq+ z&Yhpr=Vs?b)H_)YImu~5G}wL>Dlqc7@BZlYGH{k>m}1+4fwHX*ARgpi=YoH2n812ewN>s?W8aU9+*ny-(Wzmj*@8RVodAhz*>lLE6<0?ET|P`VW8xLLp6wT&4Y~qHi#0k z>%`si1=jxj%DX;sy}EGuaPJAkn}06pztBAYs~>;=H1uH@?{aybYukabYJt%fn4X)} z?}FjRyYH%ZX6MCiWzcEotP1eq#F+Z8n(Z6E^2m?gUh1P4G+H(fpKcdm9Uz1-97!Cx zzDlY$2(wk4R%G;D2&)VuR(sU)rL?TN0L%6VQC|VhLlDzvL4P0A+BnOj z3?of5G==U9J{!!UO`~FUmh+lJRN}6=B8?cJ+_lt4mlWwIzWm7}nRVMTvBm&v0vDrG z^sivo)hbn8h_R!AA-g7wG8|}Vh`UeV zU7{KR!qWh54u;Hefcfoy7=N>V^aTNqrUAuWlrELQdSg63`q=09eRV~EAN%6oEtyl} znJBGR{Ad`3I+X}2rNz{JRf4SwSc-87=1bQB%#ApzjH`<83LC5-AY=nQn&cZm0f4Fk1DmIeI8*#3j? zwZl2I7JAFk6=TABL{YM1px(g*t1Kp7;Pi|)^KE95#x@l6&8wd39@Lro_~R$h5F#ouF*!|>;$Hk zPUh1PZ3Brz+%2IiL9<_dRbkn&uQaZ>Q4459C2BZS?JPvjdoL?isg_aT3VyKds zmKhTRGMi`@m|9_h0CmAalykL^VIDW2R@2)?CoxxiNz{dN zOc~%%q>IrU;(vDOTOWW|Q?T#n-i{J#{lw;`Z+~|0ZSMmND}OknmGU!Jj8q7AL+Y;P z3zK3(K;xmQE5?YC;M9-*RNOwOR#*7Wt{(SRTrWXiAvZdASOC)lkY%V)Ao@&$nNV8b zHBySTPGZLJ0ks~Ai77Tv*V6cF3ji~GgfH9XXsY1pXn&az#lY|4MQOsRA7a~-F9+CA zbX$y6A2a&ovIXb_wNlx2*9^Sz3_+6*FIo6D*aXX%ouw`n zrU4p&nPs6Q@MfwfK#lzQ=p9#f0k^Z@)BM4DhBdPmvFL8%L~j$(S+SDTTggf=CXkQo zdT!i=T7P{Jpa3U8OIFJPAZQ-bG~L9TqdcIS5;tkQgb9=4Apnx|ZyGMvgkmkKCNUp$ zIaeRLa^rz6U|hR3=QIv65?{u6Ih7Zrn#V{c^RfI!oi)abJye&L?r3Gl?z&oi5l{eR z7qRQgYdk`n8NLnaUAyb(;)E81ihjz77or`~h=0ZO$EuJ>QAuMwJQ!ozvAYE@V`jYL zdif+!L=OWNTfrjkz=D&kOqSQqY24-6RnVUrs(B1s7)#tPybI7|{~u%NpTV-cCi`4{_t zjNpy7PsKYvvSK&1xKt_?%UUogZIXeb>wmqj-g8%UQ$f7zqm%GAGng4U?fsMzRrBJF z5HwEUJLsW-!Sb5`V)j zakI>MWrUDM(abG*pBp$)8~GUHPCKO+G%G)2^Uhk_ z(BeW6B^ar5b8~Wzqb+|c20(t}b$^`K$7EB^@NvY=*e3A zR>s<7Ij!v8T}MjyD8sPgdf`EYD5ifzT6tvD#izk=U<%`0=x-=D2F4WDPk)!r8(1xa z)6kBM4+kA$<_xJacWu3j#m_&BIA&yoMdy6gc zwvl*3#dKRnCVz4dBSY#Z@0Vfwq&%t4p6MU z(?+?6_r8mK7D{CZNxv*>eSgKXED;HTbps?W5`+>4cT;z==yQ%ELskVWMMA8e_*=2a zTn*sr!G=3NHl^0D2-pIY1BeA#OrEorzc0GS4Gau0&NfICOd->E!WArgSK^JBfDL4l zLk~tbW{LeA|8NxiXc*6|Dm*qvFURa{K3@+*)h*~SJ8cUPmhBR7(SMeT&c1JQ!Ful8 zIld<4pRC!MkX$X)&d&zOv|$!gVvA5LIOuooRhqE3jStf(&W?VXp`$AdGucHN^ymtb za;qxnuwxw>8sc2om7arbUgxI=2M4=t{>JkXIG*FR7&Y89x_>5bw;yvPMwLOb=Bj~? z0wywyPgEEqSbtu+B!7vNwVzgL4hZztK^-RfR@ z?KNAr>-G8qHgUcn!AEesPxY|f^Gp|yZZ^krEVUNC8TxBf62$+~y&(uI$3j{(E>yuX zXPx%Z-?{Iv>gqC<8*jYPzVgZ|(%GWjtHW}{^)AELU3Z=1J;i;!_t>5zSysRO`LCU@ zkWjKrMSn)V{Om`*@vW!3fOm~gHo*E*6ak3C>A74VRhPNE@WKny;k|qJ=8UFBMn+f{ zFk0Lr_2rjeUhrFaFYn>AJz=O|vZ_4}^3E#1Xmm`yCk4JtkB<%h>~F^=UwrVZ*Qo!W zVgQzmnDOy(Q*^Yq2F35e62Eot>3O!izng1+{(l>PIs9)Aj*XoJw({DV_i3#|>3-WA z7u{{kkBiQ`5BY$j_t`SCDo?v@_3N?>!)K2_3NeU>GuIk8J3oK!jW^zWr^#&xv$<~J z_ZHgtEB7|#Z>wym^3)&RyO`ycGqMYgeB$Q<<%uup62CGHi?bTC8&_Pp@oMDlG%}o6 zQh%wbv>G>t?)=0lwHm-~`uK1sb1$|!?ZNqGQ_sq#uz93bTe2grCHpEm5}agoV>v_6 zB06J!&`RZI1abcUD0{oKmrz%J+?5#>C5vTR&gCd;SAox2aapA}mt`JVS&*e5W>{ra zlWWCTMPyD|Baun$HNo55B8_4t2Dh9?Gt%K>uE-&{_mQi+nFx+WFIWZ)#`)9};(DKvgv>GSm&*cP z^3Vx$(Oe-Z5|4%(VlJ>bZ%M%Mt~*b;=YGN&(wOwB*lWR*2~$AKdBxld*>1U38-HEo zK1g)DqwzPFPiaZJIBr3(g*D;)x;r%~4393Oe`k$fym93Q7UP#vWLoF*Q?f9?oOy~B zL$bBp$@|WK#5d8Bx(yreg#sbT;$=M1N$X2+KcM zH9e0c^i%DIixasLZo3y9V;q44N5s4LBd^3fq7(hXz z2^JEN71s$|+6B`DP5l+4ro2v z`JayCjYkB42aXhw71jw%T#*OKJ%e6RH#4a_#Py_D974Tfd4od`j=QeMYUKtSOdu&rf3}jukv( z4se@9kw+3XmGa`N3V-qSV(ib$YsC^|v3%nfVEw9rXWOs)`fH^@D~(%`vYCWKp3pb! zYOJ>Jmo#~B|NhMO+~DI{?Udax&a>y-!YX9?w)eIE=`y?MiS};VTWw`jxyoOH^xKx) z3?iF})v~&7fV;q-|LF+cbU)zivCg|4?}CI*5qqCcSzuGTvwxhDbX}x}x!NHsA70Pj z!Ic@j<)KRfT9$R49#Yg{jz-YaPkGkMok5aA^t&W<5mmdwL~B{mR(_MRa>d9n7j**m z_c(Gh$JQdc7b=%+K1^4pn%Q<}?+6&$4tX5F0>%8_9?D9#RzogRe f)Ov#KE&m5`*b=340|;SV00000NkvXXu0mjfxYtWZ From a2cf43651c6d27a8701ce4486cc100d96e8e1cd5 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 31 May 2023 17:36:16 -0500 Subject: [PATCH 143/187] SFT-2043: second pass of brandmark mono fix --- .../images/mono/LARGE_ICON_BRANDMARK.c | 6 +++--- ...LARGE_ICON_BRANDMARK__CF_INDEXED_1_BIT.png | Bin 1553 -> 1560 bytes 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c b/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c index b1d140ff1..4c01bfd9c 100644 --- a/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c +++ b/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK.c @@ -19,7 +19,7 @@ const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_LARGE_ICON_BRANDMARK uint8_t LARGE_ICON_BRANDMARK_map[] = { 0xfe, 0xfe, 0xfe, 0xff, /*Color of index 0*/ - 0x1a, 0x1a, 0x1a, 0xff, /*Color of index 1*/ + 0x1a, 0x19, 0x19, 0xff, /*Color of index 1*/ 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0xff, 0x00, 0x00, 0x00, @@ -74,8 +74,8 @@ const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_LARGE_ICO 0x00, 0x52, 0xbf, 0xff, 0xff, 0xd4, 0xa0, 0x00, 0x00, 0x36, 0xd7, 0xff, 0xfe, 0xb6, 0xc0, 0x00, 0x00, 0x04, 0xad, 0x6f, 0x6b, 0x52, 0x00, 0x00, - 0x00, 0x05, 0x5a, 0xd9, 0xb5, 0xaa, 0x00, 0x00, - 0x00, 0x01, 0x22, 0xa9, 0x54, 0x48, 0x00, 0x00, + 0x00, 0x05, 0x5a, 0xdb, 0xb5, 0xaa, 0x00, 0x00, + 0x00, 0x01, 0x22, 0xad, 0x54, 0x48, 0x00, 0x00, 0x00, 0x00, 0xad, 0x56, 0xab, 0x50, 0x00, 0x00, 0x00, 0x00, 0x48, 0xa9, 0x51, 0x20, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x26, 0x4d, 0x00, 0x00, 0x00, diff --git a/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/LARGE_ICON_BRANDMARK__CF_INDEXED_1_BIT.png index 211233bf5a7d7e2ba9b79c923b85866ababd8f74..53d14b5ac83dfa974aabc005fd9c6196ff84568d 100644 GIT binary patch delta 1492 zcmV;_1uOcI444d%R)4KYL_t(|0o_^)lB6IE1#6C=&i${4cWAb0jfDKQdv>SxRn4?Y z2>C!l(EO;i=JW%o&%cB5vMjIPZQDdr){gpqT%@PIHQj_H7YMJRDTVt*=)Ezo;OiY$ znA#J3r>>|U9xzNxPmhBIwr< zWwR;3@+~P_IUVAAuIcZ^@pN`%>onbg`}L$T@fq@^KL}ZML2Ghyb5(d6%MMtJ|ydy>v zhzk75v1Lm&AeiXoXWx~KFOB2zmZ0Y0$d(V&G>@zork^&Z6tyvLX>3hC3E~=#c(>8y z)GZHQjlx>L7~pLfC#Sf46yh3|2x+yydqktbjcimN-SVDW|15AH9OkTBM0 zbiL97Y+E_G@r{QhWKO3wVJ)2k=ERlN_<$xz5$4@Pkvs^z4RS1KO@mCD+~lGwe0ocdVL^dMN>x&Kn9}PZ6By4^{5;c&?w5!3Q#KMQvpj&o)9XJ5 zvYkegA*zF#mT1rzqG=hUYE{(YejZau4^(4zSbxMFTOMU0%3@l}$g09M>6MGBn6W-G z`L9(-_#R++PpYb{Wom9bsO5m6ia;uo_;`wHV@k4lQ+x6VwDdqX2?6(VK6u087zGcZ zDHhRXl7yp)o~>ab$T?9f7tX>^Y#7JB=QEPSsZ4AmBp5m`^Bj8hK-bA9!HjqWZOOQ_ zAAgn2!mD_Q_S@0_)M^n6axUXwls`pe2I1vK z`@uEuFYKkMNLM0s4Ls2d!96X9K%nysCr@v*wM+&BD^OwNz!N&W?#;2Fr*sl$8o=;# z3a0RK@$Bdh;AlvLCp4wO&!qg0G3g@xU4KNB^bhDUWF02CEaR_4ehQaTUDkuARH90{ zxz*B7DtiT59Dzcjy%F?IG+)(HH5%!xh~`)iIA{$I5uyi$ASXU!u(HW;OpAjFST2$F zv*(*&`{yjQ-{D)v9U;|kf`$gs@)B;xH2jT6Vg>V+j1WDHr?t0Q9>y$u)z$VJHh*tS zIg(eSjU#jrua`kNOnC>fb)1bhj!9x>?M1!$9H*>Ip~!w);v+%RC+OjyK-LQgqJtLI z_h*sMAJC}pe2MpK5PYrE@DDwVQ9nfEclkd&d;wopV>l;=OlA=VnFPtqQr7$A0q?wi zGrY5HfTD1Z0*yhtDx39MLpObR0)M!)ycHMz>#?h%uVxsR=-0H%`QmCF2D<`Dp(_Rf zj3=nOOdERfXGQGEl`!F>o^N(e4FW_^gU=-3vG6%G$RwRzOPC@9dMB6*`Wk>%D0gvI zZdsm9{z)YVD-SKg-J*q6A8_5@=&i$A!gNIts%-Mv^1i!T*_%pCw~td!dVdcuT`R@I zeNg9R-hXHQOP?*|8Cw@B{Tg&#LifABeIQ(G$E@+_W ucb#Y7t(Bu4|0m4hz*!hv+f-@X8vX#q;4a#rg~CDr0000w`6SNa!BtvroW35>FjXpGChF%{iG@J74o4!kZd~9mYlV@DLM`1cJJ%9P2M6L z>Be}r#Zj}Ogn#A4C|}SO!8ki7n5BfHi+{&2Grn~h&_iu!w4K#+^Q_13qCr}NBt2?S-@`aZlTwh8dp{>#B zdZq8xM(OPNz3vES&^%;>K!vz!GE#i|%1a9tf`kkAlWDaME~_n{MzKUBy|r z8*BF}8h^UUf*}d7<#qV|7KaAqz2{D>RKZRzli&Pa)FpTt#xUPWWl^WzUJlG5osYS- z#L4#Fjq15XME9sp1G)o8RH|9 z|5}EGe*>)ONm-ROOwEl4^&BWv5m<^OJ)WUjn-Vv#Yfqklwmi^HLLj_c58kjiPQguR zhDB_dByx12XJeQUIXi0OnBJ|k;5<-|5Zf}?Yp=g_MMI!-QAxZkey{Yf{~Y5_y%zBx*D^Ln^;1N85FT!{ z9^CW#!d{wEx-vtzz!S|8Jks(M2y&j|L@- z+-&J5jlBYG9)Uz+dn4$bXuh(gW)#w15nW?F;7MzEh!8y}1fKYe!CFm*V_H0!faek^ zKWn}Twtvn-`5nD=+!0dyCMeh-dS1fqISqf~kyyffWkrY{#?#zeO%G!pz8Y%#4S$>0 zraY53ql_bT5U-~}IV^bxv2mP@GLA`7X6;42{v4NV%%I4AThb#zvnLqgpFq|V2x5aa ztMAVupFf~h-}w^n*C6;>XTv{?Fh={3j9=ydi0}n`S%u*>Ipi`+FsLLbW~Q>%0VZGOSuA^9ADnPhhU%teI%FG? zC*UcZuSDfTGIzOdP`mWQt=jKrBLX^UyG)an+E+OW0$=jT)@OGq-yPP#1KN(qdJ8F* z9qX#}=E3DC37D=jp?8G`x<eh1mP(^eQbsT=Me-|`J^j}?P->uc7 n9RDZE;lNpFT-#J>+BW Date: Fri, 26 May 2023 17:12:32 -0500 Subject: [PATCH 144/187] SFT-2127: renamed output files, will test upon 2.2.0-beta-3 --- ports/stm32/Justfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ports/stm32/Justfile b/ports/stm32/Justfile index 542920155..3e7853f92 100644 --- a/ports/stm32/Justfile +++ b/ports/stm32/Justfile @@ -123,6 +123,7 @@ sign-beta version="1.0.0" beta-num="1": rm -rf "{{version}}-beta-{{beta-num}}" mkdir -p "{{version}}-beta-{{beta-num}}" screens=("color" "mono") + screen_names=("" "-founders") paths=("passport-key-user" "passport-fe-key-user") builds=("" "dev") build_names=("" "-dev") @@ -132,9 +133,9 @@ sign-beta version="1.0.0" beta-num="1": for build in "${builds[@]}"; do just clean just sign {{version}} $screen $build - mv "build-Passport/v{{version}}-${paths[$i]}.bin" "build-Passport/v{{version}}-beta-{{beta-num}}-${screen}${build_names[$j]}-passport.bin" - just hash "build-Passport/v{{version}}-beta-{{beta-num}}-${screen}${build_names[$j]}-passport.bin" "${screen}" "{{version}}-beta-{{beta-num}}/v{{version}}-beta-{{beta-num}}-${screen}${build_names[$j]}-notes.md" - cp build-Passport/v{{version}}-beta-{{beta-num}}-${screen}${build_names[$j]}* "{{version}}-beta-{{beta-num}}/" + mv "build-Passport/v{{version}}-${paths[$i]}.bin" "build-Passport/v{{version}}-beta-{{beta-num}}${screen_names[$i]}${build_names[$j]}-passport.bin" + just hash "build-Passport/v{{version}}-beta-{{beta-num}}${screen_names[$i]}${build_names[$j]}-passport.bin" "${screen}" "{{version}}-beta-{{beta-num}}/v{{version}}-beta-{{beta-num}}${screen_names[$i]}${build_names[$j]}-notes.md" + cp build-Passport/v{{version}}-beta-{{beta-num}}${screen_names[$i]}${build_names[$j]}* "{{version}}-beta-{{beta-num}}/" j=$((j + 1)) done i=$((i + 1)) From d19fa39c37be174d54acf52b84fc5e295da70a85 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 26 May 2023 16:37:03 -0500 Subject: [PATCH 145/187] SFT-2183: reversed order of qr transaction files --- .../stm32/boards/Passport/modules/flows/file_picker_flow.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py index 8ca167abd..ea9756d16 100644 --- a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py @@ -94,7 +94,8 @@ async def on_file_result(self, res): return True async def show_file_picker(self): - from utils import show_page_with_sd_card, get_backups_folder_path + from utils import show_page_with_sd_card, get_backups_folder_path, get_folder_path + from public_constants import DIR_TRANSACTIONS while True: # Get list of files/folders at the current path @@ -109,7 +110,8 @@ async def show_file_picker(self): filter_fn=self.filter_fn) reverse = False - if active_path == get_backups_folder_path(): + if (active_path == get_backups_folder_path() or + active_path == get_folder_path(DIR_TRANSACTIONS)): reverse = True files = sorted(files, key=file_key, reverse=reverse) From 0e8e7897317cfaad203b6ce7583dd861c896140e Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 26 May 2023 10:51:53 -0500 Subject: [PATCH 146/187] SFT-2182: changed key manager rename icon to match account rename --- ports/stm32/boards/Passport/modules/menus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 8ff60e6ab..0b19983e7 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -143,7 +143,7 @@ def key_item_menu(): HideDerivedKeyFlow) return [ {'icon': lv.ICON_ONE_KEY, 'label': 'View Details', 'flow': ViewDerivedKeyDetailsFlow}, - {'icon': lv.ICON_SIGN, 'label': 'Rename', 'flow': RenameDerivedKeyFlow, 'auto_card_header': False}, + {'icon': lv.ICON_INFO, 'label': 'Rename', 'flow': RenameDerivedKeyFlow, 'auto_card_header': False}, {'icon': lv.ICON_SCAN_QR, 'label': 'Export', 'flow': ExportDerivedKeyFlow}, {'icon': lv.ICON_ERASE, 'label': 'Toggle Hidden', 'flow': HideDerivedKeyFlow}, ] From 91531d53008a71c84fdb1ad87bc3fba8235611d3 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 26 May 2023 09:16:14 -0500 Subject: [PATCH 147/187] SFT-1994: fixed seed list copy texts and back button --- .../boards/Passport/modules/flows/export_derived_key_flow.py | 4 ++-- .../boards/Passport/modules/flows/view_seed_words_flow.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py index 932ef9b70..c7569f7a1 100644 --- a/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/export_derived_key_flow.py @@ -30,7 +30,7 @@ async def generate_key(self): self.set_result(False) return - (vals, error) = await spinner_task(text='Generating Key', + (vals, error) = await spinner_task(text='Generating key', task=self.key_type['task'], args=[self.key['index']]) self.pk = vals['priv'] @@ -96,7 +96,7 @@ async def confirm_qr(self): from pages import InfoPage, LongTextPage import microns - text = 'Confirm the exported {} on the following page.'.format(self.key_type['title']) + text = 'Confirm the exported {} on the following page'.format(self.key_type['title']) result = await InfoPage(text=text, left_micron=microns.Back).show() if not result: diff --git a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py index 02b271d49..84c06f8ff 100644 --- a/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/view_seed_words_flow.py @@ -64,7 +64,7 @@ async def choose_mode(self): if isinstance(mode, int) and mode in [QRType.SEED_QR, QRType.COMPACT_SEED_QR]: self.qr_type = mode mode = self.show_qr - self.seed_micron = microns.Cancel + self.seed_micron = microns.Back self.goto(mode) From 4afc1fa31a1326bcee2f692dc2374c4e6587ef0b Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 25 May 2023 17:53:49 -0500 Subject: [PATCH 148/187] SFT-2176: moved fcc_copy_files_task to developer folder --- ports/stm32/boards/Passport/manifest_dev.py | 1 + ports/stm32/boards/Passport/modules/developer/__init__.py | 1 + .../modules/{tasks => developer}/fcc_copy_files_task.py | 0 ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py | 2 +- ports/stm32/boards/Passport/modules/tasks/__init__.py | 1 - 5 files changed, 3 insertions(+), 2 deletions(-) rename ports/stm32/boards/Passport/modules/{tasks => developer}/fcc_copy_files_task.py (100%) diff --git a/ports/stm32/boards/Passport/manifest_dev.py b/ports/stm32/boards/Passport/manifest_dev.py index 86b9743fc..1a6d2a2df 100644 --- a/ports/stm32/boards/Passport/manifest_dev.py +++ b/ports/stm32/boards/Passport/manifest_dev.py @@ -10,6 +10,7 @@ 'developer/delete_derived_keys_flow.py', 'developer/developer_functions_flow.py', 'developer/fcc_test_flow.py', + 'developer/fcc_copy_files_task.py', 'developer/spin_delay_flow.py', )) diff --git a/ports/stm32/boards/Passport/modules/developer/__init__.py b/ports/stm32/boards/Passport/modules/developer/__init__.py index 102e9880b..ccb34af3f 100644 --- a/ports/stm32/boards/Passport/modules/developer/__init__.py +++ b/ports/stm32/boards/Passport/modules/developer/__init__.py @@ -5,6 +5,7 @@ from .developer_functions_flow import * from .fcc_test_flow import * +from .fcc_copy_files_task import * from .spin_delay_flow import * from .delete_derived_keys_flow import * from .battery_page import * diff --git a/ports/stm32/boards/Passport/modules/tasks/fcc_copy_files_task.py b/ports/stm32/boards/Passport/modules/developer/fcc_copy_files_task.py similarity index 100% rename from ports/stm32/boards/Passport/modules/tasks/fcc_copy_files_task.py rename to ports/stm32/boards/Passport/modules/developer/fcc_copy_files_task.py diff --git a/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py b/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py index e887153e2..12659ffe7 100644 --- a/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py +++ b/ports/stm32/boards/Passport/modules/developer/fcc_test_flow.py @@ -9,7 +9,7 @@ import microns from pages import ProgressPage from styles.colors import COPPER -from tasks import fcc_copy_files_task +from developer import fcc_copy_files_task from utils import start_task from files import CardSlot import common diff --git a/ports/stm32/boards/Passport/modules/tasks/__init__.py b/ports/stm32/boards/Passport/modules/tasks/__init__.py index 7156338db..630a54521 100644 --- a/ports/stm32/boards/Passport/modules/tasks/__init__.py +++ b/ports/stm32/boards/Passport/modules/tasks/__init__.py @@ -26,7 +26,6 @@ from .double_check_psbt_change_task import double_check_psbt_change_task from .erase_passport_task import erase_passport_task from .format_microsd_task import format_microsd_task -# from .fcc_copy_files_task import fcc_copy_files_task from .generate_addresses_task import generate_addresses_task from .get_security_words_task import get_security_words_task from .get_seed_words_task import get_seed_words_task From 8896430e801b93a8ffb5b6b905b981ccd2b1ea82 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 26 May 2023 16:51:11 -0500 Subject: [PATCH 149/187] SFT-1807: fixed details in passphrase flow --- .../modules/flows/apply_passphrase_flow.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index ce4460220..419bf5142 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -78,7 +78,8 @@ async def clear_passphrase(self): result = await QuestionPage(text='Clear the active passphrase?').show() if not result: - self.back() + if not self.back(): + self.set_result(False) return self.msg = 'Clear' @@ -112,15 +113,17 @@ async def confirm_xfp(self): # Make a success page if len(self.passphrase) == 0 or self.passphrase == self.prev_passphrase: - await SuccessPage( - text='Passphrase {}ed\n\nFingerprint:\n\n{}'.format( - self.msg.lower(), # this is either 'revert' or 'clear' at this point - xfp2str(common.settings.get('xfp', '---'))) - ).show() + result = False + while not result: + result = await SuccessPage( + text='Passphrase {}ed.\n\nFingerprint:\n\n{}'.format( + self.msg.lower(), # this is either 'revert' or 'clear' at this point + xfp2str(common.settings.get('xfp', '---'))) + ).show() else: self.attempted = True result = await QuestionPage( - text='Passphrase applied\n\nFingerprint correct?\n\n{}'.format( + text='Passphrase applied.\n\nFingerprint correct?\n\n{}'.format( xfp2str(common.settings.get('xfp', '---'))) ).show() From e14a5350fbc0977e6842eba5c495325d911be366 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 26 May 2023 17:21:06 -0500 Subject: [PATCH 150/187] SFT-1807: simplified left button disabling --- .../Passport/modules/flows/apply_passphrase_flow.py | 13 ++++++------- .../boards/Passport/modules/pages/status_page.py | 6 ++++-- .../boards/Passport/modules/pages/success_page.py | 6 ++++-- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index 419bf5142..5899b95e0 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -113,13 +113,12 @@ async def confirm_xfp(self): # Make a success page if len(self.passphrase) == 0 or self.passphrase == self.prev_passphrase: - result = False - while not result: - result = await SuccessPage( - text='Passphrase {}ed.\n\nFingerprint:\n\n{}'.format( - self.msg.lower(), # this is either 'revert' or 'clear' at this point - xfp2str(common.settings.get('xfp', '---'))) - ).show() + await SuccessPage( + text='Passphrase {}ed.\n\nFingerprint:\n\n{}'.format( + self.msg.lower(), # this is either 'revert' or 'clear' at this point + xfp2str(common.settings.get('xfp', '---'))), + use_left_button=False + ).show() else: self.attempted = True result = await QuestionPage( diff --git a/ports/stm32/boards/Passport/modules/pages/status_page.py b/ports/stm32/boards/Passport/modules/pages/status_page.py index 56657553e..684e1563d 100644 --- a/ports/stm32/boards/Passport/modules/pages/status_page.py +++ b/ports/stm32/boards/Passport/modules/pages/status_page.py @@ -18,7 +18,8 @@ class StatusPage(Page): def __init__(self, text=None, icon=None, icon_color=None, show_progress=False, percent=0, centered=True, show_spinner=False, interactive=True, card_header=None, - statusbar=None, left_micron=microns.Back, right_micron=microns.Forward): + statusbar=None, left_micron=microns.Back, right_micron=microns.Forward, + use_left_button=True): super().__init__(card_header=card_header, statusbar=statusbar, left_micron=left_micron, @@ -38,6 +39,7 @@ def __init__(self, text=None, icon=None, icon_color=None, show_progress=False, p self.centered = centered self.show_spinner = show_spinner self.interactive = interactive + self.use_left_button = use_left_button self.is_list_mode = isinstance(self.text, list) @@ -169,7 +171,7 @@ def right_action(self, is_pressed): self.set_result(True) def left_action(self, is_pressed): - if self.interactive: + if self.interactive and self.use_left_button: if not is_pressed: if self.is_list_mode and self.page_idx > 0: self.page_idx -= 1 diff --git a/ports/stm32/boards/Passport/modules/pages/success_page.py b/ports/stm32/boards/Passport/modules/pages/success_page.py index 8d29c7621..bcd0e1ada 100644 --- a/ports/stm32/boards/Passport/modules/pages/success_page.py +++ b/ports/stm32/boards/Passport/modules/pages/success_page.py @@ -16,7 +16,8 @@ def __init__( card_header=None, statusbar=None, left_micron=None, - right_micron=microns.Checkmark): + right_micron=microns.Checkmark, + use_left_button=True): super().__init__( text=text, card_header=card_header, @@ -24,4 +25,5 @@ def __init__( icon=lv.LARGE_ICON_SUCCESS, icon_color=DEFAULT_LARGE_ICON_COLOR, left_micron=left_micron, - right_micron=right_micron) + right_micron=right_micron, + use_left_button=use_left_button) From 23b6c78e09a9b491346e4d7cfb3a5157e644ce72 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 1 Jun 2023 12:55:34 -0500 Subject: [PATCH 151/187] SFT-1807: only none-blank microns can be pressed --- .../Passport/modules/flows/apply_passphrase_flow.py | 3 +-- ports/stm32/boards/Passport/modules/pages/status_page.py | 8 +++----- ports/stm32/boards/Passport/modules/pages/success_page.py | 6 ++---- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py index 5899b95e0..32771d4a8 100644 --- a/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/apply_passphrase_flow.py @@ -116,8 +116,7 @@ async def confirm_xfp(self): await SuccessPage( text='Passphrase {}ed.\n\nFingerprint:\n\n{}'.format( self.msg.lower(), # this is either 'revert' or 'clear' at this point - xfp2str(common.settings.get('xfp', '---'))), - use_left_button=False + xfp2str(common.settings.get('xfp', '---'))) ).show() else: self.attempted = True diff --git a/ports/stm32/boards/Passport/modules/pages/status_page.py b/ports/stm32/boards/Passport/modules/pages/status_page.py index 684e1563d..5d0dcc386 100644 --- a/ports/stm32/boards/Passport/modules/pages/status_page.py +++ b/ports/stm32/boards/Passport/modules/pages/status_page.py @@ -18,8 +18,7 @@ class StatusPage(Page): def __init__(self, text=None, icon=None, icon_color=None, show_progress=False, percent=0, centered=True, show_spinner=False, interactive=True, card_header=None, - statusbar=None, left_micron=microns.Back, right_micron=microns.Forward, - use_left_button=True): + statusbar=None, left_micron=microns.Back, right_micron=microns.Forward): super().__init__(card_header=card_header, statusbar=statusbar, left_micron=left_micron, @@ -39,7 +38,6 @@ def __init__(self, text=None, icon=None, icon_color=None, show_progress=False, p self.centered = centered self.show_spinner = show_spinner self.interactive = interactive - self.use_left_button = use_left_button self.is_list_mode = isinstance(self.text, list) @@ -162,7 +160,7 @@ def detach(self): super().detach() def right_action(self, is_pressed): - if self.interactive: + if self.interactive and self.right_micron: if not is_pressed: if self.is_list_mode and self.page_idx < len(self.text) - 1: self.page_idx += 1 @@ -171,7 +169,7 @@ def right_action(self, is_pressed): self.set_result(True) def left_action(self, is_pressed): - if self.interactive and self.use_left_button: + if self.interactive and self.left_micron: if not is_pressed: if self.is_list_mode and self.page_idx > 0: self.page_idx -= 1 diff --git a/ports/stm32/boards/Passport/modules/pages/success_page.py b/ports/stm32/boards/Passport/modules/pages/success_page.py index bcd0e1ada..8d29c7621 100644 --- a/ports/stm32/boards/Passport/modules/pages/success_page.py +++ b/ports/stm32/boards/Passport/modules/pages/success_page.py @@ -16,8 +16,7 @@ def __init__( card_header=None, statusbar=None, left_micron=None, - right_micron=microns.Checkmark, - use_left_button=True): + right_micron=microns.Checkmark): super().__init__( text=text, card_header=card_header, @@ -25,5 +24,4 @@ def __init__( icon=lv.LARGE_ICON_SUCCESS, icon_color=DEFAULT_LARGE_ICON_COLOR, left_micron=left_micron, - right_micron=right_micron, - use_left_button=use_left_button) + right_micron=right_micron) From 4b3cb2b0bd478939792a33a5156136916761673c Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 31 May 2023 16:09:08 -0500 Subject: [PATCH 152/187] SFT-2019: special case for restoring same seed on same device --- .../Passport/modules/flows/backup_flow.py | 42 +++++++++++-------- .../modules/flows/restore_backup_flow.py | 3 +- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/backup_flow.py b/ports/stm32/boards/Passport/modules/flows/backup_flow.py index d3eb4e89f..87c93ff3e 100644 --- a/ports/stm32/boards/Passport/modules/flows/backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/backup_flow.py @@ -13,14 +13,37 @@ class BackupFlow(Flow): - def __init__(self): + def __init__(self, input_backup_code=None): from common import settings - super().__init__(initial_state=self.show_intro, name='BackupFlow') + super().__init__(initial_state=self.get_backup_code, name='BackupFlow') self.backup_quiz_passed = settings.get('backup_quiz', False) self.quiz_result = [None] * TOTAL_BACKUP_CODE_DIGITS + self.input_backup_code = input_backup_code self.statusbar = {'title': 'BACKUP', 'icon': lv.ICON_BACKUP} + async def get_backup_code(self): + from utils import spinner_task + from tasks import get_backup_code_task + from pages import ErrorPage, InfoPage + + (self.backup_code, error) = await spinner_task('Retrieving Backup Code', get_backup_code_task) + + if error is not None: + await ErrorPage(text='Unable to retrieve Backup Code: {}'.format(error)).show() + self.set_result(False) + + if self.input_backup_code is not None: + if self.backup_code == self.input_backup_code: + self.backup_quiz_passed = True + else: + await InfoPage("You will receive a new backup code to use with your new Passport.").show() + + if self.backup_quiz_passed: + self.goto(self.do_backup, save_curr=False) + else: + self.goto(self.show_intro, save_curr=False) + async def show_intro(self): from pages import InfoPage from utils import recolor @@ -53,21 +76,6 @@ async def show_intro(self): else: return - async def get_backup_code(self): - from utils import spinner_task - from tasks import get_backup_code_task - from pages import ErrorPage - - (self.backup_code, error) = await spinner_task('Retrieving Backup Code', get_backup_code_task) - if error is None: - if self.backup_quiz_passed: - self.goto(self.do_backup, save_curr=False) - else: - self.goto(self.show_backup_code, save_curr=False) - else: - await ErrorPage(text='Unable to retrieve Backup Code: {}'.format(error)).show() - self.set_result(False) - async def show_backup_code(self): from pages import InfoPage, BackupCodePage diff --git a/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py b/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py index 31c9f9a67..2a392d38b 100644 --- a/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py @@ -118,8 +118,7 @@ async def do_restore(self): self.set_result(True) if self.full_backup: - await InfoPage("You will receive a new backup code to use with your new Passport.").show() - await BackupFlow().run() + await BackupFlow(self.backup_code).run() elif self.autobackup: await AutoBackupFlow(offer=True).run() From 4ffa3269d7598a07844d6b833b00a58b2c2073b2 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 31 May 2023 16:37:55 -0500 Subject: [PATCH 153/187] SFT-2019: completed rearrangement of backup flow, ensured same-device restore counts as completing backup test --- .../Passport/modules/flows/backup_flow.py | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/backup_flow.py b/ports/stm32/boards/Passport/modules/flows/backup_flow.py index 87c93ff3e..77b7cc3d7 100644 --- a/ports/stm32/boards/Passport/modules/flows/backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/backup_flow.py @@ -26,15 +26,17 @@ async def get_backup_code(self): from utils import spinner_task from tasks import get_backup_code_task from pages import ErrorPage, InfoPage + from common import settings - (self.backup_code, error) = await spinner_task('Retrieving Backup Code', get_backup_code_task) + (self.backup_code, error) = await spinner_task('Retrieving backup code', get_backup_code_task) if error is not None: - await ErrorPage(text='Unable to retrieve Backup Code: {}'.format(error)).show() + await ErrorPage(text='Unable to retrieve backup code: {}'.format(error)).show() self.set_result(False) if self.input_backup_code is not None: if self.backup_code == self.input_backup_code: + settings.set('backup_quiz', True) self.backup_quiz_passed = True else: await InfoPage("You will receive a new backup code to use with your new Passport.").show() @@ -54,9 +56,9 @@ async def show_intro(self): 'The Backup Code is the same as what you were previously shown.'] else: msgs = ['Passport is about to create your first encrypted microSD backup.', - 'The next screen will show you the Backup Code that is {} to decrypt the backup.'.format( + 'The next screen will show you the backup code that is {} to decrypt the backup.'.format( recolor(HIGHLIGHT_TEXT_HEX, 'REQUIRED')), - 'We recommend writing down the Backup Code on the included security card.', + 'We recommend writing down the backup code on the included security card.', 'We consider this safe since physical access to the microSD card is required to access the backup.'] if stash.bip39_passphrase != '': msgs.append('The current passphrase applied to Passport will not be saved as part of this backup.') @@ -67,9 +69,9 @@ async def show_intro(self): left_micron=microns.Back, right_micron=microns.Forward).show() if result: - self.goto(self.get_backup_code) + self.goto(self.show_backup_code) else: - result = await QuestionPage(text='Skip initial Backup?\n\n{}'.format( + result = await QuestionPage(text='Skip initial backup?\n\n{}'.format( recolor(HIGHLIGHT_TEXT_HEX, '(Not recommended)')), left_micron=microns.Retry).show() if result: self.set_result(False) @@ -87,7 +89,7 @@ async def show_backup_code(self): result = await InfoPage( icon=lv.LARGE_ICON_BACKUP, card_header={'title': 'Backup Code Quiz'}, - text='Let\'s check that you recorded the Backup Code correctly.').show() + text='Let\'s check that you recorded the backup code correctly.').show() if not result: self.back() else: @@ -103,12 +105,12 @@ async def do_backup_code_quiz(self): if result == self.backup_code: from common import settings settings.set('backup_quiz', True) - await SuccessPage(text='You entered the Backup Code correctly!').show() + await SuccessPage(text='You entered the backup code correctly!').show() self.goto(self.do_backup) else: # Save this so the user doesn't lose their input self.quiz_result = result - await ErrorPage(text='The Backup Code you entered is incorrect, please try again.').show() + await ErrorPage(text='The backup code you entered is incorrect, please try again.').show() else: # Clear out quiz result self.quiz_result = [None] * TOTAL_BACKUP_CODE_DIGITS From 6c3167fd05424d50909a77cc112b9c010829426d Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 1 Jun 2023 11:18:28 -0500 Subject: [PATCH 154/187] SFT-2019: reverted Backup Code capitalization change --- .../boards/Passport/modules/flows/backup_flow.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/backup_flow.py b/ports/stm32/boards/Passport/modules/flows/backup_flow.py index 77b7cc3d7..9b3ca37c2 100644 --- a/ports/stm32/boards/Passport/modules/flows/backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/backup_flow.py @@ -28,10 +28,10 @@ async def get_backup_code(self): from pages import ErrorPage, InfoPage from common import settings - (self.backup_code, error) = await spinner_task('Retrieving backup code', get_backup_code_task) + (self.backup_code, error) = await spinner_task('Retrieving Backup Code', get_backup_code_task) if error is not None: - await ErrorPage(text='Unable to retrieve backup code: {}'.format(error)).show() + await ErrorPage(text='Unable to retrieve Backup Code: {}'.format(error)).show() self.set_result(False) if self.input_backup_code is not None: @@ -39,7 +39,7 @@ async def get_backup_code(self): settings.set('backup_quiz', True) self.backup_quiz_passed = True else: - await InfoPage("You will receive a new backup code to use with your new Passport.").show() + await InfoPage("You will receive a new Backup Code to use with your new Passport.").show() if self.backup_quiz_passed: self.goto(self.do_backup, save_curr=False) @@ -56,9 +56,9 @@ async def show_intro(self): 'The Backup Code is the same as what you were previously shown.'] else: msgs = ['Passport is about to create your first encrypted microSD backup.', - 'The next screen will show you the backup code that is {} to decrypt the backup.'.format( + 'The next screen will show you the Backup Code that is {} to decrypt the backup.'.format( recolor(HIGHLIGHT_TEXT_HEX, 'REQUIRED')), - 'We recommend writing down the backup code on the included security card.', + 'We recommend writing down the Backup Code on the included security card.', 'We consider this safe since physical access to the microSD card is required to access the backup.'] if stash.bip39_passphrase != '': msgs.append('The current passphrase applied to Passport will not be saved as part of this backup.') @@ -89,7 +89,7 @@ async def show_backup_code(self): result = await InfoPage( icon=lv.LARGE_ICON_BACKUP, card_header={'title': 'Backup Code Quiz'}, - text='Let\'s check that you recorded the backup code correctly.').show() + text='Let\'s check that you recorded the Backup Code correctly.').show() if not result: self.back() else: @@ -105,12 +105,12 @@ async def do_backup_code_quiz(self): if result == self.backup_code: from common import settings settings.set('backup_quiz', True) - await SuccessPage(text='You entered the backup code correctly!').show() + await SuccessPage(text='You entered the Backup Code correctly!').show() self.goto(self.do_backup) else: # Save this so the user doesn't lose their input self.quiz_result = result - await ErrorPage(text='The backup code you entered is incorrect, please try again.').show() + await ErrorPage(text='The Backup Code you entered is incorrect, please try again.').show() else: # Clear out quiz result self.quiz_result = [None] * TOTAL_BACKUP_CODE_DIGITS From ffdf3ce869f6fb0715044bf0f1d9d97c830838ff Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 31 May 2023 15:19:47 -0500 Subject: [PATCH 155/187] SFT-936: added multisig support to MicroSD outputs of QR signing --- .../modules/flows/sign_psbt_microsd_flow.py | 1 + .../modules/flows/sign_psbt_qr_flow.py | 63 +++++++++++++++---- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py index fc8483063..a2b233bca 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py @@ -88,6 +88,7 @@ async def common_flow(self): # This flow validates and signs if all goes well, and returns the signed psbt result = await SignPsbtCommonFlow(self.psbt_len).run() + if result is None: self.set_result(False) else: diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 8c9667e08..7ec6f00d5 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -13,7 +13,9 @@ def __init__(self): self.ur_type = None self.psbt = None self.txid = None + self.is_comp = None self.out_fn = None + self.out2_fn = None self.signed_bytes = None self.max_frames = 35 @@ -92,11 +94,12 @@ async def common_flow(self): from flows import SignPsbtCommonFlow # This flow validates and signs if all goes well, and returns the signed psbt - self.psbt = await SignPsbtCommonFlow(self.psbt_len).run() + result = await SignPsbtCommonFlow(self.psbt_len).run() - if self.psbt is None: + if result is None: self.set_result(False) else: + self.psbt = result self.goto(self.get_signed_bytes) async def get_signed_bytes(self): @@ -105,7 +108,6 @@ async def get_signed_bytes(self): from passport import mem # Copy signed txn into a bytearray and show the data as a UR - # try: try: with FixedBytesIO(mem.psbt_output) as bfd: with self.output_encoder(bfd) as fd: @@ -158,25 +160,58 @@ def write_final_fn(self, filename): # write psbt to file as hex with HexWriter(open(filename, 'w+t')) as fd: self.txid = self.psbt.finalize(fd) + self.out2_fn = filename + + def write_psbt_fn(self, filename): + # Attempt to write-out the transaction + with self.output_encoder(open(filename, 'wb')) as fd: + # save as updated PSBT + self.psbt.serialize(fd) self.out_fn = filename async def save_to_microsd(self): from flows import SaveToMicroSDFlow + from pages import ErrorPage from utils import get_folder_path from public_constants import DIR_TRANSACTIONS - if self.out_fn is not None: + # Check that the psbt has been written, and the transaction has been written if complete + if self.out_fn and (self.is_comp == bool(self.out2_fn)): self.goto(self.show_success) return - result = await SaveToMicroSDFlow(filename='QR.txn', - write_fn=self.write_final_fn, - success_text="transaction", - path=get_folder_path(DIR_TRANSACTIONS)).run() - if not result: + base = 'QR' + + self.is_comp = self.psbt.is_complete() + if not self.is_comp: + # Keep the filename under control during multiple passes + target_fname = base + '-part.psbt' + else: + # Add -signed to end. We won't offer to sign again. + target_fname = base + '-signed.psbt' + + result_1 = await SaveToMicroSDFlow(filename=target_fname, + write_fn=self.write_psbt_fn, + success_text="psbt", + path=get_folder_path(DIR_TRANSACTIONS), + automatic=True).run() + if not result_1: + await ErrorPage(text='Unable to save {} to MicroSD'.format(target_fname)).show() self.back() return + if self.is_comp: + target2_fname = base + '-final.txn' + result_2 = await SaveToMicroSDFlow(filename=target2_fname, + write_fn=self.write_final_fn, + success_text="transaction", + path=get_folder_path(DIR_TRANSACTIONS), + automatic=True).run() + if not result_2: + await ErrorPage(text='Unable to save {} to MicroSD'.format(target2_fname)).show() + self.back() + return + self.goto(self.show_success) async def show_success(self): @@ -185,17 +220,19 @@ async def show_success(self): from styles.colors import DEFAULT_LARGE_ICON_COLOR from pages import LongTextPage - msg = 'Finalized transaction (ready for broadcast):\n\n%s' % self.out_fn + msg = "Updated PSBT is:\n\n%s" % self.out_fn + if self.out2_fn: + msg += '\n\nFinalized transaction (ready for broadcast):\n\n%s' % self.out2_fn - if self.txid: - msg += '\n\nFinal TXID:\n' + self.txid + if self.txid: + msg += '\n\nFinal TXID:\n' + self.txid result = await LongTextPage(text=msg, centered=True, left_micron=microns.ScanQR, right_micron=microns.Checkmark, icon=LARGE_ICON_SUCCESS, - icon_color=DEFAULT_LARGE_ICON_COLOR,).show() + icon_color=DEFAULT_LARGE_ICON_COLOR).show() if not result: self.goto(self.show_signed_transaction) From 90496bce56e5cd98c43ca4e2025c2ba9e50071b0 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 1 Jun 2023 11:24:00 -0500 Subject: [PATCH 156/187] SFT-936: updated microSD capitalization --- .../boards/Passport/modules/flows/sign_psbt_microsd_flow.py | 4 ++-- .../boards/Passport/modules/flows/sign_psbt_qr_flow.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py index a2b233bca..b8592772f 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py @@ -121,7 +121,7 @@ async def write_signed_transaction(self): automatic=True).run() if not result_1: # Fall through - await ErrorPage(text='Unable to save {} to MicroSD'.format(target_fname)).show() + await ErrorPage(text='Unable to save {} to microSD'.format(target_fname)).show() return if is_comp: @@ -132,7 +132,7 @@ async def write_signed_transaction(self): path=orig_path, automatic=True).run() if not result_2: - await ErrorPage(text='Unable to save {} to MicroSD'.format(target2_fname)).show() + await ErrorPage(text='Unable to save {} to microSD'.format(target2_fname)).show() # Fall through return diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 7ec6f00d5..ea2606f8b 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -41,7 +41,7 @@ async def scan_transaction(self): How would you like to proceed?\n" result = await YesNoChooserPage(text=text, yes_text='Continue with QR', - no_text='Sign with MicroSD', + no_text='Sign with microSD', left_micron=microns.Back).show() if result is None or result: @@ -196,7 +196,7 @@ async def save_to_microsd(self): path=get_folder_path(DIR_TRANSACTIONS), automatic=True).run() if not result_1: - await ErrorPage(text='Unable to save {} to MicroSD'.format(target_fname)).show() + await ErrorPage(text='Unable to save {} to microSD'.format(target_fname)).show() self.back() return @@ -208,7 +208,7 @@ async def save_to_microsd(self): path=get_folder_path(DIR_TRANSACTIONS), automatic=True).run() if not result_2: - await ErrorPage(text='Unable to save {} to MicroSD'.format(target2_fname)).show() + await ErrorPage(text='Unable to save {} to microSD'.format(target2_fname)).show() self.back() return From 759005a0e9ced35dd3d8789ea1cc889e020b5983 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 26 May 2023 17:01:14 -0500 Subject: [PATCH 157/187] SFT-2105: removed invisible button while preserving QR scan pages that use the right button --- ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py | 3 ++- ports/stm32/boards/Passport/modules/pages/scan_qr_page.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py index 0c302a0f0..aa2e199df 100644 --- a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py @@ -54,7 +54,8 @@ async def scan(self): from errors import Error result = await ScanQRPage(max_frames=self.max_frames, - qr_type=self.explicit_type) \ + qr_type=self.explicit_type, + use_right_button=False) \ .show(auto_close_timeout=self.auto_close_timeout) if result is None: diff --git a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py index 24f235e1d..10c5fd074 100644 --- a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py +++ b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py @@ -27,6 +27,7 @@ def __init__(self, statusbar=None, left_micron=microns.Back, right_micron=None, + use_right_button=True, qr_type=None, max_frames=None): super().__init__(flex_flow=None, @@ -39,6 +40,7 @@ def __init__(self, self.prev_card_header = None self.timer = None self.camera = CameraQRScanner(qr_type) + self.use_right_button = use_right_button self.qr_type = qr_type self.max_frames = max_frames @@ -131,7 +133,7 @@ def left_action(self, is_pressed): # Either the user goes back or the scan finishes def right_action(self, is_pressed): - if not is_pressed: + if not is_pressed and self.use_right_button: self.set_result(None) From 64ff0e53e34b3dc754db2116fec52eb2f28a9dce Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 1 Jun 2023 13:02:23 -0500 Subject: [PATCH 158/187] SFT-2105: blank microns have no actions for any ScanQRPage --- ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py | 3 +-- ports/stm32/boards/Passport/modules/pages/scan_qr_page.py | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py index aa2e199df..0c302a0f0 100644 --- a/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scan_qr_flow.py @@ -54,8 +54,7 @@ async def scan(self): from errors import Error result = await ScanQRPage(max_frames=self.max_frames, - qr_type=self.explicit_type, - use_right_button=False) \ + qr_type=self.explicit_type) \ .show(auto_close_timeout=self.auto_close_timeout) if result is None: diff --git a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py index 10c5fd074..14c2a76c0 100644 --- a/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py +++ b/ports/stm32/boards/Passport/modules/pages/scan_qr_page.py @@ -27,7 +27,6 @@ def __init__(self, statusbar=None, left_micron=microns.Back, right_micron=None, - use_right_button=True, qr_type=None, max_frames=None): super().__init__(flex_flow=None, @@ -40,7 +39,6 @@ def __init__(self, self.prev_card_header = None self.timer = None self.camera = CameraQRScanner(qr_type) - self.use_right_button = use_right_button self.qr_type = qr_type self.max_frames = max_frames @@ -128,12 +126,12 @@ def update(self): # Just return None. def left_action(self, is_pressed): - if not is_pressed: + if not is_pressed and self.left_micron: self.set_result(None) # Either the user goes back or the scan finishes def right_action(self, is_pressed): - if not is_pressed and self.use_right_button: + if not is_pressed and self.right_micron: self.set_result(None) From 9f96541ddfe8df73ac9b5b9c5054503f17706b79 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Wed, 7 Jun 2023 15:52:56 +0200 Subject: [PATCH 159/187] SFT-2250: Move CFLAGS to mpconfigboard.mk Signed-off-by: Jean-Pierre De Jesus DIAZ --- ports/stm32/Justfile | 7 +------ ports/stm32/boards/Passport/mpconfigboard.mk | 12 ++++++++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ports/stm32/Justfile b/ports/stm32/Justfile index 3e7853f92..d704e76fa 100644 --- a/ports/stm32/Justfile +++ b/ports/stm32/Justfile @@ -10,11 +10,6 @@ contribdir := join(justfile_directory(), "boards/Passport/contrib") openocd_cfg := join(contribdir, "openocd.cfg") compile_commands := join(builddir, "compile_commands.json") -base_cflags := "-DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP -DLV_TICK_CUSTOM=1" -color_cflags := "-DSCREEN_MODE_COLOR -DHAS_FUEL_GAUGE " -mono_cflags := "-DSCREEN_MODE_MONO" -dev_cflags := "-DDEV_BUILD" - # Number of jobs to use when building jobs := if os() == "macos" { `sysctl -n hw.logicalcpu` @@ -83,7 +78,7 @@ build screen="mono" dev="" +ext='': @echo {{ if screen == "mono" { "Building with SCREEN_MODE=MONO" } else if screen == "color" { "Building with SCREEN_MODE=COLOR" } else { error("Unsupported screen type. Use 'mono' or 'color'") } }} make -j{{jobs}} \ - LV_CFLAGS='{{base_cflags}} {{ if screen == "mono" { mono_cflags } else { color_cflags } }} {{ if dev == "dev" { dev_cflags } else { "" } }}' \ + {{ if dev == "dev" { "DEV_BUILD=1" } else { "" } }} \ BOARD=Passport \ SCREEN_MODE={{ uppercase(screen) }} \ FROZEN_MANIFEST={{ if dev == "dev" { 'boards/Passport/manifest_dev.py' } else { 'boards/Passport/manifest.py' } }} \ diff --git a/ports/stm32/boards/Passport/mpconfigboard.mk b/ports/stm32/boards/Passport/mpconfigboard.mk index e4d928771..c6bed7a73 100644 --- a/ports/stm32/boards/Passport/mpconfigboard.mk +++ b/ports/stm32/boards/Passport/mpconfigboard.mk @@ -40,6 +40,8 @@ CFLAGS_MOD += -I$(MICROPY_EXTMOD_DIR) \ -I$(MICROPY_EXTMOD_DIR)/foundation \ -I$(MICROPY_EXTMOD_DIR)/quirc +LV_CFLAGS += -DLV_COLOR_DEPTH=16 -DLV_COLOR_16_SWAP -DLV_TICK_CUSTOM=1 + # settings that apply only to crypto C-lang code build-Passport/boards/Passport/crypto/%.o: CFLAGS_MOD += -DRAND_PLATFORM_INDEPENDENT=1 @@ -74,13 +76,19 @@ SRC_MOD += $(addprefix boards/$(BOARD)/common/,\ ifeq ($(SCREEN_MODE), MONO) SRC_MOD += $(addprefix boards/$(BOARD)/common/,\ lcd-sharp-ls018b7dh02.c) - CFLAGS += -DSCREEN_MODE_MONO=1 + LV_CFLAGS += -DSCREEN_MODE_MONO=1 + CFLAGS += -DSCREEN_MODE_MONO=1 endif ifeq ($(SCREEN_MODE), COLOR) SRC_MOD += $(addprefix boards/$(BOARD)/common/,\ lcd-st7789.c st7789.c) - CFLAGS += -DSCREEN_MODE_COLOR=1 + LV_CFLAGS += -DSCREEN_MODE_COLOR=1 -DHAS_FUEL_GAUGE=1 + CFLAGS += -DSCREEN_MODE_COLOR=1 -DHAS_FUEL_GAUGE=1 +endif + +ifeq ($(DEV_BUILD),1) + LV_CFLAGS += -DDEV_BUILD endif RUST_TARGET := thumbv7em-none-eabihf From 02620208a2b774b15a6567b58167a04d0f1e743e Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Wed, 7 Jun 2023 15:26:40 +0200 Subject: [PATCH 160/187] SFT-2251: Make add-secrets Makefile self-contained Signed-off-by: Jean-Pierre De Jesus DIAZ --- ports/stm32/boards/Passport/tools/add-secrets/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/ports/stm32/boards/Passport/tools/add-secrets/Makefile b/ports/stm32/boards/Passport/tools/add-secrets/Makefile index 561de890e..bb4fc3ff1 100644 --- a/ports/stm32/boards/Passport/tools/add-secrets/Makefile +++ b/ports/stm32/boards/Passport/tools/add-secrets/Makefile @@ -1,8 +1,6 @@ # SPDX-FileCopyrightText: © 2020 Foundation Devices, Inc. # SPDX-License-Identifier: GPL-3.0-or-later -TOP = ../.. - SOURCES = add-secrets.c VPATH = @@ -11,7 +9,6 @@ ARCH ?= x86 CFLAGS = -Wall -fno-strict-aliasing CFLAGS += -fno-omit-frame-pointer -CFLAGS += -I$(TOP)/include LDFLAGS = -Wl,-Map,$(MAP) From 62d429f3c60bfcadb449358df5ec57766d6fd93f Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 8 Jun 2023 17:17:39 -0500 Subject: [PATCH 161/187] SFT-2231: updated founders seed icon --- .../boards/Passport/images/mono/ICON_SEED.c | 40 +++++++++--------- .../mono/ICON_SEED__CF_INDEXED_1_BIT.png | Bin 219 -> 226 bytes 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SEED.c b/ports/stm32/boards/Passport/images/mono/ICON_SEED.c index 81f311f45..e56649ec6 100644 --- a/ports/stm32/boards/Passport/images/mono/ICON_SEED.c +++ b/ports/stm32/boards/Passport/images/mono/ICON_SEED.c @@ -21,26 +21,26 @@ const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SEED 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ 0xff, 0xff, 0xff, 0xff, /*Color of index 1*/ - 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x00, - 0x00, 0x7c, 0x00, - 0x00, 0x60, 0x00, - 0x0f, 0xff, 0x00, - 0x1f, 0xff, 0x80, - 0x30, 0x00, 0xc0, - 0x20, 0x00, 0x40, - 0x30, 0x00, 0xc0, - 0x1f, 0xff, 0x80, - 0x1f, 0xff, 0x80, - 0x30, 0x00, 0xc0, - 0x30, 0x00, 0xc0, - 0x18, 0x01, 0x80, - 0x0c, 0x03, 0x00, - 0x06, 0x06, 0x00, - 0x03, 0x0c, 0x00, - 0x01, 0xf8, 0x00, - 0x00, 0x60, 0x00, - 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x3c, 0x00, + 0x00, 0x7c, 0x00, + 0x00, 0x60, 0x00, + 0x0f, 0xff, 0x00, + 0x1f, 0xff, 0x80, + 0x38, 0x01, 0xc0, + 0x30, 0x00, 0xc0, + 0x30, 0x00, 0xc0, + 0x1f, 0xff, 0x80, + 0x1f, 0xff, 0x80, + 0x30, 0x00, 0xc0, + 0x38, 0x01, 0xc0, + 0x1c, 0x03, 0x80, + 0x0e, 0x07, 0x00, + 0x07, 0x0e, 0x00, + 0x03, 0xfc, 0x00, + 0x01, 0xf8, 0x00, + 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, }; const lv_img_dsc_t ICON_SEED = { diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SEED__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SEED__CF_INDEXED_1_BIT.png index d6be544165a807e4a5e9ed517e7e85936ee01145..c10843985e198656758a2a5664a431a634fb3489 100644 GIT binary patch delta 148 zcmV;F0Bir-0pbCWR)2R%L_t(|0j-iz4!|G?Lkrpcuk8HTOf(=xd7q|~0s_SdD{P&q zuw&^I2WC4SB=AyA8eF8Yn#hfrWh#~#Gn!YUyKb3eKh%{ol<%-S;h=pW$y%qD01318 z&D~*iZBHw#kkzCMqK58R(JsC8^qv?qn$s^;!V7usTmj%IUJVie0000WmV%j zwFIX;-v9yo(t(DeR*MH4ZM-421B;*!i~)u@w%t2Bq6G$aOMZr>cSuQfDgQO}rb+x& vXlr<8rp`MGWiZR2Zm96 Date: Thu, 8 Jun 2023 17:00:31 -0500 Subject: [PATCH 162/187] SFT-2227: made some pages long for founders edition --- ports/stm32/boards/Passport/manifest.py | 3 ++ .../modules/flows/erase_passport_flow.py | 6 ++-- .../modules/flows/verify_address_flow.py | 13 +++++--- .../modules/flows/verify_backup_flow.py | 8 +++-- .../boards/Passport/modules/pages/__init__.py | 3 ++ .../Passport/modules/pages/long_error_page.py | 28 +++++++++++++++++ .../modules/pages/long_question_page.py | 31 +++++++++++++++++++ .../modules/pages/long_success_page.py | 28 +++++++++++++++++ 8 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 ports/stm32/boards/Passport/modules/pages/long_error_page.py create mode 100644 ports/stm32/boards/Passport/modules/pages/long_question_page.py create mode 100644 ports/stm32/boards/Passport/modules/pages/long_success_page.py diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index f47ecabb1..e77866987 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -176,6 +176,9 @@ 'pages/file_picker_page.py', 'pages/info_page.py', 'pages/insert_microsd_page.py', + 'pages/long_error_page.py', + 'pages/long_question_page.py', + 'pages/long_success_page.py', 'pages/long_text_page.py', 'pages/menu_page.py', 'pages/page.py', diff --git a/ports/stm32/boards/Passport/modules/flows/erase_passport_flow.py b/ports/stm32/boards/Passport/modules/flows/erase_passport_flow.py index 64231de49..0f3b7aa73 100644 --- a/ports/stm32/boards/Passport/modules/flows/erase_passport_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/erase_passport_flow.py @@ -6,11 +6,12 @@ import lvgl as lv from flows import Flow -from pages import SuccessPage, QuestionPage +from pages import SuccessPage, QuestionPage, LongQuestionPage from tasks import erase_passport_task from utils import spinner_task from translations import t, T import microns +import passport class ErasePassportFlow(Flow): @@ -28,7 +29,8 @@ async def confirm_erase(self): self.set_result(False) return - if not await QuestionPage( + page_class = QuestionPage if passport.IS_COLOR else LongQuestionPage + if not await page_class( 'Without a proper backup, you could lose all funds associated with this device.\n\n' + 'Please confirm you understand these risks.').show(): self.set_result(False) diff --git a/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py b/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py index fb238dc26..0596fb079 100644 --- a/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/verify_address_flow.py @@ -187,7 +187,8 @@ async def search_for_address(self): self.goto(self.not_found) async def not_found(self): - from pages import ErrorPage + from pages import ErrorPage, LongErrorPage + import passport # Address was not found in that batch of 100, so offer to keep searching msg = 'Address Not Found\nRanges Checked:\n' @@ -201,15 +202,18 @@ async def not_found(self): msg += '\n\nContinue searching?' - result = await ErrorPage(msg, left_micron=microns.Cancel, right_micron=microns.Checkmark).show() + page_class = ErrorPage if passport.IS_COLOR else LongErrorPage + + result = await page_class(msg, left_micron=microns.Cancel, right_micron=microns.Checkmark).show() if result: self.goto(self.search_for_address) else: self.set_result(False) async def found(self): - from pages import SuccessPage + from pages import SuccessPage, LongSuccessPage from utils import save_next_addr, format_btc_address + import passport # Remember where to start from next time save_next_addr(self.acct_num, self.addr_type, self.found_addr_idx, self.found_is_change) @@ -222,5 +226,6 @@ async def found(self): 'Change' if self.found_is_change == 1 else 'Receive', self.found_addr_idx) - await SuccessPage(msg).show() + page_class = SuccessPage if passport.IS_COLOR else LongSuccessPage + await page_class(msg).show() self.set_result(True) diff --git a/ports/stm32/boards/Passport/modules/flows/verify_backup_flow.py b/ports/stm32/boards/Passport/modules/flows/verify_backup_flow.py index 38f6f332f..f71ec4622 100644 --- a/ports/stm32/boards/Passport/modules/flows/verify_backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/verify_backup_flow.py @@ -5,10 +5,11 @@ from flows import Flow, FilePickerFlow -from pages import ErrorPage, SuccessPage, InsertMicroSDPage +from pages import ErrorPage, SuccessPage, LongSuccessPage, InsertMicroSDPage from utils import get_backups_folder_path, spinner_task from tasks import verify_backup_task from errors import Error +import passport class VerifyBackupFlow(Flow): @@ -34,8 +35,9 @@ async def do_verify(self): verify_backup_task, args=[self.backup_file_path]) if error is None: - await SuccessPage(text='Backup file appears to be valid.\n\nPlease note this is only a check to ensure ' + - 'the file has not been modified or damaged.').show() + page_class = SuccessPage if passport.IS_COLOR else LongSuccessPage + await page_class(text='Backup file appears to be valid.\n\nPlease note this is only a check to ensure ' + + 'the file has not been modified or damaged.').show() self.set_result(True) elif error is Error.MICROSD_CARD_MISSING: result = await InsertMicroSDPage().show() diff --git a/ports/stm32/boards/Passport/modules/pages/__init__.py b/ports/stm32/boards/Passport/modules/pages/__init__.py index 10a6f3fab..aa9936ee2 100644 --- a/ports/stm32/boards/Passport/modules/pages/__init__.py +++ b/ports/stm32/boards/Passport/modules/pages/__init__.py @@ -23,6 +23,9 @@ from .file_picker_page import * from .info_page import * from .insert_microsd_page import * +from .long_error_page import * +from .long_question_page import * +from .long_success_page import * from .menu_page import * from .multisig_policy_setting_page import * from .pin_entry_page import * diff --git a/ports/stm32/boards/Passport/modules/pages/long_error_page.py b/ports/stm32/boards/Passport/modules/pages/long_error_page.py new file mode 100644 index 000000000..f431d8593 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/pages/long_error_page.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# long_error_page.py + +import lvgl as lv +from pages import LongTextPage +from styles.colors import COPPER +import microns + + +class LongErrorPage(LongTextPage): + def __init__( + self, + text=None, + card_header=None, + statusbar=None, + left_micron=None, + right_micron=microns.Checkmark): + super().__init__( + text=text, + card_header=card_header, + statusbar=statusbar, + centered=True, + icon=lv.LARGE_ICON_ERROR, + icon_color=COPPER, + left_micron=left_micron, + right_micron=right_micron) diff --git a/ports/stm32/boards/Passport/modules/pages/long_question_page.py b/ports/stm32/boards/Passport/modules/pages/long_question_page.py new file mode 100644 index 000000000..136d2e730 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/pages/long_question_page.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# long_question_page.py + +import lvgl as lv +from pages import LongTextPage +from styles.colors import DEFAULT_LARGE_ICON_COLOR +import microns + + +class LongQuestionPage(LongTextPage): + def __init__( + self, + text=None, + icon=lv.LARGE_ICON_QUESTION, + icon_color=DEFAULT_LARGE_ICON_COLOR, + card_header=None, + statusbar=None, + left_micron=microns.Cancel, + right_micron=microns.Checkmark + ): + super().__init__( + text=text, + icon=icon, + icon_color=icon_color, + card_header=card_header, + statusbar=statusbar, + centered=True, + left_micron=left_micron, + right_micron=right_micron) diff --git a/ports/stm32/boards/Passport/modules/pages/long_success_page.py b/ports/stm32/boards/Passport/modules/pages/long_success_page.py new file mode 100644 index 000000000..9e30c7623 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/pages/long_success_page.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# long_success_page.py + +import lvgl as lv +from pages import LongTextPage +from styles.colors import DEFAULT_LARGE_ICON_COLOR +import microns + + +class LongSuccessPage(LongTextPage): + def __init__( + self, + text=None, + card_header=None, + statusbar=None, + left_micron=None, + right_micron=microns.Checkmark): + super().__init__( + text=text, + card_header=card_header, + statusbar=statusbar, + icon=lv.LARGE_ICON_SUCCESS, + icon_color=DEFAULT_LARGE_ICON_COLOR, + centered=True, + left_micron=left_micron, + right_micron=right_micron) From 1d9b327b0d316809b536bd21d0a9d35402e1f5e1 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 7 Jun 2023 13:59:16 -0500 Subject: [PATCH 163/187] SFT-2234: adjusted spacing on large transaction warning screen for FE --- .../boards/Passport/modules/flows/sign_psbt_qr_flow.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index ea2606f8b..86164c8be 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -26,6 +26,7 @@ async def scan_transaction(self): from errors import Error from pages import YesNoChooserPage import microns + import passport result = await ScanQRFlow(qr_types=[QRType.QR, QRType.UR2], ur_types=[ur.Value.CRYPTO_PSBT, ur.Value.BYTES], @@ -37,8 +38,12 @@ async def scan_transaction(self): return if result == Error.PSBT_OVERSIZED: - text = "\nThis transaction is large and will take some time to scan. \ -How would you like to proceed?\n" + text = "This transaction is large and will take some time to scan. \ +How would you like to proceed?" + + if passport.IS_COLOR: + text = '\n' + text + '\n' + result = await YesNoChooserPage(text=text, yes_text='Continue with QR', no_text='Sign with microSD', From f3286974c3bb44b501302ac19ead1b3c1684a1d9 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 7 Jun 2023 10:27:56 -0500 Subject: [PATCH 164/187] SFT-2229: fixed character type indicator color in FE --- ports/stm32/boards/Passport/modules/views/pin_input.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/views/pin_input.py b/ports/stm32/boards/Passport/modules/views/pin_input.py index a135b34db..59d86483c 100644 --- a/ports/stm32/boards/Passport/modules/views/pin_input.py +++ b/ports/stm32/boards/Passport/modules/views/pin_input.py @@ -6,7 +6,7 @@ import lvgl as lv from styles import Stylize -from styles.colors import TEXT_GREY, TEXT_INPUT_BG, TEXT_INPUT_CURSOR, TEXT_INPUT_TEXT, TEXT_INPUT_CURSOR +from styles.colors import TEXT_INPUT_ICON, TEXT_INPUT_BG, TEXT_INPUT_CURSOR, TEXT_INPUT_TEXT, TEXT_INPUT_CURSOR from views import View from utils import InputMode from views import Label, Icon @@ -38,7 +38,7 @@ def __init__(self, pin='', input_mode=InputMode.UPPER_ALPHA): default.pad(left=2) default.flex_align(main=lv.FLEX_ALIGN.CENTER, cross=lv.FLEX_ALIGN.CENTER, track=lv.FLEX_ALIGN.CENTER) - self.mode_icon = Icon(InputMode.get_icon(self.input_mode), color=TEXT_GREY) + self.mode_icon = Icon(InputMode.get_icon(self.input_mode), color=TEXT_INPUT_ICON) self.mode_view.add_child(self.mode_icon) self.pin_container = View(flex_flow=lv.FLEX_FLOW.ROW) @@ -63,8 +63,6 @@ def update_pin(self): num_chars = len(self.pin) for i in range(num_chars): - # ch = self.pin[i] - # item = Label(text=ch, color=TEXT_GREY) ch = self.pin[i] if not self.hidden_mode: item = Label(text=ch, color=TEXT_INPUT_TEXT) From 1a1d2df097fe2cf31a64251dff91b1f387c23e0f Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 2 Jun 2023 11:02:28 -0500 Subject: [PATCH 165/187] SFT-2019: skipped backup when restoring to same device --- ports/stm32/boards/Passport/modules/flows/backup_flow.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/flows/backup_flow.py b/ports/stm32/boards/Passport/modules/flows/backup_flow.py index 9b3ca37c2..a986ef013 100644 --- a/ports/stm32/boards/Passport/modules/flows/backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/backup_flow.py @@ -37,7 +37,9 @@ async def get_backup_code(self): if self.input_backup_code is not None: if self.backup_code == self.input_backup_code: settings.set('backup_quiz', True) - self.backup_quiz_passed = True + await InfoPage("Backup restored, no new Backup Code needed\n").show() + self.set_result(True) + return else: await InfoPage("You will receive a new Backup Code to use with your new Passport.").show() From 300841223cbc86083c339f6b7c8be6df117214e1 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 7 Jun 2023 13:24:23 -0500 Subject: [PATCH 166/187] SFT-2019: made restore to same device more seamless --- .../Passport/modules/flows/backup_flow.py | 48 +++++++------------ .../modules/flows/restore_backup_flow.py | 8 +++- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/backup_flow.py b/ports/stm32/boards/Passport/modules/flows/backup_flow.py index a986ef013..10ecca546 100644 --- a/ports/stm32/boards/Passport/modules/flows/backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/backup_flow.py @@ -13,41 +13,14 @@ class BackupFlow(Flow): - def __init__(self, input_backup_code=None): + def __init__(self): from common import settings - super().__init__(initial_state=self.get_backup_code, name='BackupFlow') + super().__init__(initial_state=self.show_intro, name='BackupFlow') self.backup_quiz_passed = settings.get('backup_quiz', False) self.quiz_result = [None] * TOTAL_BACKUP_CODE_DIGITS - self.input_backup_code = input_backup_code self.statusbar = {'title': 'BACKUP', 'icon': lv.ICON_BACKUP} - async def get_backup_code(self): - from utils import spinner_task - from tasks import get_backup_code_task - from pages import ErrorPage, InfoPage - from common import settings - - (self.backup_code, error) = await spinner_task('Retrieving Backup Code', get_backup_code_task) - - if error is not None: - await ErrorPage(text='Unable to retrieve Backup Code: {}'.format(error)).show() - self.set_result(False) - - if self.input_backup_code is not None: - if self.backup_code == self.input_backup_code: - settings.set('backup_quiz', True) - await InfoPage("Backup restored, no new Backup Code needed\n").show() - self.set_result(True) - return - else: - await InfoPage("You will receive a new Backup Code to use with your new Passport.").show() - - if self.backup_quiz_passed: - self.goto(self.do_backup, save_curr=False) - else: - self.goto(self.show_intro, save_curr=False) - async def show_intro(self): from pages import InfoPage from utils import recolor @@ -71,7 +44,7 @@ async def show_intro(self): left_micron=microns.Back, right_micron=microns.Forward).show() if result: - self.goto(self.show_backup_code) + self.goto(self.get_backup_code) else: result = await QuestionPage(text='Skip initial backup?\n\n{}'.format( recolor(HIGHLIGHT_TEXT_HEX, '(Not recommended)')), left_micron=microns.Retry).show() @@ -80,6 +53,21 @@ async def show_intro(self): else: return + async def get_backup_code(self): + from utils import spinner_task + from tasks import get_backup_code_task + from pages import ErrorPage + + (self.backup_code, error) = await spinner_task('Retrieving Backup Code', get_backup_code_task) + if error is None: + if self.backup_quiz_passed: + self.goto(self.do_backup, save_curr=False) + else: + self.goto(self.show_backup_code, save_curr=False) + else: + await ErrorPage(text='Unable to retrieve Backup Code: {}'.format(error)).show() + self.set_result(False) + async def show_backup_code(self): from pages import InfoPage, BackupCodePage diff --git a/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py b/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py index 2a392d38b..b440b04f8 100644 --- a/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/restore_backup_flow.py @@ -18,7 +18,7 @@ YesNoChooserPage ) from utils import get_backups_folder_path, spinner_task, get_backup_code_as_password -from tasks import restore_backup_task +from tasks import restore_backup_task, get_backup_code_task from errors import Error import common @@ -113,12 +113,16 @@ async def do_restore(self): restore_backup_task, args=[self.decryption_password, self.backup_file_path]) + (new_backup_code, error_2) = await spinner_task('Restoring Backup', get_backup_code_task) + if error is None: await SuccessPage(text='Restore Complete!').show() self.set_result(True) if self.full_backup: - await BackupFlow(self.backup_code).run() + if error_2 is not None or self.backup_code != new_backup_code: + await InfoPage("You will receive a new Backup Code to use with your new Passport.").show() + await BackupFlow(self.backup_code).run() elif self.autobackup: await AutoBackupFlow(offer=True).run() From 19aad65628a288df515217833c6a090216e4bed8 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 9 Jun 2023 10:56:44 -0500 Subject: [PATCH 167/187] SFT-2228: fixed scrollbar color in founders edition --- ports/stm32/boards/Passport/modules/pages/chooser_page.py | 6 ++++-- .../stm32/boards/Passport/modules/pages/file_picker_page.py | 4 +++- ports/stm32/boards/Passport/modules/pages/menu_page.py | 4 ++++ .../Passport/modules/pages/predictive_text_input_page.py | 5 ++++- .../boards/Passport/modules/pages/seed_words_list_page.py | 5 ++++- ports/stm32/boards/Passport/modules/pages/status_page.py | 4 +++- ports/stm32/boards/Passport/modules/styles/colors.py | 3 +++ 7 files changed, 25 insertions(+), 6 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/pages/chooser_page.py b/ports/stm32/boards/Passport/modules/pages/chooser_page.py index db265d5b2..b78d26553 100644 --- a/ports/stm32/boards/Passport/modules/pages/chooser_page.py +++ b/ports/stm32/boards/Passport/modules/pages/chooser_page.py @@ -6,7 +6,7 @@ import lvgl as lv import microns -from styles.colors import CHOOSER_ICON +from styles.colors import CHOOSER_ICON, SCROLLBAR_BG_COLOR from styles import Stylize from pages import Page import common @@ -26,6 +26,7 @@ def __init__( left_micron=None, right_micron=None): from views import ListItem, View + import passport left_micron = left_micron or microns.Cancel right_micron = right_micron or microns.Checkmark @@ -66,7 +67,6 @@ def __init__( # Add icon if provided if icon is not None: from views import Icon - import passport self.icon_view = Icon(self.icon) with Stylize(self.icon_view) as default: @@ -96,6 +96,8 @@ def __init__( # Adjust scrollbar position with Stylize(self.scroll_container, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) with Stylize(self.scroll_container) as default: default.flex_fill() diff --git a/ports/stm32/boards/Passport/modules/pages/file_picker_page.py b/ports/stm32/boards/Passport/modules/pages/file_picker_page.py index 39fc7a90d..e81113083 100644 --- a/ports/stm32/boards/Passport/modules/pages/file_picker_page.py +++ b/ports/stm32/boards/Passport/modules/pages/file_picker_page.py @@ -6,7 +6,7 @@ import lvgl as lv import microns -from styles.colors import TEXT_GREY +from styles.colors import TEXT_GREY, SCROLLBAR_BG_COLOR from styles import Stylize from pages import Page from views import FileItem, View @@ -50,6 +50,8 @@ def __init__(self, # Adjust scrollbar position with Stylize(self.scroll_container, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) # Add the file items to the scroll container num_files = min(MAX_FILE_DISPLAY, len(self.files)) diff --git a/ports/stm32/boards/Passport/modules/pages/menu_page.py b/ports/stm32/boards/Passport/modules/pages/menu_page.py index f805fc741..f04431ee6 100644 --- a/ports/stm32/boards/Passport/modules/pages/menu_page.py +++ b/ports/stm32/boards/Passport/modules/pages/menu_page.py @@ -6,10 +6,12 @@ import lvgl as lv from styles import Stylize +from styles.colors import SCROLLBAR_BG_COLOR from pages import Page from views import MenuItem import common import microns +import passport class MenuPage(Page): @@ -39,6 +41,8 @@ def __init__(self, # Adjust scrollbar position with Stylize(self, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) # Set non-style props self.set_width(lv.pct(100)) diff --git a/ports/stm32/boards/Passport/modules/pages/predictive_text_input_page.py b/ports/stm32/boards/Passport/modules/pages/predictive_text_input_page.py index 609cd8122..30c363d91 100644 --- a/ports/stm32/boards/Passport/modules/pages/predictive_text_input_page.py +++ b/ports/stm32/boards/Passport/modules/pages/predictive_text_input_page.py @@ -5,7 +5,7 @@ import lvgl as lv -from styles.colors import BLACK +from styles.colors import BLACK, SCROLLBAR_BG_COLOR from pages import Page from utils import InputMode, set_list from views import TextInput, Label, View, ListItem, TextInput @@ -13,6 +13,7 @@ from keys import KEY_0, KEY_9 import microns from predictive_utils import get_words_matching_prefix, word_to_keypad_numbers +import passport class PredictiveTextInputPage(Page): @@ -73,6 +74,8 @@ def __init__(self, # Adjust scrollbar position with Stylize(self.predictions_container, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) self.add_child(self.predictions_container) diff --git a/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py b/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py index 61acdc732..d15ba30ac 100644 --- a/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py +++ b/ports/stm32/boards/Passport/modules/pages/seed_words_list_page.py @@ -8,9 +8,10 @@ from styles.style import Stylize from views import View, Label import microns -from styles.colors import HIGHLIGHT_TEXT_HEX, TEXT_GREY +from styles.colors import HIGHLIGHT_TEXT_HEX, TEXT_GREY, SCROLLBAR_BG_COLOR from micropython import const import common +import passport _NUM_COLUMNS = const(2) @@ -63,6 +64,8 @@ def __init__( with Stylize(self, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) self.update() diff --git a/ports/stm32/boards/Passport/modules/pages/status_page.py b/ports/stm32/boards/Passport/modules/pages/status_page.py index 5d0dcc386..21bf24d54 100644 --- a/ports/stm32/boards/Passport/modules/pages/status_page.py +++ b/ports/stm32/boards/Passport/modules/pages/status_page.py @@ -7,7 +7,7 @@ from styles.style import Stylize from views import Arc, Label, View, Icon, Spinner from pages import Page -from styles.colors import DEFAULT_SPINNER, TEXT_GREY +from styles.colors import DEFAULT_SPINNER, TEXT_GREY, SCROLLBAR_BG_COLOR import microns import common import passport @@ -53,6 +53,8 @@ def __init__(self, text=None, icon=None, icon_color=None, show_progress=False, p with Stylize(self.container, selector=lv.PART.SCROLLBAR) as scrollbar: scrollbar.pad(right=0) + if not passport.IS_COLOR: + scrollbar.bg_color(SCROLLBAR_BG_COLOR) self.update() diff --git a/ports/stm32/boards/Passport/modules/styles/colors.py b/ports/stm32/boards/Passport/modules/styles/colors.py index bbababdfd..e8ba83b9b 100644 --- a/ports/stm32/boards/Passport/modules/styles/colors.py +++ b/ports/stm32/boards/Passport/modules/styles/colors.py @@ -63,6 +63,7 @@ DIGIT_BORDER_COLOR_FOCUSED_HEX = FD_BLUE_HEX PIN_ENTRY_MESSAGE_COLOR_HEX = FD_BLUE_HEX BATTERY_FILL_COLOR_HEX = FD_BLUE_HEX + SCROLLBAR_BG_COLOR_HEX = BLACK_HEX else: # On monochrome, white is white, and everything else is black # Shades of grey @@ -121,6 +122,7 @@ DIGIT_BORDER_COLOR_UNFOCUSED_HEX = BLACK_HEX PIN_ENTRY_MESSAGE_COLOR_HEX = BLACK_HEX BATTERY_FILL_COLOR_HEX = BLACK_HEX + SCROLLBAR_BG_COLOR_HEX = BLACK_HEX WHITE = lv.color_hex(WHITE_HEX) VERY_LIGHT_GREY = lv.color_hex(VERY_LIGHT_GREY_HEX) @@ -176,6 +178,7 @@ DIGIT_BORDER_COLOR_UNFOCUSED = lv.color_hex(DIGIT_BORDER_COLOR_UNFOCUSED_HEX) PIN_ENTRY_MESSAGE_COLOR = lv.color_hex(PIN_ENTRY_MESSAGE_COLOR_HEX) BATTERY_FILL_COLOR = lv.color_hex(BATTERY_FILL_COLOR_HEX) +SCROLLBAR_BG_COLOR = lv.color_hex(SCROLLBAR_BG_COLOR_HEX) # Account Colors if passport.IS_SIMULATOR: From 88d28e0e70259f53ba6c0ed1cc5901867b27709f Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 2 Jun 2023 10:48:35 -0500 Subject: [PATCH 168/187] SFT-2064: improved inheritance structure of show_card_missing function --- ports/stm32/boards/Passport/manifest.py | 1 + .../boards/Passport/modules/flows/__init__.py | 1 + .../modules/flows/file_picker_flow.py | 20 +++++---- .../boards/Passport/modules/flows/flow.py | 21 --------- .../Passport/modules/flows/read_file_flow.py | 13 +++--- .../modules/flows/save_to_microsd_flow.py | 21 +++++---- .../modules/flows/sign_psbt_microsd_flow.py | 6 ++- .../modules/flows/sign_psbt_qr_flow.py | 6 ++- .../modules/flows/uses_microsd_flow.py | 45 +++++++++++++++++++ 9 files changed, 86 insertions(+), 48 deletions(-) create mode 100644 ports/stm32/boards/Passport/modules/flows/uses_microsd_flow.py diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index e77866987..22d49a288 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -151,6 +151,7 @@ 'flows/sign_text_file_flow.py', 'flows/terms_of_use_flow.py', 'flows/update_firmware_flow.py', + 'flows/uses_microsd_flow.py', 'flows/verify_address_flow.py', 'flows/verify_backup_flow.py', 'flows/view_backup_code_flow.py', diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index baddb7e4b..ab1748052 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -10,6 +10,7 @@ from .menu_flow import * from .main_flow import * from .login_flow import * +from .uses_microsd_flow import * from .save_to_microsd_flow import * from .scan_qr_flow import * from .backup_common_flow import * diff --git a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py index ea9756d16..82628a905 100644 --- a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py @@ -6,7 +6,7 @@ import lvgl as lv from animations.constants import TRANSITION_DIR_POP, TRANSITION_DIR_PUSH from files import CardMissingError, CardSlot -from flows import Flow, SelectedFileFlow +from flows import UsesMicroSDFlow, SelectedFileFlow from pages import FilePickerPage, StatusPage, InsertMicroSDPage from styles.colors import COPPER import microns @@ -19,17 +19,23 @@ def file_key(f): return '{}::{}'.format('0' if is_folder else '1', filename.lower()) -class FilePickerFlow(Flow): +class FilePickerFlow(UsesMicroSDFlow): def __init__( - self, initial_path=None, show_folders=False, enable_parent_nav=False, suffix=None, - filter_fn=None, select_text="Select"): + self, + initial_path=None, + show_folders=False, + enable_parent_nav=False, + suffix=None, + filter_fn=None, + select_text="Select"): from files import CardSlot if not initial_path: initial_path = CardSlot.get_sd_root() - super().__init__(initial_state=self.show_file_picker, name='FilePickerFlow: {}'.format( - initial_path)) + super().__init__(initial_state=self.show_file_picker, + name='FilePickerFlow: {}'.format(initial_path), + return_bool=False) self.initial_path = initial_path self.paths = [initial_path] self.show_folders = show_folders @@ -40,8 +46,6 @@ def __init__( self.status_page = None self.empty_result = None self.finished = False - # return_bool attribute required to use show_card_missing - self.return_bool = False def on_empty_sd_card_change(self, sd_card_present): if sd_card_present: diff --git a/ports/stm32/boards/Passport/modules/flows/flow.py b/ports/stm32/boards/Passport/modules/flows/flow.py index 676c8a315..88861b9ce 100644 --- a/ports/stm32/boards/Passport/modules/flows/flow.py +++ b/ports/stm32/boards/Passport/modules/flows/flow.py @@ -148,24 +148,3 @@ async def run(self): return self.result except Exception as e: handle_fatal_error(e) - - async def show_card_missing(self): - from pages import InsertMicroSDPage - - # This makes the return type consistent with the subclass - if hasattr(self, 'return_bool') and self.return_bool: - print("returning False") - result = False - else: - print("returning None") - result = None - - if hasattr(self, 'automatic') and self.automatic: - self.set_result(result) - return - - retry = await InsertMicroSDPage().show() - if not retry: - self.set_result(result) - else: - self.back() diff --git a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py index 822c6e013..fb4e5fdfc 100644 --- a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py @@ -3,18 +3,19 @@ # # read_file_flow.py - Read a file and handle errors -from flows import Flow +from flows import UsesMicroSDFlow -class ReadFileFlow(Flow): +class ReadFileFlow(UsesMicroSDFlow): def __init__(self, file_path, binary=True, automatic=False, read_fn=None): self.file_path = file_path self.binary = binary self.automatic = automatic self.read_fn = read_fn - # return_bool attribute required to use show_card_missing - self.return_bool = False - super().__init__(initial_state=self.read_file, name='ReadFileFlow') + super().__init__(initial_state=self.read_file, + name='ReadFileFlow', + automatic=automatic, + return_bool=False) async def read_file(self): from utils import spinner_task @@ -28,7 +29,7 @@ async def read_file(self): if error is Error.MICROSD_CARD_MISSING: # show_card_missing is a global flow state - self.goto(self.show_card_missing, self.automatic) + self.goto(self.show_card_missing) return if error is Error.FILE_READ_ERROR: diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index f3128683f..2ca348b43 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -3,10 +3,10 @@ # # save_to_microsd_flow.py - Save a file to the microSD card -from flows import Flow +from flows import UsesMicroSDFlow -class SaveToMicroSDFlow(Flow): +class SaveToMicroSDFlow(UsesMicroSDFlow): def __init__(self, filename, data=None, @@ -14,7 +14,8 @@ def __init__(self, success_text="file", path=None, mode='', - automatic=False): + automatic=False, + auto_prompt=None): import microns self.filename = filename.replace(' ', '_') @@ -24,12 +25,14 @@ def __init__(self, self.path = path self.mode = mode self.out_full = None - self.automatic = automatic - self.auto_timeout = 1000 if automatic else None - self.show_check = None if automatic else microns.Checkmark - # return_bool attribute required to use show_card_missing - self.return_bool = True - super().__init__(initial_state=self.check_inputs, name='SaveToMicroSDFlow') + # If auto_prompt isn't specified, use automatic value + auto_prompt = auto_prompt or automatic + self.auto_timeout = 1000 if auto_prompt else None + self.show_check = None if auto_prompt else microns.Checkmark + super().__init__(initial_state=self.check_inputs, + name='SaveToMicroSDFlow', + automatic=automatic, + return_bool=True) def default_write_fn(self, filename): with open(self.out_full, 'w' + self.mode) as fd: diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py index b8592772f..1076c585f 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_microsd_flow.py @@ -118,7 +118,8 @@ async def write_signed_transaction(self): write_fn=self.write_psbt_fn, success_text="psbt", path=orig_path, - automatic=True).run() + automatic=False, + auto_prompt=True).run() if not result_1: # Fall through await ErrorPage(text='Unable to save {} to microSD'.format(target_fname)).show() @@ -130,7 +131,8 @@ async def write_signed_transaction(self): write_fn=self.write_final_fn, success_text="transaction", path=orig_path, - automatic=True).run() + automatic=False, + auto_prompt=True).run() if not result_2: await ErrorPage(text='Unable to save {} to microSD'.format(target2_fname)).show() # Fall through diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 86164c8be..194e581af 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -199,7 +199,8 @@ async def save_to_microsd(self): write_fn=self.write_psbt_fn, success_text="psbt", path=get_folder_path(DIR_TRANSACTIONS), - automatic=True).run() + automatic=False, + auto_prompt=True).run() if not result_1: await ErrorPage(text='Unable to save {} to microSD'.format(target_fname)).show() self.back() @@ -211,7 +212,8 @@ async def save_to_microsd(self): write_fn=self.write_final_fn, success_text="transaction", path=get_folder_path(DIR_TRANSACTIONS), - automatic=True).run() + automatic=False, + auto_prompt=True).run() if not result_2: await ErrorPage(text='Unable to save {} to microSD'.format(target2_fname)).show() self.back() diff --git a/ports/stm32/boards/Passport/modules/flows/uses_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/uses_microsd_flow.py new file mode 100644 index 000000000..9c5f126a0 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/flows/uses_microsd_flow.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# uses_microsd_flow.py - Base class for all UI flows + +from flows import Flow + + +class UsesMicroSDFlow(Flow): + def __init__(self, + initial_state=None, + name='UsesMicroSDFlow', + settings_key=None, + statusbar=None, + automatic=False, + return_bool=True, + back_out=False): + + self.automatic = automatic + self.return_bool = return_bool + self.back_out = back_out + + super().__init__(initial_state=initial_state, + name=name, + settings_key=settings_key, + statusbar=statusbar) + + async def show_card_missing(self): + from pages import InsertMicroSDPage + + # This makes the return type consistent with the subclass + if self.return_bool: + result = False + else: + result = None + + if self.automatic: + self.set_result(result) + return + + retry = await InsertMicroSDPage().show() + if retry or self.back_out: + self.back() + else: + self.set_result(result) From bb3f5a51742e881c359c7626508330d57e98c149 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 6 Jun 2023 16:21:13 -0500 Subject: [PATCH 169/187] SFT-2064: used composition instead of inheritance --- ports/stm32/boards/Passport/manifest.py | 1 - .../boards/Passport/modules/flows/__init__.py | 1 - .../modules/flows/file_picker_flow.py | 15 ++++--- .../Passport/modules/flows/read_file_flow.py | 18 +++++--- .../modules/flows/save_to_microsd_flow.py | 18 +++++--- .../modules/flows/sign_psbt_qr_flow.py | 2 - .../modules/flows/uses_microsd_flow.py | 45 ------------------- ports/stm32/boards/Passport/modules/utils.py | 20 +++++++++ 8 files changed, 51 insertions(+), 69 deletions(-) delete mode 100644 ports/stm32/boards/Passport/modules/flows/uses_microsd_flow.py diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index 22d49a288..e77866987 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -151,7 +151,6 @@ 'flows/sign_text_file_flow.py', 'flows/terms_of_use_flow.py', 'flows/update_firmware_flow.py', - 'flows/uses_microsd_flow.py', 'flows/verify_address_flow.py', 'flows/verify_backup_flow.py', 'flows/view_backup_code_flow.py', diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index ab1748052..baddb7e4b 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -10,7 +10,6 @@ from .menu_flow import * from .main_flow import * from .login_flow import * -from .uses_microsd_flow import * from .save_to_microsd_flow import * from .scan_qr_flow import * from .backup_common_flow import * diff --git a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py index 82628a905..6a6a6da39 100644 --- a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py @@ -6,7 +6,7 @@ import lvgl as lv from animations.constants import TRANSITION_DIR_POP, TRANSITION_DIR_PUSH from files import CardMissingError, CardSlot -from flows import UsesMicroSDFlow, SelectedFileFlow +from flows import Flow, SelectedFileFlow from pages import FilePickerPage, StatusPage, InsertMicroSDPage from styles.colors import COPPER import microns @@ -19,7 +19,7 @@ def file_key(f): return '{}::{}'.format('0' if is_folder else '1', filename.lower()) -class FilePickerFlow(UsesMicroSDFlow): +class FilePickerFlow(Flow): def __init__( self, initial_path=None, @@ -34,8 +34,8 @@ def __init__( initial_path = CardSlot.get_sd_root() super().__init__(initial_state=self.show_file_picker, - name='FilePickerFlow: {}'.format(initial_path), - return_bool=False) + name='FilePickerFlow: {}'.format(initial_path)) + self.initial_path = initial_path self.paths = [initial_path] self.show_folders = show_folders @@ -53,7 +53,6 @@ def on_empty_sd_card_change(self, sd_card_present): else: self.reset_paths() self.status_page.set_result(None) - # show_card_missing is a global flow state self.goto(self.show_card_missing) return False @@ -68,7 +67,6 @@ def on_exception(self, exception): def on_file_sd_card_change(self, sd_card_present): if not sd_card_present: self.reset_paths() - # show_card_missing is a global flow state self.goto(self.show_card_missing) return True @@ -121,7 +119,6 @@ async def show_file_picker(self): except CardMissingError: self.reset_paths() - # show_card_missing is a global flow state self.goto(self.show_card_missing) return @@ -175,3 +172,7 @@ async def show_file_picker(self): def reset_paths(self): self.paths = [self.initial_path] + + async def show_card_missing(self): + from utils import flow_show_card_missing + await flow_show_card_missing(self) diff --git a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py index fb4e5fdfc..bee39fb41 100644 --- a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py @@ -3,19 +3,20 @@ # # read_file_flow.py - Read a file and handle errors -from flows import UsesMicroSDFlow +from flows import Flow -class ReadFileFlow(UsesMicroSDFlow): +class ReadFileFlow(Flow): def __init__(self, file_path, binary=True, automatic=False, read_fn=None): self.file_path = file_path self.binary = binary - self.automatic = automatic self.read_fn = read_fn + + # Used in flow_show_card_missing + self.automatic = automatic + super().__init__(initial_state=self.read_file, - name='ReadFileFlow', - automatic=automatic, - return_bool=False) + name='ReadFileFlow') async def read_file(self): from utils import spinner_task @@ -28,7 +29,6 @@ async def read_file(self): args=[self.file_path, self.binary, self.read_fn]) if error is Error.MICROSD_CARD_MISSING: - # show_card_missing is a global flow state self.goto(self.show_card_missing) return @@ -45,3 +45,7 @@ async def read_file(self): return self.set_result(data) + + async def show_card_missing(self): + from utils import flow_show_card_missing + await flow_show_card_missing(self) diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index 2ca348b43..7aeb0890b 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -3,10 +3,10 @@ # # save_to_microsd_flow.py - Save a file to the microSD card -from flows import UsesMicroSDFlow +from flows import Flow -class SaveToMicroSDFlow(UsesMicroSDFlow): +class SaveToMicroSDFlow(Flow): def __init__(self, filename, data=None, @@ -29,10 +29,13 @@ def __init__(self, auto_prompt = auto_prompt or automatic self.auto_timeout = 1000 if auto_prompt else None self.show_check = None if auto_prompt else microns.Checkmark + + # Used in flow_show_card_missing + self.automatic = automatic + self.return_bool = True + super().__init__(initial_state=self.check_inputs, - name='SaveToMicroSDFlow', - automatic=automatic, - return_bool=True) + name='SaveToMicroSDFlow') def default_write_fn(self, filename): with open(self.out_full, 'w' + self.mode) as fd: @@ -76,7 +79,6 @@ async def save(self): break except CardMissingError: - # show_card_missing is a global flow state self.goto(self.show_card_missing) return @@ -100,3 +102,7 @@ async def success(self): right_micron=self.show_check) \ .show(auto_close_timeout=self.auto_timeout) self.set_result(True) + + async def show_card_missing(self): + from utils import flow_show_card_missing + await flow_show_card_missing(self) diff --git a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py index 194e581af..0821fc0f5 100644 --- a/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/sign_psbt_qr_flow.py @@ -202,7 +202,6 @@ async def save_to_microsd(self): automatic=False, auto_prompt=True).run() if not result_1: - await ErrorPage(text='Unable to save {} to microSD'.format(target_fname)).show() self.back() return @@ -215,7 +214,6 @@ async def save_to_microsd(self): automatic=False, auto_prompt=True).run() if not result_2: - await ErrorPage(text='Unable to save {} to microSD'.format(target2_fname)).show() self.back() return diff --git a/ports/stm32/boards/Passport/modules/flows/uses_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/uses_microsd_flow.py deleted file mode 100644 index 9c5f126a0..000000000 --- a/ports/stm32/boards/Passport/modules/flows/uses_microsd_flow.py +++ /dev/null @@ -1,45 +0,0 @@ -# SPDX-FileCopyrightText: © 2023 Foundation Devices, Inc. -# SPDX-License-Identifier: GPL-3.0-or-later -# -# uses_microsd_flow.py - Base class for all UI flows - -from flows import Flow - - -class UsesMicroSDFlow(Flow): - def __init__(self, - initial_state=None, - name='UsesMicroSDFlow', - settings_key=None, - statusbar=None, - automatic=False, - return_bool=True, - back_out=False): - - self.automatic = automatic - self.return_bool = return_bool - self.back_out = back_out - - super().__init__(initial_state=initial_state, - name=name, - settings_key=settings_key, - statusbar=statusbar) - - async def show_card_missing(self): - from pages import InsertMicroSDPage - - # This makes the return type consistent with the subclass - if self.return_bool: - result = False - else: - result = None - - if self.automatic: - self.set_result(result) - return - - retry = await InsertMicroSDPage().show() - if retry or self.back_out: - self.back() - else: - self.set_result(result) diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index a6d777486..3c2d0906b 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1374,4 +1374,24 @@ def timestamp_to_str(time): ) +async def flow_show_card_missing(flow): + from pages import InsertMicroSDPage + + # This makes the return type consistent with the caller + if hasattr(flow, "return_bool") and flow.return_bool: + result = False + else: + result = None + + if hasattr(flow, "automatic") and flow.automatic: + flow.set_result(result) + return + + retry = await InsertMicroSDPage().show() + if retry: + flow.back() + else: + flow.set_result(result) + + # EOF From 71619ea7e741e8ebe3b86ab2ce344d0b8fd20c38 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 9 Jun 2023 17:14:58 -0500 Subject: [PATCH 170/187] SFT-2064: used suggested bind function --- .../boards/Passport/modules/flows/file_picker_flow.py | 7 +++---- .../boards/Passport/modules/flows/read_file_flow.py | 8 ++++---- .../Passport/modules/flows/save_to_microsd_flow.py | 7 +++---- ports/stm32/boards/Passport/modules/utils.py | 11 ++++++++++- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py index 6a6a6da39..44f04f2e7 100644 --- a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py @@ -29,6 +29,7 @@ def __init__( filter_fn=None, select_text="Select"): from files import CardSlot + from utils import bind, show_card_missing if not initial_path: initial_path = CardSlot.get_sd_root() @@ -47,6 +48,8 @@ def __init__( self.empty_result = None self.finished = False + bind(self, show_card_missing) + def on_empty_sd_card_change(self, sd_card_present): if sd_card_present: return True # This will cause a refresh @@ -172,7 +175,3 @@ async def show_file_picker(self): def reset_paths(self): self.paths = [self.initial_path] - - async def show_card_missing(self): - from utils import flow_show_card_missing - await flow_show_card_missing(self) diff --git a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py index bee39fb41..818e57b57 100644 --- a/ports/stm32/boards/Passport/modules/flows/read_file_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/read_file_flow.py @@ -8,6 +8,8 @@ class ReadFileFlow(Flow): def __init__(self, file_path, binary=True, automatic=False, read_fn=None): + from utils import bind, show_card_missing + self.file_path = file_path self.binary = binary self.read_fn = read_fn @@ -15,6 +17,8 @@ def __init__(self, file_path, binary=True, automatic=False, read_fn=None): # Used in flow_show_card_missing self.automatic = automatic + bind(self, show_card_missing) + super().__init__(initial_state=self.read_file, name='ReadFileFlow') @@ -45,7 +49,3 @@ async def read_file(self): return self.set_result(data) - - async def show_card_missing(self): - from utils import flow_show_card_missing - await flow_show_card_missing(self) diff --git a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py index 7aeb0890b..524ee72e1 100644 --- a/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/save_to_microsd_flow.py @@ -17,6 +17,7 @@ def __init__(self, automatic=False, auto_prompt=None): import microns + from utils import bind, show_card_missing self.filename = filename.replace(' ', '_') self.data = data @@ -34,6 +35,8 @@ def __init__(self, self.automatic = automatic self.return_bool = True + bind(self, show_card_missing) + super().__init__(initial_state=self.check_inputs, name='SaveToMicroSDFlow') @@ -102,7 +105,3 @@ async def success(self): right_micron=self.show_check) \ .show(auto_close_timeout=self.auto_timeout) self.set_result(True) - - async def show_card_missing(self): - from utils import flow_show_card_missing - await flow_show_card_missing(self) diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index 3c2d0906b..270c07bd1 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1374,7 +1374,8 @@ def timestamp_to_str(time): ) -async def flow_show_card_missing(flow): +# This is a flow function, so it needs to be async +async def show_card_missing(flow): from pages import InsertMicroSDPage # This makes the return type consistent with the caller @@ -1394,4 +1395,12 @@ async def flow_show_card_missing(flow): flow.set_result(result) +def bind_function(instance, func, as_name=None): + if as_name is None: + as_name = func.__name__ + bound_method = func.__get__(instance, instance.__class__) + setattr(instance, as_name, bound_method) + return bound_method + + # EOF From 100ecbdf90ffcae51832ae4de18424078f9e9b53 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 9 Jun 2023 17:41:01 -0500 Subject: [PATCH 171/187] SFT-2064: fixed function name --- ports/stm32/boards/Passport/modules/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index 270c07bd1..6144fd2bb 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1395,7 +1395,7 @@ async def show_card_missing(flow): flow.set_result(result) -def bind_function(instance, func, as_name=None): +def bind(instance, func, as_name=None): if as_name is None: as_name = func.__name__ bound_method = func.__get__(instance, instance.__class__) From 53d9de4a408d8160e6318d68b297154be9a76f72 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 9 Jun 2023 17:57:14 -0500 Subject: [PATCH 172/187] SFT-2064: fixed bind function to account for async functions --- ports/stm32/boards/Passport/modules/utils.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index 6144fd2bb..f8057983d 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1395,12 +1395,16 @@ async def show_card_missing(flow): flow.set_result(result) +# This assums the func passed in is async def bind(instance, func, as_name=None): if as_name is None: as_name = func.__name__ - bound_method = func.__get__(instance, instance.__class__) - setattr(instance, as_name, bound_method) - return bound_method + + async def method(*args, **kwargs): + return await func(instance, *args, **kwargs) + + setattr(instance, as_name, method) + return method # EOF From 0f85ea6fa07349d49634daf60c219249efc53892 Mon Sep 17 00:00:00 2001 From: Ken Carpenter <62639971+FoundationKen@users.noreply.github.com> Date: Fri, 9 Jun 2023 16:17:00 -0700 Subject: [PATCH 173/187] Update utils.py --- ports/stm32/boards/Passport/modules/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index f8057983d..8dedb79a3 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1395,7 +1395,7 @@ async def show_card_missing(flow): flow.set_result(result) -# This assums the func passed in is async +# This assumes the function passed in is async def bind(instance, func, as_name=None): if as_name is None: as_name = func.__name__ From 1770a87e61c818b14ae05767322f8cd20c44f7a3 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Sun, 11 Jun 2023 08:01:09 -0500 Subject: [PATCH 174/187] SFT-2276: moved nip26 to developer build --- ports/stm32/boards/Passport/manifest.py | 1 - ports/stm32/boards/Passport/manifest_dev.py | 1 + ports/stm32/boards/Passport/modules/developer/__init__.py | 7 ++++--- .../modules/{flows => developer}/nostr_delegation_flow.py | 0 ports/stm32/boards/Passport/modules/flows/__init__.py | 1 - ports/stm32/boards/Passport/modules/menus.py | 7 +++++-- 6 files changed, 10 insertions(+), 7 deletions(-) rename ports/stm32/boards/Passport/modules/{flows => developer}/nostr_delegation_flow.py (100%) diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index e77866987..ba65a05bb 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -126,7 +126,6 @@ 'flows/new_account_flow.py', 'flows/new_derived_key_flow.py', 'flows/new_seed_flow.py', - 'flows/nostr_delegation_flow.py', 'flows/connect_wallet_flow.py', 'flows/page_flow.py', 'flows/read_file_flow.py', diff --git a/ports/stm32/boards/Passport/manifest_dev.py b/ports/stm32/boards/Passport/manifest_dev.py index 1a6d2a2df..484515427 100644 --- a/ports/stm32/boards/Passport/manifest_dev.py +++ b/ports/stm32/boards/Passport/manifest_dev.py @@ -11,6 +11,7 @@ 'developer/developer_functions_flow.py', 'developer/fcc_test_flow.py', 'developer/fcc_copy_files_task.py', + 'developer/nostr_delegation_flow.py', 'developer/spin_delay_flow.py', )) diff --git a/ports/stm32/boards/Passport/modules/developer/__init__.py b/ports/stm32/boards/Passport/modules/developer/__init__.py index ccb34af3f..8434e6ffc 100644 --- a/ports/stm32/boards/Passport/modules/developer/__init__.py +++ b/ports/stm32/boards/Passport/modules/developer/__init__.py @@ -3,9 +3,10 @@ # # __init__.py +from .battery_page import * +from .delete_derived_keys_flow import * from .developer_functions_flow import * -from .fcc_test_flow import * from .fcc_copy_files_task import * +from .fcc_test_flow import * +from .nostr_delegation_flow import * from .spin_delay_flow import * -from .delete_derived_keys_flow import * -from .battery_page import * diff --git a/ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py b/ports/stm32/boards/Passport/modules/developer/nostr_delegation_flow.py similarity index 100% rename from ports/stm32/boards/Passport/modules/flows/nostr_delegation_flow.py rename to ports/stm32/boards/Passport/modules/developer/nostr_delegation_flow.py diff --git a/ports/stm32/boards/Passport/modules/flows/__init__.py b/ports/stm32/boards/Passport/modules/flows/__init__.py index baddb7e4b..72719015f 100644 --- a/ports/stm32/boards/Passport/modules/flows/__init__.py +++ b/ports/stm32/boards/Passport/modules/flows/__init__.py @@ -51,7 +51,6 @@ from .new_account_flow import * from .new_derived_key_flow import * from .new_seed_flow import * -from .nostr_delegation_flow import * from .connect_wallet_flow import * from .read_file_flow import * from .remove_dev_pubkey_flow import * diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 0b19983e7..6b6ecfa00 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -179,9 +179,12 @@ def manage_keys(): def nostr_menu(): - from flows import NostrDelegationFlow + from utils import is_dev_build - return [{'icon': lv.ICON_SIGN, 'label': 'Delegate', 'flow': NostrDelegationFlow}] + if is_dev_build(): + from developer import NostrDelegationFlow + return [{'icon': lv.ICON_SIGN, 'label': 'Delegate', 'flow': NostrDelegationFlow}] + return [] def key_manager_menu(): From 52a4cf42dfe63f2043612ef7092fb99d479b3753 Mon Sep 17 00:00:00 2001 From: Jean-Pierre De Jesus DIAZ Date: Thu, 15 Jun 2023 13:14:50 +0200 Subject: [PATCH 175/187] SFT-2306: Update bootloader build instructions Signed-off-by: Jean-Pierre De Jesus DIAZ --- DEVELOPMENT.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index ddc24c215..4fe04e22f 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -154,5 +154,10 @@ To build the bootloader for a reproducibility check, go to the repo root folder: Then run one of the following commands to build the corresponding bootloader: - just build color - just build mono + just build-bootloader color + just build-bootloader mono + +Please note that building the mono bootloader is not yet supported on this +repository, if you need to build it please follow the instruction on: + +https://github.com/Foundation-Devices/passport-firmware From bb9b7a4172a4699da8e12a043c33e92e182a8e7f Mon Sep 17 00:00:00 2001 From: Ken Carpenter <62639971+FoundationKen@users.noreply.github.com> Date: Thu, 15 Jun 2023 07:58:18 -0700 Subject: [PATCH 176/187] Update DEVELOPMENT.md Improve message --- DEVELOPMENT.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 4fe04e22f..46dffd4f3 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -157,7 +157,6 @@ Then run one of the following commands to build the corresponding bootloader: just build-bootloader color just build-bootloader mono -Please note that building the mono bootloader is not yet supported on this -repository, if you need to build it please follow the instruction on: +Please note that building the mono bootloader is not yet supported in this repository. If you need to build it, please follow the instructions at: https://github.com/Foundation-Devices/passport-firmware From 04cf86e86ac35d8e490af27156c93a8707e5bc93 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 25 May 2023 17:33:14 -0500 Subject: [PATCH 177/187] SFT-1071: added black background image files --- ...N_ADD_ACCOUNT_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 186 bytes ...ICON_ADVANCED_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 190 bytes .../ICON_BACKUP_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 176 bytes .../ICON_BACK_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 201 bytes .../ICON_BATTERY_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 173 bytes .../ICON_BITCOIN_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 203 bytes ...ON_BRIGHTNESS_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 206 bytes .../ICON_CANCEL_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 221 bytes .../ICON_CASA_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 149 bytes ...CON_CHECKMARK_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 206 bytes ..._CIRCLE_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 206 bytes .../ICON_CLOCK_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 193 bytes .../ICON_CONNECT_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 218 bytes ...CON_COUNTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 202 bytes .../ICON_DEVICE_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 166 bytes .../ICON_EDIT1_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 223 bytes .../ICON_EDIT2_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 184 bytes .../ICON_ERASE_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 184 bytes ...ON_EXTENSIONS_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 185 bytes .../ICON_FILE_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 164 bytes ...ICON_FIRMWARE_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 190 bytes .../ICON_FOLDER_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 186 bytes .../ICON_FORWARD_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 199 bytes ...CON_HAMBURGER_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 150 bytes ..._HEALTH_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 200 bytes .../ICON_HOME_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 175 bytes .../ICON_INFO_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 193 bytes .../ICON_MICROSD_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 171 bytes .../ICON_NETWORK_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 224 bytes .../ICON_NOSTR_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 228 bytes .../ICON_ONE_KEY_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 212 bytes ...ON_PASSPHRASE_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 184 bytes .../ICON_PIN_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 180 bytes .../ICON_RETRY_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 237 bytes .../ICON_SCAN_QR_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 204 bytes .../ICON_SEED_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 195 bytes ...ICON_SETTINGS_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 195 bytes .../ICON_SETUP_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 213 bytes .../ICON_SHIELD_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 184 bytes ...ICON_SHUTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 195 bytes .../ICON_SIGN_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 216 bytes .../ICON_SPIRAL_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 205 bytes ...ICON_TWO_KEYS_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 213 bytes ...ERIFY_ADDRESS_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 185 bytes .../ICON_WARNING_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 0 -> 197 bytes 45 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_NOSTR_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND__CF_INDEXED_1_BIT.png create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_WARNING_BACKGROUND__CF_INDEXED_1_BIT.png diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..0fc5595307180d3f1b1817b3a369f364741ee7d1 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzQ3o7V@L(#+pCs*3`Yr` z@UT2;k49_PpJ{yA(|>>2^0P^=ka@vnACIrv3;bl19p~SOEO@X*Qaq;M;Ov0+g+_w* c9!@Jw_xN(i&j{N68)!6xr>mdKI;Vst08B1Ae*gdg literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..370ce8c059d37db0a2631f0d14ab230f26bf25b8 GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBez2#DV@L(#+bND*3``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzN@E;V@L(#+pC6r3<@017a#q7-!q#tt4Hze zwfzS_xG}gKHB+xTntjoAeZ_PWX;nPrl4#?VHv1#}`GWZ5ud}$ca+%UJ*p&(n SC(Z&I$l&Sf=d#Wzp$Py3gf$ER literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..3ad9f03a187438beede02cd57624e6728389e631 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBew?R^V@L(#)hnJt3<5kZ7YqJd2lF-j^KA9X z|0rfOBh=e?-a?7HNiWP;rUf!7m$?3X{IIgVIrhcd3%&F7S}us*$}74b9N~AX!A3t$ r;=h?fUW~3>-1;Tj0`triz8W!lP2-h`U9Hvww28sf)z4*}Q$iB}hw466 literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..1332b7a7967e12cf033e3d04384654bfff4fd56f GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzLTemV@L(#+bf1#3<^BV2SWb*pDsFG>BY5_ zfTG~tDI8lGRvtCuzj7pZWt-eXUZqV5Wuh literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..eb46d6be38ded05442c10a27052121a98ad98ed7 GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBeuAfqV@L(#*(=^$3p9+3^1b%in6av!TP5h~tu&xr44$rjF6*2UngIJaKl=ax literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..2535e7c14d6382f60344d939e6b7ede898a8eb31 GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBezK>FV@L(#)v4Zm42m4iFH_#tr>0v6USxXN z^zO%x90NAvi4Na-U+g^YQnlRT)tR^ZE#*$$di3IkPe)nI{)fxgWbbffli#;{an^LB{Ts5!puoa literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..3b0d05cd10455bc1cd353e91e28055a438aba180 GIT binary patch literal 221 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBevzk(V@L(#)v4Zm4GKIilJD!&?`F09ymF-_ z((!gBXFx*F-Im)wR4kXRe9yrX$jcnO_=M*NE`{*s0}Tt(svOSU3wn|LiIGoI<3J)i z^N&mKOI$to=ewSMxOGePY1WNAd226=8YJ^;8gyB5mC03oH@@K@Zhlo%YK!3O1fcB< Mp00i_>zopr0MOk@ZU6uP literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..46e8c7db6715b08bdc8839a2eefde326e5666c6f GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzLuwpV@L(#+cOIV85lSYADH&Hob52j7ru!z mc1(Awyua)0(trbCa9-+Z9HWL3pGgQ%7lWs(pUXO@geCye{wk{g literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..30901e39467d993da196a44a187980b8cda329bb GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBezK>FV@L(#+ewCe2NZaih5!9e55KDwB4jO? z^w2Hmu0u}Q&E9DFKbGxZ4`{vU5Nr)K+~oAM|KN|Bz;AtDQaPBSq&m|ls{FNEc06E7 x@q$yaoRK@jxn|CpwZclf>U-eCyWgG)@TdP3``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBezK>FV@L(#+bbKn4k+-jT!{Jif4=V90Itx* zAM*tEIEs8sop8iQgyp;HZ#hqc5(kIX(-X*N9QI{9?_VP4YE79+=KOa xjhoAVrfl8%@wPyL2|xFb3k&9JI{g1)AkK7$Tk#6>HW#3E44$rjF6*2UngAkYL74ym literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..bc88391a35d7a376710580bb989823feb558ba95 GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBewe3=V@L(#+bf2A3`GQMU7IeMr{!AT+0ZNO7xDc5>DQc^3&U%o kXUF|n@gm=D!?T~6x>nqBC(QJFfHp9Ay85}Sb4q9e0M5`oyZ`_I literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..486b1e8ecc56a517b291e6ed33c0d7a2c39d1c78 GIT binary patch literal 218 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBe!i!RV@L(#)vFJ=8WaSWA879TuPy%7dC#U@ z7u~k(KgG^|kHtsx!6t>5h988b&gjf>wT?^d;>|NpfAd4}YGd5N^%o^|9Q!x$+zsM+ zk+*7obi9SC%(e*D`Kufm{eLfW?CAX&&)KUS=z1>BtKN2gDyzpUZuQvto?bw!89ZJ6 KT-G@yGywqJ07qK@ literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..43620376931152aee88e4f8280fbf1ba89b387e9 GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBe!QoPV@L(#+o_Ix3<5kXyC40JSCeru;l1?q zie+GrZAX_4Q~U2zZ!6c|_@eSKAg*(&O*D7hj817~nQKg(8-)3tWRlMQsoZd{sJzbe s&WB}fQUXs5)cGv8wVvkovli&*dfUJwUsE{e3D7DAPgg&ebxsLQ0H+5(D*ylh literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..2dd9b6f3594bc25313c0961e83d60af0b0b0ee75 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzO|=|V@L(#+bbJ+85DS!51Rje&%@0i#N{dY zGuk^`YSN|D*(^M)7Z)$)e{oGpCH2OJ#KX1^FDYB>EE}B*4p@z;ppfL=du6{1- HoD!M``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBeu<}xV@L(#)~g5k8Web#FFgGJ-tb0>ZJEN-7=$5Eo zNyLr|>)Tjs&2wKAAMV;_pwI6XDlto6hlgL6ZJC-P*X3gA#_)am^?piU`4s;zZFmf{ OpTX1B&t;ucLK6T)Z$`iX literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..d7b83e8c5f57209c76145aac4896faac861a3124 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzOSc?V@L(#+o_g(3``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzOSc?V@L(#+bh~k3tc3mz=1KJ#b+_bH~= bF?D<_xm@x;=G<8WG?>BD)z4*}Q$iB}5bZn~ literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..d3679ff0f24924c204257c93631eb2ea71a5e84b GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzMrRyV@L(#+sTG}3wQA3Ji;!qfCh zXY|G92}~UZk9zn2={+KM``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzNM#&V@L(#+bau285DS!FLM8W&%+$x9(C~a z$qs#H-<3Da*xcE+Y)Ns_&%YS*;6Nkuf6jiHzubDutggwks%$NKt^hQI!PC{xWt~$( F69DhCEvNth literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..ab4a1e74b4171c44b9fdc7c7d6af1a1ef9b10564 GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBez2#DV@L(#+o|4M3zs z!R=ia#Aht>FmX6$njJUMeMv``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzQ3o7V@L(#+pCs*3`Yr` z@UT2;k49_PpJ{yA(|>>2^0P^=ka@vnACIrv3;bl19p~SOEO@X*Qaq;M;Ov0+g+_w* c9!@Jw_xN(i&j{N68)!6xr>mdKI;Vst08B1Ae*gdg literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..4ac7dcc3326943b1894788c32d17fc401b0648c0 GIT binary patch literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBevGG!V@L(#)yal@3<^9``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzP6`}V@L(#+cOJ!85lT@9BBVr-o|p2p{D7@ q%2i$k-B*`NfA*PakalK{uKbLh*2~7aS5GcO@ literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..2e8a484dc70407b5782ecf5608a2ea585309da28 GIT binary patch literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBeypd9V@L(#+bI|M7z8+6cmMl8zcR_#%acF% zobb}aJsq1E)#6&W2KDj2>C#D%w3*;{&dJf^`?F7NbANQRSI&=CfAYNYX@WZ6&yAdS rPb}n``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzKf@eV@L(#+cTCz3<@01fsg*a@7em8NsGs~ zPP#(L^I+j({rzHVj`h7h*eJ(avnZOK@x>)40jo+57xvAbK`orZYB5pli+-{z9pReX Q1T>Gq)78&qol`;+017EE#sB~S literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..a8914d40067e96d95b09a0b822e68c81cddf2de2 GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBewe3=V@L(#+pE@G3<^BV7moeD9~l@RU@zj! zzEo0n-prsAR)Hmr-vYVwbSGRm$SnBQXTrrcc0;ecGkMWT*KQ=X*Eih1(V!Z literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..ce36d48cf621f508dd85489bab030f58a93b9f35 GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzJsTWV@L(#+pCIv3<^BX7pMKcFKHs_sPi^t z|D1{``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBeyOL6V@L(#-Ya*x4k&Q2CQRM?U)%bI!i1%k z)@AFQK4||^&f*HTm5L0Fm}^zf#&Bgu{X``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBex;|2V@L(#*{R-q2NXD18!P^6U*591j>E=b z(m6lo#g2i?Y<@{?7ESR}JG#t2qr>pyBHJ3TsGEi*dM_So3VbebUFy)HW~BJ_i0;di zw={Qu{>}Czopr0Hw}MfdBvi literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..8ee3e462ee0594d9d8f7748726f6ae5fe235c21e GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBex|33V@L(#+bP~$4F)_e>X&}US1xH%xM3C_ z+mU~><+wl_6Tjk#!xM|0`OdLP8ipTUG2@oglVhv4RPXK7y~NyqL+9<5H3@AY+<{jf zFZ`nQZJFrXwTkC9t-8AW$I)^nTeH9V>s9O)CVzK+)2YIvY_y`08)zwmr>mdKI;Vst E0F&5BKmY&$ literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..383fb23ef40c647cbae931ece4ba03c2a6e11960 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzOSc?V@L(#+bh~k3tc3mz=1KJ#b+_bH~= bF?D<_xm@x;=G<8WG?>BD)z4*}Q$iB}5bZn~ literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..a616cc03a2684ed9c4a18a27aa5e1e8eaf8032ce GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzNe>)V@L(#+bf1#3aWYp7PCM9$RYfX@o*ihj`XkX W>`F%t)tvwu%HZkh=d#Wzp$PzdVK#RF literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..f25ae243a944649df7ba133160f370f048aee325 GIT binary patch literal 237 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBev_w*V@L(#)yW5i8WcEO4u1S!e^ZVBY=(i3 zw`|RJmbjfOyUq&moD~Up`7YvFRN$*~8CMP@``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBexj#~V@L(#+sWQs42nF?!83oy?_}0vv2PW* zG&ODck#sK20F~%-eif4ZQklzw!tJ>eIlWP;b425shfUzvsGb7{nJAI}9^#^CAd=d#Wzp$PyK5j)HP literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..561df6bb0fc623e0cd0e25974e71a824c91756ff GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBeuSrsV@L(#+pFe$3<^BV2WI^LFPY|2dP}6A zQP#DogN60TopTbtIWG+N8_d0H_~Pzc9gBtC?CvE-hu`gZ&?NkD%JlT3>+4&^j&ELY m;A5;x!3E}i))~{D&1T$rn_DjX{2vXV9SokXelF{r5}E*rEkKt5 literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..1435487e2bbd6d7b798ff5a55cf9459e9b818c8b GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBeuSrsV@L(#+bf2A3``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBewL?;V@L(#+ewB(2NXD1EdT#c4^lOj^nGw) za}hW9R96;bL5VjzKN`xOtypv``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzOSc?V@L(#+bh~k3tc3mz=1KJ#b+_bH~= bF?D<_xm@x;=G<8WG?>BD)z4*}Q$iB}5bZn~ literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..c822c5dc9817714e23fd2db74dc48dd6049b2e3f GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBeuSrsV@L(#+pE@m3``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBey*pBV@L(#)vLF;7!)~J0`C6*|9o1U*fyiN zfgR7*a7x}}dhW9#kXN5j^fVB3`*p7yQhtW5h&{)db9{OIA8R=Xl4544!U)78&q Iol`;+0QY1^?*IS* literal 0 HcmV?d00001 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND__CF_INDEXED_1_BIT.png new file mode 100644 index 0000000000000000000000000000000000000000..45399af3b6036de983f27aac95f8631c7ceab8d5 GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBev+q)V@L(#+o_IR2NZZ%HvjxTKRRkfNRh#- zbqW^h7Y)`3Et<)p@_Jp0?4hI}i6;u)-FH|oiHCd0J4_RsKf9wo>6CDdU*sd@Yu(@9 vCcE*6Z%``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBewL?;V@L(#(JPL84GKIi7gv7#7rxGL;?!$r z9Mu2J<(|hYz!1#1H>HO;J7Xr(``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzMrRyV@L(#+o_IR3``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBew3$+V@L(#)k~IK3<^9h7hn8+za~MkW7b)p z11rxy7Zqv@oAQ3vSHG$Yd%jO~czk5iwA>}#TW@8nhvr??~MB)Gd literal 0 HcmV?d00001 From 848f5c5d6669b6aea24882565acb2f3a61535891 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 2 Jun 2023 11:30:19 -0500 Subject: [PATCH 178/187] SFT-1071: added c files for black backgrounds --- .../images/mono/ICON_ADD_ACCOUNT_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_ADVANCED_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_BACKUP_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_BACK_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_BATTERY_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_BITCOIN_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_BRIGHTNESS_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_CANCEL_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_CASA_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_CHECKMARK_BACKGROUND.c | 56 +++++++++++++++++++ .../mono/ICON_CIRCLE_CHECK_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_CLOCK_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_CONNECT_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_COUNTDOWN_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_DEVICE_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_EDIT1_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_EDIT2_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_ERASE_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_EXTENSIONS_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_FILE_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_FIRMWARE_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_FOLDER_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_FORWARD_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_HAMBURGER_BACKGROUND.c | 56 +++++++++++++++++++ .../mono/ICON_HEALTH_CHECK_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_HOME_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_INFO_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_MICROSD_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_NETWORK_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_NOSTR_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_ONE_KEY_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_PASSPHRASE_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_PIN_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_RETRY_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_SCAN_QR_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_SEED_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_SETTINGS_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_SETUP_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_SHIELD_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_SHUTDOWN_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_SIGN_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_SPIRAL_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_TWO_KEYS_BACKGROUND.c | 56 +++++++++++++++++++ .../mono/ICON_VERIFY_ADDRESS_BACKGROUND.c | 56 +++++++++++++++++++ .../images/mono/ICON_WARNING_BACKGROUND.c | 56 +++++++++++++++++++ 45 files changed, 2520 insertions(+) create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_NOSTR_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND.c create mode 100644 ports/stm32/boards/Passport/images/mono/ICON_WARNING_BACKGROUND.c diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND.c new file mode 100644 index 000000000..d7cd4dd87 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_ADD_ACCOUNT_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_ADD_ACCOUNT_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_ADD_ACCOUNT_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_ADD_ACCOUNT_BACKGROUND uint8_t ICON_ADD_ACCOUNT_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x1f, 0xff, 0x00, + 0x3f, 0xff, 0x80, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_ADD_ACCOUNT_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_ADD_ACCOUNT_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND.c new file mode 100644 index 000000000..37baac2de --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_ADVANCED_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_ADVANCED_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_ADVANCED_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_ADVANCED_BACKGROUND uint8_t ICON_ADVANCED_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x01, 0xfe, 0x00, + 0x01, 0xfe, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x0f, 0xff, 0xc0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_ADVANCED_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_ADVANCED_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND.c new file mode 100644 index 000000000..0fb96beb6 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_BACKUP_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_BACKUP_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_BACKUP_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_BACKUP_BACKGROUND uint8_t ICON_BACKUP_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x1f, 0xff, 0x80, + 0x3f, 0xff, 0xc0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_BACKUP_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_BACKUP_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND.c new file mode 100644 index 000000000..64692ce4a --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_BACK_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_BACK_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_BACK_BACKGROUND uint8_t ICON_BACK_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x00, + 0x00, 0x1f, 0x00, + 0x00, 0x3f, 0x00, + 0x00, 0x7f, 0x00, + 0x00, 0xfe, 0x00, + 0x01, 0xfc, 0x00, + 0x03, 0xf8, 0x00, + 0x07, 0xf0, 0x00, + 0x07, 0xe0, 0x00, + 0x07, 0xe0, 0x00, + 0x07, 0xf0, 0x00, + 0x03, 0xf8, 0x00, + 0x01, 0xfc, 0x00, + 0x00, 0xfe, 0x00, + 0x00, 0x7f, 0x00, + 0x00, 0x3f, 0x00, + 0x00, 0x1f, 0x00, + 0x00, 0x0f, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_BACK_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_BACK_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND.c new file mode 100644 index 000000000..b821e678e --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_BATTERY_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_BATTERY_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_BATTERY_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_BATTERY_BACKGROUND uint8_t ICON_BATTERY_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x3f, 0xff, 0xc0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xe0, + 0x3f, 0xff, 0xc0, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_BATTERY_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_BATTERY_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND.c new file mode 100644 index 000000000..c6636ac7f --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_BITCOIN_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_BITCOIN_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_BITCOIN_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_BITCOIN_BACKGROUND uint8_t ICON_BITCOIN_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x7c, 0x00, + 0x00, 0xff, 0x00, + 0x0f, 0xff, 0x00, + 0x0f, 0xff, 0x00, + 0x0f, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x03, 0xff, 0xc0, + 0x03, 0xff, 0xc0, + 0x07, 0xff, 0xc0, + 0x07, 0xff, 0xc0, + 0x07, 0xff, 0xc0, + 0x07, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xc0, + 0x1f, 0xff, 0xc0, + 0x1f, 0xff, 0xc0, + 0x0f, 0xff, 0x80, + 0x0f, 0xff, 0x00, + 0x0f, 0xf0, 0x00, + 0x01, 0xe0, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_BITCOIN_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_BITCOIN_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND.c new file mode 100644 index 000000000..d78539ecd --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_BRIGHTNESS_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_BRIGHTNESS_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_BRIGHTNESS_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_BRIGHTNESS_BACKGROUND uint8_t ICON_BRIGHTNESS_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x1e, 0x79, 0xe0, + 0x1f, 0x7b, 0xe0, + 0x1f, 0xff, 0xe0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x1f, 0xff, 0xe0, + 0x1f, 0x7b, 0xe0, + 0x1e, 0x79, 0xe0, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_BRIGHTNESS_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_BRIGHTNESS_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND.c new file mode 100644 index 000000000..ab2e5efc4 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_CANCEL_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_CANCEL_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CANCEL_BACKGROUND uint8_t ICON_CANCEL_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x3c, 0x00, 0xf0, + 0x3e, 0x01, 0xf0, + 0x3f, 0x03, 0xf0, + 0x3f, 0x87, 0xf0, + 0x1f, 0xcf, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x01, 0xfe, 0x00, + 0x03, 0xff, 0x00, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x1f, 0xcf, 0xe0, + 0x3f, 0x87, 0xf0, + 0x3f, 0x03, 0xf0, + 0x3e, 0x01, 0xf0, + 0x3c, 0x00, 0xf0, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_CANCEL_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_CANCEL_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND.c new file mode 100644 index 000000000..43100c124 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_CASA_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_CASA_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CASA_BACKGROUND uint8_t ICON_CASA_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_CASA_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_CASA_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND.c new file mode 100644 index 000000000..944f9ea82 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_CHECKMARK_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_CHECKMARK_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CHECKMARK_BACKGROUND uint8_t ICON_CHECKMARK_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, + 0x00, 0x01, 0xf0, + 0x00, 0x03, 0xf0, + 0x00, 0x07, 0xf0, + 0x00, 0x0f, 0xe0, + 0x78, 0x1f, 0xc0, + 0x7c, 0x3f, 0x80, + 0x7e, 0x7f, 0x00, + 0x7f, 0xfe, 0x00, + 0x3f, 0xfc, 0x00, + 0x1f, 0xf8, 0x00, + 0x0f, 0xf0, 0x00, + 0x07, 0xe0, 0x00, + 0x03, 0xc0, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_CHECKMARK_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_CHECKMARK_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND.c new file mode 100644 index 000000000..652f67e0e --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_CIRCLE_CHECK_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_CIRCLE_CHECK_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_CIRCLE_CHECK_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CIRCLE_CHECK_BACKGROUND uint8_t ICON_CIRCLE_CHECK_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x01, 0xfe, 0x00, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xc0, + 0x3f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x01, 0xfe, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_CIRCLE_CHECK_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_CIRCLE_CHECK_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND.c new file mode 100644 index 000000000..5de1377c5 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_CLOCK_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_CLOCK_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_CLOCK_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CLOCK_BACKGROUND uint8_t ICON_CLOCK_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x01, 0xfe, 0x00, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x01, 0xfe, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_CLOCK_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_CLOCK_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND.c new file mode 100644 index 000000000..9e71c0e14 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_CONNECT_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_CONNECT_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_CONNECT_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CONNECT_BACKGROUND uint8_t ICON_CONNECT_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x1f, 0xe0, + 0x00, 0x3f, 0xf0, + 0x00, 0x7f, 0xf8, + 0x00, 0x7f, 0xf8, + 0x00, 0x7f, 0xf8, + 0x03, 0xff, 0xf8, + 0x07, 0xff, 0xf8, + 0x0f, 0xff, 0xf8, + 0x1f, 0xff, 0xf8, + 0x3f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xc0, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x3f, 0xf0, 0x00, + 0x1f, 0xe0, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_CONNECT_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_CONNECT_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND.c new file mode 100644 index 000000000..30ed3ccb8 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_COUNTDOWN_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_COUNTDOWN_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_COUNTDOWN_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_COUNTDOWN_BACKGROUND uint8_t ICON_COUNTDOWN_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x7e, 0x00, + 0x00, 0x7f, 0x80, + 0x00, 0x7f, 0xc0, + 0x00, 0x7f, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x01, 0xfe, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_COUNTDOWN_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_COUNTDOWN_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND.c new file mode 100644 index 000000000..d7e046dd4 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_DEVICE_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_DEVICE_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_DEVICE_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_DEVICE_BACKGROUND uint8_t ICON_DEVICE_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x03, 0xff, 0x00, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_DEVICE_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_DEVICE_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND.c new file mode 100644 index 000000000..535929be6 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT1_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_EDIT1_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_EDIT1_BACKGROUND uint8_t ICON_EDIT1_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x03, 0xc0, + 0x00, 0x07, 0xe0, + 0x00, 0x0f, 0xf0, + 0x00, 0x1f, 0xf8, + 0x00, 0x3f, 0xf8, + 0x00, 0x7f, 0xf8, + 0x00, 0xff, 0xf8, + 0x01, 0xff, 0xf0, + 0x03, 0xff, 0xe0, + 0x07, 0xff, 0xc0, + 0x0f, 0xff, 0x80, + 0x1f, 0xff, 0x00, + 0x3f, 0xfe, 0x00, + 0x7f, 0xfc, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf0, 0x00, + 0x7f, 0xe0, 0x00, + 0x7f, 0xc0, 0x00, + 0x7f, 0x80, 0x00, + 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_EDIT1_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_EDIT1_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND.c new file mode 100644 index 000000000..392dac3b3 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT2_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_EDIT2_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_EDIT2_BACKGROUND uint8_t ICON_EDIT2_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x1f, 0xf1, 0xe0, + 0x3f, 0xf3, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xc0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_EDIT2_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_EDIT2_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND.c new file mode 100644 index 000000000..7ee4d84b4 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_ERASE_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_ERASE_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_ERASE_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_ERASE_BACKGROUND uint8_t ICON_ERASE_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x03, 0xff, 0x00, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_ERASE_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_ERASE_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND.c new file mode 100644 index 000000000..a58b22e41 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_EXTENSIONS_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_EXTENSIONS_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_EXTENSIONS_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_EXTENSIONS_BACKGROUND uint8_t ICON_EXTENSIONS_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, + 0x01, 0xfe, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x3f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_EXTENSIONS_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_EXTENSIONS_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND.c new file mode 100644 index 000000000..8fae5a9cd --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_FILE_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_FILE_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_FILE_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_FILE_BACKGROUND uint8_t ICON_FILE_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x0f, 0xff, 0x80, + 0x1f, 0xff, 0xc0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x1f, 0xff, 0xc0, + 0x0f, 0xff, 0x80, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_FILE_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_FILE_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND.c new file mode 100644 index 000000000..bcbb4d6d1 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_FIRMWARE_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_FIRMWARE_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_FIRMWARE_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_FIRMWARE_BACKGROUND uint8_t ICON_FIRMWARE_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x78, 0x00, + 0x0f, 0x7b, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_FIRMWARE_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_FIRMWARE_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND.c new file mode 100644 index 000000000..e32d44bcd --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_FOLDER_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_FOLDER_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_FOLDER_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_FOLDER_BACKGROUND uint8_t ICON_FOLDER_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x1f, 0xff, 0x00, + 0x3f, 0xff, 0x80, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_FOLDER_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_FOLDER_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND.c new file mode 100644 index 000000000..e874e0bfe --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_FORWARD_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_FORWARD_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_FORWARD_BACKGROUND uint8_t ICON_FORWARD_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x03, 0xc0, 0x00, + 0x03, 0xe0, 0x00, + 0x03, 0xf0, 0x00, + 0x03, 0xf8, 0x00, + 0x01, 0xfc, 0x00, + 0x00, 0xfe, 0x00, + 0x00, 0x7f, 0x00, + 0x00, 0x3f, 0x80, + 0x00, 0x1f, 0x80, + 0x00, 0x1f, 0x80, + 0x00, 0x3f, 0x80, + 0x00, 0x7f, 0x00, + 0x00, 0xfe, 0x00, + 0x01, 0xfc, 0x00, + 0x03, 0xf8, 0x00, + 0x03, 0xf0, 0x00, + 0x03, 0xe0, 0x00, + 0x03, 0xc0, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_FORWARD_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_FORWARD_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND.c new file mode 100644 index 000000000..624f6bec4 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_HAMBURGER_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_HAMBURGER_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_HAMBURGER_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_HAMBURGER_BACKGROUND uint8_t ICON_HAMBURGER_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_HAMBURGER_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_HAMBURGER_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND.c new file mode 100644 index 000000000..9561ff111 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_HEALTH_CHECK_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_HEALTH_CHECK_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_HEALTH_CHECK_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_HEALTH_CHECK_BACKGROUND uint8_t ICON_HEALTH_CHECK_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x07, 0xcf, 0x80, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x00, 0xfc, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_HEALTH_CHECK_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_HEALTH_CHECK_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND.c new file mode 100644 index 000000000..0c1f9b1d1 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_HOME_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_HOME_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_HOME_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_HOME_BACKGROUND uint8_t ICON_HOME_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, + 0x01, 0xfe, 0x00, + 0x03, 0xff, 0x00, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_HOME_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_HOME_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND.c new file mode 100644 index 000000000..100a9ba7d --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_INFO_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_INFO_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_INFO_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_INFO_BACKGROUND uint8_t ICON_INFO_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x03, 0xff, 0x00, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x07, 0xff, 0xc0, + 0x03, 0xff, 0x00, +}; + +const lv_img_dsc_t ICON_INFO_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_INFO_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND.c new file mode 100644 index 000000000..35c91796e --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_MICROSD_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_MICROSD_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_MICROSD_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_MICROSD_BACKGROUND uint8_t ICON_MICROSD_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x3f, 0xff, 0xe0, + 0x1f, 0xff, 0xc0, + 0x0f, 0xff, 0x80, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_MICROSD_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_MICROSD_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND.c new file mode 100644 index 000000000..7dbeb9dee --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_NETWORK_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_NETWORK_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_NETWORK_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_NETWORK_BACKGROUND uint8_t ICON_NETWORK_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x03, 0xc0, + 0x00, 0x07, 0xe0, + 0x00, 0x0f, 0xf0, + 0x00, 0x1f, 0xf8, + 0x0f, 0x7f, 0xf8, + 0x1f, 0xff, 0xf8, + 0x3f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xc0, + 0x7f, 0xff, 0xc0, + 0x3f, 0xff, 0xe0, + 0x1f, 0xff, 0xf0, + 0x0f, 0x7f, 0xf8, + 0x00, 0x1f, 0xf8, + 0x00, 0x1f, 0xf8, + 0x00, 0x1f, 0xf8, + 0x00, 0x0f, 0xf0, + 0x00, 0x07, 0xe0, + 0x00, 0x03, 0xc0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_NETWORK_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_NETWORK_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_NOSTR_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_NOSTR_BACKGROUND.c new file mode 100644 index 000000000..cf49ef358 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_NOSTR_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_NOSTR_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_NOSTR_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_NOSTR_BACKGROUND uint8_t ICON_NOSTR_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x0f, 0x00, + 0x00, 0x0f, 0xe0, + 0x00, 0x0f, 0xe0, + 0x00, 0x0f, 0xe0, + 0x00, 0x0f, 0x80, + 0x00, 0x07, 0x80, + 0x00, 0x7f, 0xc0, + 0x01, 0xff, 0xc0, + 0x03, 0xff, 0xc0, + 0x07, 0xff, 0xc0, + 0x3f, 0xff, 0xc0, + 0x3f, 0xff, 0xc0, + 0x3f, 0xff, 0x80, + 0x1f, 0xff, 0x00, + 0x07, 0xff, 0x80, + 0x0f, 0xdf, 0xc0, + 0x1f, 0x9f, 0xc0, + 0x3f, 0x01, 0xc0, + 0x3e, 0x00, 0x00, + 0x3c, 0x00, 0x00, + 0x38, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_NOSTR_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_NOSTR_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND.c new file mode 100644 index 000000000..8c7231925 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_ONE_KEY_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_ONE_KEY_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_ONE_KEY_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_ONE_KEY_BACKGROUND uint8_t ICON_ONE_KEY_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, + 0x00, 0x01, 0xf0, + 0x00, 0x03, 0xf0, + 0x00, 0x07, 0xf0, + 0x00, 0x0f, 0xf8, + 0x00, 0x1f, 0xf8, + 0x00, 0x3f, 0xf8, + 0x0f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xe0, + 0x7f, 0xfb, 0xc0, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x7f, 0xf8, 0x00, + 0x3f, 0xf0, 0x00, + 0x3f, 0xf0, 0x00, + 0x0f, 0xc0, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_ONE_KEY_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_ONE_KEY_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND.c new file mode 100644 index 000000000..ef821d27d --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_PASSPHRASE_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_PASSPHRASE_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_PASSPHRASE_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_PASSPHRASE_BACKGROUND uint8_t ICON_PASSPHRASE_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x03, 0xff, 0x00, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_PASSPHRASE_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_PASSPHRASE_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND.c new file mode 100644 index 000000000..8983be9a0 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_PIN_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_PIN_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_PIN_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_PIN_BACKGROUND uint8_t ICON_PIN_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_PIN_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_PIN_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND.c new file mode 100644 index 000000000..c8dded83f --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_RETRY_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_RETRY_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_RETRY_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_RETRY_BACKGROUND uint8_t ICON_RETRY_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x07, 0xfe, 0x00, + 0x0f, 0xff, 0x3c, + 0x1f, 0xff, 0xbc, + 0x3f, 0xff, 0xfc, + 0x7f, 0x0f, 0xfc, + 0x7e, 0x07, 0xfc, + 0x7c, 0x03, 0xfc, + 0x78, 0x0f, 0xfc, + 0x00, 0x0f, 0xfc, + 0x00, 0x0f, 0xfc, + 0x00, 0x0f, 0xfc, + 0xff, 0xc0, 0x00, + 0xff, 0xc0, 0x00, + 0xff, 0xc0, 0x00, + 0xff, 0xc0, 0x78, + 0xff, 0x00, 0xf8, + 0xff, 0x81, 0xf8, + 0xff, 0xc3, 0xf8, + 0xff, 0xff, 0xf0, + 0xf7, 0xff, 0xe0, + 0xf3, 0xff, 0xc0, + 0x01, 0xff, 0x80, +}; + +const lv_img_dsc_t ICON_RETRY_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_RETRY_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND.c new file mode 100644 index 000000000..91287f3b8 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SCAN_QR_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SCAN_QR_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SCAN_QR_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SCAN_QR_BACKGROUND uint8_t ICON_SCAN_QR_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x1f, 0xcf, 0xe0, + 0x3f, 0xcf, 0xf0, + 0x7f, 0xcf, 0xf8, + 0x7f, 0xcf, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0xc0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xcf, 0xf8, + 0x3f, 0xcf, 0xf0, + 0x1f, 0xcf, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SCAN_QR_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SCAN_QR_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND.c new file mode 100644 index 000000000..57e18b885 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SEED_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SEED_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SEED_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SEED_BACKGROUND uint8_t ICON_SEED_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x3f, 0x00, + 0x00, 0x7f, 0x00, + 0x00, 0x7f, 0x00, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SEED_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SEED_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND.c new file mode 100644 index 000000000..996185cff --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SETTINGS_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SETTINGS_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SETTINGS_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SETTINGS_BACKGROUND uint8_t ICON_SETTINGS_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x00, + 0x01, 0xfe, 0x00, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x01, 0xfe, 0x00, + 0x00, 0xfc, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SETTINGS_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SETTINGS_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND.c new file mode 100644 index 000000000..cbdec6274 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SETUP_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SETUP_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SETUP_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SETUP_BACKGROUND uint8_t ICON_SETUP_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x0f, 0xf0, 0x00, + 0x0f, 0xf8, 0x00, + 0x0f, 0xfc, 0x00, + 0x7f, 0xfe, 0x00, + 0x7f, 0xff, 0x00, + 0x7f, 0xff, 0x00, + 0x7f, 0xff, 0x00, + 0x7f, 0xff, 0x00, + 0x7f, 0xff, 0x00, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0xc0, + 0x7f, 0xff, 0xe0, + 0x1f, 0xff, 0xf0, + 0x0f, 0xff, 0xf8, + 0x07, 0xff, 0xf8, + 0x00, 0x3f, 0xf8, + 0x00, 0x1f, 0xf8, + 0x00, 0x0f, 0xf8, + 0x00, 0x07, 0xf8, + 0x00, 0x03, 0xf0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SETUP_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SETUP_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND.c new file mode 100644 index 000000000..2fdf3747b --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SHIELD_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SHIELD_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SHIELD_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SHIELD_BACKGROUND uint8_t ICON_SHIELD_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x03, 0xff, 0x00, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x07, 0xff, 0x80, + 0x03, 0xff, 0x00, + 0x01, 0xfe, 0x00, + 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SHIELD_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SHIELD_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND.c new file mode 100644 index 000000000..f31045bab --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SHUTDOWN_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SHUTDOWN_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SHUTDOWN_BACKGROUND uint8_t ICON_SHUTDOWN_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x78, 0x00, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x0f, 0xff, 0xc0, + 0x03, 0xff, 0x00, +}; + +const lv_img_dsc_t ICON_SHUTDOWN_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SHUTDOWN_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND.c new file mode 100644 index 000000000..45b2ed727 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SIGN_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SIGN_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SIGN_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SIGN_BACKGROUND uint8_t ICON_SIGN_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x07, 0x80, + 0x00, 0x0f, 0xc0, + 0x00, 0x1f, 0xe0, + 0x00, 0x3f, 0xf0, + 0x00, 0x7f, 0xf0, + 0x00, 0xff, 0xf0, + 0x01, 0xff, 0xf0, + 0x03, 0xff, 0xe0, + 0x07, 0xff, 0xc0, + 0x0f, 0xff, 0x80, + 0x1f, 0xff, 0x00, + 0x1f, 0xfe, 0x00, + 0x3f, 0xfc, 0x00, + 0x3f, 0xf8, 0x00, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xbf, 0xf0, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SIGN_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SIGN_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND.c new file mode 100644 index 000000000..4104795f5 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_SPIRAL_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_SPIRAL_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SPIRAL_BACKGROUND uint8_t ICON_SPIRAL_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x7f, 0xe0, + 0x01, 0xff, 0xf0, + 0x03, 0xff, 0xf8, + 0x07, 0xff, 0xf8, + 0x0f, 0xff, 0xf8, + 0x1f, 0xff, 0xe0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x1f, 0xff, 0xe0, + 0x7f, 0xff, 0xc0, + 0x7f, 0xff, 0x80, + 0x7f, 0xff, 0x00, + 0x3f, 0xfe, 0x00, + 0x1f, 0xf8, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_SPIRAL_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_SPIRAL_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND.c new file mode 100644 index 000000000..23f69d7f8 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_TWO_KEYS_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_TWO_KEYS_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_TWO_KEYS_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_TWO_KEYS_BACKGROUND uint8_t ICON_TWO_KEYS_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x00, + 0x00, 0x1f, 0x00, + 0x00, 0x3f, 0x00, + 0x00, 0x7f, 0x00, + 0x0f, 0xff, 0x80, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xc0, + 0x0f, 0xff, 0x00, + 0x07, 0xff, 0x00, + 0x07, 0xff, 0x00, + 0x03, 0xfe, 0x00, + 0x03, 0xfe, 0x00, + 0x00, 0xf8, 0x00, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_TWO_KEYS_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_TWO_KEYS_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND.c new file mode 100644 index 000000000..a224fb3fd --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_VERIFY_ADDRESS_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_VERIFY_ADDRESS_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_VERIFY_ADDRESS_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_VERIFY_ADDRESS_BACKGROUND uint8_t ICON_VERIFY_ADDRESS_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, + 0x00, 0x00, 0xf8, + 0x3f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x7f, 0xff, 0xe0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf0, + 0x1f, 0xff, 0xe0, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_VERIFY_ADDRESS_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_VERIFY_ADDRESS_BACKGROUND_map, +}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_WARNING_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_WARNING_BACKGROUND.c new file mode 100644 index 000000000..0778b12d2 --- /dev/null +++ b/ports/stm32/boards/Passport/images/mono/ICON_WARNING_BACKGROUND.c @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#if defined(LV_LVGL_H_INCLUDE_SIMPLE) +#include "lvgl.h" +#else +#include "lvgl/lvgl.h" +#endif + + +#ifndef LV_ATTRIBUTE_MEM_ALIGN +#define LV_ATTRIBUTE_MEM_ALIGN +#endif + +#ifndef LV_ATTRIBUTE_IMG_ICON_WARNING_BACKGROUND +#define LV_ATTRIBUTE_IMG_ICON_WARNING_BACKGROUND +#endif + +const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_WARNING_BACKGROUND uint8_t ICON_WARNING_BACKGROUND_map[] = { + 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ + + 0x00, 0x00, 0x00, + 0x00, 0x78, 0x00, + 0x01, 0xfe, 0x00, + 0x01, 0xfe, 0x00, + 0x03, 0xff, 0x00, + 0x03, 0xff, 0x00, + 0x07, 0xff, 0x80, + 0x07, 0xff, 0x80, + 0x0f, 0xff, 0xc0, + 0x0f, 0xff, 0xc0, + 0x1f, 0xff, 0xe0, + 0x1f, 0xff, 0xe0, + 0x3f, 0xff, 0xf0, + 0x3f, 0xff, 0xf0, + 0x7f, 0xff, 0xf8, + 0x7f, 0xff, 0xf8, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xfc, + 0x7f, 0xff, 0xf8, + 0x00, 0x00, 0x00, +}; + +const lv_img_dsc_t ICON_WARNING_BACKGROUND = { + .header.cf = LV_IMG_CF_INDEXED_1BIT, + .header.always_zero = 0, + .header.reserved = 0, + .header.w = 22, + .header.h = 22, + .data_size = 74, + .data = ICON_WARNING_BACKGROUND_map, +}; From 1c3f4d9fe9c63ebe533869aa7858a4ec2288e077 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Fri, 2 Jun 2023 11:30:53 -0500 Subject: [PATCH 179/187] SFT-1071: added black backgrounds to image header --- ports/stm32/boards/Passport/images/images.h | 45 +++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/ports/stm32/boards/Passport/images/images.h b/ports/stm32/boards/Passport/images/images.h index 886ae5f44..cb44a8216 100644 --- a/ports/stm32/boards/Passport/images/images.h +++ b/ports/stm32/boards/Passport/images/images.h @@ -87,42 +87,73 @@ extern const lv_img_dsc_t LARGE_ICON_SUCCESS; #endif #ifdef SCREEN_MODE_MONO +extern const lv_img_dsc_t ICON_ADD_ACCOUNT_BACKGROUND; extern const lv_img_dsc_t ICON_ADD_ACCOUNT; +extern const lv_img_dsc_t ICON_ADVANCED_BACKGROUND; extern const lv_img_dsc_t ICON_ADVANCED; +extern const lv_img_dsc_t ICON_BACKUP_BACKGROUND; extern const lv_img_dsc_t ICON_BACKUP; +extern const lv_img_dsc_t ICON_BACK_BACKGROUND; extern const lv_img_dsc_t ICON_BACK; +extern const lv_img_dsc_t ICON_BATTERY_BACKGROUND; extern const lv_img_dsc_t ICON_BATTERY_CHARGING; extern const lv_img_dsc_t ICON_BATTERY; +extern const lv_img_dsc_t ICON_BITCOIN_BACKGROUND; extern const lv_img_dsc_t ICON_BITCOIN; +extern const lv_img_dsc_t ICON_BRIGHTNESS_BACKGROUND; extern const lv_img_dsc_t ICON_BRIGHTNESS; +extern const lv_img_dsc_t ICON_CANCEL_BACKGROUND; extern const lv_img_dsc_t ICON_CANCEL; +extern const lv_img_dsc_t ICON_CASA_BACKGROUND; extern const lv_img_dsc_t ICON_CASA; +extern const lv_img_dsc_t ICON_CHECKMARK_BACKGROUND; extern const lv_img_dsc_t ICON_CHECKMARK; +extern const lv_img_dsc_t ICON_CIRCLE_CHECK_BACKGROUND; extern const lv_img_dsc_t ICON_CIRCLE_CHECK; +extern const lv_img_dsc_t ICON_CLOCK_BACKGROUND; extern const lv_img_dsc_t ICON_CLOCK; +extern const lv_img_dsc_t ICON_CONNECT_BACKGROUND; extern const lv_img_dsc_t ICON_CONNECT; +extern const lv_img_dsc_t ICON_COUNTDOWN_BACKGROUND; extern const lv_img_dsc_t ICON_COUNTDOWN; +extern const lv_img_dsc_t ICON_DEVICE_BACKGROUND; extern const lv_img_dsc_t ICON_DEVICE; +extern const lv_img_dsc_t ICON_EDIT1_BACKGROUND; extern const lv_img_dsc_t ICON_EDIT1; +extern const lv_img_dsc_t ICON_EDIT2_BACKGROUND; extern const lv_img_dsc_t ICON_EDIT2; +extern const lv_img_dsc_t ICON_ERASE_BACKGROUND; extern const lv_img_dsc_t ICON_ERASE; +extern const lv_img_dsc_t ICON_EXTENSIONS_BACKGROUND; extern const lv_img_dsc_t ICON_EXTENSIONS; +extern const lv_img_dsc_t ICON_FILE_BACKGROUND; extern const lv_img_dsc_t ICON_FILE; +extern const lv_img_dsc_t ICON_FIRMWARE_BACKGROUND; extern const lv_img_dsc_t ICON_FIRMWARE; +extern const lv_img_dsc_t ICON_FOLDER_BACKGROUND; extern const lv_img_dsc_t ICON_FOLDER; +extern const lv_img_dsc_t ICON_FORWARD_BACKGROUND; extern const lv_img_dsc_t ICON_FORWARD; +extern const lv_img_dsc_t ICON_HAMBURGER_BACKGROUND; extern const lv_img_dsc_t ICON_HAMBURGER; +extern const lv_img_dsc_t ICON_HEALTH_CHECK_BACKGROUND; extern const lv_img_dsc_t ICON_HEALTH_CHECK; +extern const lv_img_dsc_t ICON_HOME_BACKGROUND; extern const lv_img_dsc_t ICON_HOME; +extern const lv_img_dsc_t ICON_INFO_BACKGROUND; extern const lv_img_dsc_t ICON_INFO; extern const lv_img_dsc_t ICON_INPUT_MODE_LOWER_ALPHA; extern const lv_img_dsc_t ICON_INPUT_MODE_NUMERIC; extern const lv_img_dsc_t ICON_INPUT_MODE_PUNCTUATION; extern const lv_img_dsc_t ICON_INPUT_MODE_UPPER_ALPHA; +extern const lv_img_dsc_t ICON_MICROSD_BACKGROUND; extern const lv_img_dsc_t ICON_MICROSD; extern const lv_img_dsc_t ICON_MULTISIG; +extern const lv_img_dsc_t ICON_NETWORK_BACKGROUND; extern const lv_img_dsc_t ICON_NETWORK; +extern const lv_img_dsc_t ICON_NOSTR_BACKGROUND; extern const lv_img_dsc_t ICON_NOSTR; +extern const lv_img_dsc_t ICON_ONE_KEY_BACKGROUND; extern const lv_img_dsc_t ICON_ONE_KEY; extern const lv_img_dsc_t ICON_PAGE_DOT; extern const lv_img_dsc_t ICON_PAGE_HOME; @@ -131,21 +162,35 @@ extern const lv_img_dsc_t ICON_PAGE_PLUS; extern const lv_img_dsc_t ICON_PAGE_QR_LG; extern const lv_img_dsc_t ICON_PAGE_QR_MD; extern const lv_img_dsc_t ICON_PAGE_QR_SM; +extern const lv_img_dsc_t ICON_PASSPHRASE_BACKGROUND; extern const lv_img_dsc_t ICON_PASSPHRASE; +extern const lv_img_dsc_t ICON_PIN_BACKGROUND; extern const lv_img_dsc_t ICON_PIN; extern const lv_img_dsc_t ICON_PLUS; +extern const lv_img_dsc_t ICON_RETRY_BACKGROUND; extern const lv_img_dsc_t ICON_RETRY; +extern const lv_img_dsc_t ICON_SCAN_QR_BACKGROUND; extern const lv_img_dsc_t ICON_SCAN_QR; +extern const lv_img_dsc_t ICON_SEED_BACKGROUND; extern const lv_img_dsc_t ICON_SEED; +extern const lv_img_dsc_t ICON_SETTINGS_BACKGROUND; extern const lv_img_dsc_t ICON_SETTINGS; +extern const lv_img_dsc_t ICON_SETUP_BACKGROUND; extern const lv_img_dsc_t ICON_SETUP; +extern const lv_img_dsc_t ICON_SHIELD_BACKGROUND; extern const lv_img_dsc_t ICON_SHIELD; +extern const lv_img_dsc_t ICON_SHUTDOWN_BACKGROUND; extern const lv_img_dsc_t ICON_SHUTDOWN; +extern const lv_img_dsc_t ICON_SIGN_BACKGROUND; extern const lv_img_dsc_t ICON_SIGN; extern const lv_img_dsc_t ICON_SMALL_CHECKMARK; +extern const lv_img_dsc_t ICON_SPIRAL_BACKGROUND; extern const lv_img_dsc_t ICON_SPIRAL; +extern const lv_img_dsc_t ICON_TWO_KEYS_BACKGROUND; extern const lv_img_dsc_t ICON_TWO_KEYS; +extern const lv_img_dsc_t ICON_VERIFY_ADDRESS_BACKGROUND; extern const lv_img_dsc_t ICON_VERIFY_ADDRESS; +extern const lv_img_dsc_t ICON_WARNING_BACKGROUND; extern const lv_img_dsc_t ICON_WARNING; extern const lv_img_dsc_t IMAGE_CARD_BOTTOM; extern const lv_img_dsc_t IMAGE_DIAGONAL_LINES; From 2a783a877eb725f67fb528b1ce03875c04d00c93 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 12 Jun 2023 12:44:03 -0500 Subject: [PATCH 180/187] SFT-1071: added mono icon backgrounds --- .../boards/Passport/modules/derived_key.py | 6 +- .../modules/extensions/casa_extension.py | 4 +- .../extensions/key_manager_extension.py | 4 +- .../modules/extensions/postmix_extension.py | 4 +- .../Passport/modules/flows/backup_flow.py | 2 +- .../modules/flows/connect_wallet_flow.py | 2 +- .../modules/flows/envoy_setup_flow.py | 8 +- .../modules/flows/file_picker_flow.py | 4 +- .../modules/flows/initial_seed_setup_flow.py | 2 +- .../modules/flows/manual_setup_flow.py | 4 +- .../boards/Passport/modules/flows/scv_flow.py | 2 +- .../modules/flows/select_setup_mode_flow.py | 4 +- .../Passport/modules/flows/set_chain_flow.py | 2 +- .../modules/flows/set_initial_pin_flow.py | 2 +- .../modules/flows/terms_of_use_flow.py | 2 +- ports/stm32/boards/Passport/modules/menus.py | 198 +++++++++--------- .../Passport/modules/pages/chooser_page.py | 2 +- .../Passport/modules/pages/pin_entry_page.py | 2 +- ports/stm32/boards/Passport/modules/ui/ui.py | 14 +- ports/stm32/boards/Passport/modules/utils.py | 8 +- .../modules/views/battery_indicator.py | 6 +- .../Passport/modules/views/file_item.py | 2 +- .../boards/Passport/modules/views/icon.py | 6 +- .../Passport/modules/views/list_item.py | 2 +- .../Passport/modules/views/micron_bar.py | 2 +- .../Passport/modules/views/pin_input.py | 2 +- .../Passport/modules/views/statusbar.py | 20 +- 27 files changed, 163 insertions(+), 153 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/derived_key.py b/ports/stm32/boards/Passport/modules/derived_key.py index 8969ff97f..3bfc6eb02 100644 --- a/ports/stm32/boards/Passport/modules/derived_key.py +++ b/ports/stm32/boards/Passport/modules/derived_key.py @@ -13,19 +13,19 @@ key_types = [ {'tn': 0, 'title': '24 Word Seed', - 'icon': lv.ICON_SEED, + 'icon': 'ICON_SEED', 'indexed': True, 'words': True, 'task': bip85_24_word_seed_task}, {'tn': 1, 'title': '12 Word Seed', - 'icon': lv.ICON_SEED, + 'icon': 'ICON_SEED', 'indexed': True, 'words': True, 'task': bip85_12_word_seed_task}, {'tn': 2, 'title': 'Nostr Key', - 'icon': lv.ICON_NOSTR, + 'icon': 'ICON_NOSTR', 'indexed': True, 'words': False, 'task': nostr_key_task, diff --git a/ports/stm32/boards/Passport/modules/extensions/casa_extension.py b/ports/stm32/boards/Passport/modules/extensions/casa_extension.py index e6cd62aef..d2282983a 100644 --- a/ports/stm32/boards/Passport/modules/extensions/casa_extension.py +++ b/ports/stm32/boards/Passport/modules/extensions/casa_extension.py @@ -14,7 +14,7 @@ # Casa account - account number is zero, but they use a special derivation path name = 'casa' casa_account = {'name': 'Casa', 'acct_num': 0} -icon = lv.ICON_CASA +icon = 'ICON_CASA' CasaExtension = { 'name': name, @@ -29,7 +29,7 @@ 'right_icon': icon, 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'EXTENSION', 'icon': lv.ICON_EXTENSIONS, 'fg_color': WHITE}, + 'statusbar': {'title': 'EXTENSION', 'icon': 'ICON_EXTENSIONS', 'fg_color': WHITE}, 'title': casa_account.get('name'), 'page_micron': microns.PageDot, 'bg_color': CASA_PURPLE, diff --git a/ports/stm32/boards/Passport/modules/extensions/key_manager_extension.py b/ports/stm32/boards/Passport/modules/extensions/key_manager_extension.py index 30cf9960a..ef491f8f5 100644 --- a/ports/stm32/boards/Passport/modules/extensions/key_manager_extension.py +++ b/ports/stm32/boards/Passport/modules/extensions/key_manager_extension.py @@ -13,7 +13,7 @@ name = 'key_manager' label = 'Key Manager' -icon = lv.ICON_ONE_KEY +icon = 'ICON_ONE_KEY' KeyManagerExtension = { 'name': name, @@ -28,7 +28,7 @@ 'right_icon': icon, 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'EXTENSION', 'icon': lv.ICON_EXTENSIONS, 'fg_color': WHITE}, + 'statusbar': {'title': 'EXTENSION', 'icon': 'ICON_EXTENSIONS', 'fg_color': WHITE}, 'title': label, 'page_micron': microns.PageDot, 'bg_color': LIGHT_COPPER, diff --git a/ports/stm32/boards/Passport/modules/extensions/postmix_extension.py b/ports/stm32/boards/Passport/modules/extensions/postmix_extension.py index aa5eeb2ff..3873211f2 100644 --- a/ports/stm32/boards/Passport/modules/extensions/postmix_extension.py +++ b/ports/stm32/boards/Passport/modules/extensions/postmix_extension.py @@ -14,7 +14,7 @@ # Postmix account for CoinJoin name = 'postmix' postmix_account = {'name': 'Postmix', 'acct_num': 2_147_483_646} -icon = lv.ICON_SPIRAL +icon = 'ICON_SPIRAL' PostmixExtension = { 'name': name, @@ -29,7 +29,7 @@ 'right_icon': icon, 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'EXTENSION', 'icon': lv.ICON_EXTENSIONS, 'fg_color': WHITE}, + 'statusbar': {'title': 'EXTENSION', 'icon': 'ICON_EXTENSIONS', 'fg_color': WHITE}, 'title': postmix_account.get('name'), 'page_micron': microns.PageDot, 'bg_color': RED, diff --git a/ports/stm32/boards/Passport/modules/flows/backup_flow.py b/ports/stm32/boards/Passport/modules/flows/backup_flow.py index 10ecca546..7d05ccb03 100644 --- a/ports/stm32/boards/Passport/modules/flows/backup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/backup_flow.py @@ -19,7 +19,7 @@ def __init__(self): self.backup_quiz_passed = settings.get('backup_quiz', False) self.quiz_result = [None] * TOTAL_BACKUP_CODE_DIGITS - self.statusbar = {'title': 'BACKUP', 'icon': lv.ICON_BACKUP} + self.statusbar = {'title': 'BACKUP', 'icon': 'ICON_BACKUP'} async def show_intro(self): from pages import InfoPage diff --git a/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py b/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py index 75b4bba00..dd20129f4 100644 --- a/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/connect_wallet_flow.py @@ -277,7 +277,7 @@ async def export_by_qr(self): # Show the QR code result = await ShowQRPage( - statusbar={'title': 'CONNECT', 'icon': lv.ICON_CONNECT}, + statusbar={'title': 'CONNECT', 'icon': 'ICON_CONNECT'}, qr_type=qr_type, qr_data=data).show() if result is False: diff --git a/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py index aeac93669..cac6f31bb 100644 --- a/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/envoy_setup_flow.py @@ -83,7 +83,7 @@ async def update_firmware(self): result = await QuestionPage( icon=lv.LARGE_ICON_FIRMWARE, text='Do you want to update Passport\'s firmware now?', - statusbar={'title': title, 'icon': lv.ICON_FIRMWARE}).show() + statusbar={'title': title, 'icon': 'ICON_FIRMWARE'}).show() if not result: await ErrorPage(text='We recommend updating Passport\'s firmware at your earliest convenience.').show() self.goto(self.setup_seed) @@ -91,7 +91,7 @@ async def update_firmware(self): result = await UpdateFirmwareFlow( reset_after=False, - statusbar={'title': title, 'icon': lv.ICON_FIRMWARE} + statusbar={'title': title, 'icon': 'ICON_FIRMWARE'} ).run() if result: import machine @@ -138,7 +138,7 @@ async def connect_with_envoy_intro(self): await self.ensure_logged_in() result = await InfoPage( - statusbar={'title': 'CONNECT', 'icon': lv.ICON_CONNECT}, + statusbar={'title': 'CONNECT', 'icon': 'ICON_CONNECT'}, text='Now, let\'s connect Passport with Envoy.', left_micron=None).show() self.goto(self.connect_with_envoy) @@ -168,7 +168,7 @@ async def connect_with_envoy(self): result = await ConnectWalletFlow( sw_wallet='Envoy', - statusbar={'title': 'CONNECT', 'icon': lv.ICON_CONNECT} + statusbar={'title': 'CONNECT', 'icon': 'ICON_CONNECT'} ).run() if result: self.goto(self.show_success) diff --git a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py index 44f04f2e7..6aa51830b 100644 --- a/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/file_picker_flow.py @@ -128,11 +128,11 @@ async def show_file_picker(self): is_root = active_path == CardSlot.get_sd_root() if is_root: title = 'microSD' - icon = lv.ICON_MICROSD + icon = 'ICON_MICROSD' else: leaf_folder_name = active_path.split('/')[-1] title = leaf_folder_name - icon = lv.ICON_FOLDER + icon = 'ICON_FOLDER' if len(files) == 0: self.status_page = StatusPage( diff --git a/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py index 5c187e00a..6a2c7ea24 100644 --- a/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/initial_seed_setup_flow.py @@ -11,7 +11,7 @@ class InitialSeedSetupFlow(Flow): def __init__(self, is_envoy=True, allow_backtrack=True): super().__init__(initial_state=self.show_intro, name='InitialSeedSetupFlow') self.is_envoy = is_envoy - self.statusbar = {'title': 'CREATE SEED', 'icon': lv.ICON_SEED} + self.statusbar = {'title': 'CREATE SEED', 'icon': 'ICON_SEED'} self.allow_backtrack = allow_backtrack async def show_intro(self): diff --git a/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py b/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py index 89bd158a1..f6eaba5df 100644 --- a/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/manual_setup_flow.py @@ -77,7 +77,7 @@ async def update_firmware(self): result = await QuestionPage( icon=lv.LARGE_ICON_FIRMWARE, text='Do you want to update Passport\'s firmware now?', - statusbar={'title': title, 'icon': lv.ICON_FIRMWARE}).show() + statusbar={'title': title, 'icon': 'ICON_FIRMWARE'}).show() if not result: await ErrorPage(text='We recommend updating Passport\'s firmware at your earliest convenience.').show() self.goto(self.setup_seed) @@ -85,7 +85,7 @@ async def update_firmware(self): result = await UpdateFirmwareFlow( reset_after=False, - statusbar={'title': title, 'icon': lv.ICON_FIRMWARE} + statusbar={'title': title, 'icon': 'ICON_FIRMWARE'} ).run() if result: import machine diff --git a/ports/stm32/boards/Passport/modules/flows/scv_flow.py b/ports/stm32/boards/Passport/modules/flows/scv_flow.py index 3eeaa8398..c76233017 100644 --- a/ports/stm32/boards/Passport/modules/flows/scv_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/scv_flow.py @@ -26,7 +26,7 @@ def __init__(self, envoy=True, ask_to_skip=True): super().__init__(initial_state=self.show_intro, name='ScvFlow', - statusbar={'title': 'SECURITY CHECK', 'icon': lv.ICON_SHIELD}) + statusbar={'title': 'SECURITY CHECK', 'icon': 'ICON_SHIELD'}) self.words = None self.envoy = envoy self.ask_to_skip = ask_to_skip diff --git a/ports/stm32/boards/Passport/modules/flows/select_setup_mode_flow.py b/ports/stm32/boards/Passport/modules/flows/select_setup_mode_flow.py index f0306c495..79d1f00a5 100644 --- a/ports/stm32/boards/Passport/modules/flows/select_setup_mode_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/select_setup_mode_flow.py @@ -19,7 +19,7 @@ def __init__(self): self.set_result(True) return - self.statusbar = {'title': 'PASSPORT SETUP', 'icon': lv.ICON_SETUP} + self.statusbar = {'title': 'PASSPORT SETUP', 'icon': 'ICON_SETUP'} async def show_welcome(self): from pages import BrandmarkPage, ShutdownPage @@ -27,7 +27,7 @@ async def show_welcome(self): result = await BrandmarkPage( text='Welcome to Passport\n\nCongratulations on taking custody of your Bitcoin ' + 'and reclaiming your sovereignty!', - statusbar={'title': 'WELCOME', 'icon': lv.ICON_HOME}, + statusbar={'title': 'WELCOME', 'icon': 'ICON_HOME'}, left_micron=microns.Shutdown, right_micron=microns.Forward).show() if result: diff --git a/ports/stm32/boards/Passport/modules/flows/set_chain_flow.py b/ports/stm32/boards/Passport/modules/flows/set_chain_flow.py index d5565611f..1528f7e01 100644 --- a/ports/stm32/boards/Passport/modules/flows/set_chain_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/set_chain_flow.py @@ -13,7 +13,7 @@ def __init__(self): super().__init__(initial_state=self.show_setting_page, name='SetChainFlow') async def show_setting_page(self): - network = await ChainSettingPage(card_header={'title': 'Network', 'icon': lv.ICON_NETWORK}).show() + network = await ChainSettingPage(card_header={'title': 'Network', 'icon': 'ICON_NETWORK'}).show() if network is 'TBTC': text = "Passport is in Testnet mode. Use a separate seed to avoid issues " \ diff --git a/ports/stm32/boards/Passport/modules/flows/set_initial_pin_flow.py b/ports/stm32/boards/Passport/modules/flows/set_initial_pin_flow.py index cac873529..ff53e5e6e 100644 --- a/ports/stm32/boards/Passport/modules/flows/set_initial_pin_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/set_initial_pin_flow.py @@ -12,7 +12,7 @@ class SetInitialPINFlow(Flow): def __init__(self): super().__init__(initial_state=self.intro, name='SetInitialPINFlow') - self.statusbar = {'title': 'SET PIN', 'icon': lv.ICON_PIN} + self.statusbar = {'title': 'SET PIN', 'icon': 'ICON_PIN'} async def intro(self): from common import pa diff --git a/ports/stm32/boards/Passport/modules/flows/terms_of_use_flow.py b/ports/stm32/boards/Passport/modules/flows/terms_of_use_flow.py index f3781c7f2..7e76f36a2 100644 --- a/ports/stm32/boards/Passport/modules/flows/terms_of_use_flow.py +++ b/ports/stm32/boards/Passport/modules/flows/terms_of_use_flow.py @@ -13,7 +13,7 @@ class TermsOfUseFlow(Flow): def __init__(self): super().__init__(initial_state=self.show_terms, name='TermsOfUseFlow') - self.statusbar = {'title': 'TERMS OF USE', 'icon': lv.ICON_INFO} + self.statusbar = {'title': 'TERMS OF USE', 'icon': 'ICON_INFO'} # Skip if already accepted if common.settings.get('terms_ok') == 1: self.goto(self.show_status) diff --git a/ports/stm32/boards/Passport/modules/menus.py b/ports/stm32/boards/Passport/modules/menus.py index 6b6ecfa00..b03100079 100644 --- a/ports/stm32/boards/Passport/modules/menus.py +++ b/ports/stm32/boards/Passport/modules/menus.py @@ -12,7 +12,7 @@ ######################################################################################## # field # type # description ######################################################################################## -# icon # lv.ICON* # icon +# icon # string # icon # label # string # label # submenu # menu function # a function that returns a list of menu items # page # Page # page to display @@ -33,11 +33,11 @@ def manage_account_menu(): from pages import AccountDetailsPage return [ - {'icon': lv.ICON_FOLDER, 'label': 'Account Details', 'page': AccountDetailsPage}, - {'icon': lv.ICON_INFO, 'label': 'Rename Account', 'flow': RenameAccountFlow}, - {'icon': lv.ICON_CONNECT, 'label': 'Connect Wallet', 'flow': ConnectWalletFlow, + {'icon': 'ICON_FOLDER', 'label': 'Account Details', 'page': AccountDetailsPage}, + {'icon': 'ICON_INFO', 'label': 'Rename Account', 'flow': RenameAccountFlow}, + {'icon': 'ICON_CONNECT', 'label': 'Connect Wallet', 'flow': ConnectWalletFlow, 'statusbar': {'title': 'CONNECT'}}, - {'icon': lv.ICON_CANCEL, 'label': 'Delete Account', 'flow': DeleteAccountFlow}, + {'icon': 'ICON_CANCEL', 'label': 'Delete Account', 'flow': DeleteAccountFlow}, ] @@ -45,12 +45,12 @@ def account_menu(): from flows import VerifyAddressFlow, SignPsbtQRFlow, SignPsbtMicroSDFlow return [ - {'icon': lv.ICON_SCAN_QR, 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, + {'icon': 'ICON_SCAN_QR', 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_MICROSD, 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, + {'icon': 'ICON_MICROSD', 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_VERIFY_ADDRESS, 'label': 'Verify Address', 'flow': VerifyAddressFlow}, - {'icon': lv.ICON_FOLDER, 'label': 'Manage Account', 'submenu': manage_account_menu}, + {'icon': 'ICON_VERIFY_ADDRESS', 'label': 'Verify Address', 'flow': VerifyAddressFlow}, + {'icon': 'ICON_FOLDER', 'label': 'Manage Account', 'submenu': manage_account_menu}, ] @@ -58,9 +58,9 @@ def health_check_submenu(): from flows import CasaHealthCheckQRFlow, CasaHealthCheckMicrosdFlow return [ - {'icon': lv.ICON_SCAN_QR, 'label': 'Check with QR Code', 'flow': CasaHealthCheckQRFlow, + {'icon': 'ICON_SCAN_QR', 'label': 'Check with QR Code', 'flow': CasaHealthCheckQRFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_MICROSD, 'label': 'Check with microSD', 'flow': CasaHealthCheckMicrosdFlow, + {'icon': 'ICON_MICROSD', 'label': 'Check with microSD', 'flow': CasaHealthCheckMicrosdFlow, 'statusbar': {'title': 'SIGN'}}, ] @@ -69,13 +69,13 @@ def casa_menu(): from flows import VerifyAddressFlow, SignPsbtQRFlow, SignPsbtMicroSDFlow, ConnectWalletFlow return [ - {'icon': lv.ICON_SCAN_QR, 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, + {'icon': 'ICON_SCAN_QR', 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_MICROSD, 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, + {'icon': 'ICON_MICROSD', 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_VERIFY_ADDRESS, 'label': 'Verify Address', 'flow': VerifyAddressFlow}, - {'icon': lv.ICON_HEALTH_CHECK, 'label': 'Health Check', 'submenu': health_check_submenu}, - {'icon': lv.ICON_CONNECT, 'label': 'Connect to Casa', 'flow': ConnectWalletFlow, + {'icon': 'ICON_VERIFY_ADDRESS', 'label': 'Verify Address', 'flow': VerifyAddressFlow}, + {'icon': 'ICON_HEALTH_CHECK', 'label': 'Health Check', 'submenu': health_check_submenu}, + {'icon': 'ICON_CONNECT', 'label': 'Connect to Casa', 'flow': ConnectWalletFlow, 'statusbar': {'title': 'CONNECT'}, 'args': {'sw_wallet': 'Casa'}}, ] @@ -84,12 +84,12 @@ def postmix_menu(): from flows import VerifyAddressFlow, SignPsbtQRFlow, SignPsbtMicroSDFlow, ConnectWalletFlow return [ - {'icon': lv.ICON_SCAN_QR, 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, + {'icon': 'ICON_SCAN_QR', 'label': 'Sign with QR Code', 'flow': SignPsbtQRFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_MICROSD, 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, + {'icon': 'ICON_MICROSD', 'label': 'Sign with microSD', 'flow': SignPsbtMicroSDFlow, 'statusbar': {'title': 'SIGN'}}, - {'icon': lv.ICON_VERIFY_ADDRESS, 'label': 'Verify Address', 'flow': VerifyAddressFlow}, - {'icon': lv.ICON_CONNECT, 'label': 'Connect Wallet', 'flow': ConnectWalletFlow, + {'icon': 'ICON_VERIFY_ADDRESS', 'label': 'Verify Address', 'flow': VerifyAddressFlow}, + {'icon': 'ICON_CONNECT', 'label': 'Connect Wallet', 'flow': ConnectWalletFlow, 'statusbar': {'title': 'CONNECT'}}, ] @@ -99,12 +99,12 @@ def plus_menu(): from flows import NewAccountFlow, ApplyPassphraseFlow return [ - {'icon': lv.ICON_ADD_ACCOUNT, 'label': 'New Account', 'flow': NewAccountFlow}, - {'icon': lv.ICON_PASSPHRASE, 'label': 'Enter Passphrase', 'flow': ApplyPassphraseFlow, + {'icon': 'ICON_ADD_ACCOUNT', 'label': 'New Account', 'flow': NewAccountFlow}, + {'icon': 'ICON_PASSPHRASE', 'label': 'Enter Passphrase', 'flow': ApplyPassphraseFlow, 'statusbar': {'title': 'PASSPHRASE'}, 'is_visible': lambda: not is_passphrase_active()}, - {'icon': lv.ICON_PASSPHRASE, 'label': 'Clear Passphrase', 'flow': ApplyPassphraseFlow, + {'icon': 'ICON_PASSPHRASE', 'label': 'Clear Passphrase', 'flow': ApplyPassphraseFlow, 'args': {'passphrase': ''}, 'statusbar': {'title': 'PASSPHRASE'}, 'is_visible': is_passphrase_active}, - {'icon': lv.ICON_PASSPHRASE, 'label': 'Change Passphrase', 'flow': ApplyPassphraseFlow, + {'icon': 'ICON_PASSPHRASE', 'label': 'Change Passphrase', 'flow': ApplyPassphraseFlow, 'statusbar': {'title': 'PASSPHRASE'}, 'is_visible': is_passphrase_active}, ] @@ -115,10 +115,10 @@ def device_menu(): from utils import is_logged_in return [ - {'icon': lv.ICON_BRIGHTNESS, 'label': 'Screen Brightness', 'page': BrightnessSettingPage}, - {'icon': lv.ICON_COUNTDOWN, 'label': 'Auto-Shutdown', 'page': AutoShutdownSettingPage}, - {'icon': lv.ICON_PIN, 'label': 'Change PIN', 'flow': ChangePINFlow, 'is_visible': is_logged_in}, - {'icon': lv.ICON_INFO, 'label': 'About', 'flow': AboutFlow}, + {'icon': 'ICON_BRIGHTNESS', 'label': 'Screen Brightness', 'page': BrightnessSettingPage}, + {'icon': 'ICON_COUNTDOWN', 'label': 'Auto-Shutdown', 'page': AutoShutdownSettingPage}, + {'icon': 'ICON_PIN', 'label': 'Change PIN', 'flow': ChangePINFlow, 'is_visible': is_logged_in}, + {'icon': 'ICON_INFO', 'label': 'About', 'flow': AboutFlow}, ] @@ -126,12 +126,12 @@ def backup_menu(): from flows import BackupFlow, RestoreBackupFlow, VerifyBackupFlow, ViewBackupCodeFlow return [ - {'icon': lv.ICON_BACKUP, 'label': 'Backup Now', 'flow': BackupFlow, 'is_visible': has_seed}, - {'icon': lv.ICON_RETRY, 'label': 'Restore', 'flow': RestoreBackupFlow, + {'icon': 'ICON_BACKUP', 'label': 'Backup Now', 'flow': BackupFlow, 'is_visible': has_seed}, + {'icon': 'ICON_RETRY', 'label': 'Restore', 'flow': RestoreBackupFlow, 'args': {'refresh_cards_when_done': True}}, - {'icon': lv.ICON_CIRCLE_CHECK, 'label': 'Verify Backup', 'flow': VerifyBackupFlow}, - {'icon': lv.ICON_PIN, 'label': 'View Backup Code', 'flow': ViewBackupCodeFlow, - 'statusbar': {'title': 'BACKUP', 'icon': lv.ICON_PIN}, 'is_visible': has_seed} + {'icon': 'ICON_CIRCLE_CHECK', 'label': 'Verify Backup', 'flow': VerifyBackupFlow}, + {'icon': 'ICON_PIN', 'label': 'View Backup Code', 'flow': ViewBackupCodeFlow, + 'statusbar': {'title': 'BACKUP', 'icon': 'ICON_PIN'}, 'is_visible': has_seed} ] @@ -142,10 +142,10 @@ def key_item_menu(): ExportDerivedKeyFlow, HideDerivedKeyFlow) return [ - {'icon': lv.ICON_ONE_KEY, 'label': 'View Details', 'flow': ViewDerivedKeyDetailsFlow}, - {'icon': lv.ICON_INFO, 'label': 'Rename', 'flow': RenameDerivedKeyFlow, 'auto_card_header': False}, - {'icon': lv.ICON_SCAN_QR, 'label': 'Export', 'flow': ExportDerivedKeyFlow}, - {'icon': lv.ICON_ERASE, 'label': 'Toggle Hidden', 'flow': HideDerivedKeyFlow}, + {'icon': 'ICON_ONE_KEY', 'label': 'View Details', 'flow': ViewDerivedKeyDetailsFlow}, + {'icon': 'ICON_INFO', 'label': 'Rename', 'flow': RenameDerivedKeyFlow, 'auto_card_header': False}, + {'icon': 'ICON_SCAN_QR', 'label': 'Export', 'flow': ExportDerivedKeyFlow}, + {'icon': 'ICON_ERASE', 'label': 'Toggle Hidden', 'flow': HideDerivedKeyFlow}, ] @@ -170,7 +170,7 @@ def new_key_menu(): def manage_keys(): from utils import toggle_showing_hidden_keys, are_hidden_keys_showing return [ - {'icon': lv.ICON_TWO_KEYS, + {'icon': 'ICON_TWO_KEYS', 'label': 'Show Hidden', 'action': lambda item: toggle_showing_hidden_keys(), 'is_toggle': True, @@ -183,7 +183,7 @@ def nostr_menu(): if is_dev_build(): from developer import NostrDelegationFlow - return [{'icon': lv.ICON_SIGN, 'label': 'Delegate', 'flow': NostrDelegationFlow}] + return [{'icon': 'ICON_SIGN', 'label': 'Delegate', 'flow': NostrDelegationFlow}] return [] @@ -216,8 +216,8 @@ def key_manager_menu(): 'args': {'context': key, 'dynamic': key_type.get('menu', None)}, 'auto_card_header': False}) - result.append({'icon': lv.ICON_ONE_KEY, 'label': 'New Key', 'submenu': new_key_menu}) - result.append({'icon': lv.ICON_SETTINGS, 'label': 'Manage', 'submenu': manage_keys}) + result.append({'icon': 'ICON_ONE_KEY', 'label': 'New Key', 'submenu': new_key_menu}) + result.append({'icon': 'ICON_SETTINGS', 'label': 'Manage', 'submenu': manage_keys}) return result @@ -228,9 +228,9 @@ def bitcoin_menu(): from utils import is_logged_in return [ - {'icon': lv.ICON_BITCOIN, 'label': 'Units', 'page': UnitsSettingPage, 'is_visible': is_logged_in}, - {'icon': lv.ICON_TWO_KEYS, 'label': 'Multisig', 'submenu': multisig_menu, 'is_visible': has_seed}, - {'icon': lv.ICON_NETWORK, 'label': 'Network', 'flow': SetChainFlow, 'statusbar': {}, + {'icon': 'ICON_BITCOIN', 'label': 'Units', 'page': UnitsSettingPage, 'is_visible': is_logged_in}, + {'icon': 'ICON_TWO_KEYS', 'label': 'Multisig', 'submenu': multisig_menu, 'is_visible': has_seed}, + {'icon': 'ICON_NETWORK', 'label': 'Network', 'flow': SetChainFlow, 'statusbar': {}, 'is_visible': is_logged_in}, ] @@ -239,11 +239,11 @@ def security_menu(): from flows import ChangePINFlow, SignTextFileFlow, NewSeedFlow, RestoreSeedFlow return [ - {'icon': lv.ICON_SEED, 'label': 'Restore Seed', 'flow': RestoreSeedFlow, 'is_visible': lambda: not has_seed(), + {'icon': 'ICON_SEED', 'label': 'Restore Seed', 'flow': RestoreSeedFlow, 'is_visible': lambda: not has_seed(), 'args': {'refresh_cards_when_done': True}}, - {'icon': lv.ICON_SEED, 'label': 'New Seed', 'flow': NewSeedFlow, 'is_visible': lambda: not has_seed(), + {'icon': 'ICON_SEED', 'label': 'New Seed', 'flow': NewSeedFlow, 'is_visible': lambda: not has_seed(), 'args': {'refresh_cards_when_done': True}}, - {'icon': lv.ICON_SIGN, 'label': 'Sign Text File', 'flow': SignTextFileFlow, 'is_visible': has_seed}, + {'icon': 'ICON_SIGN', 'label': 'Sign Text File', 'flow': SignTextFileFlow, 'is_visible': has_seed}, ] @@ -254,12 +254,12 @@ def update_menu(): title = 'UPDATE' + (' FIRMWARE' if passport.IS_COLOR else '') return [ - {'icon': lv.ICON_FIRMWARE, + {'icon': 'ICON_FIRMWARE', 'label': 'Update Firmware', 'flow': UpdateFirmwareFlow, 'is_visible': is_logged_in, - 'statusbar': {'title': title, 'icon': lv.ICON_FIRMWARE}}, - {'icon': lv.ICON_INFO, 'label': 'Current Version', 'flow': ViewCurrentFirmwareFlow, 'statusbar': {}}, + 'statusbar': {'title': title, 'icon': 'ICON_FIRMWARE'}}, + {'icon': 'ICON_INFO', 'label': 'Current Version', 'flow': ViewCurrentFirmwareFlow, 'statusbar': {}}, ] @@ -267,9 +267,9 @@ def microsd_menu(): from flows import FormatMicroSDFlow, ListFilesFlow, ExportSummaryFlow return [ - {'icon': lv.ICON_MICROSD, 'label': 'Format Card', 'flow': FormatMicroSDFlow}, - {'icon': lv.ICON_FILE, 'label': 'List Files', 'flow': ListFilesFlow}, - {'icon': lv.ICON_INFO, 'label': 'Export Summary', 'flow': ExportSummaryFlow, 'is_visible': has_seed}, + {'icon': 'ICON_MICROSD', 'label': 'Format Card', 'flow': FormatMicroSDFlow}, + {'icon': 'ICON_FILE', 'label': 'List Files', 'flow': ListFilesFlow}, + {'icon': 'ICON_INFO', 'label': 'Export Summary', 'flow': ExportSummaryFlow, 'is_visible': has_seed}, ] @@ -278,13 +278,13 @@ def multisig_item_menu(): ExportMultisigQRFlow, ExportMultisigMicrosdFlow) return [ - {'icon': lv.ICON_TWO_KEYS, 'label': 'View Details', 'flow': ViewMultisigDetailsFlow}, - {'icon': lv.ICON_SCAN_QR, 'label': 'Export via QR', 'flow': ExportMultisigQRFlow, + {'icon': 'ICON_TWO_KEYS', 'label': 'View Details', 'flow': ViewMultisigDetailsFlow}, + {'icon': 'ICON_SCAN_QR', 'label': 'Export via QR', 'flow': ExportMultisigQRFlow, 'statusbar': {'title': 'EXPORT'}}, - {'icon': lv.ICON_MICROSD, 'label': 'Export via microSD', 'flow': ExportMultisigMicrosdFlow, + {'icon': 'ICON_MICROSD', 'label': 'Export via microSD', 'flow': ExportMultisigMicrosdFlow, 'statusbar': {'title': 'EXPORT'}}, - {'icon': lv.ICON_TWO_KEYS, 'label': 'Rename', 'flow': RenameMultisigFlow, 'exit_on_success': True}, - {'icon': lv.ICON_TWO_KEYS, 'label': 'Delete', 'flow': DeleteMultisigFlow, 'exit_on_success': True}, + {'icon': 'ICON_TWO_KEYS', 'label': 'Rename', 'flow': RenameMultisigFlow, 'exit_on_success': True}, + {'icon': 'ICON_TWO_KEYS', 'label': 'Delete', 'flow': DeleteMultisigFlow, 'exit_on_success': True}, ] @@ -294,14 +294,14 @@ def multisig_menu(): from flows import ImportMultisigWalletFromMicroSDFlow, ImportMultisigWalletFromQRFlow if not MultisigWallet.exists(): - items = [{'icon': lv.ICON_TWO_KEYS, 'label': '(None setup yet)', 'page': ErrorPage, + items = [{'icon': 'ICON_TWO_KEYS', 'label': '(None setup yet)', 'page': ErrorPage, 'args': {'text': "You haven't imported any multisig wallets yet."}}] else: items = [] for ms in MultisigWallet.get_all(): nice_name = '%d/%d: %s' % (ms.M, ms.N, ms.name) items.append({ - 'icon': lv.ICON_TWO_KEYS, + 'icon': 'ICON_TWO_KEYS', 'label': nice_name, 'submenu': multisig_item_menu, # Adding this below causes the header to stick around after it shoudl be gone @@ -310,11 +310,11 @@ def multisig_menu(): 'args': {'context': ms.storage_idx} }) - items.append({'icon': lv.ICON_SCAN_QR, 'label': 'Import from QR', 'flow': ImportMultisigWalletFromQRFlow, + items.append({'icon': 'ICON_SCAN_QR', 'label': 'Import from QR', 'flow': ImportMultisigWalletFromQRFlow, 'statusbar': {'title': 'IMPORT'}}) - items.append({'icon': lv.ICON_MICROSD, 'label': 'Import from microSD', + items.append({'icon': 'ICON_MICROSD', 'label': 'Import from microSD', 'flow': ImportMultisigWalletFromMicroSDFlow, 'statusbar': {'title': 'IMPORT'}}) - items.append({'icon': lv.ICON_SETTINGS, 'label': 'Multisig Policy', 'page': MultisigPolicySettingPage}) + items.append({'icon': 'ICON_SETTINGS', 'label': 'Multisig Policy', 'page': MultisigPolicySettingPage}) return items @@ -324,11 +324,11 @@ def developer_pubkey_menu(): from flows import InstallDevPubkeyFlow, ViewDevPubkeyFlow, RemoveDevPubkeyFlow return [ - {'icon': lv.ICON_ONE_KEY, 'label': 'Install PubKey', 'flow': InstallDevPubkeyFlow, + {'icon': 'ICON_ONE_KEY', 'label': 'Install PubKey', 'flow': InstallDevPubkeyFlow, 'is_visible': lambda: not has_dev_pubkey()}, - {'icon': lv.ICON_ONE_KEY, 'label': 'View PubKey', 'flow': ViewDevPubkeyFlow, + {'icon': 'ICON_ONE_KEY', 'label': 'View PubKey', 'flow': ViewDevPubkeyFlow, 'is_visible': has_dev_pubkey}, - {'icon': lv.ICON_CANCEL, 'label': 'Remove Pubkey', 'flow': RemoveDevPubkeyFlow, + {'icon': 'ICON_CANCEL', 'label': 'Remove Pubkey', 'flow': RemoveDevPubkeyFlow, 'is_visible': has_dev_pubkey} ] @@ -337,14 +337,14 @@ def advanced_menu(): from flows import ViewSeedWordsFlow, ErasePassportFlow, ScvFlow, ShowSecurityWordsSettingFlow return [ - {'icon': lv.ICON_SETTINGS, 'label': 'Security Words', 'flow': ShowSecurityWordsSettingFlow}, - {'icon': lv.ICON_SEED, 'label': 'View Seed Words', 'flow': ViewSeedWordsFlow, 'is_visible': has_seed, - 'statusbar': {'title': 'SEED WORDS', 'icon': lv.ICON_SEED}}, - {'icon': lv.ICON_ONE_KEY, 'label': 'Developer Pubkey', 'submenu': developer_pubkey_menu, + {'icon': 'ICON_SETTINGS', 'label': 'Security Words', 'flow': ShowSecurityWordsSettingFlow}, + {'icon': 'ICON_SEED', 'label': 'View Seed Words', 'flow': ViewSeedWordsFlow, 'is_visible': has_seed, + 'statusbar': {'title': 'SEED WORDS', 'icon': 'ICON_SEED'}}, + {'icon': 'ICON_ONE_KEY', 'label': 'Developer Pubkey', 'submenu': developer_pubkey_menu, 'statusbar': {'title': 'DEV. PUBKEY'}}, - {'icon': lv.ICON_MICROSD, 'label': 'microSD', 'submenu': microsd_menu}, - {'icon': lv.ICON_ERASE, 'label': 'Erase Passport', 'flow': ErasePassportFlow}, - {'icon': lv.ICON_SHIELD, 'label': 'Security Check', 'flow': ScvFlow, + {'icon': 'ICON_MICROSD', 'label': 'microSD', 'submenu': microsd_menu}, + {'icon': 'ICON_ERASE', 'label': 'Erase Passport', 'flow': ErasePassportFlow}, + {'icon': 'ICON_SHIELD', 'label': 'Security Check', 'flow': ScvFlow, 'args': {'envoy': False, 'ask_to_skip': False}}, ] @@ -371,32 +371,32 @@ def developer_menu(): from foundation import ur return [ - {'icon': lv.ICON_BATTERY, 'label': 'Battery', 'page': BatteryPage}, - {'icon': lv.ICON_ERASE, 'label': 'Factory Reset', + {'icon': 'ICON_BATTERY', 'label': 'Battery', 'page': BatteryPage}, + {'icon': 'ICON_ERASE', 'label': 'Factory Reset', 'flow': DeveloperFunctionsFlow, 'args': {'fn_name': 'factory_reset'}}, - {'icon': lv.ICON_RETRY, 'label': 'Spin!!!', 'flow': SpinDelayFlow, 'args': {'delay_ms': 10000}}, - {'icon': lv.ICON_SETTINGS, 'label': 'Dump Settings', + {'icon': 'ICON_RETRY', 'label': 'Spin!!!', 'flow': SpinDelayFlow, 'args': {'delay_ms': 10000}}, + {'icon': 'ICON_SETTINGS', 'label': 'Dump Settings', 'flow': DeveloperFunctionsFlow, 'args': {'fn_name': 'dump_settings'}}, - {'icon': lv.ICON_SCAN_QR, 'label': 'Show Setup QR', 'page': StatusPage, 'args': { + {'icon': 'ICON_SCAN_QR', 'label': 'Show Setup QR', 'page': StatusPage, 'args': { 'text': 'Scan the QR code above with Envoy.', 'icon': lv.LARGE_ICON_SETUP_QR}, 'card_header': {}}, - {'icon': lv.ICON_SCAN_QR, 'label': 'Show Test UR', 'page': ShowQRPage, 'args': { + {'icon': 'ICON_SCAN_QR', 'label': 'Show Test UR', 'page': ShowQRPage, 'args': { 'qr_type': QRType.UR2, 'qr_data': ur.new_bytes('test data' * 10)}}, - {'icon': lv.ICON_SHIELD, 'label': 'Supply Chain', 'flow': ScvFlow}, - {'icon': lv.ICON_ONE_KEY, 'label': 'Login', 'flow': LoginFlow}, - {'icon': lv.ICON_SEED, 'label': 'New Seed', 'flow': NewSeedFlow, 'args': {'refresh_cards_when_done': True}}, - {'icon': lv.ICON_ONE_KEY, 'label': 'Set PIN', 'flow': SetInitialPINFlow}, - {'icon': lv.ICON_ERASE, 'label': 'Erase Child Keys', 'flow': DeleteDerivedKeysFlow}, - {'icon': lv.ICON_SETTINGS, 'label': 'FCC Test', 'flow': FCCTestFlow}, - # {'icon': lv.ICON_SETTINGS, 'label': 'I\'m Busy!', 'page': LongTextPage, + {'icon': 'ICON_SHIELD', 'label': 'Supply Chain', 'flow': ScvFlow}, + {'icon': 'ICON_ONE_KEY', 'label': 'Login', 'flow': LoginFlow}, + {'icon': 'ICON_SEED', 'label': 'New Seed', 'flow': NewSeedFlow, 'args': {'refresh_cards_when_done': True}}, + {'icon': 'ICON_ONE_KEY', 'label': 'Set PIN', 'flow': SetInitialPINFlow}, + {'icon': 'ICON_ERASE', 'label': 'Erase Child Keys', 'flow': DeleteDerivedKeysFlow}, + {'icon': 'ICON_SETTINGS', 'label': 'FCC Test', 'flow': FCCTestFlow}, + # {'icon': 'ICON_SETTINGS', 'label': 'I\'m Busy!', 'page': LongTextPage, # 'args': {'show_busy': True, 'message': 'Signing Transaction...'}}, - # {'icon': lv.ICON_ABOUT, 'label': 'Color Picker', 'page': ColorPickerPage}, - # {'icon': lv.ICON_CHANGE_PIN, 'label': 'Enter PIN', 'page': PINEntryPage, + # {'icon': 'ICON_ABOUT', 'label': 'Color Picker', 'page': ColorPickerPage}, + # {'icon': 'ICON_CHANGE_PIN', 'label': 'Enter PIN', 'page': PINEntryPage, # 'args': {'title': 'Enter Initial PIN'}}, - # {'icon': lv.ICON_FOLDER, 'label': 'Rename Account', 'page': TextInputPage, - # 'args': {'card_header': {'title': 'Rename Account', 'icon': lv.ICON_ABOUT, 'right_text': '!!', + # {'icon': 'ICON_FOLDER', 'label': 'Rename Account', 'page': TextInputPage, + # 'args': {'card_header': {'title': 'Rename Account', 'icon': 'ICON_ABOUT', 'right_text': '!!', # 'bg_color': RED, 'fg_color': FD_BLUE}}}, - # {'icon': lv.ICON_SEED, 'label': 'Enter Seed', 'page': PredictiveTextInputPage}, - # {'icon': lv.ICON_CHANGE_PIN, 'label': 'Enter Backup Code', 'page': BackupCodePage}, + # {'icon': 'ICON_SEED', 'label': 'Enter Seed', 'page': PredictiveTextInputPage}, + # {'icon': 'ICON_CHANGE_PIN', 'label': 'Enter Backup Code', 'page': BackupCodePage}, ] else: return [] @@ -411,11 +411,11 @@ def settings_menu(): from utils import is_logged_in, is_dev_build return [ - {'icon': lv.ICON_DEVICE, 'label': 'Device', 'submenu': device_menu}, - {'icon': lv.ICON_BACKUP, 'label': 'Backup', 'submenu': backup_menu, 'is_visible': is_logged_in}, - {'icon': lv.ICON_FIRMWARE, 'label': 'Firmware', 'submenu': update_menu}, - {'icon': lv.ICON_BITCOIN, 'label': 'Bitcoin', 'submenu': bitcoin_menu, 'is_visible': is_logged_in}, - {'icon': lv.ICON_ADVANCED, 'label': 'Advanced', 'submenu': advanced_menu, 'is_visible': is_logged_in}, - {'icon': lv.ICON_EXTENSIONS, 'label': 'Extensions', 'submenu': extensions_menu}, - {'icon': lv.ICON_ADVANCED, 'label': 'Developer', 'submenu': developer_menu, 'is_visible': is_dev_build} + {'icon': 'ICON_DEVICE', 'label': 'Device', 'submenu': device_menu}, + {'icon': 'ICON_BACKUP', 'label': 'Backup', 'submenu': backup_menu, 'is_visible': is_logged_in}, + {'icon': 'ICON_FIRMWARE', 'label': 'Firmware', 'submenu': update_menu}, + {'icon': 'ICON_BITCOIN', 'label': 'Bitcoin', 'submenu': bitcoin_menu, 'is_visible': is_logged_in}, + {'icon': 'ICON_ADVANCED', 'label': 'Advanced', 'submenu': advanced_menu, 'is_visible': is_logged_in}, + {'icon': 'ICON_EXTENSIONS', 'label': 'Extensions', 'submenu': extensions_menu}, + {'icon': 'ICON_ADVANCED', 'label': 'Developer', 'submenu': developer_menu, 'is_visible': is_dev_build} ] diff --git a/ports/stm32/boards/Passport/modules/pages/chooser_page.py b/ports/stm32/boards/Passport/modules/pages/chooser_page.py index b78d26553..8be334cd5 100644 --- a/ports/stm32/boards/Passport/modules/pages/chooser_page.py +++ b/ports/stm32/boards/Passport/modules/pages/chooser_page.py @@ -22,7 +22,7 @@ class ChooserPage(Page): def __init__( self, card_header=None, statusbar=None, options=[], initial_value=None, on_change=None, scroll_fix=False, - icon=None, icon_color=CHOOSER_ICON, text=None, center=False, item_icon=lv.ICON_SMALL_CHECKMARK, + icon=None, icon_color=CHOOSER_ICON, text=None, center=False, item_icon='ICON_SMALL_CHECKMARK', left_micron=None, right_micron=None): from views import ListItem, View diff --git a/ports/stm32/boards/Passport/modules/pages/pin_entry_page.py b/ports/stm32/boards/Passport/modules/pages/pin_entry_page.py index 54f64e4e9..88df83ad0 100644 --- a/ports/stm32/boards/Passport/modules/pages/pin_entry_page.py +++ b/ports/stm32/boards/Passport/modules/pages/pin_entry_page.py @@ -98,7 +98,7 @@ def show_brick_warning(self): message = 'This is your FINAL attempt before Passport is permanently disabled.' else: message = '{} attempts left\nuntil Passport is permanently disabled.'.format(pa.attempts_left) - self.update_message(show_security_words=False, title='WARNING', icon=lv.ICON_WARNING, + self.update_message(show_security_words=False, title='WARNING', icon='ICON_WARNING', message=message, color=COPPER) self.brick_warning_shown = True diff --git a/ports/stm32/boards/Passport/modules/ui/ui.py b/ports/stm32/boards/Passport/modules/ui/ui.py index 223888cdd..b5bbc9008 100644 --- a/ports/stm32/boards/Passport/modules/ui/ui.py +++ b/ports/stm32/boards/Passport/modules/ui/ui.py @@ -149,7 +149,7 @@ def create_single_card(self, flow, card=None, args=None, add_settings=False): card = { 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'PASSPORT', 'icon': lv.ICON_HAMBURGER, 'fg_color': WHITE}, + 'statusbar': {'title': 'PASSPORT', 'icon': 'ICON_HAMBURGER', 'fg_color': WHITE}, 'page_micron': microns.PageDot, 'bg_color': TEXT_GREY, 'flow': flow @@ -182,7 +182,7 @@ def make_settings_card(self): return { 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'SETTINGS', 'icon': lv.ICON_HAMBURGER, 'fg_color': WHITE}, + 'statusbar': {'title': 'SETTINGS', 'icon': 'ICON_HAMBURGER', 'fg_color': WHITE}, 'page_micron': microns.PageHome, 'bg_color': TEXT_GREY, 'flow': MenuFlow, @@ -244,10 +244,10 @@ def update_cards( # print('account[{}]={}'.format(account, i)) account_card = { - 'right_icon': lv.ICON_BITCOIN, + 'right_icon': 'ICON_BITCOIN', 'header_color': LIGHT_GREY, 'header_fg_color': LIGHT_TEXT, - 'statusbar': {'title': 'ACCOUNT', 'icon': lv.ICON_FOLDER, 'fg_color': get_account_fg(account)}, + 'statusbar': {'title': 'ACCOUNT', 'icon': 'ICON_FOLDER', 'fg_color': get_account_fg(account)}, 'title': account.get('name'), 'page_micron': microns.PageDot, 'bg_color': get_account_bg(account), @@ -256,7 +256,7 @@ def update_cards( 'account': account } if len(stash.bip39_passphrase) > 0: - account_card['icon'] = lv.ICON_PASSPHRASE + account_card['icon'] = 'ICON_PASSPHRASE' card_descs.append(account_card) @@ -265,13 +265,13 @@ def update_cards( for extension in supported_extensions: if common.settings.get('ext.{}.enabled'.format(extension['name']), False): if len(stash.bip39_passphrase) > 0: - extension['card']['icon'] = lv.ICON_PASSPHRASE + extension['card']['icon'] = 'ICON_PASSPHRASE' else: extension['card']['icon'] = None card_descs.append(extension['card']) more_card = { - 'statusbar': {'title': 'MORE', 'icon': lv.ICON_ADD_ACCOUNT, 'fg_color': WHITE}, + 'statusbar': {'title': 'MORE', 'icon': 'ICON_ADD_ACCOUNT', 'fg_color': WHITE}, 'page_micron': microns.PagePlus, 'bg_color': DARK_GREY, 'flow': MenuFlow, diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index 8dedb79a3..506750735 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -174,7 +174,7 @@ def sd_card_cb(): sd_card_change = False saved = save_error_log(msg, filename) if saved: - common.ui.set_card_header(title='Saved to microSD', icon=lv.ICON_MICROSD) + common.ui.set_card_header(title='Saved to microSD', icon='ICON_MICROSD') await sleep_ms(100) @@ -214,7 +214,7 @@ def handle_fatal_error(exc): # Switch immediately to a new card to show the error fatal_error_card = { - 'statusbar': {'title': 'FATAL ERROR', 'icon': lv.ICON_INFO}, + 'statusbar': {'title': 'FATAL ERROR', 'icon': 'ICON_INFO'}, 'page_micron': microns.PageDot, 'bg_color': BLACK, 'flow': PageFlow, @@ -224,9 +224,9 @@ def handle_fatal_error(exc): common.ui.set_cards([fatal_error_card]) if saved: - common.ui.set_card_header(title='Saved to microSD', icon=lv.ICON_MICROSD) + common.ui.set_card_header(title='Saved to microSD', icon='ICON_MICROSD') else: - common.ui.set_card_header(title='Insert microSD', icon=lv.ICON_MICROSD) + common.ui.set_card_header(title='Insert microSD', icon='ICON_MICROSD') loop = get_event_loop() _fatal_card_task = loop.create_task(card_task(fatal_error_card)) diff --git a/ports/stm32/boards/Passport/modules/views/battery_indicator.py b/ports/stm32/boards/Passport/modules/views/battery_indicator.py index 561a2d4e9..838dbca0d 100644 --- a/ports/stm32/boards/Passport/modules/views/battery_indicator.py +++ b/ports/stm32/boards/Passport/modules/views/battery_indicator.py @@ -23,7 +23,7 @@ def __init__(self, outline_color=WHITE): self.is_charging = False self.outline_color = outline_color - self.icon = Icon(lv.ICON_BATTERY, color=WHITE) + self.icon = Icon('ICON_BATTERY', color=WHITE) self.set_size(lv.SIZE.CONTENT, lv.SIZE.CONTENT) with Stylize(self.icon) as default: default.align(lv.ALIGN.CENTER) @@ -58,9 +58,9 @@ def set_percent(self, percent): def set_is_charging(self, is_charging): self.is_charging = is_charging if self.is_charging: - self.icon.set_icon(lv.ICON_BATTERY_CHARGING) + self.icon.set_icon('ICON_BATTERY_CHARGING') else: - self.icon.set_icon(lv.ICON_BATTERY) + self.icon.set_icon('ICON_BATTERY') def set_outline_color(self, outline_color): self.outline_color = outline_color diff --git a/ports/stm32/boards/Passport/modules/views/file_item.py b/ports/stm32/boards/Passport/modules/views/file_item.py index 0e0fe4fc9..3317e918e 100644 --- a/ports/stm32/boards/Passport/modules/views/file_item.py +++ b/ports/stm32/boards/Passport/modules/views/file_item.py @@ -38,7 +38,7 @@ def __init__(self, filename='', is_folder=False): focus.img_recolor(FOCUSED_LIST_ITEM_TEXT) # Icon - self.icon_view = Icon(icon=lv.ICON_FOLDER if self.is_folder else lv.ICON_FILE) + self.icon_view = Icon(icon='ICON_FOLDER' if self.is_folder else 'ICON_FILE') # Filename self.filename_view = Label(text=self.filename) diff --git a/ports/stm32/boards/Passport/modules/views/icon.py b/ports/stm32/boards/Passport/modules/views/icon.py index 685b5a785..d37bea9a4 100644 --- a/ports/stm32/boards/Passport/modules/views/icon.py +++ b/ports/stm32/boards/Passport/modules/views/icon.py @@ -11,7 +11,11 @@ class Icon(View): def __init__(self, icon, color=None, opa=None): super().__init__() - self.icon = icon + # Icon is expected to be a string + if isinstance(icon, str): + self.icon = getattr(lv, icon) + else: + self.icon = icon self.color = color self.opa = opa diff --git a/ports/stm32/boards/Passport/modules/views/list_item.py b/ports/stm32/boards/Passport/modules/views/list_item.py index f73e8db09..4e1fdba9e 100644 --- a/ports/stm32/boards/Passport/modules/views/list_item.py +++ b/ports/stm32/boards/Passport/modules/views/list_item.py @@ -13,7 +13,7 @@ class ListItem(View): - def __init__(self, label='', is_selected=False, icon=lv.ICON_SMALL_CHECKMARK, center=False): + def __init__(self, label='', is_selected=False, icon='ICON_SMALL_CHECKMARK', center=False): super().__init__(flex_flow=lv.FLEX_FLOW.ROW) self.icon = icon diff --git a/ports/stm32/boards/Passport/modules/views/micron_bar.py b/ports/stm32/boards/Passport/modules/views/micron_bar.py index 49001b9ae..8cb91073d 100644 --- a/ports/stm32/boards/Passport/modules/views/micron_bar.py +++ b/ports/stm32/boards/Passport/modules/views/micron_bar.py @@ -117,7 +117,7 @@ def update_pagination_dots(self): page_dot.add_child(icon) if i == self.active_card_idx: - indicator = Icon(icon=lv.ICON_PAGE_INDICATOR, color=WHITE) + indicator = Icon(icon='ICON_PAGE_INDICATOR', color=WHITE) page_dot.add_child(indicator) # print('page_dot={}'.format(page_dot)) diff --git a/ports/stm32/boards/Passport/modules/views/pin_input.py b/ports/stm32/boards/Passport/modules/views/pin_input.py index 59d86483c..f2511d3d0 100644 --- a/ports/stm32/boards/Passport/modules/views/pin_input.py +++ b/ports/stm32/boards/Passport/modules/views/pin_input.py @@ -69,7 +69,7 @@ def update_pin(self): elif i == num_chars - 1 and self.show_last_char: item = Label(text=ch, color=TEXT_INPUT_TEXT) else: - item = Icon(lv.ICON_PAGE_DOT, color=TEXT_INPUT_TEXT) + item = Icon('ICON_PAGE_DOT', color=TEXT_INPUT_TEXT) self.pin_container.add_child(item) # Finally, draw a "cursor", which is always at the end diff --git a/ports/stm32/boards/Passport/modules/views/statusbar.py b/ports/stm32/boards/Passport/modules/views/statusbar.py index 193f64a21..59420c8be 100644 --- a/ports/stm32/boards/Passport/modules/views/statusbar.py +++ b/ports/stm32/boards/Passport/modules/views/statusbar.py @@ -19,14 +19,12 @@ def __init__(self, title='', icon=None, fg_color=WHITE): self.title = title self.icon = icon self.fg_color = fg_color + self.bg_color = BLACK self.title_view = None self.icon_view = None with Stylize(self) as default: - # if not passport.IS_COLOR: - # default.bg_color(BLACK) - if passport.IS_COLOR: top_pad = 0 else: @@ -64,11 +62,16 @@ def update_icon(self): if self.is_mounted(): self.icon_view.unmount() self.remove_child(self.icon_view) + if hasattr(self, "bg_view"): + self.bg_view.unmount() + self.remove_child(self.bg_view) if self.icon is None: - icon_view = Icon(icon=lv.ICON_SETTINGS, opa=0) # Transparent placeholder - else: - icon_view = Icon(icon=self.icon, color=self.fg_color) + self.icon = 'ICON_SETTINGS' + + icon_view = Icon(icon=self.icon, color=self.fg_color) + if not passport.IS_COLOR and isinstance(self.icon, str): + bg_view = Icon(icon=(self.icon + '_BACKGROUND'), color=self.bg_color) if passport.IS_COLOR: self.icon_view = icon_view @@ -76,11 +79,14 @@ def update_icon(self): self.icon_view = View(flex_flow=None) self.icon_view.set_size(lv.SIZE.CONTENT, lv.SIZE.CONTENT) with Stylize(self.icon_view) as default: - default.bg_color(BLACK) default.pad_all(2) default.radius(4) default.align(lv.ALIGN.CENTER) + if isinstance(self.icon, str): + self.icon_view.add_child(bg_view) + icon_view.set_pos(1, 1) + self.icon_view.add_child(icon_view) self.insert_child(0, self.icon_view) From 5af467d078368e030c1460c7a2513c940f9c6725 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Mon, 12 Jun 2023 12:58:29 -0500 Subject: [PATCH 181/187] SFT-1071: added background to battery indicator --- ports/stm32/boards/Passport/modules/views/statusbar.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/views/statusbar.py b/ports/stm32/boards/Passport/modules/views/statusbar.py index 59420c8be..21d3cd9cd 100644 --- a/ports/stm32/boards/Passport/modules/views/statusbar.py +++ b/ports/stm32/boards/Passport/modules/views/statusbar.py @@ -46,15 +46,18 @@ def __init__(self, title='', icon=None, fg_color=WHITE): if passport.IS_COLOR: self.add_child(self.battery) else: + battery_bg = Icon(icon='ICON_BATTERY_BACKGROUND', color=self.bg_color) + self.battery_container = View(flex_flow=None) self.battery_container.set_size(lv.SIZE.CONTENT, lv.SIZE.CONTENT) # self.battery_container.set_size(24, 24) with Stylize(self.battery_container) as default: - default.bg_color(BLACK) default.pad(left=2, right=2) default.radius(4) default.align(lv.ALIGN.CENTER) + self.battery_container.add_child(battery_bg) + self.battery.set_pos(1, 1) self.battery_container.add_child(self.battery) self.add_child(self.battery_container) From c67d6ed87c1efc69bc923f46d303093235f54144 Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 13 Jun 2023 10:04:12 -0500 Subject: [PATCH 182/187] SFT-1071: added fallback to black fill for mono backgrounds --- ports/stm32/boards/Passport/images/images.h | 3 - .../images/mono/ICON_BACK_BACKGROUND.c | 56 ------------------ ...ICON_BACK_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 201 -> 0 bytes .../images/mono/ICON_CANCEL_BACKGROUND.c | 56 ------------------ ...ON_CANCEL_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 221 -> 0 bytes .../images/mono/ICON_FORWARD_BACKGROUND.c | 56 ------------------ ...N_FORWARD_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 199 -> 0 bytes .../Passport/modules/views/statusbar.py | 13 ++-- 8 files changed, 8 insertions(+), 176 deletions(-) delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND__CF_INDEXED_1_BIT.png diff --git a/ports/stm32/boards/Passport/images/images.h b/ports/stm32/boards/Passport/images/images.h index cb44a8216..471adaba6 100644 --- a/ports/stm32/boards/Passport/images/images.h +++ b/ports/stm32/boards/Passport/images/images.h @@ -93,7 +93,6 @@ extern const lv_img_dsc_t ICON_ADVANCED_BACKGROUND; extern const lv_img_dsc_t ICON_ADVANCED; extern const lv_img_dsc_t ICON_BACKUP_BACKGROUND; extern const lv_img_dsc_t ICON_BACKUP; -extern const lv_img_dsc_t ICON_BACK_BACKGROUND; extern const lv_img_dsc_t ICON_BACK; extern const lv_img_dsc_t ICON_BATTERY_BACKGROUND; extern const lv_img_dsc_t ICON_BATTERY_CHARGING; @@ -102,7 +101,6 @@ extern const lv_img_dsc_t ICON_BITCOIN_BACKGROUND; extern const lv_img_dsc_t ICON_BITCOIN; extern const lv_img_dsc_t ICON_BRIGHTNESS_BACKGROUND; extern const lv_img_dsc_t ICON_BRIGHTNESS; -extern const lv_img_dsc_t ICON_CANCEL_BACKGROUND; extern const lv_img_dsc_t ICON_CANCEL; extern const lv_img_dsc_t ICON_CASA_BACKGROUND; extern const lv_img_dsc_t ICON_CASA; @@ -132,7 +130,6 @@ extern const lv_img_dsc_t ICON_FIRMWARE_BACKGROUND; extern const lv_img_dsc_t ICON_FIRMWARE; extern const lv_img_dsc_t ICON_FOLDER_BACKGROUND; extern const lv_img_dsc_t ICON_FOLDER; -extern const lv_img_dsc_t ICON_FORWARD_BACKGROUND; extern const lv_img_dsc_t ICON_FORWARD; extern const lv_img_dsc_t ICON_HAMBURGER_BACKGROUND; extern const lv_img_dsc_t ICON_HAMBURGER; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND.c deleted file mode 100644 index 64692ce4a..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND.c +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_BACK_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_BACK_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_BACK_BACKGROUND uint8_t ICON_BACK_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x0f, 0x00, - 0x00, 0x1f, 0x00, - 0x00, 0x3f, 0x00, - 0x00, 0x7f, 0x00, - 0x00, 0xfe, 0x00, - 0x01, 0xfc, 0x00, - 0x03, 0xf8, 0x00, - 0x07, 0xf0, 0x00, - 0x07, 0xe0, 0x00, - 0x07, 0xe0, 0x00, - 0x07, 0xf0, 0x00, - 0x03, 0xf8, 0x00, - 0x01, 0xfc, 0x00, - 0x00, 0xfe, 0x00, - 0x00, 0x7f, 0x00, - 0x00, 0x3f, 0x00, - 0x00, 0x1f, 0x00, - 0x00, 0x0f, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_BACK_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_BACK_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_BACK_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index 3ad9f03a187438beede02cd57624e6728389e631..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBew?R^V@L(#)hnJt3<5kZ7YqJd2lF-j^KA9X z|0rfOBh=e?-a?7HNiWP;rUf!7m$?3X{IIgVIrhcd3%&F7S}us*$}74b9N~AX!A3t$ r;=h?fUW~3>-1;Tj0`triz8W!lP2-h`U9Hvww28sf)z4*}Q$iB}hw466 diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND.c deleted file mode 100644 index ab2e5efc4..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND.c +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_CANCEL_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_CANCEL_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CANCEL_BACKGROUND uint8_t ICON_CANCEL_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x3c, 0x00, 0xf0, - 0x3e, 0x01, 0xf0, - 0x3f, 0x03, 0xf0, - 0x3f, 0x87, 0xf0, - 0x1f, 0xcf, 0xe0, - 0x0f, 0xff, 0xc0, - 0x07, 0xff, 0x80, - 0x03, 0xff, 0x00, - 0x01, 0xfe, 0x00, - 0x01, 0xfe, 0x00, - 0x03, 0xff, 0x00, - 0x07, 0xff, 0x80, - 0x0f, 0xff, 0xc0, - 0x1f, 0xcf, 0xe0, - 0x3f, 0x87, 0xf0, - 0x3f, 0x03, 0xf0, - 0x3e, 0x01, 0xf0, - 0x3c, 0x00, 0xf0, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_CANCEL_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_CANCEL_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CANCEL_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index 3b0d05cd10455bc1cd353e91e28055a438aba180..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 221 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBevzk(V@L(#)v4Zm4GKIilJD!&?`F09ymF-_ z((!gBXFx*F-Im)wR4kXRe9yrX$jcnO_=M*NE`{*s0}Tt(svOSU3wn|LiIGoI<3J)i z^N&mKOI$to=ewSMxOGePY1WNAd226=8YJ^;8gyB5mC03oH@@K@Zhlo%YK!3O1fcB< Mp00i_>zopr0MOk@ZU6uP diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND.c deleted file mode 100644 index e874e0bfe..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND.c +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_FORWARD_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_FORWARD_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_FORWARD_BACKGROUND uint8_t ICON_FORWARD_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x03, 0xc0, 0x00, - 0x03, 0xe0, 0x00, - 0x03, 0xf0, 0x00, - 0x03, 0xf8, 0x00, - 0x01, 0xfc, 0x00, - 0x00, 0xfe, 0x00, - 0x00, 0x7f, 0x00, - 0x00, 0x3f, 0x80, - 0x00, 0x1f, 0x80, - 0x00, 0x1f, 0x80, - 0x00, 0x3f, 0x80, - 0x00, 0x7f, 0x00, - 0x00, 0xfe, 0x00, - 0x01, 0xfc, 0x00, - 0x03, 0xf8, 0x00, - 0x03, 0xf0, 0x00, - 0x03, 0xe0, 0x00, - 0x03, 0xc0, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_FORWARD_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_FORWARD_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_FORWARD_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index 4ac7dcc3326943b1894788c32d17fc401b0648c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBevGG!V@L(#)yal@3<^9 Date: Tue, 13 Jun 2023 14:59:41 -0500 Subject: [PATCH 183/187] SFT-1071: removed unused images and backgrounds --- .../boards/Passport/images/color/ICON_EDIT1.c | 53 ----------------- .../color/ICON_EDIT1__CF_INDEXED_2_BIT.png | Bin 269 -> 0 bytes .../boards/Passport/images/color/ICON_EDIT2.c | 53 ----------------- .../color/ICON_EDIT2__CF_INDEXED_2_BIT.png | Bin 361 -> 0 bytes ports/stm32/boards/Passport/images/images.h | 12 ---- .../images/mono/ICON_CASA_BACKGROUND.c | 56 ------------------ ...ICON_CASA_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 149 -> 0 bytes .../images/mono/ICON_CHECKMARK_BACKGROUND.c | 56 ------------------ ...CHECKMARK_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 206 -> 0 bytes .../boards/Passport/images/mono/ICON_EDIT1.c | 54 ----------------- .../images/mono/ICON_EDIT1_BACKGROUND.c | 56 ------------------ ...CON_EDIT1_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 223 -> 0 bytes .../mono/ICON_EDIT1__CF_INDEXED_1_BIT.png | Bin 216 -> 0 bytes .../boards/Passport/images/mono/ICON_EDIT2.c | 54 ----------------- .../images/mono/ICON_EDIT2_BACKGROUND.c | 56 ------------------ ...CON_EDIT2_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 184 -> 0 bytes .../mono/ICON_EDIT2__CF_INDEXED_1_BIT.png | Bin 233 -> 0 bytes .../images/mono/ICON_NOSTR_BACKGROUND.c | 56 ------------------ ...CON_NOSTR_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 228 -> 0 bytes .../images/mono/ICON_SHUTDOWN_BACKGROUND.c | 56 ------------------ ..._SHUTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 195 -> 0 bytes .../images/mono/ICON_SPIRAL_BACKGROUND.c | 56 ------------------ ...ON_SPIRAL_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 205 -> 0 bytes .../images/mono/ICON_WARNING_BACKGROUND.c | 56 ------------------ ...N_WARNING_BACKGROUND__CF_INDEXED_1_BIT.png | Bin 197 -> 0 bytes 25 files changed, 674 deletions(-) delete mode 100644 ports/stm32/boards/Passport/images/color/ICON_EDIT1.c delete mode 100644 ports/stm32/boards/Passport/images/color/ICON_EDIT1__CF_INDEXED_2_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/color/ICON_EDIT2.c delete mode 100644 ports/stm32/boards/Passport/images/color/ICON_EDIT2__CF_INDEXED_2_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT1.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT1__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT2.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_EDIT2__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_NOSTR_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_NOSTR_BACKGROUND__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND__CF_INDEXED_1_BIT.png delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_WARNING_BACKGROUND.c delete mode 100644 ports/stm32/boards/Passport/images/mono/ICON_WARNING_BACKGROUND__CF_INDEXED_1_BIT.png diff --git a/ports/stm32/boards/Passport/images/color/ICON_EDIT1.c b/ports/stm32/boards/Passport/images/color/ICON_EDIT1.c deleted file mode 100644 index 992a8c485..000000000 --- a/ports/stm32/boards/Passport/images/color/ICON_EDIT1.c +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif -#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT1 -#define LV_ATTRIBUTE_IMG_ICON_EDIT1 -#endif -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_ICON_EDIT1 uint8_t ICON_EDIT1_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0xff, 0xff, 0xff, 0x28, /*Color of index 1*/ - 0xfe, 0xfe, 0xfe, 0x99, /*Color of index 2*/ - 0xfe, 0xfe, 0xfe, 0xe9, /*Color of index 3*/ - - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1b, 0xe0, - 0x00, 0x00, 0x00, 0x7e, 0xb8, - 0x00, 0x00, 0x01, 0xf4, 0x3c, - 0x00, 0x00, 0x07, 0xd0, 0x2c, - 0x00, 0x00, 0x1f, 0x40, 0x78, - 0x00, 0x00, 0x7d, 0x01, 0xf4, - 0x00, 0x01, 0xf4, 0x07, 0xd0, - 0x00, 0x07, 0xd0, 0x1f, 0x40, - 0x00, 0x1f, 0x40, 0x7d, 0x00, - 0x00, 0x7d, 0x01, 0xf4, 0x00, - 0x01, 0xf4, 0x07, 0xd0, 0x00, - 0x07, 0xd0, 0x1f, 0x40, 0x00, - 0x0b, 0x40, 0x7d, 0x00, 0x00, - 0x1e, 0x01, 0xf4, 0x00, 0x00, - 0x1d, 0x07, 0xd0, 0x00, 0x00, - 0x2c, 0x6f, 0x40, 0x00, 0x00, - 0x3f, 0xfd, 0x00, 0x00, 0x00, - 0x7e, 0x90, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_EDIT1 = { - .header.cf = LV_IMG_CF_INDEXED_2BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 20, - .header.h = 20, - .data_size = 117, - .data = ICON_EDIT1_map, -}; diff --git a/ports/stm32/boards/Passport/images/color/ICON_EDIT1__CF_INDEXED_2_BIT.png b/ports/stm32/boards/Passport/images/color/ICON_EDIT1__CF_INDEXED_2_BIT.png deleted file mode 100644 index 3211950e90d67558ba41fd626672f31c6bf6ba8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 269 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`j)FbFd;%$g$s6l5$8 za(7}_cTVOdki(Mh=%mT+#MYZ*LU L{an^LB{Ts5HG*6B diff --git a/ports/stm32/boards/Passport/images/color/ICON_EDIT2.c b/ports/stm32/boards/Passport/images/color/ICON_EDIT2.c deleted file mode 100644 index 94bf05b8e..000000000 --- a/ports/stm32/boards/Passport/images/color/ICON_EDIT2.c +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif -#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT2 -#define LV_ATTRIBUTE_IMG_ICON_EDIT2 -#endif -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_ICON_EDIT2 uint8_t ICON_EDIT2_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0xff, 0xff, 0xff, 0x20, /*Color of index 1*/ - 0xfe, 0xfe, 0xfe, 0x65, /*Color of index 2*/ - 0xfe, 0xfe, 0xfe, 0xee, /*Color of index 3*/ - - 0x00, 0x00, 0x00, 0x00, 0x50, - 0x00, 0x00, 0x00, 0x07, 0xf8, - 0x06, 0xaa, 0x90, 0x1f, 0xbd, - 0x2f, 0xff, 0xf0, 0x7d, 0x2d, - 0x79, 0x55, 0x51, 0xf4, 0x7c, - 0x78, 0x00, 0x07, 0xd1, 0xf4, - 0x78, 0x00, 0x1f, 0x47, 0xd0, - 0x78, 0x00, 0x7d, 0x1f, 0x40, - 0x78, 0x01, 0xf4, 0x7d, 0x00, - 0x78, 0x07, 0xd1, 0xf4, 0x00, - 0x78, 0x0b, 0x47, 0xd1, 0xd0, - 0x78, 0x0f, 0x1f, 0x41, 0xe0, - 0x78, 0x0f, 0xfd, 0x01, 0xe0, - 0x78, 0x1f, 0xa4, 0x01, 0xe0, - 0x78, 0x04, 0x00, 0x01, 0xe0, - 0x78, 0x00, 0x00, 0x01, 0xe0, - 0x78, 0x00, 0x00, 0x01, 0xe0, - 0x3e, 0xaa, 0xaa, 0xaa, 0xe0, - 0x1f, 0xff, 0xff, 0xff, 0x80, - 0x01, 0x55, 0x55, 0x55, 0x00, -}; - -const lv_img_dsc_t ICON_EDIT2 = { - .header.cf = LV_IMG_CF_INDEXED_2BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 20, - .header.h = 20, - .data_size = 117, - .data = ICON_EDIT2_map, -}; diff --git a/ports/stm32/boards/Passport/images/color/ICON_EDIT2__CF_INDEXED_2_BIT.png b/ports/stm32/boards/Passport/images/color/ICON_EDIT2__CF_INDEXED_2_BIT.png deleted file mode 100644 index f6f51b4c91abd8854d6c6b46775f94e2043605af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 361 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`j)FbFd;%$g$s6l5$8 za(7}_cTVOdki(Mh=6AvnCIcSV;PZ?U3w;=rAFx?9 z_B>#Fp|Yz<_yyYr#=8z?D^3b-`Eu*hq5Y?y&hnO1T*8nuc#QVEb&EL&7OsGFM4gM@yaNPSi5-hyn`aEE&VSkK0Z8ma_ltLg#9yqx&-kS z8W$g0c7snT-ZO#6(-m$!0AD$ZkLxRE6)z4*}Q$iB} DkN$_; diff --git a/ports/stm32/boards/Passport/images/images.h b/ports/stm32/boards/Passport/images/images.h index 471adaba6..0ec2dbeab 100644 --- a/ports/stm32/boards/Passport/images/images.h +++ b/ports/stm32/boards/Passport/images/images.h @@ -21,8 +21,6 @@ extern const lv_img_dsc_t ICON_CLOCK; extern const lv_img_dsc_t ICON_CONNECT; extern const lv_img_dsc_t ICON_COUNTDOWN; extern const lv_img_dsc_t ICON_DEVICE; -extern const lv_img_dsc_t ICON_EDIT1; -extern const lv_img_dsc_t ICON_EDIT2; extern const lv_img_dsc_t ICON_ERASE; extern const lv_img_dsc_t ICON_EXTENSIONS; extern const lv_img_dsc_t ICON_FILE; @@ -102,9 +100,7 @@ extern const lv_img_dsc_t ICON_BITCOIN; extern const lv_img_dsc_t ICON_BRIGHTNESS_BACKGROUND; extern const lv_img_dsc_t ICON_BRIGHTNESS; extern const lv_img_dsc_t ICON_CANCEL; -extern const lv_img_dsc_t ICON_CASA_BACKGROUND; extern const lv_img_dsc_t ICON_CASA; -extern const lv_img_dsc_t ICON_CHECKMARK_BACKGROUND; extern const lv_img_dsc_t ICON_CHECKMARK; extern const lv_img_dsc_t ICON_CIRCLE_CHECK_BACKGROUND; extern const lv_img_dsc_t ICON_CIRCLE_CHECK; @@ -116,10 +112,6 @@ extern const lv_img_dsc_t ICON_COUNTDOWN_BACKGROUND; extern const lv_img_dsc_t ICON_COUNTDOWN; extern const lv_img_dsc_t ICON_DEVICE_BACKGROUND; extern const lv_img_dsc_t ICON_DEVICE; -extern const lv_img_dsc_t ICON_EDIT1_BACKGROUND; -extern const lv_img_dsc_t ICON_EDIT1; -extern const lv_img_dsc_t ICON_EDIT2_BACKGROUND; -extern const lv_img_dsc_t ICON_EDIT2; extern const lv_img_dsc_t ICON_ERASE_BACKGROUND; extern const lv_img_dsc_t ICON_ERASE; extern const lv_img_dsc_t ICON_EXTENSIONS_BACKGROUND; @@ -148,7 +140,6 @@ extern const lv_img_dsc_t ICON_MICROSD; extern const lv_img_dsc_t ICON_MULTISIG; extern const lv_img_dsc_t ICON_NETWORK_BACKGROUND; extern const lv_img_dsc_t ICON_NETWORK; -extern const lv_img_dsc_t ICON_NOSTR_BACKGROUND; extern const lv_img_dsc_t ICON_NOSTR; extern const lv_img_dsc_t ICON_ONE_KEY_BACKGROUND; extern const lv_img_dsc_t ICON_ONE_KEY; @@ -176,18 +167,15 @@ extern const lv_img_dsc_t ICON_SETUP_BACKGROUND; extern const lv_img_dsc_t ICON_SETUP; extern const lv_img_dsc_t ICON_SHIELD_BACKGROUND; extern const lv_img_dsc_t ICON_SHIELD; -extern const lv_img_dsc_t ICON_SHUTDOWN_BACKGROUND; extern const lv_img_dsc_t ICON_SHUTDOWN; extern const lv_img_dsc_t ICON_SIGN_BACKGROUND; extern const lv_img_dsc_t ICON_SIGN; extern const lv_img_dsc_t ICON_SMALL_CHECKMARK; -extern const lv_img_dsc_t ICON_SPIRAL_BACKGROUND; extern const lv_img_dsc_t ICON_SPIRAL; extern const lv_img_dsc_t ICON_TWO_KEYS_BACKGROUND; extern const lv_img_dsc_t ICON_TWO_KEYS; extern const lv_img_dsc_t ICON_VERIFY_ADDRESS_BACKGROUND; extern const lv_img_dsc_t ICON_VERIFY_ADDRESS; -extern const lv_img_dsc_t ICON_WARNING_BACKGROUND; extern const lv_img_dsc_t ICON_WARNING; extern const lv_img_dsc_t IMAGE_CARD_BOTTOM; extern const lv_img_dsc_t IMAGE_DIAGONAL_LINES; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND.c deleted file mode 100644 index 43100c124..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND.c +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_CASA_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_CASA_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CASA_BACKGROUND uint8_t ICON_CASA_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_CASA_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_CASA_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CASA_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index 46e8c7db6715b08bdc8839a2eefde326e5666c6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzLuwpV@L(#+cOIV85lSYADH&Hob52j7ru!z mc1(Awyua)0(trbCa9-+Z9HWL3pGgQ%7lWs(pUXO@geCye{wk{g diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND.c deleted file mode 100644 index 944f9ea82..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND.c +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_CHECKMARK_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_CHECKMARK_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_CHECKMARK_BACKGROUND uint8_t ICON_CHECKMARK_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, - 0x00, 0x01, 0xf0, - 0x00, 0x03, 0xf0, - 0x00, 0x07, 0xf0, - 0x00, 0x0f, 0xe0, - 0x78, 0x1f, 0xc0, - 0x7c, 0x3f, 0x80, - 0x7e, 0x7f, 0x00, - 0x7f, 0xfe, 0x00, - 0x3f, 0xfc, 0x00, - 0x1f, 0xf8, 0x00, - 0x0f, 0xf0, 0x00, - 0x07, 0xe0, 0x00, - 0x03, 0xc0, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_CHECKMARK_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_CHECKMARK_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CHECKMARK_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index 30901e39467d993da196a44a187980b8cda329bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBezK>FV@L(#+ewCe2NZaih5!9e55KDwB4jO? z^w2Hmu0u}Q&E9DFKbGxZ4`{vU5Nr)K+~oAM|KN|Bz;AtDQaPBSq&m|ls{FNEc06E7 x@q$yaoRK@jxn|CpwZclf>U-eCyWgG)@TdP3 -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT1 -#define LV_ATTRIBUTE_IMG_ICON_EDIT1 -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_EDIT1 uint8_t ICON_EDIT1_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0xfe, 0xfe, 0xfe, 0x8f, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x00, 0x07, 0xc0, - 0x00, 0x0f, 0xe0, - 0x00, 0x1e, 0x60, - 0x00, 0x3c, 0x60, - 0x00, 0x78, 0xe0, - 0x00, 0xf1, 0xe0, - 0x01, 0xe3, 0xc0, - 0x03, 0xc7, 0x80, - 0x07, 0x8f, 0x00, - 0x0f, 0x1e, 0x00, - 0x1e, 0x3c, 0x00, - 0x3c, 0x78, 0x00, - 0x38, 0xf0, 0x00, - 0x71, 0xe0, 0x00, - 0x73, 0xc0, 0x00, - 0x6f, 0x80, 0x00, - 0x7f, 0x00, 0x00, - 0xfc, 0x00, 0x00, - 0x40, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_EDIT1 = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 20, - .header.h = 20, - .data_size = 68, - .data = ICON_EDIT1_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND.c deleted file mode 100644 index 535929be6..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND.c +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT1_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_EDIT1_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_EDIT1_BACKGROUND uint8_t ICON_EDIT1_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x00, 0x03, 0xc0, - 0x00, 0x07, 0xe0, - 0x00, 0x0f, 0xf0, - 0x00, 0x1f, 0xf8, - 0x00, 0x3f, 0xf8, - 0x00, 0x7f, 0xf8, - 0x00, 0xff, 0xf8, - 0x01, 0xff, 0xf0, - 0x03, 0xff, 0xe0, - 0x07, 0xff, 0xc0, - 0x0f, 0xff, 0x80, - 0x1f, 0xff, 0x00, - 0x3f, 0xfe, 0x00, - 0x7f, 0xfc, 0x00, - 0x7f, 0xf8, 0x00, - 0x7f, 0xf0, 0x00, - 0x7f, 0xe0, 0x00, - 0x7f, 0xc0, 0x00, - 0x7f, 0x80, 0x00, - 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_EDIT1_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_EDIT1_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_EDIT1_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index d4be859552981b5a66eecee132b6d67c3152d01f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBeu<}xV@L(#)~g5k8Web#FFgGJ-tb0>ZJEN-7=$5Eo zNyLr|>)Tjs&2wKAAMV;_pwI6XDlto6hlgL6ZJC-P*X3gA#_)am^?piU`4s;zZFmf{ OpTX1B&t;ucLK6T)Z$`iX diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT1__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_EDIT1__CF_INDEXED_1_BIT.png deleted file mode 100644 index 7fb884eab81375e5ee54fd5b1365b8b4a45fe71e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`j)FbFd;%$g$s6l5$8 za(7}_cTVOdki(Mh=CrhOTZZ7?N_S|HKNR7J(7i_I;jx)3Q4|15XERGO&*`U^u zq<11g^h6TZoW{Qobaa--adn3(blZN{UBK5IvF@j(!i`CK?M4M+n?lcg2U^VF>FVdQ I&MBb@08@TQe*gdg diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2.c b/ports/stm32/boards/Passport/images/mono/ICON_EDIT2.c deleted file mode 100644 index 6677684da..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2.c +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT2 -#define LV_ATTRIBUTE_IMG_ICON_EDIT2 -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_EDIT2 uint8_t ICON_EDIT2_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0xfe, 0xfe, 0xfe, 0x84, /*Color of index 1*/ - - 0x00, 0x00, 0xc0, - 0x00, 0x03, 0xe0, - 0x3f, 0xc7, 0xf0, - 0x7f, 0xcf, 0x70, - 0xff, 0xde, 0xe0, - 0xe0, 0x3d, 0xe0, - 0xe0, 0x7b, 0xc0, - 0xe0, 0xf7, 0x80, - 0xe1, 0xef, 0x00, - 0xe3, 0xde, 0x00, - 0xe3, 0xbd, 0xc0, - 0xe3, 0x79, 0xc0, - 0xe3, 0xf1, 0xc0, - 0xe7, 0xe1, 0xc0, - 0xe2, 0x01, 0xc0, - 0xe0, 0x01, 0xc0, - 0xe0, 0x01, 0xc0, - 0x7f, 0xff, 0xc0, - 0x7f, 0xff, 0x80, - 0x1f, 0xff, 0x00, -}; - -const lv_img_dsc_t ICON_EDIT2 = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 20, - .header.h = 20, - .data_size = 68, - .data = ICON_EDIT2_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND.c deleted file mode 100644 index 392dac3b3..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND.c +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_EDIT2_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_EDIT2_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_EDIT2_BACKGROUND uint8_t ICON_EDIT2_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x1f, 0xf1, 0xe0, - 0x3f, 0xf3, 0xf0, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf0, - 0x7f, 0xff, 0xe0, - 0x7f, 0xff, 0xc0, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x3f, 0xff, 0xf0, - 0x1f, 0xff, 0xe0, - 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_EDIT2_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_EDIT2_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_EDIT2_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index d7b83e8c5f57209c76145aac4896faac861a3124..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBzOSc?V@L(#+o_g(3ow~oK8GEO^mOfow9?=K&LGu`j5zy7CXF*#-O%e^m-aiuBucC_D=;!%>| zStP+?6v4IWhFHpmLUk7H$xDU9Ht0qiTqh%WBth{6gIT}&X8XSK -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_NOSTR_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_NOSTR_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_NOSTR_BACKGROUND uint8_t ICON_NOSTR_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x0f, 0x00, - 0x00, 0x0f, 0xe0, - 0x00, 0x0f, 0xe0, - 0x00, 0x0f, 0xe0, - 0x00, 0x0f, 0x80, - 0x00, 0x07, 0x80, - 0x00, 0x7f, 0xc0, - 0x01, 0xff, 0xc0, - 0x03, 0xff, 0xc0, - 0x07, 0xff, 0xc0, - 0x3f, 0xff, 0xc0, - 0x3f, 0xff, 0xc0, - 0x3f, 0xff, 0x80, - 0x1f, 0xff, 0x00, - 0x07, 0xff, 0x80, - 0x0f, 0xdf, 0xc0, - 0x1f, 0x9f, 0xc0, - 0x3f, 0x01, 0xc0, - 0x3e, 0x00, 0x00, - 0x3c, 0x00, 0x00, - 0x38, 0x00, 0x00, - 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_NOSTR_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_NOSTR_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_NOSTR_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_NOSTR_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index d3adad718995deaef0c2072fddbee8000b6dd622..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 228 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBex;|2V@L(#*{R-q2NXD18!P^6U*591j>E=b z(m6lo#g2i?Y<@{?7ESR}JG#t2qr>pyBHJ3TsGEi*dM_So3VbebUFy)HW~BJ_i0;di zw={Qu{>}Czopr0Hw}MfdBvi diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND.c b/ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND.c deleted file mode 100644 index f31045bab..000000000 --- a/ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND.c +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_SHUTDOWN_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_SHUTDOWN_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SHUTDOWN_BACKGROUND uint8_t ICON_SHUTDOWN_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x78, 0x00, - 0x0f, 0xff, 0xc0, - 0x1f, 0xff, 0xe0, - 0x3f, 0xff, 0xf0, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0x3f, 0xff, 0xf0, - 0x1f, 0xff, 0xe0, - 0x0f, 0xff, 0xc0, - 0x03, 0xff, 0x00, -}; - -const lv_img_dsc_t ICON_SHUTDOWN_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_SHUTDOWN_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SHUTDOWN_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index c822c5dc9817714e23fd2db74dc48dd6049b2e3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBeuSrsV@L(#+pE@m3 -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_SPIRAL_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_SPIRAL_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_SPIRAL_BACKGROUND uint8_t ICON_SPIRAL_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x00, 0x7f, 0xe0, - 0x01, 0xff, 0xf0, - 0x03, 0xff, 0xf8, - 0x07, 0xff, 0xf8, - 0x0f, 0xff, 0xf8, - 0x1f, 0xff, 0xe0, - 0x1f, 0xff, 0xe0, - 0x3f, 0xff, 0xf0, - 0x3f, 0xff, 0xf0, - 0x3f, 0xff, 0xf0, - 0x3f, 0xff, 0xf0, - 0x3f, 0xff, 0xf0, - 0x3f, 0xff, 0xf0, - 0x1f, 0xff, 0xe0, - 0x1f, 0xff, 0xe0, - 0x7f, 0xff, 0xc0, - 0x7f, 0xff, 0x80, - 0x7f, 0xff, 0x00, - 0x3f, 0xfe, 0x00, - 0x1f, 0xf8, 0x00, - 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_SPIRAL_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_SPIRAL_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_SPIRAL_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index 45399af3b6036de983f27aac95f8631c7ceab8d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBev+q)V@L(#+o_IR2NZZ%HvjxTKRRkfNRh#- zbqW^h7Y)`3Et<)p@_Jp0?4hI}i6;u)-FH|oiHCd0J4_RsKf9wo>6CDdU*sd@Yu(@9 vCcE*6Z% -// SPDX-License-Identifier: GPL-3.0-or-later -// - -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef LV_ATTRIBUTE_IMG_ICON_WARNING_BACKGROUND -#define LV_ATTRIBUTE_IMG_ICON_WARNING_BACKGROUND -#endif - -const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_WARNING_BACKGROUND uint8_t ICON_WARNING_BACKGROUND_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0x00, 0x00, 0x00, 0xff, /*Color of index 1*/ - - 0x00, 0x00, 0x00, - 0x00, 0x78, 0x00, - 0x01, 0xfe, 0x00, - 0x01, 0xfe, 0x00, - 0x03, 0xff, 0x00, - 0x03, 0xff, 0x00, - 0x07, 0xff, 0x80, - 0x07, 0xff, 0x80, - 0x0f, 0xff, 0xc0, - 0x0f, 0xff, 0xc0, - 0x1f, 0xff, 0xe0, - 0x1f, 0xff, 0xe0, - 0x3f, 0xff, 0xf0, - 0x3f, 0xff, 0xf0, - 0x7f, 0xff, 0xf8, - 0x7f, 0xff, 0xf8, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0xff, 0xff, 0xfc, - 0x7f, 0xff, 0xf8, - 0x00, 0x00, 0x00, -}; - -const lv_img_dsc_t ICON_WARNING_BACKGROUND = { - .header.cf = LV_IMG_CF_INDEXED_1BIT, - .header.always_zero = 0, - .header.reserved = 0, - .header.w = 22, - .header.h = 22, - .data_size = 74, - .data = ICON_WARNING_BACKGROUND_map, -}; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_WARNING_BACKGROUND__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_WARNING_BACKGROUND__CF_INDEXED_1_BIT.png deleted file mode 100644 index c04a488211a44c952348ef0ddc807291e80dd114..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 197 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9GG!XV7ZFl&wkP>``W z$lZxy-8q?;Kn_c~qpu?a!^VE@KZ&eBew3$+V@L(#)k~IK3<^9h7hn8+za~MkW7b)p z11rxy7Zqv@oAQ3vSHG$Yd%jO~czk5iwA>}#TW@8nhvr??~MB)Gd From 825fbef122c960046310c8655db14188190d456a Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Tue, 13 Jun 2023 16:07:58 -0500 Subject: [PATCH 184/187] SFT-1071: fixed battery backgrounds on founders device --- ports/stm32/boards/Passport/modules/views/icon.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/views/icon.py b/ports/stm32/boards/Passport/modules/views/icon.py index d37bea9a4..d1dd25a9f 100644 --- a/ports/stm32/boards/Passport/modules/views/icon.py +++ b/ports/stm32/boards/Passport/modules/views/icon.py @@ -26,7 +26,10 @@ def __init__(self, icon, color=None, opa=None): default.opa(self.opa) def set_icon(self, icon): - self.icon = icon + if isinstance(icon, str): + self.icon = getattr(lv, icon) + else: + self.icon = icon self.update() def set_color(self, color=None, opa=None): From 046b7a8738c4220fa511819c868b3ba2ce629c8d Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Wed, 14 Jun 2023 12:51:26 -0500 Subject: [PATCH 185/187] SFT-2294: first pass fix of whitespace trimming of md5 --- ports/stm32/Justfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ports/stm32/Justfile b/ports/stm32/Justfile index d704e76fa..71b8d8eaa 100644 --- a/ports/stm32/Justfile +++ b/ports/stm32/Justfile @@ -333,8 +333,7 @@ hash filepath screen="mono" output_file="": echo "$sha" > ${directory}/${release_name}-sha256 # MD5 - md5=`mdsum {{filepath}} | sed -rn 's/^(.*) .*$/\1/p'` - md5=${md5::-1} + md5=`mdsum {{filepath}} | sed -rn 's/^(.*) .*$/\1/p' | xargs` echo "$md5" > ${directory}/${release_name}-md5 # Build Hash From 3b48190544ac134015a1cc07d17fd2c476b6eeba Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 15 Jun 2023 13:37:45 -0500 Subject: [PATCH 186/187] SFT-2311: fixed list item icons --- ports/stm32/boards/Passport/modules/views/list_item.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ports/stm32/boards/Passport/modules/views/list_item.py b/ports/stm32/boards/Passport/modules/views/list_item.py index 4e1fdba9e..2dc9b8c3c 100644 --- a/ports/stm32/boards/Passport/modules/views/list_item.py +++ b/ports/stm32/boards/Passport/modules/views/list_item.py @@ -16,7 +16,10 @@ class ListItem(View): def __init__(self, label='', is_selected=False, icon='ICON_SMALL_CHECKMARK', center=False): super().__init__(flex_flow=lv.FLEX_FLOW.ROW) - self.icon = icon + if isinstance(icon, str): + self.icon = getattr(lv, icon) + else: + self.icon = icon self.label = label self.is_selected = is_selected self.center = center From b62501901327a54d16ac7df0191c770285f2393d Mon Sep 17 00:00:00 2001 From: Matt Gleason Date: Thu, 15 Jun 2023 13:46:55 -0500 Subject: [PATCH 187/187] SFT-2311: pulled out common icon code --- ports/stm32/boards/Passport/modules/utils.py | 7 +++++++ ports/stm32/boards/Passport/modules/views/icon.py | 8 +++----- ports/stm32/boards/Passport/modules/views/list_item.py | 6 ++---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/utils.py b/ports/stm32/boards/Passport/modules/utils.py index 506750735..4afd1391e 100644 --- a/ports/stm32/boards/Passport/modules/utils.py +++ b/ports/stm32/boards/Passport/modules/utils.py @@ -1407,4 +1407,11 @@ async def method(*args, **kwargs): return method +def derive_icon(icon): + if isinstance(icon, str): + return getattr(lv, icon) + else: + return icon + + # EOF diff --git a/ports/stm32/boards/Passport/modules/views/icon.py b/ports/stm32/boards/Passport/modules/views/icon.py index d1dd25a9f..da5e6f445 100644 --- a/ports/stm32/boards/Passport/modules/views/icon.py +++ b/ports/stm32/boards/Passport/modules/views/icon.py @@ -10,12 +10,10 @@ class Icon(View): def __init__(self, icon, color=None, opa=None): + from utils import derive_icon + super().__init__() - # Icon is expected to be a string - if isinstance(icon, str): - self.icon = getattr(lv, icon) - else: - self.icon = icon + self.icon = derive_icon(icon) self.color = color self.opa = opa diff --git a/ports/stm32/boards/Passport/modules/views/list_item.py b/ports/stm32/boards/Passport/modules/views/list_item.py index 2dc9b8c3c..3947b7c30 100644 --- a/ports/stm32/boards/Passport/modules/views/list_item.py +++ b/ports/stm32/boards/Passport/modules/views/list_item.py @@ -14,12 +14,10 @@ class ListItem(View): def __init__(self, label='', is_selected=False, icon='ICON_SMALL_CHECKMARK', center=False): + from utils import derive_icon super().__init__(flex_flow=lv.FLEX_FLOW.ROW) - if isinstance(icon, str): - self.icon = getattr(lv, icon) - else: - self.icon = icon + self.icon = derive_icon(icon) self.label = label self.is_selected = is_selected self.center = center