From edab66960a38be6235f5aee35cfd07c462aec3dd Mon Sep 17 00:00:00 2001 From: Emma Turner Date: Sun, 24 Sep 2023 21:19:47 +0100 Subject: [PATCH] stax: advance screens on user tap --- app/src/ui_stream.h | 16 +++ app/src/ui_stream_nbgl.c | 108 ++++++++++++++++++ .../snapshots/operation_0_transaction.png | Bin 0 -> 8324 bytes .../integration/stax/test_reject_transfer.py | 46 ++++++++ 4 files changed, 170 insertions(+) create mode 100644 tests/integration/stax/snapshots/operation_0_transaction.png create mode 100755 tests/integration/stax/test_reject_transfer.py diff --git a/app/src/ui_stream.h b/app/src/ui_stream.h index b15886bbe..ee66fd5b5 100644 --- a/app/src/ui_stream.h +++ b/app/src/ui_stream.h @@ -36,6 +36,10 @@ `tz_ui_stream_push`, calling `tz_ui_stream_close`, and launching with a `refill` callback set to NULL. */ +#ifdef HAVE_NBGL +#include +#endif + #include #define TZ_UI_STREAM_HISTORY_SCREENS 8 @@ -90,6 +94,15 @@ typedef struct { char body[TZ_UI_STREAM_CONTENTS_LINES][TZ_UI_STREAM_CONTENTS_WIDTH + 1]; } tz_ui_stream_screen_t; +#ifdef HAVE_NBGL +typedef struct { + char title[TZ_UI_STREAM_TITLE_WIDTH + 1]; + char body[TZ_UI_STREAM_CONTENTS_WIDTH + 1]; + nbgl_layoutTagValue_t pair; + nbgl_layoutTagValueList_t list; +} tz_ui_stream_display_t; +#endif // HAVE_NBGL + typedef struct { void (*cb)(tz_ui_cb_type_t); tz_ui_stream_screen_t screens[TZ_UI_STREAM_HISTORY_SCREENS]; @@ -99,6 +112,9 @@ typedef struct { // FIXME: workaround for issue with non-local control flow. Remove once // fixed see !66 bool pressed_right; +#ifdef HAVE_NBGL + tz_ui_stream_display_t current_screen; +#endif // HAVE_NBGL } tz_ui_stream_t; void tz_ui_stream_init(void (*)(tz_ui_cb_type_t)); diff --git a/app/src/ui_stream_nbgl.c b/app/src/ui_stream_nbgl.c index 03ecd1f87..219635b4a 100644 --- a/app/src/ui_stream_nbgl.c +++ b/app/src/ui_stream_nbgl.c @@ -22,6 +22,8 @@ #include "globals.h" +bool tz_ui_nav_cb(uint8_t, nbgl_pageContent_t *); + void tz_reject(void) { @@ -45,11 +47,41 @@ tz_reject_ui(void) nbgl_useCaseStatus("Rejected", false, tz_reject); } +void +tz_choice_ui(bool accept) +{ + FUNC_ENTER(("accept=%d", accept)); + + if (accept) { + // FIXME: implement accept workflow + } else { + tz_reject_ui(); + } + + FUNC_LEAVE(); +} + +void +tz_ui_continue(void) +{ + FUNC_ENTER(("void")); + + tz_ui_stream_t *s = &global.stream; + + if (!s->full) + s->cb(TZ_UI_STREAM_CB_REFILL); + + FUNC_LEAVE(); + return; +} + void tz_ui_start(void) { FUNC_ENTER(("void")); + nbgl_useCaseForwardOnlyReview("Reject", NULL, tz_ui_nav_cb, tz_choice_ui); + FUNC_LEAVE(); return; } @@ -73,4 +105,80 @@ tz_ui_stream_init(void (*cb)(uint8_t)) FUNC_LEAVE(); } +static nbgl_layoutTagValue_t * +tz_ui_current_screen(__attribute__((unused)) uint8_t pairIndex) +{ + FUNC_ENTER(("pairIndex=%d", pairIndex)); + + tz_ui_stream_t *s = &global.stream; + tz_ui_stream_display_t *c = &s->current_screen; + + PRINTF("[DEBUG] pressed_right=%d\n", s->pressed_right); + + if (s->current < s->total && s->pressed_right) { + s->current++; + s->pressed_right = false; + } + + c->title[0] = 0; + c->body[0] = 0; + + size_t bucket = s->current % TZ_UI_STREAM_HISTORY_SCREENS; + STRLCPY(c->title, s->screens[bucket].title); + STRLCPY(c->body, s->screens[bucket].body[0]); + + c->pair.item = c->title; + c->pair.value = c->body; + + PRINTF("show title=%s, body=%s from bucket=%d\n", c->title, c->body, + bucket); + FUNC_LEAVE(); + return &c->pair; +} + +bool +tz_ui_nav_cb(uint8_t page, nbgl_pageContent_t *content) +{ + FUNC_ENTER(("page=%d, content=%p", page, content)); + + tz_ui_stream_t *s = &global.stream; + tz_ui_stream_display_t *c = &s->current_screen; + + if (s->total < 0) { + return false; + } + + if (page > 0 && !s->pressed_right) { + s->pressed_right = true; + } + + PRINTF("pressed_right=%d, current=%d, total=%d, full=%d\n", + s->pressed_right, s->current, s->total, s->full); + + if ((s->current == s->total) && !s->full) { + tz_ui_continue(); + } + + if (!s->full) { + c->list.pairs = NULL; + c->list.callback = tz_ui_current_screen; + c->list.startIndex = 0; + c->list.nbPairs = 1; + c->list.smallCaseForValue = false; + c->list.wrapping = false; + + content->type = TAG_VALUE_LIST; + content->tagValueList = c->list; + } else { + content->type = INFO_LONG_PRESS; + content->infoLongPress.icon = &C_tezos; + content->infoLongPress.text = "Sign"; + content->infoLongPress.longPressText = "Sign"; + } + + FUNC_LEAVE(); + + return true; +} + #endif diff --git a/tests/integration/stax/snapshots/operation_0_transaction.png b/tests/integration/stax/snapshots/operation_0_transaction.png new file mode 100644 index 0000000000000000000000000000000000000000..8a9dd89d193e4501d988062e5de777aeeeab70af GIT binary patch literal 8324 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̤tzqmq)GY>CqY@4nOW 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 + +# 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. + +from utils import * + +# full input: 0300000000000000000000000000000000000000000000000000000000000000006c016e8874874d31c3fbd636e924d5a036a43ec8faa7d0860308362d80d30e01000000000000000000000000000000000000000000ff02000000020316 +# full output: CAR +# signer: tz1dyX3B1CFYa2DfdFLyPtiJCfQRUgPVME6E +# path: m/44'/1729'/0'/0' + +if __name__ == "__main__": + app = stax_app() + + app.assert_screen(SCREEN_HOME_DEFAULT) + + app.send_apdu("800f000011048000002c800006c18000000080000000") + app.expect_apdu_return("9000") + + app.assert_screen("review_request_sign_operation") + app.review.tap() + + # Ensure we don't advance to a blank screen + app.assert_screen("review_request_sign_operation") + + app.send_apdu("800f81005e0300000000000000000000000000000000000000000000000000000000000000006c016e8874874d31c3fbd636e924d5a036a43ec8faa7d0860308362d80d30e01000000000000000000000000000000000000000000ff02000000020316"); + + app.review.tap() + app.assert_screen("operation_0_transaction") + + app.review_reject_signing() + app.expect_apdu_failure("6985") + + app.assert_screen(SCREEN_HOME_DEFAULT) + app.welcome.quit()