Skip to content

Commit

Permalink
refactor eth tx handling
Browse files Browse the repository at this point in the history
  • Loading branch information
bitgamma committed Nov 19, 2024
1 parent be8444f commit 5d2fa88
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 68 deletions.
23 changes: 18 additions & 5 deletions app/ethereum/eip712.c
Original file line number Diff line number Diff line change
Expand Up @@ -678,15 +678,19 @@ size_t eip712_to_string(const eip712_ctx_t* ctx, uint8_t* out) {
return eip712_encode_object(ctx, out, &root, 0);
}

static inline int eip712_find_data_from_str(const eip712_ctx_t* ctx, int parent, const char* key) {
static inline void eip712_wrap_cstr(const char* cstr, struct eip712_string* out) {
out->str = cstr;
out->len = strlen(cstr);
}

static inline int eip712_find_data_cstr(const eip712_ctx_t* ctx, int parent, const char* key) {
struct eip712_string k;
k.str = key;
k.len = strlen(key);
eip712_wrap_cstr(key, &k);
return eip712_find_data(&k, parent, ctx);
}

app_err_t eip712_extract_string(const eip712_ctx_t* ctx, int parent, const char* key, char* out, int out_len) {
int found = eip712_find_data_from_str(ctx, parent, key);
int found = eip712_find_data_cstr(ctx, parent, key);

if (found == -1) {
return ERR_DATA;
Expand All @@ -700,7 +704,7 @@ app_err_t eip712_extract_string(const eip712_ctx_t* ctx, int parent, const char*
}

app_err_t eip712_extract_uint256(const eip712_ctx_t* ctx, int parent, const char* key, uint8_t out[32]) {
int found = eip712_find_data_from_str(ctx, parent, key);
int found = eip712_find_data_cstr(ctx, parent, key);

if (found == -1) {
return ERR_DATA;
Expand All @@ -709,3 +713,12 @@ app_err_t eip712_extract_uint256(const eip712_ctx_t* ctx, int parent, const char
return eip712_copy_uint(found, false, out, ctx);
}

int eip712_field_eq(const eip712_ctx_t* ctx, int field, const char* str) {
struct eip712_string str1;
eip712_string_from_field(&str1, field, ctx);

struct eip712_string str2;
eip712_wrap_cstr(str, &str2);

return eip712_streq(&str1, &str2);
}
1 change: 1 addition & 0 deletions app/ethereum/eip712.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ size_t eip712_to_string(const eip712_ctx_t* ctx, uint8_t* out);

app_err_t eip712_extract_string(const eip712_ctx_t* ctx, int parent, const char* key, char* out, int out_len);
app_err_t eip712_extract_uint256(const eip712_ctx_t* ctx, int parent, const char* key, uint8_t out[32]);
int eip712_field_eq(const eip712_ctx_t* ctx, int field, const char* str);

#endif
66 changes: 65 additions & 1 deletion app/ethereum/eth_data.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#include "eth_data.h"
#include <string.h>

#include "crypto/secp256k1.h"
#include "crypto/util.h"
#include "eth_data.h"

#define ETH_ERC20_TRANSFER_SIGNATURE_LEN 16
#define ETH_ERC20_TRANSFER_LEN 68

#define ETH_ERC20_TRANSFER_ADDR_OFF 16
#define ETH_ERC20_TRANSFER_VALUE_OFF 36

const uint8_t ETH_ERC20_TRANSFER_SIGNATURE[] = {
0xa9, 0x05, 0x9c, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
Expand All @@ -19,6 +25,10 @@ eth_data_type_t eth_data_recognize(const txContent_t* tx) {
}

eip712_data_type_t eip712_recognize(const eip712_ctx_t* msg) {
if (eip712_field_eq(msg, msg->index.primary_type, "Permit")) {
return EIP712_PERMIT;
}

return EIP712_UNKNOWN;
}

Expand All @@ -41,3 +51,57 @@ app_err_t eip712_extract_domain(const eip712_ctx_t* ctx, eip712_domain_t* out) {

return ERR_OK;
}

static void eth_calculate_fees(const txContent_t* tx, bignum256* fees) {
bignum256 gas_amount;
bignum256 prime;
bn_read_be(secp256k1.prime, &prime);
bn_read_compact_be(tx->startgas.value, tx->startgas.length, &gas_amount);
bn_read_compact_be(tx->gasprice.value, tx->gasprice.length, fees);
bn_multiply(&gas_amount, fees, &prime);
}

void eth_extract_transfer_info(const txContent_t* tx, eth_transfer_info* info) {
info->data_str_len = 0;
info->chain.chain_id = tx->chainID;

uint8_t num[11];
if (eth_db_lookup_chain(&info->chain) != ERR_OK) {
info->chain.name = (char*) u32toa(info->chain.chain_id, num, 11);
info->chain.ticker = "???";
}

const uint8_t* value;
uint8_t value_len;

if (info->data_type == ETH_DATA_ERC20_TRANSFER) {
info->token.chain = info->chain.chain_id;
info->token.addr = tx->destination;

value = &tx->data[ETH_ERC20_TRANSFER_VALUE_OFF];
value_len = INT256_LENGTH;

info->to = &tx->data[ETH_ERC20_TRANSFER_ADDR_OFF];

if (eth_db_lookup_erc20(&info->token) != ERR_OK) {
info->token.ticker = "???";
info->token.decimals = 18;
}
} else {
info->token.ticker = info->chain.ticker;
info->token.decimals = 18;

value = tx->value.value;
value_len = tx->value.length;

info->to = tx->destination;

if (info->data_type == ETH_DATA_UNKNOWN) {
base16_encode(tx->data, (char *) info->data_str, tx->dataLength);
info->data_str_len = tx->dataLength * 2;
}
}

bn_read_compact_be(value, value_len, &info->value);
eth_calculate_fees(tx, &info->fees);
}
23 changes: 18 additions & 5 deletions app/ethereum/eth_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@
#define __ETH_DATA__

#include <stddef.h>
#include "ethUstream.h"
#include "eip712.h"

#define ETH_ERC20_ADDR_OFF 16
#define ETH_ERC20_VALUE_OFF 36
#include "crypto/bignum.h"
#include "eip712.h"
#include "eth_db.h"
#include "ethUstream.h"

#define EIP712_MAX_NAME_LEN 40
#define EIP712_ADDR_OFF 12

typedef enum {
ETH_DATA_ABSENT,
ETH_DATA_UNKNOWN,
ETH_DATA_ERC20_TRANSFER
ETH_DATA_ERC20_TRANSFER,
ETH_DATA_ERC20_APPROVE,
} eth_data_type_t;

typedef enum {
Expand All @@ -28,9 +29,21 @@ typedef struct {
uint32_t chainID;
} eip712_domain_t;

typedef struct {
chain_desc_t chain;
erc20_desc_t token;
uint8_t* data_str;
size_t data_str_len;
eth_data_type_t data_type;
const uint8_t* to;
bignum256 value;
bignum256 fees;
} eth_transfer_info;

eth_data_type_t eth_data_recognize(const txContent_t* tx);
eip712_data_type_t eip712_recognize(const eip712_ctx_t* msg);

app_err_t eip712_extract_domain(const eip712_ctx_t* ctx, eip712_domain_t* out);
void eth_extract_transfer_info(const txContent_t* tx, eth_transfer_info* info);

#endif
81 changes: 24 additions & 57 deletions app/ui/dialog.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "dialog.h"
#include "crypto/address.h"
#include "crypto/bignum.h"
#include "crypto/secp256k1.h"
#include "crypto/segwit_addr.h"
#include "crypto/script.h"
#include "crypto/util.h"
Expand Down Expand Up @@ -233,15 +232,6 @@ static void dialog_address(screen_text_ctx_t *ctx, i18n_str_id_t label, addr_typ
dialog_data(ctx, str);
}

static void dialog_calculate_fees(bignum256* fees) {
bignum256 gas_amount;
bignum256 prime;
bn_read_be(secp256k1.prime, &prime);
bn_read_compact_be(g_ui_cmd.params.eth_tx.tx->startgas.value, g_ui_cmd.params.eth_tx.tx->startgas.length, &gas_amount);
bn_read_compact_be(g_ui_cmd.params.eth_tx.tx->gasprice.value, g_ui_cmd.params.eth_tx.tx->gasprice.length, fees);
bn_multiply(&gas_amount, fees, &prime);
}

static void dialog_amount(screen_text_ctx_t* ctx, i18n_str_id_t prompt, const bignum256* amount, int decimals, const char* ticker) {
char tmp[BIGNUM_STRING_LEN+strlen(ticker)+2];
bn_format(amount, NULL, ticker, decimals, 0, 0, ',', tmp, sizeof(tmp));
Expand Down Expand Up @@ -274,23 +264,13 @@ static void dialog_indexed_string(char* dst, const char* label, size_t index) {
*dst = '\0';
}

app_err_t dialog_confirm_eth_tx() {
chain_desc_t chain;
erc20_desc_t token;
chain.chain_id = g_ui_cmd.params.eth_tx.tx->chainID;

uint8_t num[11];
if (eth_db_lookup_chain(&chain) != ERR_OK) {
chain.name = (char*) u32toa(chain.chain_id, num, 11);
chain.ticker = "???";
}
app_err_t dialog_confirm_eth_transfer(eth_data_type_t data_type) {
eth_transfer_info tx_info;
tx_info.data_str = g_camera_fb[0];
tx_info.data_type = data_type;
eth_extract_transfer_info(g_ui_cmd.params.eth_tx.tx, &tx_info);

i18n_str_id_t title;
const uint8_t* to;
eth_data_type_t data_type = eth_data_recognize(g_ui_cmd.params.eth_tx.tx);

uint8_t* data = g_camera_fb[0];
size_t data_len = 0;

screen_text_ctx_t ctx;
size_t pages[MAX_PAGE_COUNT];
Expand All @@ -299,28 +279,10 @@ app_err_t dialog_confirm_eth_tx() {

if (data_type == ETH_DATA_ERC20_TRANSFER) {
title = TX_CONFIRM_ERC20_TITLE;
token.chain = chain.chain_id;
token.addr = g_ui_cmd.params.eth_tx.tx->destination;

memmove((uint8_t*) g_ui_cmd.params.eth_tx.tx->value.value, &g_ui_cmd.params.eth_tx.tx->data[ETH_ERC20_VALUE_OFF], INT256_LENGTH);
((txContent_t*) g_ui_cmd.params.eth_tx.tx)->value.length = INT256_LENGTH;

to = &g_ui_cmd.params.eth_tx.tx->data[ETH_ERC20_ADDR_OFF];

if (eth_db_lookup_erc20(&token) != ERR_OK) {
token.ticker = "???";
token.decimals = 18;
}
} else {
title = TX_CONFIRM_TITLE;
token.ticker = chain.ticker;
token.decimals = 18;
to = g_ui_cmd.params.eth_tx.tx->destination;

if (data_type == ETH_DATA_UNKNOWN) {
base16_encode(g_ui_cmd.params.eth_tx.tx->data, (char *) data, g_ui_cmd.params.eth_tx.tx->dataLength);
data_len = g_ui_cmd.params.eth_tx.tx->dataLength * 2;

if (tx_info.data_str_len) {
last_page = 1;
pages[1] = 0;
ctx.font = TH_FONT_TEXT;
Expand All @@ -335,8 +297,8 @@ app_err_t dialog_confirm_eth_tx() {
}

size_t offset = pages[last_page];
size_t to_display = data_len - offset;
size_t remaining = screen_draw_text(&ctx, MESSAGE_MAX_X, MESSAGE_MAX_Y, &data[offset], to_display, true, false);
size_t to_display = tx_info.data_str_len - offset;
size_t remaining = screen_draw_text(&ctx, MESSAGE_MAX_X, MESSAGE_MAX_Y, &tx_info.data_str[offset], to_display, true, false);

if (!remaining || last_page == (MAX_PAGE_COUNT - 1)) {
break;
Expand All @@ -347,12 +309,6 @@ app_err_t dialog_confirm_eth_tx() {
}
}

bignum256 value;
bn_read_compact_be(g_ui_cmd.params.eth_tx.tx->value.value, g_ui_cmd.params.eth_tx.tx->value.length, &value);

bignum256 fees;
dialog_calculate_fees(&fees);

dialog_title(LSTR(title));

app_err_t ret = ERR_NEED_MORE_DATA;
Expand All @@ -362,11 +318,11 @@ app_err_t dialog_confirm_eth_tx() {

if (page == 0) {
dialog_address(&ctx, TX_SIGNER, ADDR_ETH, g_ui_cmd.params.eth_tx.addr);
dialog_address(&ctx, TX_ADDRESS, ADDR_ETH, to);
dialog_chain(&ctx, chain.name);
dialog_address(&ctx, TX_ADDRESS, ADDR_ETH, tx_info.to);
dialog_chain(&ctx, tx_info.chain.name);

dialog_amount(&ctx, TX_AMOUNT, &value, token.decimals, token.ticker);
dialog_amount(&ctx, TX_FEE, &fees, 18, chain.ticker);
dialog_amount(&ctx, TX_AMOUNT, &tx_info.value, tx_info.token.decimals, tx_info.token.ticker);
dialog_amount(&ctx, TX_FEE, &tx_info.fees, 18, tx_info.chain.ticker);
dialog_footer(ctx.y);
} else {
size_t offset = pages[page];
Expand All @@ -384,7 +340,7 @@ app_err_t dialog_confirm_eth_tx() {
dialog_footer(TH_TITLE_HEIGHT);
}

screen_draw_text(&ctx, MESSAGE_MAX_X, MESSAGE_MAX_Y, &data[offset], (data_len - offset), false, false);
screen_draw_text(&ctx, MESSAGE_MAX_X, MESSAGE_MAX_Y, &tx_info.data_str[offset], (tx_info.data_str_len - offset), false, false);
}

ret = dialog_wait_paged(&page, last_page);
Expand All @@ -393,6 +349,17 @@ app_err_t dialog_confirm_eth_tx() {
return ret;
}

app_err_t dialog_confirm_eth_tx() {
eth_data_type_t data_type = eth_data_recognize(g_ui_cmd.params.eth_tx.tx);

if (data_type == ETH_DATA_ERC20_APPROVE) {
//TODO: implement this
return ERR_DATA;
} else {
return dialog_confirm_eth_transfer(data_type);
}
}

void dialog_confirm_btc_summary(const btc_tx_ctx_t* tx) {
screen_text_ctx_t ctx;
ctx.y = TH_TITLE_HEIGHT;
Expand Down

0 comments on commit 5d2fa88

Please sign in to comment.