Better split between business logic & UI code for EIP-712
This commit is contained in:
@@ -25,6 +25,11 @@ void ui_191_switch_to_message_end(void);
|
||||
void ui_191_switch_to_sign(void);
|
||||
void ui_191_switch_to_question(void);
|
||||
|
||||
// EIP-712
|
||||
void ui_712_start(void);
|
||||
void ui_712_switch_to_message(void);
|
||||
void ui_712_switch_to_sign(void);
|
||||
|
||||
#include "ui_callbacks.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#include "ui_flow_712.h"
|
||||
#include "ui_logic.h"
|
||||
#include "shared_context.h" // strings
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_712_step_review,
|
||||
pnn,
|
||||
{
|
||||
&C_icon_eye,
|
||||
"Review",
|
||||
"typed message",
|
||||
});
|
||||
UX_STEP_NOCB(
|
||||
ux_712_step_dynamic,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = strings.tmp.tmp2,
|
||||
.text = strings.tmp.tmp,
|
||||
}
|
||||
);
|
||||
UX_STEP_INIT(
|
||||
ux_712_step_dummy,
|
||||
NULL,
|
||||
NULL,
|
||||
{
|
||||
ui_712_next_field();
|
||||
}
|
||||
);
|
||||
UX_STEP_CB(
|
||||
ux_712_step_approve,
|
||||
pb,
|
||||
ui_712_approve(NULL),
|
||||
{
|
||||
&C_icon_validate_14,
|
||||
"Approve",
|
||||
});
|
||||
UX_STEP_CB(
|
||||
ux_712_step_reject,
|
||||
pb,
|
||||
ui_712_reject(NULL),
|
||||
{
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_712_flow,
|
||||
&ux_712_step_review,
|
||||
&ux_712_step_dynamic,
|
||||
&ux_712_step_dummy,
|
||||
&ux_712_step_approve,
|
||||
&ux_712_step_reject);
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
@@ -1,12 +0,0 @@
|
||||
#ifndef UI_FLOW_712_H_
|
||||
#define UI_FLOW_712_H_
|
||||
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#include "ux_flow_engine.h"
|
||||
|
||||
extern const ux_flow_step_t* const ux_712_flow[];
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
#endif // UI_FLOW_712_H_
|
||||
@@ -1,72 +1,87 @@
|
||||
#include "shared_context.h"
|
||||
#include "ui_callbacks.h"
|
||||
#include "common_712.h"
|
||||
#include "ethUtils.h"
|
||||
#ifdef HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
void prepare_domain_hash_v0() {
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"0x%.*H",
|
||||
KECCAK256_HASH_BYTESIZE,
|
||||
tmpCtx.messageSigningContext712.domainHash);
|
||||
}
|
||||
#include "ui_logic.h"
|
||||
#include "shared_context.h" // strings
|
||||
|
||||
void prepare_message_hash_v0() {
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"0x%.*H",
|
||||
KECCAK256_HASH_BYTESIZE,
|
||||
tmpCtx.messageSigningContext712.messageHash);
|
||||
enum { UI_712_POS_REVIEW, UI_712_POS_END };
|
||||
static uint8_t ui_pos;
|
||||
|
||||
static void dummy_cb(void) {
|
||||
if (!ui_712_next_field()) {
|
||||
if (ui_pos == UI_712_POS_REVIEW) {
|
||||
ux_flow_next();
|
||||
ui_pos = UI_712_POS_END;
|
||||
} else // UI_712_POS_END
|
||||
{
|
||||
ux_flow_prev();
|
||||
ui_pos = UI_712_POS_REVIEW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_sign_712_v0_flow_1_step,
|
||||
ux_712_step_review,
|
||||
pnn,
|
||||
{
|
||||
&C_icon_certificate,
|
||||
"Sign",
|
||||
&C_icon_eye,
|
||||
"Review",
|
||||
"typed message",
|
||||
});
|
||||
UX_STEP_NOCB_INIT(
|
||||
ux_sign_712_v0_flow_2_step,
|
||||
bnnn_paging,
|
||||
prepare_domain_hash_v0(),
|
||||
{
|
||||
.title = "Domain hash",
|
||||
UX_STEP_NOCB(
|
||||
ux_712_step_dynamic,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = strings.tmp.tmp2,
|
||||
.text = strings.tmp.tmp,
|
||||
});
|
||||
UX_STEP_NOCB_INIT(
|
||||
ux_sign_712_v0_flow_3_step,
|
||||
bnnn_paging,
|
||||
prepare_message_hash_v0(),
|
||||
{
|
||||
.title = "Message hash",
|
||||
.text = strings.tmp.tmp,
|
||||
});
|
||||
}
|
||||
);
|
||||
UX_STEP_INIT(
|
||||
ux_712_step_dummy,
|
||||
NULL,
|
||||
NULL,
|
||||
{
|
||||
dummy_cb();
|
||||
}
|
||||
);
|
||||
UX_STEP_CB(
|
||||
ux_sign_712_v0_flow_4_step,
|
||||
pbb,
|
||||
ui_712_approve_cb(NULL),
|
||||
ux_712_step_approve,
|
||||
pb,
|
||||
ui_712_approve(NULL),
|
||||
{
|
||||
&C_icon_validate_14,
|
||||
"Sign",
|
||||
"message",
|
||||
"Approve",
|
||||
});
|
||||
UX_STEP_CB(
|
||||
ux_sign_712_v0_flow_5_step,
|
||||
pbb,
|
||||
ui_712_reject_cb(NULL),
|
||||
ux_712_step_reject,
|
||||
pb,
|
||||
ui_712_reject(NULL),
|
||||
{
|
||||
&C_icon_crossmark,
|
||||
"Cancel",
|
||||
"signature",
|
||||
"Reject",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_sign_712_v0_flow,
|
||||
&ux_sign_712_v0_flow_1_step,
|
||||
&ux_sign_712_v0_flow_2_step,
|
||||
&ux_sign_712_v0_flow_3_step,
|
||||
&ux_sign_712_v0_flow_4_step,
|
||||
&ux_sign_712_v0_flow_5_step);
|
||||
UX_FLOW(ux_712_flow,
|
||||
&ux_712_step_review,
|
||||
&ux_712_step_dynamic,
|
||||
&ux_712_step_dummy,
|
||||
&ux_712_step_approve,
|
||||
&ux_712_step_reject);
|
||||
|
||||
void ui_712_start(void) {
|
||||
ux_flow_init(0, ux_712_flow, NULL);
|
||||
ui_pos = UI_712_POS_REVIEW;
|
||||
}
|
||||
|
||||
void ui_712_switch_to_message(void) {
|
||||
ux_flow_init(0, ux_712_flow, &ux_712_step_dynamic);
|
||||
ui_pos = UI_712_POS_REVIEW;
|
||||
}
|
||||
|
||||
void ui_712_switch_to_sign(void) {
|
||||
ux_flow_init(0, ux_712_flow, &ux_712_step_approve);
|
||||
ui_pos = UI_712_POS_END;
|
||||
}
|
||||
|
||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||
|
||||
72
src_bagl/ui_flow_signMessage712_v0.c
Normal file
72
src_bagl/ui_flow_signMessage712_v0.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "shared_context.h"
|
||||
#include "ui_callbacks.h"
|
||||
#include "common_712.h"
|
||||
#include "ethUtils.h"
|
||||
|
||||
void prepare_domain_hash_v0() {
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"0x%.*H",
|
||||
KECCAK256_HASH_BYTESIZE,
|
||||
tmpCtx.messageSigningContext712.domainHash);
|
||||
}
|
||||
|
||||
void prepare_message_hash_v0() {
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"0x%.*H",
|
||||
KECCAK256_HASH_BYTESIZE,
|
||||
tmpCtx.messageSigningContext712.messageHash);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_sign_712_v0_flow_1_step,
|
||||
pnn,
|
||||
{
|
||||
&C_icon_certificate,
|
||||
"Sign",
|
||||
"typed message",
|
||||
});
|
||||
UX_STEP_NOCB_INIT(
|
||||
ux_sign_712_v0_flow_2_step,
|
||||
bnnn_paging,
|
||||
prepare_domain_hash_v0(),
|
||||
{
|
||||
.title = "Domain hash",
|
||||
.text = strings.tmp.tmp,
|
||||
});
|
||||
UX_STEP_NOCB_INIT(
|
||||
ux_sign_712_v0_flow_3_step,
|
||||
bnnn_paging,
|
||||
prepare_message_hash_v0(),
|
||||
{
|
||||
.title = "Message hash",
|
||||
.text = strings.tmp.tmp,
|
||||
});
|
||||
UX_STEP_CB(
|
||||
ux_sign_712_v0_flow_4_step,
|
||||
pbb,
|
||||
ui_712_approve_cb(NULL),
|
||||
{
|
||||
&C_icon_validate_14,
|
||||
"Sign",
|
||||
"message",
|
||||
});
|
||||
UX_STEP_CB(
|
||||
ux_sign_712_v0_flow_5_step,
|
||||
pbb,
|
||||
ui_712_reject_cb(NULL),
|
||||
{
|
||||
&C_icon_crossmark,
|
||||
"Cancel",
|
||||
"signature",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_sign_712_v0_flow,
|
||||
&ux_sign_712_v0_flow_1_step,
|
||||
&ux_sign_712_v0_flow_2_step,
|
||||
&ux_sign_712_v0_flow_3_step,
|
||||
&ux_sign_712_v0_flow_4_step,
|
||||
&ux_sign_712_v0_flow_5_step);
|
||||
@@ -6,8 +6,6 @@
|
||||
#include "mem.h"
|
||||
#include "mem_utils.h"
|
||||
#include "os_io.h"
|
||||
#include "ux_flow_engine.h"
|
||||
#include "ui_flow_712.h"
|
||||
#include "shared_context.h"
|
||||
#include "ethUtils.h" // getEthDisplayableAddress
|
||||
#include "utils.h" // uint256_to_decimal
|
||||
@@ -18,6 +16,7 @@
|
||||
#include "apdu_constants.h" // APDU response codes
|
||||
#include "typed_data.h"
|
||||
#include "commands_712.h"
|
||||
#include "common_ui.h"
|
||||
|
||||
static t_ui_context *ui_ctx = NULL;
|
||||
|
||||
@@ -106,43 +105,34 @@ void ui_712_set_value(const char *const str, uint8_t length) {
|
||||
void ui_712_redraw_generic_step(void) {
|
||||
if (!ui_ctx->shown) // Initialize if it is not already
|
||||
{
|
||||
ux_flow_init(0, ux_712_flow, NULL);
|
||||
ui_712_start();
|
||||
ui_ctx->shown = true;
|
||||
} else {
|
||||
// not pretty, manually changes the internal state of the UX flow
|
||||
// so that we always land on the first screen of a paging step without any visible
|
||||
// screen glitching (quick screen switching)
|
||||
G_ux.flow_stack[G_ux.stack_count - 1].index = 0;
|
||||
// since the flow now thinks we are displaying the first step, do next
|
||||
ux_flow_next();
|
||||
ui_712_switch_to_message();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on the intermediate dummy screen between the dynamic step
|
||||
* && the approve/reject screen
|
||||
* Called to fetch the next field if they have not all been processed yet
|
||||
*
|
||||
* @return whether there will be a next field
|
||||
*/
|
||||
void ui_712_next_field(void) {
|
||||
bool ui_712_next_field(void) {
|
||||
bool next = false;
|
||||
|
||||
if (ui_ctx == NULL) {
|
||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||
return;
|
||||
}
|
||||
if (ui_ctx->structs_to_review > 0) {
|
||||
ui_712_review_struct(path_get_nth_field_to_last(ui_ctx->structs_to_review));
|
||||
ui_ctx->structs_to_review -= 1;
|
||||
} else {
|
||||
if (ui_ctx->structs_to_review > 0) {
|
||||
ui_712_review_struct(path_get_nth_field_to_last(ui_ctx->structs_to_review));
|
||||
ui_ctx->structs_to_review -= 1;
|
||||
}
|
||||
if (!ui_ctx->end_reached) {
|
||||
handle_eip712_return_code(true);
|
||||
} else {
|
||||
if (ui_ctx->pos == UI_712_POS_REVIEW) {
|
||||
ux_flow_next();
|
||||
ui_ctx->pos = UI_712_POS_END;
|
||||
} else {
|
||||
ux_flow_prev();
|
||||
ui_ctx->pos = UI_712_POS_REVIEW;
|
||||
}
|
||||
next = true;
|
||||
}
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -419,7 +409,7 @@ void ui_712_end_sign(void) {
|
||||
ui_ctx->end_reached = true;
|
||||
|
||||
if (N_storage.verbose_eip712 || (ui_ctx->filtering_mode == EIP712_FILTERING_FULL)) {
|
||||
ui_712_next_field();
|
||||
ui_712_switch_to_sign();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,7 +420,6 @@ bool ui_712_init(void) {
|
||||
if ((ui_ctx = MEM_ALLOC_AND_ALIGN_TYPE(*ui_ctx))) {
|
||||
ui_ctx->shown = false;
|
||||
ui_ctx->end_reached = false;
|
||||
ui_ctx->pos = UI_712_POS_REVIEW;
|
||||
ui_ctx->filtering_mode = EIP712_FILTERING_BASIC;
|
||||
} else {
|
||||
apdu_response_code = APDU_RESPONSE_INSUFFICIENT_MEMORY;
|
||||
|
||||
@@ -11,12 +11,9 @@
|
||||
|
||||
typedef enum { EIP712_FILTERING_BASIC, EIP712_FILTERING_FULL } e_eip712_filtering_mode;
|
||||
|
||||
typedef enum { UI_712_POS_REVIEW, UI_712_POS_END } e_ui_position;
|
||||
|
||||
typedef struct {
|
||||
bool shown;
|
||||
bool end_reached;
|
||||
e_ui_position pos;
|
||||
uint8_t filtering_mode;
|
||||
uint8_t filters_to_process;
|
||||
uint8_t field_flags;
|
||||
@@ -25,7 +22,7 @@ typedef struct {
|
||||
|
||||
bool ui_712_init(void);
|
||||
void ui_712_deinit(void);
|
||||
void ui_712_next_field(void);
|
||||
bool ui_712_next_field(void);
|
||||
void ui_712_review_struct(const void *const struct_ptr);
|
||||
bool ui_712_new_field(const void *const field_ptr, const uint8_t *const data, uint8_t length);
|
||||
void ui_712_end_sign(void);
|
||||
|
||||
Reference in New Issue
Block a user