EIP712 Filtering count checking
This commit is contained in:
@@ -810,22 +810,21 @@ Full filtering is disabled by default and has to be changed with this APDU (defa
|
|||||||
|
|
||||||
Field substitution will be ignored if the full filtering is not activated.
|
Field substitution will be ignored if the full filtering is not activated.
|
||||||
|
|
||||||
If activated, fields will be by default hidden unless they receive a field name substitution.
|
This command should come before the domain & message implementations. If activated, fields will be by default hidden unless they receive a field name substitution.
|
||||||
|
|
||||||
##### Contract name substitution
|
##### Message info
|
||||||
|
|
||||||
Name substitution commands should come right after the contract address from the domain has been sent with a *SEND STRUCT IMPLEMENTATION*.
|
This command should come right after the implementation of the domain has been sent with *SEND STRUCT IMPLEMENTATION*, just before sending the message implementation.
|
||||||
Perfect moment to do it is when the domain implementation has been sent, just before sending the message implementation.
|
|
||||||
The first byte is used so that a signature of one type cannot be valid as another type.
|
The first byte is used so that a signature of one type cannot be valid as another type.
|
||||||
|
|
||||||
The signature is computed on :
|
The signature is computed on :
|
||||||
|
|
||||||
183 || chain ID (BE) || contract address || schema hash || display name
|
183 || chain ID (BE) || contract address || schema hash || filters count || display name
|
||||||
|
|
||||||
|
|
||||||
##### Field name substitution
|
##### Show field
|
||||||
|
|
||||||
Name substitution commands should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones).
|
These commands should come before the corresponding *SEND STRUCT IMPLEMENTATION* and are only usable for message fields (and not domain ones).
|
||||||
The first byte is used so that a signature of one type cannot be valid as another type.
|
The first byte is used so that a signature of one type cannot be valid as another type.
|
||||||
|
|
||||||
The signature is computed on :
|
The signature is computed on :
|
||||||
@@ -842,19 +841,31 @@ _Command_
|
|||||||
| E0 | 1E | 00
|
| E0 | 1E | 00
|
||||||
| 00 : activate
|
| 00 : activate
|
||||||
|
|
||||||
0F : contract name
|
0F : message info
|
||||||
|
|
||||||
FF : field name
|
FF : show field
|
||||||
| variable | variable
|
| variable | variable
|
||||||
|=========================================================================
|
|=========================================================================
|
||||||
|
|
||||||
_Input data_
|
_Input data_
|
||||||
|
|
||||||
##### If P1 == activate
|
##### If P2 == activate
|
||||||
|
|
||||||
None
|
None
|
||||||
|
|
||||||
##### If P1 == contract name OR P1 == field name
|
##### If P2 == message info
|
||||||
|
|
||||||
|
[width="80%"]
|
||||||
|
|==========================================
|
||||||
|
| *Description* | *Length (byte)*
|
||||||
|
| Display name length | 1
|
||||||
|
| Display name | variable
|
||||||
|
| Filters count | 1
|
||||||
|
| Signature length | 1
|
||||||
|
| Signature | variable
|
||||||
|
|==========================================
|
||||||
|
|
||||||
|
##### If P2 == show field
|
||||||
|
|
||||||
[width="80%"]
|
[width="80%"]
|
||||||
|==========================================
|
|==========================================
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
#define APDU_RESPONSE_INVALID_INS 0x6d00
|
#define APDU_RESPONSE_INVALID_INS 0x6d00
|
||||||
#define APDU_RESPONSE_INVALID_P1_P2 0x6b00
|
#define APDU_RESPONSE_INVALID_P1_P2 0x6b00
|
||||||
#define APDU_RESPONSE_CONDITION_NOT_SATISFIED 0x6985
|
#define APDU_RESPONSE_CONDITION_NOT_SATISFIED 0x6985
|
||||||
#define APDU_RESPONSE_REF_DATA_NOT_USABLE 0x6a88
|
#define APDU_RESPONSE_REF_DATA_NOT_FOUND 0x6a88
|
||||||
|
|
||||||
#ifdef HAVE_STARKWARE
|
#ifdef HAVE_STARKWARE
|
||||||
|
|
||||||
|
|||||||
@@ -139,14 +139,15 @@ bool handle_eip712_filtering(const uint8_t *const apdu_buf) {
|
|||||||
ret = compute_schema_hash();
|
ret = compute_schema_hash();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case P2_FILT_CONTRACT_NAME:
|
case P2_FILT_MESSAGE_INFO:
|
||||||
case P2_FILT_FIELD_NAME:
|
case P2_FILT_SHOW_FIELD:
|
||||||
type = (apdu_buf[OFFSET_P2] == P2_FILT_CONTRACT_NAME) ? FILTERING_CONTRACT_NAME
|
type = (apdu_buf[OFFSET_P2] == P2_FILT_MESSAGE_INFO)
|
||||||
: FILTERING_STRUCT_FIELD;
|
? FILTERING_PROVIDE_MESSAGE_INFO
|
||||||
|
: FILTERING_SHOW_FIELD;
|
||||||
if (ui_712_get_filtering_mode() == EIP712_FILTERING_FULL) {
|
if (ui_712_get_filtering_mode() == EIP712_FILTERING_FULL) {
|
||||||
ret =
|
ret =
|
||||||
provide_filtering_info(&apdu_buf[OFFSET_CDATA], apdu_buf[OFFSET_LC], type);
|
provide_filtering_info(&apdu_buf[OFFSET_CDATA], apdu_buf[OFFSET_LC], type);
|
||||||
if ((apdu_buf[OFFSET_P2] == P2_FILT_CONTRACT_NAME) && ret) {
|
if ((apdu_buf[OFFSET_P2] == P2_FILT_MESSAGE_INFO) && ret) {
|
||||||
reply_apdu = false;
|
reply_apdu = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,6 +178,10 @@ bool handle_eip712_sign(const uint8_t *const apdu_buf) {
|
|||||||
|
|
||||||
if (eip712_context == NULL) {
|
if (eip712_context == NULL) {
|
||||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||||
|
} else if ((ui_712_get_filtering_mode() == EIP712_FILTERING_FULL) &&
|
||||||
|
(ui_712_remaining_filters() != 0)) {
|
||||||
|
PRINTF("%d EIP712 filters are missing\n", ui_712_remaining_filters());
|
||||||
|
apdu_response_code = APDU_RESPONSE_REF_DATA_NOT_FOUND;
|
||||||
} else if (parseBip32(&apdu_buf[OFFSET_CDATA], &length, &tmpCtx.messageSigningContext.bip32) !=
|
} else if (parseBip32(&apdu_buf[OFFSET_CDATA], &length, &tmpCtx.messageSigningContext.bip32) !=
|
||||||
NULL) {
|
NULL) {
|
||||||
if (!N_storage.verbose_eip712 && (ui_712_get_filtering_mode() == EIP712_FILTERING_BASIC)) {
|
if (!N_storage.verbose_eip712 && (ui_712_get_filtering_mode() == EIP712_FILTERING_BASIC)) {
|
||||||
|
|||||||
@@ -11,14 +11,14 @@
|
|||||||
#define P1_PARTIAL 0xFF
|
#define P1_PARTIAL 0xFF
|
||||||
|
|
||||||
// APDUs P2
|
// APDUs P2
|
||||||
#define P2_DEF_NAME 0x00
|
#define P2_DEF_NAME 0x00
|
||||||
#define P2_DEF_FIELD 0xFF
|
#define P2_DEF_FIELD 0xFF
|
||||||
#define P2_IMPL_NAME P2_DEF_NAME
|
#define P2_IMPL_NAME P2_DEF_NAME
|
||||||
#define P2_IMPL_ARRAY 0x0F
|
#define P2_IMPL_ARRAY 0x0F
|
||||||
#define P2_IMPL_FIELD P2_DEF_FIELD
|
#define P2_IMPL_FIELD P2_DEF_FIELD
|
||||||
#define P2_FILT_ACTIVATE 0x00
|
#define P2_FILT_ACTIVATE 0x00
|
||||||
#define P2_FILT_CONTRACT_NAME 0x0F
|
#define P2_FILT_MESSAGE_INFO 0x0F
|
||||||
#define P2_FILT_FIELD_NAME 0xFF
|
#define P2_FILT_SHOW_FIELD 0xFF
|
||||||
|
|
||||||
#define DOMAIN_STRUCT_NAME "EIP712Domain"
|
#define DOMAIN_STRUCT_NAME "EIP712Domain"
|
||||||
|
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ static bool verify_filtering_signature(uint8_t dname_length,
|
|||||||
|
|
||||||
// Magic number, makes it so a signature of one type can't be used as another
|
// Magic number, makes it so a signature of one type can't be used as another
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case FILTERING_STRUCT_FIELD:
|
case FILTERING_SHOW_FIELD:
|
||||||
hash_byte(FILTERING_MAGIC_STRUCT_FIELD, (cx_hash_t *) &hash_ctx);
|
hash_byte(FILTERING_MAGIC_STRUCT_FIELD, (cx_hash_t *) &hash_ctx);
|
||||||
break;
|
break;
|
||||||
case FILTERING_CONTRACT_NAME:
|
case FILTERING_PROVIDE_MESSAGE_INFO:
|
||||||
hash_byte(FILTERING_MAGIC_CONTRACT_NAME, (cx_hash_t *) &hash_ctx);
|
hash_byte(FILTERING_MAGIC_CONTRACT_NAME, (cx_hash_t *) &hash_ctx);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -93,8 +93,11 @@ static bool verify_filtering_signature(uint8_t dname_length,
|
|||||||
sizeof(eip712_context->schema_hash),
|
sizeof(eip712_context->schema_hash),
|
||||||
(cx_hash_t *) &hash_ctx);
|
(cx_hash_t *) &hash_ctx);
|
||||||
|
|
||||||
if (type == FILTERING_STRUCT_FIELD) {
|
if (type == FILTERING_SHOW_FIELD) {
|
||||||
hash_filtering_path((cx_hash_t *) &hash_ctx);
|
hash_filtering_path((cx_hash_t *) &hash_ctx);
|
||||||
|
} else // FILTERING_PROVIDE_MESSAGE_INFO
|
||||||
|
{
|
||||||
|
hash_byte(ui_712_remaining_filters(), (cx_hash_t *) &hash_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display name
|
// Display name
|
||||||
@@ -131,13 +134,14 @@ bool provide_filtering_info(const uint8_t *const payload, uint8_t length, e_filt
|
|||||||
const char *dname;
|
const char *dname;
|
||||||
uint8_t sig_len;
|
uint8_t sig_len;
|
||||||
const uint8_t *sig;
|
const uint8_t *sig;
|
||||||
|
uint8_t offset = 0;
|
||||||
|
|
||||||
if (type == FILTERING_CONTRACT_NAME) {
|
if (type == FILTERING_PROVIDE_MESSAGE_INFO) {
|
||||||
if (path_get_root_type() != ROOT_DOMAIN) {
|
if (path_get_root_type() != ROOT_DOMAIN) {
|
||||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else // FILTERING_STRUCT_FIELD
|
} else // FILTERING_SHOW_FIELD
|
||||||
{
|
{
|
||||||
if (path_get_root_type() != ROOT_MESSAGE) {
|
if (path_get_root_type() != ROOT_MESSAGE) {
|
||||||
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
apdu_response_code = APDU_RESPONSE_CONDITION_NOT_SATISFIED;
|
||||||
@@ -145,20 +149,25 @@ bool provide_filtering_info(const uint8_t *const payload, uint8_t length, e_filt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
dname_len = payload[0];
|
dname_len = payload[offset++];
|
||||||
if ((1 + dname_len) < length) {
|
if ((1 + dname_len) < length) {
|
||||||
dname = (char *) &payload[1];
|
dname = (char *) &payload[offset];
|
||||||
sig_len = payload[1 + dname_len];
|
offset += dname_len;
|
||||||
sig = &payload[1 + dname_len + 1];
|
if (type == FILTERING_PROVIDE_MESSAGE_INFO) {
|
||||||
if ((sig_len > 0) && ((1 + dname_len + 1 + sig_len) == length)) {
|
ui_712_set_filters_count(payload[offset++]);
|
||||||
|
}
|
||||||
|
sig_len = payload[offset++];
|
||||||
|
sig = &payload[offset];
|
||||||
|
offset += sig_len;
|
||||||
|
if ((sig_len > 0) && (offset == length)) {
|
||||||
if ((ret = verify_filtering_signature(dname_len, dname, sig_len, sig, type))) {
|
if ((ret = verify_filtering_signature(dname_len, dname, sig_len, sig, type))) {
|
||||||
if (type == FILTERING_CONTRACT_NAME) {
|
if (type == FILTERING_PROVIDE_MESSAGE_INFO) {
|
||||||
if (!N_storage.verbose_eip712) {
|
if (!N_storage.verbose_eip712) {
|
||||||
ui_712_set_title("Contract", 8);
|
ui_712_set_title("Contract", 8);
|
||||||
ui_712_set_value(dname, dname_len);
|
ui_712_set_value(dname, dname_len);
|
||||||
ui_712_redraw_generic_step();
|
ui_712_redraw_generic_step();
|
||||||
}
|
}
|
||||||
} else // FILTERING_STRUCT_FIELD
|
} else // FILTERING_SHOW_FIELD
|
||||||
{
|
{
|
||||||
if (dname_len > 0) // don't substitute for an empty name
|
if (dname_len > 0) // don't substitute for an empty name
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#define FILTERING_MAGIC_CONTRACT_NAME 0b10110111 // 183
|
#define FILTERING_MAGIC_CONTRACT_NAME 0b10110111 // 183
|
||||||
#define FILTERING_MAGIC_STRUCT_FIELD 0b01001000 // ~183 = 72
|
#define FILTERING_MAGIC_STRUCT_FIELD 0b01001000 // ~183 = 72
|
||||||
|
|
||||||
typedef enum { FILTERING_CONTRACT_NAME, FILTERING_STRUCT_FIELD } e_filtering_type;
|
typedef enum { FILTERING_PROVIDE_MESSAGE_INFO, FILTERING_SHOW_FIELD } e_filtering_type;
|
||||||
|
|
||||||
bool provide_filtering_info(const uint8_t *const payload, uint8_t length, e_filtering_type type);
|
bool provide_filtering_info(const uint8_t *const payload, uint8_t length, e_filtering_type type);
|
||||||
|
|
||||||
|
|||||||
@@ -486,6 +486,7 @@ static bool path_advance_in_struct(void) {
|
|||||||
}
|
}
|
||||||
if (path_struct->depth_count > 0) {
|
if (path_struct->depth_count > 0) {
|
||||||
*depth += 1;
|
*depth += 1;
|
||||||
|
ui_712_notify_filter_change();
|
||||||
end_reached = (*depth == fields_count);
|
end_reached = (*depth == fields_count);
|
||||||
}
|
}
|
||||||
if (end_reached) {
|
if (end_reached) {
|
||||||
|
|||||||
@@ -503,6 +503,24 @@ e_eip712_filtering_mode ui_712_get_filtering_mode(void) {
|
|||||||
return ui_ctx->filtering_mode;
|
return ui_ctx->filtering_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the number of filters this message should process
|
||||||
|
*
|
||||||
|
* @param[in] count number of filters
|
||||||
|
*/
|
||||||
|
void ui_712_set_filters_count(uint8_t count) {
|
||||||
|
ui_ctx->filters_to_process = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of filters left to process
|
||||||
|
*
|
||||||
|
* @return number of filters
|
||||||
|
*/
|
||||||
|
uint8_t ui_712_remaining_filters(void) {
|
||||||
|
return ui_ctx->filters_to_process;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset all the UI struct field flags
|
* Reset all the UI struct field flags
|
||||||
*/
|
*/
|
||||||
@@ -521,4 +539,21 @@ void ui_712_queue_struct_to_review(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify of a filter change from a path advance
|
||||||
|
*
|
||||||
|
* This function figures out by itself if there is anything to do
|
||||||
|
*/
|
||||||
|
void ui_712_notify_filter_change(void) {
|
||||||
|
if (path_get_root_type() == ROOT_MESSAGE) {
|
||||||
|
if (ui_ctx->filtering_mode == EIP712_FILTERING_FULL) {
|
||||||
|
if (ui_ctx->filters_to_process > 0) {
|
||||||
|
if (ui_ctx->field_flags & UI_712_FIELD_SHOWN) {
|
||||||
|
ui_ctx->filters_to_process -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ typedef struct {
|
|||||||
bool end_reached;
|
bool end_reached;
|
||||||
e_ui_position pos;
|
e_ui_position pos;
|
||||||
uint8_t filtering_mode;
|
uint8_t filtering_mode;
|
||||||
|
uint8_t filters_to_process;
|
||||||
uint8_t field_flags;
|
uint8_t field_flags;
|
||||||
uint8_t structs_to_review;
|
uint8_t structs_to_review;
|
||||||
} t_ui_context;
|
} t_ui_context;
|
||||||
@@ -39,7 +40,10 @@ void ui_712_field_flags_reset(void);
|
|||||||
void ui_712_finalize_field(void);
|
void ui_712_finalize_field(void);
|
||||||
void ui_712_set_filtering_mode(e_eip712_filtering_mode mode);
|
void ui_712_set_filtering_mode(e_eip712_filtering_mode mode);
|
||||||
e_eip712_filtering_mode ui_712_get_filtering_mode(void);
|
e_eip712_filtering_mode ui_712_get_filtering_mode(void);
|
||||||
|
void ui_712_set_filters_count(uint8_t count);
|
||||||
|
uint8_t ui_712_remaining_filters(void);
|
||||||
void ui_712_queue_struct_to_review(void);
|
void ui_712_queue_struct_to_review(void);
|
||||||
|
void ui_712_notify_filter_change(void);
|
||||||
|
|
||||||
#endif // HAVE_EIP712_FULL_SUPPORT
|
#endif // HAVE_EIP712_FULL_SUPPORT
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ def send_struct_impl_field(value, field):
|
|||||||
if filtering_paths:
|
if filtering_paths:
|
||||||
path = ".".join(current_path)
|
path = ".".join(current_path)
|
||||||
if path in filtering_paths.keys():
|
if path in filtering_paths.keys():
|
||||||
send_filtering_field_name(filtering_paths[path])
|
send_filtering_show_field(filtering_paths[path])
|
||||||
|
|
||||||
app_client.eip712_send_struct_impl_struct_field(data)
|
app_client.eip712_send_struct_impl_struct_field(data)
|
||||||
|
|
||||||
@@ -242,37 +242,38 @@ def send_struct_impl(structs, data, structname):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
# ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures
|
# ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures
|
||||||
def send_filtering_contract_name(display_name: str):
|
def send_filtering_message_info(display_name: str, filters_count: int):
|
||||||
global sig_ctx
|
global sig_ctx
|
||||||
|
|
||||||
msg = bytearray()
|
to_sign = bytearray()
|
||||||
msg.append(183)
|
to_sign.append(183)
|
||||||
msg += sig_ctx["chainid"]
|
to_sign += sig_ctx["chainid"]
|
||||||
msg += sig_ctx["caddr"]
|
to_sign += sig_ctx["caddr"]
|
||||||
msg += sig_ctx["schema_hash"]
|
to_sign += sig_ctx["schema_hash"]
|
||||||
|
to_sign.append(filters_count)
|
||||||
for char in display_name:
|
for char in display_name:
|
||||||
msg.append(ord(char))
|
to_sign.append(ord(char))
|
||||||
|
|
||||||
sig = sig_ctx["key"].sign_deterministic(msg, sigencode=sigencode_der)
|
sig = sig_ctx["key"].sign_deterministic(to_sign, sigencode=sigencode_der)
|
||||||
app_client.eip712_filtering_send_contract_name(display_name, sig)
|
app_client.eip712_filtering_message_info(display_name, filters_count, sig)
|
||||||
|
|
||||||
# ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures
|
# ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures
|
||||||
def send_filtering_field_name(display_name):
|
def send_filtering_show_field(display_name):
|
||||||
global sig_ctx
|
global sig_ctx
|
||||||
|
|
||||||
path_str = ".".join(current_path)
|
path_str = ".".join(current_path)
|
||||||
|
|
||||||
msg = bytearray()
|
to_sign = bytearray()
|
||||||
msg.append(72)
|
to_sign.append(72)
|
||||||
msg += sig_ctx["chainid"]
|
to_sign += sig_ctx["chainid"]
|
||||||
msg += sig_ctx["caddr"]
|
to_sign += sig_ctx["caddr"]
|
||||||
msg += sig_ctx["schema_hash"]
|
to_sign += sig_ctx["schema_hash"]
|
||||||
for char in path_str:
|
for char in path_str:
|
||||||
msg.append(ord(char))
|
to_sign.append(ord(char))
|
||||||
for char in display_name:
|
for char in display_name:
|
||||||
msg.append(ord(char))
|
to_sign.append(ord(char))
|
||||||
sig = sig_ctx["key"].sign_deterministic(msg, sigencode=sigencode_der)
|
sig = sig_ctx["key"].sign_deterministic(to_sign, sigencode=sigencode_der)
|
||||||
app_client.eip712_filtering_send_field_name(display_name, sig)
|
app_client.eip712_filtering_show_field(display_name, sig)
|
||||||
|
|
||||||
def read_filtering_file(domain, message, filtering_file_path):
|
def read_filtering_file(domain, message, filtering_file_path):
|
||||||
data_json = None
|
data_json = None
|
||||||
@@ -349,9 +350,9 @@ def process_file(aclient: EthereumClient, input_file_path: str, filtering_file_p
|
|||||||
|
|
||||||
if filtering_file_path:
|
if filtering_file_path:
|
||||||
if filtr and "name" in filtr:
|
if filtr and "name" in filtr:
|
||||||
send_filtering_contract_name(filtr["name"])
|
send_filtering_message_info(filtr["name"], len(filtering_paths))
|
||||||
else:
|
else:
|
||||||
send_filtering_contract_name(domain["name"])
|
send_filtering_message_info(domain["name"], len(filtering_paths))
|
||||||
|
|
||||||
# send message implementation
|
# send message implementation
|
||||||
app_client.eip712_send_struct_impl_root_struct(message_typename)
|
app_client.eip712_send_struct_impl_root_struct(message_typename)
|
||||||
|
|||||||
@@ -144,13 +144,13 @@ class EthereumClient:
|
|||||||
self._eip712_filtering = True
|
self._eip712_filtering = True
|
||||||
assert self._recv().status == 0x9000
|
assert self._recv().status == 0x9000
|
||||||
|
|
||||||
def eip712_filtering_send_contract_name(self, name: str, sig: bytes):
|
def eip712_filtering_message_info(self, name: str, filters_count: int, sig: bytes):
|
||||||
with self._send(self._cmd_builder.eip712_filtering_send_contract_name(name, sig)):
|
with self._send(self._cmd_builder.eip712_filtering_message_info(name, filters_count, sig)):
|
||||||
self._enable_click_until_response()
|
self._enable_click_until_response()
|
||||||
self._disable_click_until_response()
|
self._disable_click_until_response()
|
||||||
assert self._recv().status == 0x9000
|
assert self._recv().status == 0x9000
|
||||||
|
|
||||||
def eip712_filtering_send_field_name(self, name: str, sig: bytes):
|
def eip712_filtering_show_field(self, name: str, sig: bytes):
|
||||||
with self._send(self._cmd_builder.eip712_filtering_send_field_name(name, sig)):
|
with self._send(self._cmd_builder.eip712_filtering_show_field(name, sig)):
|
||||||
pass
|
pass
|
||||||
assert self._recv().status == 0x9000
|
assert self._recv().status == 0x9000
|
||||||
|
|||||||
@@ -151,13 +151,19 @@ class EthereumCmdBuilder:
|
|||||||
data += sig
|
data += sig
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def eip712_filtering_send_contract_name(self, name: str, sig: bytes) -> bytes:
|
def eip712_filtering_message_info(self, name: str, filters_count: int, sig: bytes) -> bytes:
|
||||||
|
data = bytearray()
|
||||||
|
data.append(len(name))
|
||||||
|
data += self._string_to_bytes(name)
|
||||||
|
data.append(filters_count)
|
||||||
|
data.append(len(sig))
|
||||||
|
data += sig
|
||||||
return self._serialize(InsType.EIP712_SEND_FILTERING,
|
return self._serialize(InsType.EIP712_SEND_FILTERING,
|
||||||
P1Type.COMPLETE_SEND,
|
P1Type.COMPLETE_SEND,
|
||||||
P2Type.FILTERING_CONTRACT_NAME,
|
P2Type.FILTERING_CONTRACT_NAME,
|
||||||
self._eip712_filtering_send_name(name, sig))
|
data)
|
||||||
|
|
||||||
def eip712_filtering_send_field_name(self, name: str, sig: bytes) -> bytes:
|
def eip712_filtering_show_field(self, name: str, sig: bytes) -> bytes:
|
||||||
return self._serialize(InsType.EIP712_SEND_FILTERING,
|
return self._serialize(InsType.EIP712_SEND_FILTERING,
|
||||||
P1Type.COMPLETE_SEND,
|
P1Type.COMPLETE_SEND,
|
||||||
P2Type.FILTERING_FIELD_NAME,
|
P2Type.FILTERING_FIELD_NAME,
|
||||||
|
|||||||
Reference in New Issue
Block a user