# (c) Copyright 2018 by Coinkite Inc. This file is covered by license found in COPYING-CC. # # flow.py - Menu structure # from menu import MenuItem, PreloginToggleMenuItem, ToggleMenuItem, NonDefaultMenuItem, ShortcutItem import version, charcodes from glob import settings from actions import * from choosers import * from mk4 import dev_enable_repl from multisig import make_multisig_menu, import_multisig_nfc from seed import make_ephemeral_seed_menu, make_seed_vault_menu, start_b39_pw from address_explorer import address_explore from drv_entro import drv_entro_start, password_entry from backups import clone_start, clone_write_data from xor_seed import xor_split_start, xor_restore_start from countdowns import countdown_chooser from paper import make_paper_wallet from trick_pins import TrickPinMenu from tapsigner import import_tapsigner_backup_file from ccc import toggle_ccc_feature, sssp_spending_policy, sssp_feature_menu from wif import WIFStoreMenu # useful shortcut keys from charcodes import KEY_QR, KEY_NFC # Optional feature: HSM, depends on hardware # - code for HSM support won't exist on some platforms, so don't call it if version.supports_hsm: from hsm import hsm_policy_available from users import make_users_menu else: hsm_policy_available = False make_users_menu = None # Q related items if version.has_battery: from battery import battery_idle_timeout_chooser, brightness_chooser from q1 import scan_and_bag from notes import make_notes_menu from teleport import kt_start_rx, kt_send_file_psbt else: battery_idle_timeout_chooser = None brightness_chooser = None scan_and_bag = None make_notes_menu = None kt_start_rx = None kt_send_file_psbt = None # # NOTE: "Always In Title Case" # # - try to keep harmless things as first item: so double-tap of OK does no harm # # PREDICATES # all predicates must be boolean value, or a callable to be evaluated at runtime # def has_se_secrets(): # SE secret check, return False if only tmp secret is set from pincodes import pa return not pa.is_secret_blank() def has_pin(): from pincodes import pa return not pa.is_blank() def has_secrets(): # Secret is loaded, may be from SE or tmp from pincodes import pa return pa.has_secrets() qr_and_has_secrets = has_secrets if version.has_qr else False def nfc_enabled(): from glob import NFC return bool(NFC) def vdisk_enabled(): return bool(settings.get('vidsk', 0)) def is_not_tmp(): from pincodes import pa return not bool(pa.tmp_value) def is_tmp(): from pincodes import pa return bool(pa.tmp_value) def has_real_secret(): from pincodes import pa return (not pa.is_secret_blank()) and (not pa.tmp_value) def word_based_seed(): return settings.get("words", True) def hsm_available(): # contains hsm feature + can it be used (needs se2 secret and no tmp active) return version.supports_hsm and has_real_secret() def qr_and_ms(): # has QR scanner, and at least one MS wallet if not version.has_qr: return False return bool(settings.get('multisig', False)) def has_pushtx_url(): # they want to use PushTX feature return bool(settings.get("ptxurl", False)) # Spending Policy (Hobbled mode) predicates. # def is_hobble_testdrive(): from pincodes import pa return (pa.hobbled_mode == 2) def sssp_related_keys(): return sssp_spending_policy('okeys') def sssp_allow_passphrase(): return word_based_seed() and sssp_related_keys() def sssp_allow_notes(): return settings.get("secnap", False) and sssp_spending_policy('notes') def sssp_allow_vault(): return settings.master_get('seedvault') and sssp_related_keys() async def goto_home(*a): goto_top_menu() HWTogglesMenu = [ ToggleMenuItem('USB Port', 'du', ['Default On', 'Disable USB'], invert=True, on_change=change_usb_disable, story='''\ Blocks any data over USB port. Useful when your plan is air-gap usage.'''), ToggleMenuItem('Virtual Disk', 'vidsk', ['Default Off', 'Enable', 'Enable & Auto'], on_change=change_virtdisk_enable, story='''Coldcard can emulate a virtual disk drive (4MB) where new PSBT files \ can be saved. Signed PSBT files (transactions) will also be saved here. \n\ In "auto" mode, selects PSBT as soon as written.'''), ToggleMenuItem('NFC Sharing', 'nfc', ['Default Off', 'Enable NFC'], on_change=change_nfc_enable, story='''\ NFC (Near Field Communications) allows a phone to "tap" to send and receive data \ with the Coldcard.''', predicate=version.has_nfc), ] # Mostly pre-login values here. LoginPrefsMenu = [ # xxxxxxxxxxxxxxxx MenuItem('Change Main PIN', f=main_pin_changer), NonDefaultMenuItem('Trick PINs', 'tp', menu=TrickPinMenu.make_menu, predicate=has_real_secret), NonDefaultMenuItem('Set Nickname', 'nick', prelogin=True, f=pick_nickname), NonDefaultMenuItem('Scramble Keys', 'rngk', prelogin=True, f=pick_scramble, default_value=0), NonDefaultMenuItem('Kill Key', 'kbtn', prelogin=True, f=pick_killkey), NonDefaultMenuItem('Login Countdown', 'lgto', prelogin=True, chooser=countdown_chooser), NonDefaultMenuItem('MicroSD 2FA', 'sd2fa', menu=microsd_2fa, predicate=has_real_secret), PreloginToggleMenuItem('Calculator Login', 'calc', ['Default Off', 'Calculator Login'], story=('Boots into calculator mode. Enter your PIN as formula to login, ' 'or 12- to see prefix words. Normal calculator math works too.'), predicate=version.has_qwerty), MenuItem('Test Login Now', f=login_now, arg=1), ] # obscure settings, not more dangerous, just more personal BuriedSettingsMenu = [ ToggleMenuItem('Home Menu XFP', 'hmx', ['Only Tmp', 'Always Show'], story=('Forces display of XFP (seed fingerprint) ' 'at top of main menu. Normally, XFP is shown only when ' 'temporary seed is active.\n\n' 'Master seed is displayed as , temporary seeds as [XFP].'), predicate=has_real_secret, on_change=goto_home), ToggleMenuItem('Menu Wrapping', 'wa', ['Default', 'Always Wrap'], story='''When enabled, allows scrolling past menu top/bottom \ (wrap around). By default, this only happens in menus whose length is greater than 10.'''), ] SettingsMenu = [ # xxxxxxxxxxxxxxxx MenuItem('Login Settings', menu=LoginPrefsMenu), MenuItem('Hardware On/Off', menu=HWTogglesMenu), NonDefaultMenuItem('Multisig Wallets', 'multisig', menu=make_multisig_menu, predicate=has_secrets, shortcut='m'), NonDefaultMenuItem('NFC Push Tx', 'ptxurl', menu=pushtx_setup_menu), MenuItem('Display Units', chooser=value_resolution_chooser), MenuItem('Max Network Fee', chooser=max_fee_chooser), MenuItem('Idle Timeout', chooser=idle_timeout_chooser), MenuItem('Idle Timeout (on battery)', chooser=battery_idle_timeout_chooser, predicate=version.has_battery), MenuItem('LCD Brightness (on battery)', chooser=brightness_chooser, predicate=version.has_battery), ToggleMenuItem('Delete PSBTs', 'del', ['Default Keep', 'Delete PSBTs'], story='''\ PSBT files (on SDCard) will be blanked & deleted after they are used. \ The signed transaction will be named .txn, so the file name does not leak information. MS-DOS tools should not be able to find the PSBT data (ie. undelete), but forensic tools \ which take apart the flash chips of the SDCard may still be able to find the \ data or filenames.'''), ToggleMenuItem('Keyboard EMU', 'emu', ['Default Off', 'Enable'], on_change=usb_keyboard_emulation, predicate=has_secrets, # cannot generate BIP85 passwords without secret story='''This mode adds a top-level menu item for typing \ deterministically-generated passwords (BIP-85), directly into an \ attached USB computer (as an emulated keyboard).'''), MenuItem('Buried Settings', menu=BuriedSettingsMenu), ] XpubExportMenu = [ # xxxxxxxxxxxxxxxx MenuItem("Segwit (BIP-84)", f=export_xpub, arg=84), MenuItem("Classic (BIP-44)", f=export_xpub, arg=44), MenuItem("P2WPKH/P2SH "+("(BIP-49)"if version.has_qwerty else "(49)"), f=export_xpub, arg=49), MenuItem("Master XPUB", f=export_xpub, arg=0), MenuItem("Current XFP", f=export_xpub, arg=-1), ] WalletExportMenu = [ # xxxxxxxxxxxxxxxx MenuItem("Sparrow", f=named_generic_skeleton, arg="Sparrow"), MenuItem("Cove", f=named_generic_skeleton, arg="Cove"), MenuItem("Bitcoin Core", f=bitcoin_core_skeleton), MenuItem("Nunchuk", f=named_generic_skeleton, arg="Nunchuk"), MenuItem("Bull Bitcoin", f=ss_descriptor_skeleton, arg=(True, [AF_P2WPKH], "", "bull-bitcoin.txt", KEY_QR)), MenuItem("Blue Wallet", f=electrum_skeleton, arg="Blue"), MenuItem("Electrum Wallet", f=electrum_skeleton, arg="Electrum"), MenuItem("Wasabi Wallet", f=wasabi_skeleton), MenuItem("Fully Noded", f=named_generic_skeleton, arg="Fully Noded"), MenuItem("Unchained", f=unchained_capital_export), MenuItem("Theya", f=named_generic_skeleton, arg="Theya"), MenuItem("Bitcoin Safe", f=named_generic_skeleton, arg="Bitcoin Safe"), MenuItem("Zeus", f=ss_descriptor_skeleton, arg=(True, [AF_P2WPKH, AF_P2WPKH_P2SH], "Zeus Wallet", "zeus-export.txt", None)), MenuItem("Samourai Postmix", f=samourai_post_mix_descriptor_export), MenuItem("Samourai Premix", f=samourai_pre_mix_descriptor_export), # MenuItem("Samourai BadBank", f=samourai_bad_bank_descriptor_export), # not released yet MenuItem("Descriptor", f=ss_descriptor_skeleton), MenuItem("Generic JSON", f=generic_skeleton), MenuItem("Export XPUB", menu=XpubExportMenu), MenuItem("Key Expression", f=key_expression_skeleton), MenuItem("Dump Summary", predicate=has_secrets, f=dump_summary), ] # useful even if no secrets, may operate on VDisk or SDCard when inserted FileMgmtMenu = [ # xxxxxxxxxxxxxxxx MenuItem("Verify Backup", f=verify_backup), MenuItem("Backup System", predicate=has_secrets, f=backup_everything), MenuItem('Export Wallet', predicate=has_secrets, menu=WalletExportMenu), #dup elsewhere MenuItem('Sign Text File', predicate=has_secrets, f=sign_message_on_sd), MenuItem('Batch Sign PSBT', predicate=has_secrets, f=batch_sign), MenuItem('Teleport Multisig PSBT', predicate=qr_and_has_secrets, f=kt_send_file_psbt), MenuItem('List Files', f=list_files), MenuItem('Verify Sig File', f=verify_sig_file), MenuItem('NFC File Share', predicate=nfc_enabled, f=nfc_share_file, shortcut=KEY_NFC), MenuItem('BBQr File Share', predicate=version.has_qr, f=qr_share_file, arg=True), MenuItem('QR File Share', predicate=version.has_qr, f=qr_share_file, shortcut=KEY_QR), MenuItem('Clone Coldcard', predicate=has_secrets, f=clone_write_data), MenuItem('Format SD Card', f=wipe_sd_card), MenuItem('Format RAM Disk', predicate=vdisk_enabled, f=wipe_vdisk), ] UpgradeMenu = [ # xxxxxxxxxxxxxxxx MenuItem('Show Version', f=show_version), MenuItem('From MicroSD', f=microsd_upgrade, arg=False), MenuItem('From VirtDisk', predicate=vdisk_enabled, f=microsd_upgrade, arg=True), # force_vdisk=True ] DevelopersMenu = [ # xxxxxxxxxxxxxxxx MenuItem("Serial REPL", f=dev_enable_repl), MenuItem('Warm Reset', f=reset_self), MenuItem("Restore Bkup", f=restore_backup_dev), MenuItem("BKPW Override", menu=bkpw_override, predicate=has_secrets), MenuItem('Reflash GPU', f=reflash_gpu, predicate=version.has_qwerty), ] AdvancedVirginMenu = [ # No PIN, no secrets yet (factory fresh) # xxxxxxxxxxxxxxxx MenuItem("View Identity", f=view_ident), MenuItem('Paper Wallets', f=make_paper_wallet), MenuItem('Perform Selftest', f=start_selftest), MenuItem('Secure Logout', f=logout_now, predicate=not version.has_battery), ] AdvancedPinnedVirginMenu = [ # Has PIN but no secrets yet # xxxxxxxxxxxxxxxx MenuItem("View Identity", f=view_ident), MenuItem("Temporary Seed", menu=make_ephemeral_seed_menu), MenuItem("Upgrade Firmware", menu=UpgradeMenu, predicate=is_not_tmp), MenuItem("File Management", menu=FileMgmtMenu), MenuItem("Key Teleport (start)", f=kt_start_rx, predicate=version.has_qr), MenuItem('Paper Wallets', f=make_paper_wallet), MenuItem('Perform Selftest', f=start_selftest), MenuItem("I Am Developer.", menu=maybe_dev_menu), MenuItem('Secure Logout', f=logout_now, predicate=not version.has_battery), ] DebugFunctionsMenu = [ # xxxxxxxxxxxxxxxx MenuItem("Keyboard Test", f=keyboard_test), MenuItem('BBQr Demo', f=debug_bbqr_test, predicate=version.has_qwerty), MenuItem("NFC Test", f=quick_nfc_test), MenuItem('Clear Tested', f=clear_tested_flag), MenuItem('Debug: assert', f=debug_assert), MenuItem('Debug: except', f=debug_except), MenuItem('Check: BL FW', f=check_firewall_read), MenuItem('Warm Reset', f=reset_self), #MenuItem("Perform Selftest", f=start_selftest), ] SeedXORMenu = [ # xxxxxxxxxxxxxxxx MenuItem("Split Existing", f=xor_split_start, predicate=word_based_seed), MenuItem("Restore Seed XOR", f=xor_restore_start), ] SeedFunctionsMenu = [ MenuItem('View Seed Words', f=view_seed_words), # text is a little wrong sometimes, rare MenuItem('Seed XOR', menu=SeedXORMenu), MenuItem("Destroy Seed", f=clear_seed, predicate=has_real_secret), MenuItem('Lock Down Seed', f=convert_ephemeral_to_master, predicate=is_tmp), MenuItem('Export SeedQR', f=export_seedqr, predicate=word_based_seed), ] DangerZoneMenu = [ # xxxxxxxxxxxxxxxx MenuItem("Debug Functions", menu=DebugFunctionsMenu), # actually harmless MenuItem("Seed Functions", menu=SeedFunctionsMenu), MenuItem("I Am Developer.", menu=maybe_dev_menu), ToggleMenuItem('Seed Vault', 'seedvault', ['Default Off', 'Enable'], on_change=change_seed_vault, story=("Enable Seed Vault? Adds prompt to store temporary seeds " "into Seed Vault, where they can easily be reused later.\n\n" "WARNING: Seed Vault is encrypted (AES-256-CTR) by your seed," " but not held directly inside secure elements. Backups are required" " after any change to vault! Recommended for experiments or temporary use."), predicate=has_real_secret), MenuItem('Perform Selftest', f=start_selftest), # little harmful MenuItem("Set High-Water", f=set_highwater), MenuItem('Wipe HSM Policy', f=wipe_hsm_policy, predicate=hsm_policy_available), MenuItem('Clear OV cache', f=wipe_ovc), MenuItem("Clear Address cache" if version.has_qwerty else "Clear Addr cache", f=wipe_address_cache), ToggleMenuItem("Sighash Checks", "sighshchk", ["Default: Block", "Warn"], invert=True, story='''\ If you disable sighash flag restrictions, and ignore the \ warnings, funds can be stolen by specially crafted PSBT or MitM. Keep blocked unless you intend to sign special transactions.'''), ToggleMenuItem('Testnet Mode', 'chain', ['Bitcoin', 'Testnet4', 'Regtest'], value_map=['BTC', 'XTN', 'XRT'], on_change=change_which_chain, story="Testnet must only be used by developers because \ correctly- crafted transactions signed on Testnet could be broadcast on Mainnet."), ToggleMenuItem('AE Start Index', 'aei', ['Default Off', 'Enable'], story=( "Enable this option to add new menu item to Address Explorer " "allowing override of start index. By default start index is zero.\n\n" "WARNING: Some wallets will not recognize addresses that are past their gap limit" " and your deposits will seem to disappear."), predicate=has_secrets), ToggleMenuItem('B85 Idx Values', 'b85max', ['Default Off', 'Unlimited'], story=("Allow unlimited indexes for BIP-85 derivations?\n\n" "DANGER: If you forget this index number, getting your funds " "back will be a difficult search problem."), predicate=has_secrets), MenuItem('Settings Space', f=show_settings_space), MenuItem('MCU Key Slots', f=show_mcu_keys_left), MenuItem('Bless Firmware', f=bless_flash), # no need for this anymore? MenuItem("Wipe LFS", f=wipe_filesystem), # kills other-seed settings, HSM stuff, addr cache MenuItem("Nuke Device", f=nuke_device), ] BackupStuffMenu = [ # xxxxxxxxxxxxxxxx MenuItem("Backup System", f=backup_everything), MenuItem("Verify Backup", f=verify_backup), MenuItem("Restore Backup", f=need_clear_seed), # just a UX msg really MenuItem('Clone Coldcard', predicate=has_secrets, f=clone_write_data), ] NFCToolsMenu = [ MenuItem('Sign PSBT', f=nfc_sign_psbt), MenuItem('Show Address', f=nfc_show_address), MenuItem('Sign Message', f=nfc_sign_msg), MenuItem('Verify Sig File', f=nfc_sign_verify), MenuItem('Verify Address', f=nfc_address_verify), MenuItem('File Share', f=nfc_share_file), MenuItem('Import Multisig', f=import_multisig_nfc), MenuItem('Push Transaction', f=nfc_pushtx_file, predicate=has_pushtx_url), ] SpendingPolicySubMenu = [ NonDefaultMenuItem('Single-Signer', 'sssp', f=sssp_feature_menu, predicate=has_real_secret), NonDefaultMenuItem('Co-Sign Multi.' if not version.has_qwerty else 'Co-Sign Multisig (CCC)', 'ccc', f=toggle_ccc_feature, predicate=is_not_tmp), ToggleMenuItem('HSM Mode', 'hsmcmd', ['Default Off', 'Enable'], story=("Enable HSM? Enables all user management commands, and other HSM-only USB commands. " "By default these commands are disabled."), predicate=hsm_available), MenuItem('User Management', menu=make_users_menu, predicate=lambda: hsm_available() and settings.get('hsmcmd', False)), ] AdvancedNormalMenu = [ # xxxxxxxxxxxxxxxx MenuItem("Backup", menu=BackupStuffMenu), MenuItem('Export Wallet', predicate=has_secrets, menu=WalletExportMenu, shortcut='x'), # also inside FileMgmt MenuItem("Upgrade Firmware", menu=UpgradeMenu, predicate=is_not_tmp), MenuItem("File Management", menu=FileMgmtMenu), NonDefaultMenuItem('Secure Notes & Passwords', 'secnap', menu=make_notes_menu, predicate=version.has_qwerty), MenuItem('Derive Seed B85' if not version.has_qwerty else 'Derive Seeds (BIP-85)', f=drv_entro_start), MenuItem("View Identity", f=view_ident), MenuItem("Temporary Seed", menu=make_ephemeral_seed_menu), MenuItem("Key Teleport (start)", f=kt_start_rx, predicate=version.has_qr), MenuItem("Spending Policy", menu=SpendingPolicySubMenu,shortcut='s',predicate=has_real_secret), MenuItem('Paper Wallets', f=make_paper_wallet), MenuItem('WIF Store', menu=WIFStoreMenu.make), MenuItem('NFC Tools', predicate=nfc_enabled, menu=NFCToolsMenu, shortcut=KEY_NFC), MenuItem("Danger Zone", menu=DangerZoneMenu, shortcut='z'), ] # needs to create main wallet PIN VirginSystem = [ # xxxxxxxxxxxxxxxx MenuItem('Choose PIN Code', f=initial_pin_setup), MenuItem('Advanced/Tools', menu=AdvancedVirginMenu, shortcut='t'), MenuItem('Bag Number', f=show_bag_number), MenuItem('Help', f=virgin_help, predicate=not version.has_qwerty), ] ImportWallet = [ MenuItem("12 Words", menu=start_seed_import, arg=12), MenuItem("18 Words", menu=start_seed_import, arg=18), MenuItem("24 Words", menu=start_seed_import, arg=24), MenuItem('Scan QR Code', predicate=version.has_qr, shortcut=KEY_QR, f=scan_any_qr, arg=(True, False)), MenuItem("Restore Backup", f=restore_backup, arg=False), # tmp=False MenuItem("Clone Coldcard", menu=clone_start), MenuItem("Import XPRV", f=import_xprv, arg=False), # ephemeral=False MenuItem("Tapsigner Backup", f=import_tapsigner_backup_file, arg=False), MenuItem("Seed XOR", f=xor_restore_start), ] SeedFromDiceMenu = [ MenuItem("12 Word Dice Roll", f=new_from_dice, arg=12), MenuItem("24 Word Dice Roll", f=new_from_dice, arg=24), ] NewSeedMenu = [ MenuItem("12 Words", f=pick_new_seed, arg=12), MenuItem("24 Words", f=pick_new_seed, arg=24), MenuItem("Advanced", menu=SeedFromDiceMenu), ] # has PIN, but no secret seed yet EmptyWallet = [ # xxxxxxxxxxxxxxxx MenuItem('New Seed Words', menu=NewSeedMenu), MenuItem('Import Existing', menu=ImportWallet), MenuItem("Migrate Coldcard", menu=clone_start), MenuItem("Key Teleport (start)", f=kt_start_rx, predicate=version.has_qr), MenuItem('Help', f=virgin_help, predicate=not version.has_qwerty), MenuItem('Advanced/Tools', menu=AdvancedPinnedVirginMenu, shortcut='t'), MenuItem('Settings', menu=SettingsMenu), ShortcutItem(KEY_QR, predicate=version.has_qr, f=scan_any_qr, arg=(True, False)), ] # In operation, normal system, after a good PIN received. # - key shortcuts in place for all items that will be shown on Q NormalSystem = [ # xxxxxxxxxxxxxxxx MenuItem('Ready To Sign', f=ready2sign, shortcut='r'), MenuItem('Passphrase', menu=start_b39_pw, predicate=word_based_seed, shortcut='p'), MenuItem('Scan Any QR Code', predicate=version.has_qr, shortcut=KEY_QR, f=scan_any_qr, arg=(False, True)), MenuItem('Start HSM Mode', f=start_hsm_menu_item, predicate=hsm_policy_available), MenuItem("Address Explorer", menu=address_explore, shortcut='x'), MenuItem('Secure Notes & Passwords', menu=make_notes_menu, shortcut='n', predicate=lambda: version.has_qwerty and settings.get("secnap", False)), MenuItem('Type Passwords', f=password_entry, shortcut='e', predicate=lambda: settings.get("emu", False) and has_secrets()), MenuItem('Seed Vault', menu=make_seed_vault_menu, shortcut='v', predicate=lambda: settings.master_get('seedvault') and has_secrets()), MenuItem('Advanced/Tools', menu=AdvancedNormalMenu, shortcut='t'), MenuItem('Settings', menu=SettingsMenu, shortcut='s'), MenuItem('Secure Logout', f=logout_now, predicate=not version.has_battery), ShortcutItem(KEY_NFC, predicate=nfc_enabled, menu=NFCToolsMenu), ] # Shown until unit is put into a numbered bag FactoryMenu = [ MenuItem('Bag Me Now', f=scan_and_bag), MenuItem('Version: ' + version.get_mpy_version()[1], f=show_version), MenuItem('DFU Upgrade', f=start_dfu, shortcut='u'), MenuItem('Ship W/O Bag', f=ship_wo_bag), MenuItem("Debug Functions", menu=DebugFunctionsMenu, shortcut='f'), MenuItem("Perform Selftest", f=start_selftest, shortcut='s'), ] # Special menus for hobbled mode where we have a (single signer) spending policy in effect. # - no access to secrets, backups, firmware up/downgrades. # - secure notes, but readonly; can be disabled completely. # - key teleport, but only for PSBT & multisig purposes. # - can only be enabled after we have secrets, so no need for has_secrets tests here # # Slightly limited file menu when hobbled. # - no backup/restore HobbledFileMgmtMenu = [ # xxxxxxxxxxxxxxxx MenuItem('Sign Text File', f=sign_message_on_sd), MenuItem('Batch Sign PSBT', f=batch_sign), MenuItem('List Files', f=list_files), MenuItem('Export Wallet', menu=WalletExportMenu), # dup under Adv/Tools MenuItem('Verify Sig File', f=verify_sig_file), MenuItem('NFC File Share', predicate=nfc_enabled, f=nfc_share_file, shortcut=KEY_NFC), MenuItem('BBQr File Share', predicate=version.has_qr, f=qr_share_file, arg=True), MenuItem('QR File Share', predicate=version.has_qr, f=qr_share_file, shortcut=KEY_QR), MenuItem('Format SD Card', f=wipe_sd_card), MenuItem('Format RAM Disk', predicate=vdisk_enabled, f=wipe_vdisk), ] # NFC tools when hobbled: not much different. HobbledNFCToolsMenu = [ MenuItem('Sign PSBT', f=nfc_sign_psbt), MenuItem('Show Address', f=nfc_show_address), MenuItem('Sign Message', f=nfc_sign_msg), MenuItem('Verify Sig File', f=nfc_sign_verify), MenuItem('Verify Address', f=nfc_address_verify), MenuItem('File Share', f=nfc_share_file), MenuItem('Push Transaction', f=nfc_pushtx_file, predicate=has_pushtx_url), ] # Very limited advanced menu when hobbled. HobbledAdvancedMenu = [ # xxxxxxxxxxxxxxxx MenuItem("File Management", menu=HobbledFileMgmtMenu), MenuItem('Export Wallet', menu=WalletExportMenu, shortcut='x'), # also inside FileMgmt MenuItem('Teleport Multisig PSBT', predicate=qr_and_ms, f=kt_send_file_psbt), MenuItem("View Identity", f=view_ident), MenuItem("Temporary Seed", menu=make_ephemeral_seed_menu, predicate=sssp_related_keys), MenuItem('Paper Wallets', f=make_paper_wallet), MenuItem('NFC Tools', predicate=nfc_enabled, menu=HobbledNFCToolsMenu, shortcut=KEY_NFC), MenuItem('WIF Store', menu=WIFStoreMenu.make, predicate=sssp_related_keys), MenuItem('Show %s Version' % ("Firmware" if version.has_qwerty else "FW"), f=show_version), MenuItem("Destroy Seed", f=clear_seed, predicate=has_real_secret), ] # Main menu when a spending policy (hobbled) is in effect. HobbledTopMenu = [ # xxxxxxxxxxxxxxxx MenuItem('Ready To Sign', f=ready2sign, shortcut='r'), MenuItem('Passphrase', menu=start_b39_pw, predicate=sssp_allow_passphrase, shortcut='p'), MenuItem('Scan Any QR Code', predicate=version.has_qr, f=scan_any_qr, arg=(False, True), shortcut=KEY_QR), MenuItem("Address Explorer", menu=address_explore, shortcut='x'), MenuItem('Secure Notes & Passwords', menu=make_notes_menu, predicate=sssp_allow_notes, shortcut='n'), MenuItem('Type Passwords', f=password_entry, shortcut='t', predicate=lambda: settings.get("emu", False) and sssp_related_keys()), MenuItem('Seed Vault', menu=make_seed_vault_menu, predicate=sssp_allow_vault, shortcut='v'), MenuItem('Advanced/Tools', menu=HobbledAdvancedMenu, shortcut='t'), MenuItem('Secure Logout', f=logout_now, predicate=not version.has_battery), MenuItem('EXIT TEST DRIVE', f=sssp_feature_menu, predicate=is_hobble_testdrive), ShortcutItem(KEY_NFC, predicate=nfc_enabled, menu=HobbledNFCToolsMenu), ]