From 1441c296afdbc4a8f981452de6acc9718d5b5b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Palmer?= Date: Tue, 9 Apr 2024 13:42:20 +0200 Subject: [PATCH 1/8] IO: duplicate the lib_standard_app io_event function for NANOS --- src/ui_bagl.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/ui_bagl.c b/src/ui_bagl.c index 33f4da2e..73b3a408 100644 --- a/src/ui_bagl.c +++ b/src/ui_bagl.c @@ -38,6 +38,60 @@ #define G_display global.dynamic_display +#ifdef TARGET_NANOS +#include "io.h" + +uint8_t io_event(uint8_t channel); + +/** + * Function similar to the one in `lib_standard_app/` + * + */ +uint8_t io_event(uint8_t channel) { + (void) channel; + + switch (G_io_seproxyhal_spi_buffer[0]) { + case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: + UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer); + break; + case SEPROXYHAL_TAG_STATUS_EVENT: + if ((G_io_apdu_media == IO_APDU_MEDIA_USB_HID) && + !(U4BE(G_io_seproxyhal_spi_buffer, 3) & + SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) { + THROW(EXCEPTION_IO_RESET); + } + __attribute__((fallthrough)); + case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT: +#ifdef HAVE_BAGL + UX_DISPLAYED_EVENT({}); +#endif // HAVE_BAGL +#ifdef HAVE_NBGL + UX_DEFAULT_EVENT(); +#endif // HAVE_NBGL + break; +#ifdef HAVE_NBGL + case SEPROXYHAL_TAG_FINGER_EVENT: + UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer); + break; +#endif // HAVE_NBGL + case SEPROXYHAL_TAG_TICKER_EVENT: + app_ticker_event_callback(); + UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {}); + break; + default: + UX_DEFAULT_EVENT(); + break; + } + + if (!io_seproxyhal_spi_is_status_sent()) { + io_seproxyhal_general_status(); + } + + return 1; +} + +#endif // TARGET_NANOS + static void ui_refresh_idle_hwm_screen(void); /** From d79e3926634aaca29e3513a2055b5a4bda9597fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Palmer?= Date: Tue, 9 Apr 2024 14:48:43 +0200 Subject: [PATCH 2/8] UX: introduce low-cost display Low-cost display disable `TICKER_EVENT` handling. Low-cost display is deactivated at button push Low-cost display is activated at signing As `TICKER_EVENT` handling slows down the application --- src/apdu_sign.c | 4 ++++ src/globals.h | 4 ++++ src/ui.h | 11 +++++++++++ src/ui_bagl.c | 18 +++++++++++++++--- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/apdu_sign.c b/src/apdu_sign.c index ebc8b833..6fc1b92a 100644 --- a/src/apdu_sign.c +++ b/src/apdu_sign.c @@ -208,6 +208,10 @@ static int baking_sign_complete(bool const send_hash) { case MAGIC_BYTE_PREATTESTATION: case MAGIC_BYTE_ATTESTATION: TZ_CHECK(guard_baking_authorized(&G.parsed_baking_data, &global.path_with_curve)); +#ifdef TARGET_NANOS + // To be efficient, the signing needs a low-cost display + ux_set_low_cost_display_mode(true); +#endif result = perform_signature(send_hash); #ifdef HAVE_BAGL // Ignore calculation errors diff --git a/src/globals.h b/src/globals.h index 2ad8f908..c1544501 100644 --- a/src/globals.h +++ b/src/globals.h @@ -118,8 +118,12 @@ typedef struct { ui_callback_t ok_callback; /// Callback function if user rejected prompt. ui_callback_t cxl_callback; +#ifdef TARGET_NANOS + /// If the low-cost display mode is enabled + bool low_cost_display_mode; /// Screensaver is on/off. bool is_blank_screen; +#endif // TARGET_NANOS } dynamic_display; bip32_path_with_curve_t path_with_curve; ///< holds the bip32 path and curve of the current key diff --git a/src/ui.h b/src/ui.h index 2401b04f..87e2227b 100644 --- a/src/ui.h +++ b/src/ui.h @@ -42,6 +42,17 @@ void __attribute__((noreturn)) app_exit(void); #ifdef HAVE_BAGL +#ifdef TARGET_NANOS +/** + * @brief Sets low-cost display mode + * + * Low-cost display stop handling `TICKER_EVENT` + * + * @param enable: if enable the mode or not + */ +void ux_set_low_cost_display_mode(bool enable); +#endif // HAVE_BAGL + /** * @brief Calculates the chain id for the idle screens * diff --git a/src/ui_bagl.c b/src/ui_bagl.c index 73b3a408..62071d55 100644 --- a/src/ui_bagl.c +++ b/src/ui_bagl.c @@ -41,10 +41,19 @@ #ifdef TARGET_NANOS #include "io.h" +void ux_set_low_cost_display_mode(bool enable) { + G_display.low_cost_display_mode = enable; +} + uint8_t io_event(uint8_t channel); /** - * Function similar to the one in `lib_standard_app/` + * Function similar to the one in `lib_standard_app/` except that the + * `TICKER_EVENT` handling is not enabled on low-cost display mode. + * + * Low-cost display mode is deactivated when the button is pressed and + * activated during signing because `TICKER_EVENT` handling slows down + * the application. * */ uint8_t io_event(uint8_t channel) { @@ -52,6 +61,7 @@ uint8_t io_event(uint8_t channel) { switch (G_io_seproxyhal_spi_buffer[0]) { case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: + ux_set_low_cost_display_mode(false); UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer); break; case SEPROXYHAL_TAG_STATUS_EVENT: @@ -75,8 +85,10 @@ uint8_t io_event(uint8_t channel) { break; #endif // HAVE_NBGL case SEPROXYHAL_TAG_TICKER_EVENT: - app_ticker_event_callback(); - UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {}); + if (!G_display.low_cost_display_mode) { + app_ticker_event_callback(); + UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {}); + } break; default: UX_DEFAULT_EVENT(); From 838a6deb0283f2247c76e42160aa7e8cd6414fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Palmer?= Date: Wed, 10 Apr 2024 13:36:47 +0200 Subject: [PATCH 3/8] Test: check Ledger's screensaver work before signing --- test/test_instructions.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/test/test_instructions.py b/test/test_instructions.py index 501f641d..e2f708a6 100644 --- a/test/test_instructions.py +++ b/test/test_instructions.py @@ -221,12 +221,21 @@ def test_git(client: TezosClient) -> None: f"Expected {expected_commit} but got {commit}" -def test_ledger_screensaver(client: TezosClient, tezos_navigator: TezosNavigator, backend_name) -> None: +def test_ledger_screensaver(firmware: Firmware, + backend: BackendInterface, + client: TezosClient, + tezos_navigator: TezosNavigator, + backend_name) -> None: # Make sure that ledger device being tested has screensaver time set to 1 minute and PIN lock is disabled. account = DEFAULT_ACCOUNT if backend_name == "speculos": - assert True - return + assert True + return + + time.sleep(70) + + res = input("Has the Ledger screensaver been activated?") + assert (res.find("y") != -1), "Ledger screensaver should have activated" lvl = 0 main_chain_id = DEFAULT_CHAIN_ID @@ -249,6 +258,12 @@ def test_ledger_screensaver(client: TezosClient, tezos_navigator: TezosNavigator client.sign_message(account, attestation) time.sleep(1) + res = input("Has the Ledger screensaver been activated?") + if firmware.device == "nanos": + assert (res.find("y") == -1), "Ledger screensaver should not have been activated" + else: + assert (res.find("y") != -1), "Ledger screensaver should have activated" + @pytest.mark.parametrize("account", ZEBRA_ACCOUNTS) def test_benchmark_attestation_time(account: Account, client: TezosClient, tezos_navigator: TezosNavigator, backend_name) -> None: From 2c9dd63041b25317cd6590876399bcb0fb91d140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Palmer?= Date: Tue, 9 Apr 2024 15:02:10 +0200 Subject: [PATCH 4/8] UX: reintroduce the custom screensaver for NANOS --- src/globals.h | 7 ++-- src/ui_bagl.c | 5 +++ src/ui_screensaver.c | 98 ++++++++++++++++++++++++++++++++++++++++++++ src/ui_screensaver.h | 41 ++++++++++++++++++ 4 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 src/ui_screensaver.c create mode 100644 src/ui_screensaver.h diff --git a/src/globals.h b/src/globals.h index c1544501..07b046d4 100644 --- a/src/globals.h +++ b/src/globals.h @@ -28,6 +28,7 @@ #include "operations.h" #include "ui.h" +#include "ui_screensaver.h" /** * @brief Zeros out all globals that can keep track of APDU instruction state @@ -118,11 +119,11 @@ typedef struct { ui_callback_t ok_callback; /// Callback function if user rejected prompt. ui_callback_t cxl_callback; -#ifdef TARGET_NANOS +#ifdef HAVE_BAGL /// If the low-cost display mode is enabled bool low_cost_display_mode; - /// Screensaver is on/off. - bool is_blank_screen; + /// Screensaver context + ux_screensaver_state_t screensaver_state; #endif // TARGET_NANOS } dynamic_display; diff --git a/src/ui_bagl.c b/src/ui_bagl.c index 62071d55..65336a9e 100644 --- a/src/ui_bagl.c +++ b/src/ui_bagl.c @@ -32,6 +32,7 @@ #include "memory.h" #include "os_cx.h" // ui-menu #include "to_string.h" +#include "ui_screensaver.h" #include #include @@ -134,7 +135,11 @@ void ui_menu_init(void); ///> Load main menu page * - Exit screen * */ +#ifdef TARGET_NANOS +UX_STEP_CB(ux_app_is_ready_step, nn, ui_start_screensaver(), {"Application", "is ready"}); +#else // TARGET_NANOS UX_STEP_NOCB(ux_app_is_ready_step, nn, {"Application", "is ready"}); +#endif // TARGET_NANOS UX_STEP_NOCB(ux_version_step, bnnn_paging, {"Tezos Baking", APPVERSION}); UX_STEP_NOCB(ux_chain_id_step, bnnn_paging, {"Chain", home_context.chain_id}); UX_STEP_NOCB(ux_authorized_key_step, bnnn_paging, {"Public Key Hash", home_context.authorized_key}); diff --git a/src/ui_screensaver.c b/src/ui_screensaver.c new file mode 100644 index 00000000..493651a3 --- /dev/null +++ b/src/ui_screensaver.c @@ -0,0 +1,98 @@ +/* Tezos Ledger application - Screen-saver UI functions + + Copyright 2024 TriliTech + Copyright 2024 Functori + Copyright 2023 Ledger + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#ifdef HAVE_BAGL +#include "ui_screensaver.h" + +#include "bolos_target.h" +#include "globals.h" + +#define G_screensaver_state global.dynamic_display.screensaver_state + +/** + * @brief Blank screen element + * + */ +static const bagl_element_t blank_screen_elements[] = {{{BAGL_RECTANGLE, + BAGL_NONE, + 0, + 0, + BAGL_WIDTH, + BAGL_HEIGHT, + 0, + 0, + BAGL_FILL, + 0x000000, + 0xFFFFFF, + 0, + 0}, + .text = NULL}, + {}}; + +/** + * @brief This structure represents the parameters needed for the blank layout + * + * No parameters required + * + */ +typedef struct ux_layout_blank_params_s { +} ux_layout_blank_params_t; + +/** + * @brief Initializes the blank layout + * + * @param stack_slot: index stack_slot + */ +static void ux_layout_blank_init(unsigned int stack_slot) { + ux_stack_init(stack_slot); + G_ux.stack[stack_slot].element_arrays[0].element_array = blank_screen_elements; + G_ux.stack[stack_slot].element_arrays[0].element_array_count = ARRAYLEN(blank_screen_elements); + G_ux.stack[stack_slot].element_arrays_count = 1; + G_ux.stack[stack_slot].button_push_callback = ux_flow_button_callback; + ux_stack_display(stack_slot); +} + +/** + * @brief Exits the blank screen to home screen + * + */ +static void return_to_idle(void) { + G_screensaver_state.on = false; + ui_initial_screen(); +} + +/** + * @brief Blank screen flow + * + * On any click: return_to_idle + * + */ +UX_STEP_CB(blank_screen_step, blank, return_to_idle(), {}); +UX_STEP_INIT(blank_screen_border, NULL, NULL, { return_to_idle(); }); +UX_FLOW(ux_blank_flow, &blank_screen_step, &blank_screen_border, FLOW_LOOP); + +void ui_start_screensaver(void) { + if (!G_screensaver_state.on) { + G_screensaver_state.on = true; + ux_flow_init(0, ux_blank_flow, NULL); + } +} + +#endif diff --git a/src/ui_screensaver.h b/src/ui_screensaver.h new file mode 100644 index 00000000..02905545 --- /dev/null +++ b/src/ui_screensaver.h @@ -0,0 +1,41 @@ +/* Tezos Ledger application - Screen-saver UI functions + + Copyright 2024 TriliTech + Copyright 2024 Functori + Copyright 2023 Ledger + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +#pragma once + +#include + +#ifdef HAVE_BAGL + +typedef struct { + /// Screensaver is on/off. + bool on; +} ux_screensaver_state_t; + +/** + * @brief Empties the screen + * + * Waits a click to return to home screen + * + * Applies only for Nanos devices + * + */ +void ui_start_screensaver(void); + +#endif From b9f090023a1c29dc058be0e6ded22d5ca9e15f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Palmer?= Date: Wed, 10 Apr 2024 12:13:03 +0200 Subject: [PATCH 5/8] Test: add a low-cost screensaver test --- .../nanos/test_low_cost_screensaver/black.png | Bin 0 -> 92 bytes .../test_low_cost_screensaver/home_screen.png | Bin 0 -> 349 bytes test/test_instructions.py | 23 ++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 test/snapshots/nanos/test_low_cost_screensaver/black.png create mode 100644 test/snapshots/nanos/test_low_cost_screensaver/home_screen.png diff --git a/test/snapshots/nanos/test_low_cost_screensaver/black.png b/test/snapshots/nanos/test_low_cost_screensaver/black.png new file mode 100644 index 0000000000000000000000000000000000000000..3403719415c4c318537f631139477cdf2aa0d24a GIT binary patch literal 92 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!2~2j9iA5fDP>O=$B>FSZx1r^0(plPeD}}g fGhYB?!azegvw;EwO41}p;-~WL<=z+0=1Om1tEU@3H#qtw22}5*_5JCvCo4!52c$FXo$VhXU?0M$^Bekqgf%Ka;M*^X|4 zEs9YCQ(xfJKmNC#+8dY%2&wT+>D^<3C%}_*k1^mvtO~`RE00000NkvXXu0mjf-kqOA literal 0 HcmV?d00001 diff --git a/test/test_instructions.py b/test/test_instructions.py index e2f708a6..48511a44 100644 --- a/test/test_instructions.py +++ b/test/test_instructions.py @@ -200,6 +200,29 @@ def both(): backend.wait_for_screen_change() screen("home_screen") +def test_low_cost_screensaver(firmware: Firmware, + backend: BackendInterface, + tezos_navigator: TezosNavigator) -> None: + """Test if the low-cost screensaver work as intended.""" + + if firmware.name != "nanos": + pytest.skip("Only on nanos devices") + + all_click = [ + backend.both_click, + backend.left_click, + backend.right_click, + ] + tezos_navigator.assert_screen("home_screen") + for click in all_click: + backend.both_click() + backend.wait_for_screen_change() + tezos_navigator.assert_screen("black") + click() + backend.wait_for_screen_change() + tezos_navigator.assert_screen("home_screen") + + def test_version(client: TezosClient) -> None: """Test the VERSION instruction.""" From a0df344efddb02c9b91ff3b1f443968d66930b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Palmer?= Date: Wed, 10 Apr 2024 09:34:56 +0200 Subject: [PATCH 6/8] UX: add a screensaver clock In order to save screen after some time (20s) Used on low_cost_display_mode --- src/ui_bagl.c | 11 ++++++++++- src/ui_screensaver.c | 23 +++++++++++++++++++++++ src/ui_screensaver.h | 29 +++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/ui_bagl.c b/src/ui_bagl.c index 65336a9e..5537a9ce 100644 --- a/src/ui_bagl.c +++ b/src/ui_bagl.c @@ -43,7 +43,14 @@ #include "io.h" void ux_set_low_cost_display_mode(bool enable) { - G_display.low_cost_display_mode = enable; + if (G_display.low_cost_display_mode != enable) { + G_display.low_cost_display_mode = enable; + if (G_display.low_cost_display_mode) { + ux_screensaver_start_clock(); + } else { + ux_screensaver_stop_clock(); + } + } } uint8_t io_event(uint8_t channel); @@ -89,6 +96,8 @@ uint8_t io_event(uint8_t channel) { if (!G_display.low_cost_display_mode) { app_ticker_event_callback(); UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {}); + } else { + ux_screensaver_apply_tick(); } break; default: diff --git a/src/ui_screensaver.c b/src/ui_screensaver.c index 493651a3..211f27ee 100644 --- a/src/ui_screensaver.c +++ b/src/ui_screensaver.c @@ -95,4 +95,27 @@ void ui_start_screensaver(void) { } } +#define MS 100u +#define SCREENSAVER_TIMEOUT 20000u // 20u * 10u * MS + +void ux_screensaver_start_clock(void) { + G_screensaver_state.clock.on = true; + G_screensaver_state.clock.timeout = SCREENSAVER_TIMEOUT; +} + +void ux_screensaver_stop_clock(void) { + G_screensaver_state.clock.on = false; +} + +void ux_screensaver_apply_tick(void) { + if (G_screensaver_state.clock.on) { + if (G_screensaver_state.clock.timeout < MS) { + ui_start_screensaver(); + ux_screensaver_stop_clock(); + } else { + G_screensaver_state.clock.timeout -= MS; + } + } +} + #endif diff --git a/src/ui_screensaver.h b/src/ui_screensaver.h index 02905545..48c10f4b 100644 --- a/src/ui_screensaver.h +++ b/src/ui_screensaver.h @@ -23,9 +23,18 @@ #ifdef HAVE_BAGL +typedef struct { + /// Clock has started + bool on; + /// Timeout out before saving screen + unsigned int timeout; +} ux_screensaver_clock_t; + typedef struct { /// Screensaver is on/off. bool on; + /// Timeout out before saving screen + ux_screensaver_clock_t clock; } ux_screensaver_state_t; /** @@ -38,4 +47,24 @@ typedef struct { */ void ui_start_screensaver(void); +/** + * @brief Start a timeout before saving screen + * + */ +void ux_screensaver_start_clock(void); + +/** + * @brief Stop the clock + * + */ +void ux_screensaver_stop_clock(void); + +/** + * @brief Apply one tick to the clock + * + * The tick is assumed to be 100 ms + * + */ +void ux_screensaver_apply_tick(void); + #endif From da88272304d2dc8bf6439d93138132f6e3193ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Palmer?= Date: Wed, 10 Apr 2024 13:11:45 +0200 Subject: [PATCH 7/8] Test: add a test for automatic low-cost screensaver --- .../black.png | Bin 0 -> 92 bytes .../home_screen.png | Bin 0 -> 349 bytes test/test_instructions.py | 48 ++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 test/snapshots/nanos/test_automatic_low_cost_screensaver/black.png create mode 100644 test/snapshots/nanos/test_automatic_low_cost_screensaver/home_screen.png diff --git a/test/snapshots/nanos/test_automatic_low_cost_screensaver/black.png b/test/snapshots/nanos/test_automatic_low_cost_screensaver/black.png new file mode 100644 index 0000000000000000000000000000000000000000..3403719415c4c318537f631139477cdf2aa0d24a GIT binary patch literal 92 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!2~2j9iA5fDP>O=$B>FSZx1r^0(plPeD}}g fGhYB?!azegvw;EwO41}p;-~WL<=z+0=1Om1tEU@3H#qtw22}5*_5JCvCo4!52c$FXo$VhXU?0M$^Bekqgf%Ka;M*^X|4 zEs9YCQ(xfJKmNC#+8dY%2&wT+>D^<3C%}_*k1^mvtO~`RE00000NkvXXu0mjf-kqOA literal 0 HcmV?d00001 diff --git a/test/test_instructions.py b/test/test_instructions.py index 48511a44..60c782d4 100644 --- a/test/test_instructions.py +++ b/test/test_instructions.py @@ -222,6 +222,54 @@ def test_low_cost_screensaver(firmware: Firmware, backend.wait_for_screen_change() tezos_navigator.assert_screen("home_screen") +def test_automatic_low_cost_screensaver(firmware: Firmware, + backend: BackendInterface, + client: TezosClient, + tezos_navigator: TezosNavigator) -> None: + """Test the low-cost screensaver activate at sign.""" + + if firmware.name != "nanos": + pytest.skip("Only on nanos devices") + + account = DEFAULT_ACCOUNT + + tezos_navigator.authorize_baking(account) + + tezos_navigator.assert_screen("home_screen") + + time.sleep(30) + + # Low-cost screensaver activate only after signing + tezos_navigator.assert_screen("home_screen") + + attestation = build_attestation( + op_level=1, + op_round=0, + chain_id=DEFAULT_CHAIN_ID + ) + + client.sign_message(account, attestation) + + time.sleep(5) + + # Low-cost screensaver activate after 20s after signing + tezos_navigator.assert_screen("home_screen") + + time.sleep(30) + + # Low-cost screensaver has been activated + backend.wait_for_screen_change() + tezos_navigator.assert_screen("black") + + backend.both_click() + backend.wait_for_screen_change() + tezos_navigator.assert_screen("home_screen") + + time.sleep(30) + + # Low-cost screensaver desactivate after button push + tezos_navigator.assert_screen("home_screen") + def test_version(client: TezosClient) -> None: """Test the VERSION instruction.""" From 6b93eb507fbc57cdd40cb2df2ee6007db1d486c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Palmer?= Date: Wed, 10 Apr 2024 15:50:29 +0200 Subject: [PATCH 8/8] README: document the screen saver in the README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 3698daff..6b9c027f 100644 --- a/README.md +++ b/README.md @@ -457,6 +457,14 @@ $ octez-client list connected ledgers ## How the app works +### Screen saver + +The screen saver is the one provided by Ledger ([Configure screen saver timeout](https://support.ledger.com/hc/en-us/articles/360017152034-Configure-PIN-lock-and-screen-saver?docs=true)). + +On Nanos devices, the Ledger screensaver can slow down the baking app. This is why it is deactivated during signings. +After a signature, a low-cost screensaver will take over. It will switch the screen off after 20 seconds of inactivity. +Press any button to exit sleep mode. When the sleep mode is exited, the Ledger screen saver will take over again if there are no more signatures. + ### High water mark (HWM) To avoid double baking, double attestation and double pre-attestation, the application maintains a high water mark (HWM) corresponding to the last level/round encountered during signature requests. The HWMs are displayed on the home screen and are updated after each signature.