From 8714067b4add59f525e0a85d1b0aef16bdea0e9f Mon Sep 17 00:00:00 2001 From: coreylakey Date: Wed, 18 Aug 2021 10:58:39 -0700 Subject: [PATCH 1/4] PASS1-67: Change unit to sats in settings --- ports/stm32/boards/Passport/modules/chains.py | 29 ++++++++++++------- .../stm32/boards/Passport/modules/choosers.py | 20 +++++++++++++ ports/stm32/boards/Passport/modules/flow.py | 1 + 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/chains.py b/ports/stm32/boards/Passport/modules/chains.py index 2ad9b7b1..be1ff3ae 100644 --- a/ports/stm32/boards/Passport/modules/chains.py +++ b/ports/stm32/boards/Passport/modules/chains.py @@ -150,20 +150,29 @@ def hash_message(cls, msg=None, msg_len=0): @classmethod def render_value(cls, val, unpad=False): - # convert nValue from a transaction into human form. + from common import settings + + # convert nValue from a transaction into either BTC or sats # - always be precise # - return (string, units label) - if unpad: - if (val % 1E8): - # precise but unpadded - txt = ('%d.%08d' % (val // 1E8, val % 1E8)).rstrip('0') + + # BTC is the default if not set yet + units = settings.get('units', 'BTC') + if units == 'BTC': + if unpad: + if (val % 1E8): + # precise but unpadded + txt = ('%d.%08d' % (val // 1E8, val % 1E8)).rstrip('0') + else: + # round BTC amount, show no decimal + + txt = '%d' % (val // 1E8) else: - # round BTC amount, show no decimal - txt = '%d' % (val // 1E8) + # all the zeros + txt = '%d.%08d' % (val // 1E8, val % 1E8) else: - # all the zeros - txt = '%d.%08d' % (val // 1E8, val % 1E8) - return txt, cls.ctype + txt = ('%d' % (val)) + return txt, units @classmethod def render_address(cls, script): diff --git a/ports/stm32/boards/Passport/modules/choosers.py b/ports/stm32/boards/Passport/modules/choosers.py index e69b01c8..60417666 100644 --- a/ports/stm32/boards/Passport/modules/choosers.py +++ b/ports/stm32/boards/Passport/modules/choosers.py @@ -102,4 +102,24 @@ def set_chain(idx, text): return which, [t for _,t in ch], set_chain +def units_chooser(): + DEFAULT_UNITS = "BTC" + + units = settings.get('units', DEFAULT_UNITS) + + ch = ['BTC', + 'sats'] + val = ['BTC', + 'sats'] + + try: + which = val.index(units) + except ValueError: + which = 1 + + def set_units(idx, text): + settings.set('units', val[idx]) + + return which, ch, set_units + # EOF diff --git a/ports/stm32/boards/Passport/modules/flow.py b/ports/stm32/boards/Passport/modules/flow.py index 42816203..b3d86423 100644 --- a/ports/stm32/boards/Passport/modules/flow.py +++ b/ports/stm32/boards/Passport/modules/flow.py @@ -71,6 +71,7 @@ def has_pubkey(): MenuItem('View Seed Words', f=view_seed_words, predicate=lambda: settings.get('words', True)), MenuItem('Developer PubKey', menu=DeveloperPubkeyMenu, menu_title='Developer'), MenuItem('Testnet', chooser=chain_chooser), + MenuItem('Units', chooser=units_chooser), MenuItem('Erase Passport', f=erase_wallet, arg=True) ] From 4a49a7d386b04db5bcb9061180fb3398e8720b01 Mon Sep 17 00:00:00 2001 From: coreylakey Date: Wed, 18 Aug 2021 12:17:36 -0700 Subject: [PATCH 2/4] Added warnings for Testnet and made the setting volatile --- .../stm32/boards/Passport/modules/actions.py | 28 ++++++++++++++++++- ports/stm32/boards/Passport/modules/chains.py | 15 ++++++---- .../stm32/boards/Passport/modules/choosers.py | 16 ++++++----- .../boards/Passport/modules/constants.py | 4 +++ ports/stm32/boards/Passport/modules/flow.py | 4 +-- ports/stm32/boards/Passport/modules/stash.py | 2 +- 6 files changed, 52 insertions(+), 17 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/actions.py b/ports/stm32/boards/Passport/modules/actions.py index cffb83ee..23ae8135 100644 --- a/ports/stm32/boards/Passport/modules/actions.py +++ b/ports/stm32/boards/Passport/modules/actions.py @@ -23,7 +23,7 @@ from utils import (UXStateMachine, imported, pretty_short_delay, xfp2str, to_str, truncate_string_to_width, set_next_addr, scan_for_address, get_accounts, run_chooser, make_account_name_num, is_valid_address, save_next_addr, needs_microsd, format_btc_address, - is_all_zero, bytes_to_hex_str, split_to_lines, is_valid_btc_address, do_address_verify) + is_all_zero, bytes_to_hex_str, split_to_lines, is_valid_btc_address, do_address_verify, run_chooser) from wallets.utils import get_export_mode, get_addr_type_from_address, get_deriv_path_from_addr_type_and_acct from ux import (the_ux, ux_confirm, ux_enter_pin, ux_enter_text, ux_scan_qr_code, ux_shutdown, @@ -1128,6 +1128,9 @@ async def sign_tx_from_sd(*a): import stash + # Let the user know that using Testnet is potentially dangerous + await show_testnet_warning() + if stash.bip39_passphrase: title = '[%s]' % xfp2str(settings.get('xfp')) else: @@ -1323,6 +1326,9 @@ async def magic_scan(menu, label, item): title = item.arg + # Let the user know that using Testnet is potentially dangerous + await show_testnet_warning() + while True: system.turbo(True) data = await ux_scan_qr_code(title) @@ -2065,3 +2071,23 @@ async def remove_user_firmware_pubkey(*a): center=True, center_vertically=True) clear_cached_pubkey() + +async def show_testnet_warning(*a): + chain = settings.get('chain', 'BTC') + if chain == 'TBTC': + await ux_show_story('Passport is in Testnet mode. Use a separate seed to avoid issues with malicious software wallets.', + title='Warning', + center=True, + center_vertically=True) + +async def test_chooser(*a): + from choosers import chain_chooser + + old_chain = settings.get('chain', 'BTC') + await run_chooser(chain_chooser, 'Passport', show_checks=True) + new_chain = settings.get('chain', 'BTC') + + # Only display the warning if the chain changed (user selected something) + if new_chain != old_chain: + # Let the user know that using Testnet is potentially dangerous + await show_testnet_warning() \ No newline at end of file diff --git a/ports/stm32/boards/Passport/modules/chains.py b/ports/stm32/boards/Passport/modules/chains.py index be1ff3ae..c9f1589e 100644 --- a/ports/stm32/boards/Passport/modules/chains.py +++ b/ports/stm32/boards/Passport/modules/chains.py @@ -150,29 +150,30 @@ def hash_message(cls, msg=None, msg_len=0): @classmethod def render_value(cls, val, unpad=False): - from common import settings - # convert nValue from a transaction into either BTC or sats # - always be precise # - return (string, units label) + from common import settings + from constants import UNIT_TYPE_BTC, UNIT_TYPE_SATS # BTC is the default if not set yet - units = settings.get('units', 'BTC') - if units == 'BTC': + units = settings.get('units', UNIT_TYPE_BTC) + if units == UNIT_TYPE_BTC: + label = cls.ctype if unpad: if (val % 1E8): # precise but unpadded txt = ('%d.%08d' % (val // 1E8, val % 1E8)).rstrip('0') else: # round BTC amount, show no decimal - txt = '%d' % (val // 1E8) else: # all the zeros txt = '%d.%08d' % (val // 1E8, val % 1E8) else: + label = cls.ctype_sats txt = ('%d' % (val)) - return txt, units + return txt, label @classmethod def render_address(cls, script): @@ -202,6 +203,7 @@ def render_address(cls, script): class BitcoinMain(ChainsBase): # see ctype = 'BTC' + ctype_sats = 'sats' name = 'Bitcoin' core_name = 'Bitcoin Core' menu_name = 'Bitcoin Mainnet' @@ -224,6 +226,7 @@ class BitcoinMain(ChainsBase): class BitcoinTestnet(BitcoinMain): ctype = 'TBTC' + ctype_sats = 'tsats' name = 'Bitcoin Testnet' menu_name = 'Bitcoin Testnet' diff --git a/ports/stm32/boards/Passport/modules/choosers.py b/ports/stm32/boards/Passport/modules/choosers.py index 60417666..b144e409 100644 --- a/ports/stm32/boards/Passport/modules/choosers.py +++ b/ports/stm32/boards/Passport/modules/choosers.py @@ -89,7 +89,7 @@ def chain_chooser(): def set_chain(idx, text): val = ch[idx][0] assert ch[idx][1] == text - settings.set('chain', val) + settings.set_volatile('chain', val) try: # update xpub stored in settings @@ -103,14 +103,16 @@ def set_chain(idx, text): return which, [t for _,t in ch], set_chain def units_chooser(): - DEFAULT_UNITS = "BTC" + import chains + from constants import UNIT_TYPE_BTC, UNIT_TYPE_SATS - units = settings.get('units', DEFAULT_UNITS) + chain = chains.current_chain() + units = settings.get('units', UNIT_TYPE_BTC) - ch = ['BTC', - 'sats'] - val = ['BTC', - 'sats'] + ch = [chain.ctype, + chain.ctype_sats] + val = [UNIT_TYPE_BTC, + UNIT_TYPE_SATS] try: which = val.index(units) diff --git a/ports/stm32/boards/Passport/modules/constants.py b/ports/stm32/boards/Passport/modules/constants.py index 8f22c3f9..ee060cab 100644 --- a/ports/stm32/boards/Passport/modules/constants.py +++ b/ports/stm32/boards/Passport/modules/constants.py @@ -39,3 +39,7 @@ MAX_MULTISIG_NAME_LEN = 20 DEFAULT_ACCOUNT_ENTRY = {'name': 'Primary', 'acct_num': 0} + +# Unit types for labeling conversions +UNIT_TYPE_BTC = 0 +UNIT_TYPE_SATS = 1 \ No newline at end of file diff --git a/ports/stm32/boards/Passport/modules/flow.py b/ports/stm32/boards/Passport/modules/flow.py index b3d86423..f12241d9 100644 --- a/ports/stm32/boards/Passport/modules/flow.py +++ b/ports/stm32/boards/Passport/modules/flow.py @@ -19,7 +19,7 @@ from multisig import make_multisig_menu from wallets.utils import has_export_mode from export import view_backup_password -from utils import is_new_wallet_in_progress, get_accounts, is_screenshot_mode_enabled +from utils import is_new_wallet_in_progress, get_accounts, is_screenshot_mode_enabled, run_chooser from new_wallet import pair_new_wallet from ie import show_browser @@ -70,7 +70,7 @@ def has_pubkey(): MenuItem('MicroSD Settings', menu=SDCardMenu), MenuItem('View Seed Words', f=view_seed_words, predicate=lambda: settings.get('words', True)), MenuItem('Developer PubKey', menu=DeveloperPubkeyMenu, menu_title='Developer'), - MenuItem('Testnet', chooser=chain_chooser), + MenuItem('Testnet', f=test_chooser), MenuItem('Units', chooser=units_chooser), MenuItem('Erase Passport', f=erase_wallet, arg=True) ] diff --git a/ports/stm32/boards/Passport/modules/stash.py b/ports/stm32/boards/Passport/modules/stash.py index 3a404322..d2d217fd 100644 --- a/ports/stm32/boards/Passport/modules/stash.py +++ b/ports/stm32/boards/Passport/modules/stash.py @@ -221,7 +221,7 @@ def capture_xpub(self): settings.set_volatile('xfp', xfp) settings.set_volatile('xpub', xpub) - settings.set('chain', self.chain.ctype) + settings.set_volatile('chain', self.chain.ctype) settings.set('words', (self.mode == 'words')) def register(self, item): From e72df0d84bbe64c0b3f29119c1d539cf99623a43 Mon Sep 17 00:00:00 2001 From: coreylakey Date: Thu, 19 Aug 2021 16:04:54 -0700 Subject: [PATCH 3/4] Added 'chain' removal to schema_evolution and moved Units menu to top --- ports/stm32/boards/Passport/modules/actions.py | 4 ++-- ports/stm32/boards/Passport/modules/choosers.py | 2 +- ports/stm32/boards/Passport/modules/flow.py | 2 +- ports/stm32/boards/Passport/modules/schema_evolution.py | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/actions.py b/ports/stm32/boards/Passport/modules/actions.py index bc4f581d..b64dc12e 100644 --- a/ports/stm32/boards/Passport/modules/actions.py +++ b/ports/stm32/boards/Passport/modules/actions.py @@ -2079,7 +2079,7 @@ async def remove_user_firmware_pubkey(*a): center_vertically=True) clear_cached_pubkey() -async def show_testnet_warning(*a): +async def show_testnet_warning(): chain = settings.get('chain', 'BTC') if chain == 'TBTC': await ux_show_story('Passport is in Testnet mode. Use a separate seed to avoid issues with malicious software wallets.', @@ -2094,7 +2094,7 @@ async def test_chooser(*a): await run_chooser(chain_chooser, 'Passport', show_checks=True) new_chain = settings.get('chain', 'BTC') - # Only display the warning if the chain changed (user selected something) + # Only display the warning if the chain changed if new_chain != old_chain: # Let the user know that using Testnet is potentially dangerous await show_testnet_warning() \ No newline at end of file diff --git a/ports/stm32/boards/Passport/modules/choosers.py b/ports/stm32/boards/Passport/modules/choosers.py index b144e409..b1ba5d9a 100644 --- a/ports/stm32/boards/Passport/modules/choosers.py +++ b/ports/stm32/boards/Passport/modules/choosers.py @@ -117,7 +117,7 @@ def units_chooser(): try: which = val.index(units) except ValueError: - which = 1 + which = UNIT_TYPE_BTC def set_units(idx, text): settings.set('units', val[idx]) diff --git a/ports/stm32/boards/Passport/modules/flow.py b/ports/stm32/boards/Passport/modules/flow.py index f12241d9..856d1265 100644 --- a/ports/stm32/boards/Passport/modules/flow.py +++ b/ports/stm32/boards/Passport/modules/flow.py @@ -64,6 +64,7 @@ def has_pubkey(): ] AdvancedMenu = [ + MenuItem('Units', chooser=units_chooser), MenuItem('Change PIN', f=change_pin), MenuItem('Passphrase', menu_title='Passphrase', menu=PassphraseMenu), MenuItem('Sign Text File', predicate=has_secrets, f=sign_message_on_sd), @@ -71,7 +72,6 @@ def has_pubkey(): MenuItem('View Seed Words', f=view_seed_words, predicate=lambda: settings.get('words', True)), MenuItem('Developer PubKey', menu=DeveloperPubkeyMenu, menu_title='Developer'), MenuItem('Testnet', f=test_chooser), - MenuItem('Units', chooser=units_chooser), MenuItem('Erase Passport', f=erase_wallet, arg=True) ] diff --git a/ports/stm32/boards/Passport/modules/schema_evolution.py b/ports/stm32/boards/Passport/modules/schema_evolution.py index d21ec7cf..760defab 100644 --- a/ports/stm32/boards/Passport/modules/schema_evolution.py +++ b/ports/stm32/boards/Passport/modules/schema_evolution.py @@ -34,6 +34,8 @@ async def handle_schema_evolutions(update_from_to): # This no longer used, so clean it out settings.remove('backup_num') + # This is now volatile, so clean it out + settings.remove('chain') from_version = to_version continue From 3c76486e8d24dc656e1478f7707e666e1d69726f Mon Sep 17 00:00:00 2001 From: coreylakey Date: Thu, 19 Aug 2021 16:10:23 -0700 Subject: [PATCH 4/4] Moved Units below Change Pin in menu --- ports/stm32/boards/Passport/modules/actions.py | 2 +- ports/stm32/boards/Passport/modules/flow.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/stm32/boards/Passport/modules/actions.py b/ports/stm32/boards/Passport/modules/actions.py index b64dc12e..5f060952 100644 --- a/ports/stm32/boards/Passport/modules/actions.py +++ b/ports/stm32/boards/Passport/modules/actions.py @@ -2087,7 +2087,7 @@ async def show_testnet_warning(): center=True, center_vertically=True) -async def test_chooser(*a): +async def testnet_chooser(*a): from choosers import chain_chooser old_chain = settings.get('chain', 'BTC') diff --git a/ports/stm32/boards/Passport/modules/flow.py b/ports/stm32/boards/Passport/modules/flow.py index 856d1265..3f445b87 100644 --- a/ports/stm32/boards/Passport/modules/flow.py +++ b/ports/stm32/boards/Passport/modules/flow.py @@ -64,14 +64,14 @@ def has_pubkey(): ] AdvancedMenu = [ - MenuItem('Units', chooser=units_chooser), MenuItem('Change PIN', f=change_pin), + MenuItem('Units', chooser=units_chooser), MenuItem('Passphrase', menu_title='Passphrase', menu=PassphraseMenu), MenuItem('Sign Text File', predicate=has_secrets, f=sign_message_on_sd), MenuItem('MicroSD Settings', menu=SDCardMenu), MenuItem('View Seed Words', f=view_seed_words, predicate=lambda: settings.get('words', True)), MenuItem('Developer PubKey', menu=DeveloperPubkeyMenu, menu_title='Developer'), - MenuItem('Testnet', f=test_chooser), + MenuItem('Testnet', f=testnet_chooser), MenuItem('Erase Passport', f=erase_wallet, arg=True) ]