Merge pull request #106 from LedgerHQ/swap-rebase-clean

Merge swap capabilities
This commit is contained in:
Jean P
2020-10-07 16:40:48 +02:00
committed by GitHub
31 changed files with 666 additions and 315 deletions

View File

@@ -18,6 +18,7 @@
ifeq ($(BOLOS_SDK),)
$(error Environment variable BOLOS_SDK is not set)
endif
include $(BOLOS_SDK)/Makefile.defines
DEFINES_LIB = USE_LIB_ETHEREUM
@@ -245,7 +246,7 @@ DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=72
endif
# Enabling debug PRINTF
DEBUG:=0
DEBUG :=0
ifneq ($(DEBUG),0)
DEFINES += HAVE_STACK_OVERFLOW_CHECK
ifeq ($(TARGET_NAME),TARGET_NANOX)
@@ -283,7 +284,7 @@ endif
CC := $(CLANGPATH)clang
#CFLAGS += -O0
CFLAGS += -O3 -Os
CFLAGS += -O3 -Os -I/usr/include
AS := $(GCCPATH)arm-none-eabi-gcc

View File

@@ -56,12 +56,12 @@ typedef enum chain_kind_e {
} chain_kind_t;
typedef struct chain_config_s {
const char* coinName; // ticker
char coinName[10]; // ticker
uint32_t chainId;
chain_kind_t kind;
#ifdef TARGET_BLUE
const char* header_text;
unsigned int color_header;
char header_text[13];
unsigned int color_dashboard;
#endif // TARGET_BLUE

View File

@@ -0,0 +1,70 @@
#include "handle_check_address.h"
#include "os.h"
#include "shared_context.h"
#include "ethUtils.h"
#include "string.h"
#define ZERO(x) os_memset(x, 0, sizeof(x))
void handle_check_address(check_address_parameters_t* params, chain_config_t* chain_config) {
PRINTF("Params on the address %d\n",(unsigned int)params);
PRINTF("Address to check %s\n",params->address_to_check);
PRINTF("Inside handle_check_address\n");
params->result = 0;
if (params->address_to_check == 0) {
PRINTF("Address to check == 0\n");
return;
}
uint8_t i;
uint8_t *bip32_path_ptr = params->address_parameters;
uint8_t bip32PathLength = *(bip32_path_ptr++);
cx_sha3_t local_sha3;
// Common memory is used for locals that are not used concurrently
union group1
{
uint32_t bip32Path[MAX_BIP32_PATH];
cx_ecfp_private_key_t privateKey;
char address[51];
} locals_union1;
union group2
{
uint8_t privateKeyData[32];
cx_ecfp_public_key_t publicKey;
} locals_union2;
if ((bip32PathLength < 0x01) ||
(bip32PathLength > MAX_BIP32_PATH) ||
(bip32PathLength*4 != params->address_parameters_length - 1)) {
PRINTF("Invalid path\n");
return;
}
for (i = 0; i < bip32PathLength; i++) {
locals_union1.bip32Path[i] = U4BE(bip32_path_ptr, 0);
bip32_path_ptr += 4;
}
os_perso_derive_node_bip32(CX_CURVE_256K1, locals_union1.bip32Path, bip32PathLength, locals_union2.privateKeyData, NULL);
ZERO(&locals_union1);
cx_ecfp_init_private_key(CX_CURVE_256K1, locals_union2.privateKeyData, 32, &locals_union1.privateKey);
ZERO(&locals_union2);
cx_ecfp_generate_pair(CX_CURVE_256K1, &locals_union2.publicKey, &locals_union1.privateKey, 1);
ZERO(&locals_union1);
getEthAddressStringFromKey(&locals_union2.publicKey, (uint8_t*)locals_union1.address, &local_sha3, chain_config);
ZERO(&locals_union2);
uint8_t offset_0x = 0;
if(memcmp(params->address_to_check, "0x", 2) == 0){
offset_0x = 2;
}
if ((strlen(locals_union1.address) != strlen(params->address_to_check + offset_0x)) ||
os_memcmp(locals_union1.address, params->address_to_check + offset_0x, strlen(locals_union1.address)) != 0) {
os_memcpy(params->address_to_check, locals_union1.address, 45);
PRINTF("Addresses doesn't match\n");
return;
}
PRINTF("Addresses match\n");
params->result = 1;
}

View File

@@ -0,0 +1,9 @@
#ifndef _HANDLE_CHECK_ADDRESS_H_
#define _HANDLE_CHECK_ADDRESS_H_
#include "swap_lib_calls.h"
#include "chainConfig.h"
void handle_check_address(check_address_parameters_t* check_address_params, chain_config_t* chain_config);
#endif // _HANDLE_CHECK_ADDRESS_H_

View File

@@ -0,0 +1,33 @@
#include "handle_get_printable_amount.h"
#include "shared_context.h"
#include "ethUtils.h"
#include "utils.h"
#include "uint256.h"
#include "string.h"
#include <stdint.h>
void handle_get_printable_amount( get_printable_amount_parameters_t* params, chain_config_t *config) {
uint8_t decimals;
char ticker[MAX_TICKER_LEN];
os_memset(params->printable_amount, 0, sizeof(params->printable_amount));
if (params->amount_length > 32) {
PRINTF("Amount is too big, 32 bytes max but buffer has %u bytes", params->amount_length);
os_lib_end();
}
if(!parse_swap_config(params->coin_configuration, params->coin_configuration_length, ticker, &decimals)){
PRINTF("Error while parsing config\n");
os_lib_end();
}
// If the amount is a fee, its value is nominated in ETH even if we're doing an ERC20 swap
if(params->is_fee){
uint8_t ticker_len = strnlen(config->coinName, sizeof(config->coinName));
memcpy(ticker, config->coinName, ticker_len);
ticker[ticker_len] = ' ';
ticker[ticker_len+1] = '\0';
decimals = WEI_TO_ETHER;
}
amountToString(params->amount, params->amount_length, decimals, ticker, params->printable_amount, sizeof(params->printable_amount));
}

View File

@@ -0,0 +1,9 @@
#ifndef _HANDLE_GET_PRINTABLE_AMOUNT_H_
#define _HANDLE_GET_PRINTABLE_AMOUNT_H_
#include "swap_lib_calls.h"
#include "chainConfig.h"
void handle_get_printable_amount(get_printable_amount_parameters_t* get_printable_amount_params, chain_config_t *config);
#endif // _HANDLE_GET_PRINTABLE_AMOUNT_H_

View File

@@ -0,0 +1,67 @@
#include "handle_swap_sign_transaction.h"
#include "usbd_core.h"
#include "ux.h"
#include "shared_context.h"
#include "utils.h"
void copy_transaction_parameters(create_transaction_parameters_t* sign_transaction_params, chain_config_t *config) {
// first copy parameters to stack, and then to global data.
// We need this "trick" as the input data position can overlap with app-ethereum globals
txStringProperties_t stack_data;
memset(&stack_data, 0, sizeof(stack_data));
strncpy(stack_data.fullAddress, sign_transaction_params->destination_address, sizeof(stack_data.fullAddress));
if ((stack_data.fullAddress[sizeof(stack_data.fullAddress) - 1] != '\0') ||
(sign_transaction_params->amount_length > 32) ||
(sign_transaction_params->fee_amount_length > 8)) {
os_lib_end();
}
uint8_t decimals;
char ticker[MAX_TICKER_LEN];
if(!parse_swap_config(sign_transaction_params->coin_configuration, sign_transaction_params->coin_configuration_length, ticker, &decimals)){
PRINTF("Error while parsing config\n");
os_lib_end();
}
amountToString(sign_transaction_params->amount, sign_transaction_params->amount_length, decimals, ticker, stack_data.fullAmount, sizeof(stack_data.fullAmount));
// If the amount is a fee, its value is nominated in ETH even if we're doing an ERC20 swap
strcpy(ticker, config->coinName);
decimals = WEI_TO_ETHER;
amountToString(sign_transaction_params->fee_amount, sign_transaction_params->fee_amount_length, decimals, ticker, stack_data.maxFee, sizeof(stack_data.maxFee));
memcpy(&strings.common, &stack_data, sizeof(stack_data));
}
void handle_swap_sign_transaction(create_transaction_parameters_t* sign_transaction_params, chain_config_t *config) {
copy_transaction_parameters(sign_transaction_params, config);
chainConfig = config;
reset_app_context();
called_from_swap = true;
io_seproxyhal_init();
if (N_storage.initialized != 0x01) {
internalStorage_t storage;
storage.dataAllowed = 0x00;
storage.contractDetails = 0x00;
storage.initialized = 0x01;
nvm_write((void*)&N_storage, (void*)&storage, sizeof(internalStorage_t));
}
dataAllowed = N_storage.dataAllowed;
contractDetails = N_storage.contractDetails;
UX_INIT();
USB_power(0);
USB_power(1);
//ui_idle();
PRINTF("USB power ON/OFF\n");
#ifdef TARGET_NANOX
// grab the current plane mode setting
G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
#endif // TARGET_NANOX
#ifdef HAVE_BLE
BLE_power(0, NULL);
BLE_power(1, "Nano X");
#endif // HAVE_BLE
app_main();
}

View File

@@ -0,0 +1,9 @@
#ifndef _HANDLE_SWAP_SIGN_TRANSACTION_H_
#define _HANDLE_SWAP_SIGN_TRANSACTION_H_
#include "swap_lib_calls.h"
#include "chainConfig.h"
void handle_swap_sign_transaction(create_transaction_parameters_t* get_printable_amount_params, chain_config_t *config);
#endif // _HANDLE_SWAP_SIGN_TRANSACTION_H_

View File

@@ -30,6 +30,11 @@
#include "glyphs.h"
#include "utils.h"
#include "swap_lib_calls.h"
#include "handle_swap_sign_transaction.h"
#include "handle_get_printable_amount.h"
#include "handle_check_address.h"
#ifdef HAVE_STARKWARE
#include "stark_crypto.h"
#endif
@@ -46,8 +51,7 @@ txContext_t txContext;
tmpContent_t tmpContent;
dataContext_t dataContext;
strings_t strings;
cx_sha3_t sha3;
cx_sha3_t global_sha3;
uint8_t dataAllowed;
uint8_t contractDetails;
@@ -57,6 +61,7 @@ char addressSummary[32];
#endif
bool dataPresent;
contract_call_t contractProvisioned;
bool called_from_swap;
#ifdef HAVE_STARKWARE
bool quantumSet;
#endif
@@ -83,13 +88,14 @@ static const char const CONTRACT_ADDRESS[] = "New contract";
chain_config_t *chainConfig;
void reset_app_context() {
PRINTF("!!RESET_APP_CONTEXT\n");
//PRINTF("!!RESET_APP_CONTEXT\n");
appState = APP_STATE_IDLE;
os_memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
contractProvisioned = CONTRACT_NONE;
#ifdef HAVE_STARKWARE
called_from_swap = false;
#ifdef HAVE_STARKWARE
quantumSet = false;
#endif
#endif
os_memset((uint8_t*)&txContext, 0, sizeof(txContext));
os_memset((uint8_t*)&tmpContent, 0, sizeof(tmpContent));
}
@@ -506,10 +512,10 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
break;
}
CLOSE_TRY;
return;
return;
}
#endif
#endif
if (G_io_apdu_buffer[OFFSET_CLA] != CLA) {
THROW(0x6E00);
@@ -579,7 +585,7 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
END_TRY;
}
void sample_main(void) {
void app_main(void) {
unsigned int rx = 0;
unsigned int tx = 0;
unsigned int flags = 0;
@@ -611,7 +617,7 @@ void sample_main(void) {
handleApdu(&flags, &tx);
}
CATCH(EXCEPTION_IO_RESET) {
THROW(EXCEPTION_IO_RESET);
THROW(EXCEPTION_IO_RESET);
}
CATCH_OTHER(e) {
switch (e & 0xF000) {
@@ -686,7 +692,7 @@ unsigned char io_event(unsigned char channel) {
{
});
break;
#endif
#endif
}
// close the event if not done previously (by a display or whatever)
@@ -698,7 +704,7 @@ unsigned char io_event(unsigned char channel) {
return 1;
}
void app_exit(void) {
void app_exit() {
BEGIN_TRY_L(exit) {
TRY_L(exit) {
@@ -711,65 +717,13 @@ void app_exit(void) {
END_TRY_L(exit);
}
chain_config_t const C_chain_config = {
.coinName = CHAINID_COINNAME " ",
.chainId = CHAIN_ID,
.kind = CHAIN_KIND,
#ifdef TARGET_BLUE
.color_header = COLOR_APP,
.color_dashboard = COLOR_APP_LIGHT,
.header_text = CHAINID_UPCASE,
#endif // TARGET_BLUE
};
__attribute__((section(".boot"))) int main(int arg0) {
#ifdef USE_LIB_ETHEREUM
chain_config_t local_chainConfig;
os_memmove(&local_chainConfig, &C_chain_config, sizeof(chain_config_t));
unsigned int libcall_params[3];
unsigned char coinName[sizeof(CHAINID_COINNAME)];
strcpy(coinName, CHAINID_COINNAME);
#ifdef TARGET_BLUE
unsigned char coinNameUP[sizeof(CHAINID_UPCASE)];
strcpy(coinNameUP, CHAINID_UPCASE);
local_chainConfig.header_text = coinNameUP;
#endif // TARGET_BLUE
local_chainConfig.coinName = coinName;
BEGIN_TRY {
TRY {
// ensure syscall will accept us
check_api_level(CX_COMPAT_APILEVEL);
// delegate to Ethereum app/lib
libcall_params[0] = "Ethereum";
libcall_params[1] = 0x100; // use the Init call, as we won't exit
libcall_params[2] = &local_chainConfig;
os_lib_call(&libcall_params);
}
FINALLY {
app_exit();
}
}
END_TRY;
#else
// exit critical section
__asm volatile("cpsie i");
if (arg0) {
if (((unsigned int *)arg0)[0] != 0x100) {
os_lib_throw(INVALID_PARAMETER);
}
chainConfig = (chain_config_t *)((unsigned int *)arg0)[1];
}
else {
chainConfig = (chain_config_t *)PIC(&C_chain_config);
}
void coin_main_with_config(chain_config_t *config) {
chainConfig = config;
reset_app_context();
tmpCtx.transactionContext.currentTokenIndex = 0;
// ensure exception will work as planned
os_boot();
for (;;) {
UX_INIT();
@@ -783,11 +737,11 @@ __attribute__((section(".boot"))) int main(int arg0) {
#endif // TARGET_NANOX
if (N_storage.initialized != 0x01) {
internalStorage_t storage;
storage.dataAllowed = 0x00;
storage.contractDetails = 0x00;
storage.initialized = 0x01;
nvm_write((void*)&N_storage, (void*)&storage, sizeof(internalStorage_t));
internalStorage_t storage;
storage.dataAllowed = 0x00;
storage.contractDetails = 0x00;
storage.initialized = 0x01;
nvm_write((void*)&N_storage, (void*)&storage, sizeof(internalStorage_t));
}
dataAllowed = N_storage.dataAllowed;
contractDetails = N_storage.contractDetails;
@@ -801,28 +755,156 @@ __attribute__((section(".boot"))) int main(int arg0) {
BLE_power(0, NULL);
BLE_power(1, "Nano X");
#endif // HAVE_BLE
#if defined(TARGET_BLUE)
#if defined(TARGET_BLUE)
// setup the status bar colors (remembered after wards, even more if another app does not resetup after app switch)
UX_SET_STATUS_BAR_COLOR(0xFFFFFF, chainConfig->color_header);
#endif // #if defined(TARGET_BLUE)
#endif // #if defined(TARGET_BLUE)
sample_main();
app_main();
}
CATCH(EXCEPTION_IO_RESET) {
// reset IO and UX before continuing
CLOSE_TRY;
continue;
// reset IO and UX before continuing
CLOSE_TRY;
continue;
}
CATCH_ALL {
CLOSE_TRY;
break;
CLOSE_TRY;
break;
}
FINALLY {
}
}
END_TRY;
}
app_exit();
app_exit();
}
void init_coin_config(chain_config_t *coin_config) {
os_memset(coin_config, 0, sizeof(chain_config_t));
strcpy(coin_config->coinName, CHAINID_COINNAME " ");
coin_config->chainId = CHAIN_ID;
coin_config->kind = CHAIN_KIND;
#ifdef TARGET_BLUE
coin_config.color_header = COLOR_APP;
coin_config.color_dashboard = COLOR_APP_LIGHT;
strcpy(coin_config->header_text, CHAINID_UPCASE);
#endif // TARGET_BLUE
}
void coin_main() {
chain_config_t coin_config;
init_coin_config(&coin_config);
coin_main_with_config(&coin_config);
}
void library_main_with_config(chain_config_t *config, unsigned int command, unsigned int* call_parameters) {
BEGIN_TRY {
TRY {
check_api_level(CX_COMPAT_APILEVEL);
PRINTF("Inside a library \n");
switch (command) {
case CHECK_ADDRESS:
handle_check_address((check_address_parameters_t*)call_parameters, config);
break;
case SIGN_TRANSACTION:
handle_swap_sign_transaction((create_transaction_parameters_t*)call_parameters, config);
break;
case GET_PRINTABLE_AMOUNT:
handle_get_printable_amount((get_printable_amount_parameters_t*)call_parameters, config);
break;
}
os_lib_end();
}
FINALLY {}
}
END_TRY;
}
void library_main(unsigned int call_id, unsigned int* call_parameters) {
chain_config_t coin_config;
init_coin_config(&coin_config);
library_main_with_config(&coin_config, call_id, call_parameters);
}
__attribute__((section(".boot"))) int main(int arg0) {
#ifdef USE_LIB_ETHEREUM
BEGIN_TRY {
TRY {
unsigned int libcall_params[5];
chain_config_t local_chainConfig;
init_coin_config(&local_chainConfig);
PRINTF("Hello from Eth-clone\n");
check_api_level(CX_COMPAT_APILEVEL);
// delegate to Ethereum app/lib
libcall_params[0] = "Ethereum";
libcall_params[1] = 0x100;
libcall_params[2] = RUN_APPLICATION;
libcall_params[3] = &local_chainConfig;
libcall_params[4] = 0;
if (arg0) {
// call as a library
libcall_params[2] = ((unsigned int *)arg0)[1];
libcall_params[4] = ((unsigned int *)arg0)[3]; // library arguments
os_lib_call(&libcall_params);
((unsigned int *)arg0)[0] = libcall_params[1];
os_lib_end();
}
else {
// launch coin application
libcall_params[1] = 0x100; // use the Init call, as we won't exit
os_lib_call(&libcall_params);
}
}
FINALLY {}
}
END_TRY;
// no return
#else
// exit critical section
__asm volatile("cpsie i");
// ensure exception will work as planned
os_boot();
if (!arg0) {
// called from dashboard as standalone eth app
coin_main();
return 0;
}
if (((unsigned int *)arg0)[0] != 0x100) {
app_exit();
return 0;
}
unsigned int command = ((unsigned int *)arg0)[1];
chain_config_t * chain_config = ((unsigned int *)arg0)[2];
switch (command) {
case RUN_APPLICATION:
// coin application launched from dashboard
if (chain_config == NULL)
app_exit();
else
coin_main_with_config(chain_config);
break;
default:
if (chain_config == NULL)
// Called as standalone eth library
library_main(command, ((unsigned int *)arg0)[3]);// called as bitcoin library
else
// Called as a library from an altcoin
library_main_with_config(chain_config, command, ((unsigned int *)arg0)[3]);// called as coin library
break;
}
#endif
return 0;
}

View File

@@ -125,11 +125,11 @@ typedef enum {
#endif
} contract_call_t;
typedef struct strData_t {
typedef struct txStringProperties_t {
char fullAddress[43];
char fullAmount[50];
char maxFee[50];
} strData_t;
} txStringProperties_t;
typedef struct strDataTmp_t {
char tmp[100];
@@ -137,7 +137,7 @@ typedef struct strDataTmp_t {
} strDataTmp_t;
typedef union {
strData_t common;
txStringProperties_t common;
strDataTmp_t tmp;
} strings_t;
@@ -148,7 +148,7 @@ extern txContext_t txContext;
extern tmpContent_t tmpContent;
extern dataContext_t dataContext;
extern strings_t strings;
extern cx_sha3_t sha3;
extern cx_sha3_t global_sha3;
extern const internalStorage_t N_storage_real;
#ifdef TARGET_BLUE
@@ -156,6 +156,9 @@ extern bagl_element_t tmp_element;
extern char addressSummary[32];
#endif
extern bool called_from_swap;
extern uint8_t dataAllowed;
extern uint8_t contractDetails;
extern bool dataPresent;
extern uint8_t appState;
extern contract_call_t contractProvisioned;

52
src/swap_lib_calls.h Normal file
View File

@@ -0,0 +1,52 @@
#ifndef SWAP_LIB_CALLS
#define SWAP_LIB_CALLS
#include "stdbool.h"
#define RUN_APPLICATION 1
#define SIGN_TRANSACTION 2
#define CHECK_ADDRESS 3
#define GET_PRINTABLE_AMOUNT 4
// structure that should be send to specific coin application to get address
typedef struct check_address_parameters_s {
// IN
unsigned char* coin_configuration;
unsigned char coin_configuration_length;
// serialized path, segwit, version prefix, hash used, dictionary etc.
// fields and serialization format depends on spesific coin app
unsigned char* address_parameters;
unsigned char address_parameters_length;
char *address_to_check;
char *extra_id_to_check;
// OUT
int result;
} check_address_parameters_t;
// structure that should be send to specific coin application to get printable amount
typedef struct get_printable_amount_parameters_s {
// IN
unsigned char* coin_configuration;
unsigned char coin_configuration_length;
unsigned char* amount;
unsigned char amount_length;
bool is_fee;
// OUT
char printable_amount[30];
} get_printable_amount_parameters_t;
typedef struct create_transaction_parameters_s {
unsigned char* coin_configuration;
unsigned char coin_configuration_length;
unsigned char* amount;
unsigned char amount_length;
unsigned char* fee_amount;
unsigned char fee_amount_length;
char *destination_address;
char *destination_address_extra_id;
} create_transaction_parameters_t;
#endif

View File

@@ -20,12 +20,14 @@
#include <stdint.h>
#define MAX_TICKER_LEN 12 // 10 characters + ' ' + '\0'
typedef struct tokenDefinition_t {
#ifdef HAVE_CONTRACT_NAME_IN_DESCRIPTOR
uint8_t contractName[20];
#endif
uint8_t address[20];
uint8_t ticker[12]; // 10 characters + ' \0'
uint8_t ticker[MAX_TICKER_LEN];
uint8_t decimals;
} tokenDefinition_t;

View File

@@ -39,13 +39,13 @@ UX_FLOW_DEF_VALID(
&C_icon_dashboard_x,
"Quit",
});
const ux_flow_step_t * const ux_idle_flow [] = {
UX_FLOW(ux_idle_flow,
&ux_idle_flow_1_step,
&ux_idle_flow_2_step,
&ux_idle_flow_3_step,
&ux_idle_flow_4_step,
FLOW_END_STEP,
};
FLOW_LOOP
);
#if defined(TARGET_NANOS)

View File

@@ -19,7 +19,9 @@
#include <string.h>
#include "ethUstream.h"
#include "ethUtils.h"
#include "uint256.h"
#include "tokens.h"
static const unsigned char hex_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
@@ -75,4 +77,40 @@ uint32_t getV(txContent_t *txContent) {
THROW(EXCEPTION);
}
return v;
}
void amountToString(uint8_t* amount, uint8_t amount_size, uint8_t decimals, char* ticker, char* out_buffer, uint8_t out_buffer_size){
uint256_t amount_256;
char tmp_buffer[100];
convertUint256BE(amount, amount_size, &amount_256);
tostring256(&amount_256, 10, tmp_buffer, 100);
uint8_t amount_len = strnlen(tmp_buffer, sizeof(tmp_buffer));
uint8_t ticker_len = strnlen(ticker, MAX_TICKER_LEN);
memcpy(out_buffer, ticker, MIN(out_buffer_size, ticker_len));
adjustDecimals(tmp_buffer, amount_len, out_buffer + ticker_len, out_buffer_size - ticker_len -1, decimals);
out_buffer[out_buffer_size-1] = '\0';
}
bool parse_swap_config(uint8_t* config, uint8_t config_len, char* ticker, uint8_t* decimals){
uint8_t ticker_len, offset = 0;
if (config_len == 0){
return false;
}
ticker_len = config[offset++];
if(ticker_len == 0 || ticker_len > MAX_TICKER_LEN - 2 || config_len - offset < ticker_len){
return false;
}
memcpy(ticker, config+offset, ticker_len);
offset += ticker_len;
ticker[ticker_len] = ' ';
ticker[ticker_len+1] = '\0';
if(config_len - offset < 1){
return false;
}
*decimals = config[offset];
return true;
}

View File

@@ -30,4 +30,8 @@ int local_strchr(char *string, char ch);
uint32_t getV(txContent_t *txContent);
void amountToString(uint8_t* amount, uint8_t amount_len, uint8_t decimals, char* ticker, char* out_buffer, uint8_t out_buffer_size);
bool parse_swap_config(uint8_t* config, uint8_t config_len, char* ticker, uint8_t* decimals);
#endif /* _UTILS_H_ */

View File

@@ -32,8 +32,6 @@
#include "ethUtils.h"
#include "chainConfig.h"
extern chain_config_t *chainConfig;
bool rlpCanDecode(uint8_t *buffer, uint32_t bufferLength, bool *valid) {
if (*buffer <= 0x7f) {
} else if (*buffer <= 0xb7) {
@@ -156,15 +154,16 @@ char convertDigit(uint8_t *address, uint8_t index, uint8_t *hash) {
}
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
cx_sha3_t *sha3Context) {
cx_sha3_t *sha3Context, chain_config_t* chain_config) {
uint8_t hashAddress[32];
cx_keccak_init(sha3Context, 256);
cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32);
getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context);
getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context, chain_config);
}
void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
cx_sha3_t *sha3Context) {
cx_sha3_t *sha3Context, chain_config_t* chain_config) {
UNUSED(chain_config);
uint8_t hashChecksum[32];
uint8_t i;
cx_keccak_init(sha3Context, 256);
@@ -180,37 +179,43 @@ void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
static const uint8_t const HEXDIGITS[] = "0123456789abcdef";
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
cx_sha3_t *sha3Context) {
cx_sha3_t *sha3Context, chain_config_t* chain_config) {
uint8_t hashAddress[32];
cx_keccak_init(sha3Context, 256);
cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32);
getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context);
getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context, chain_config);
}
void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
cx_sha3_t *sha3Context) {
uint8_t hashChecksum[32];
uint8_t tmp[100];
cx_sha3_t *sha3Context, chain_config_t* chain_config) {
// save some precious stack space
union locals_union
{
uint8_t hashChecksum[32];
uint8_t tmp[51];
} locals_union;
uint8_t i;
bool eip1191 = false;
uint32_t offset = 0;
switch(chainConfig->chainId) {
switch(chain_config->chainId) {
case 30:
case 31:
eip1191 = true;
break;
}
if (eip1191) {
snprintf((char*)tmp, sizeof(tmp), "%d0x", chainConfig->chainId);
offset = strlen((char*)tmp);
snprintf((char*)locals_union.tmp, sizeof(locals_union.tmp), "%d0x", chain_config->chainId);
offset = strlen((char*)locals_union.tmp);
}
for (i = 0; i < 20; i++) {
uint8_t digit = address[i];
tmp[offset + 2 * i] = HEXDIGITS[(digit >> 4) & 0x0f];
tmp[offset + 2 * i + 1] = HEXDIGITS[digit & 0x0f];
locals_union.tmp[offset + 2 * i] = HEXDIGITS[(digit >> 4) & 0x0f];
locals_union.tmp[offset + 2 * i + 1] = HEXDIGITS[digit & 0x0f];
}
cx_keccak_init(sha3Context, 256);
cx_hash((cx_hash_t*)sha3Context, CX_LAST, tmp, offset + 40, hashChecksum, 32);
cx_hash((cx_hash_t*)sha3Context, CX_LAST, locals_union.tmp, offset + 40, locals_union.hashChecksum, 32);
for (i = 0; i < 40; i++) {
uint8_t digit = address[i / 2];
if ((i % 2) == 0) {
@@ -222,7 +227,7 @@ void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
out[i] = HEXDIGITS[digit];
}
else {
int v = (hashChecksum[i / 2] >> (4 * (1 - i % 2))) & 0x0f;
int v = (locals_union.hashChecksum[i / 2] >> (4 * (1 - i % 2))) & 0x0f;
if (v >= 8) {
out[i] = HEXDIGITS[digit] - 'a' + 'A';
}

View File

@@ -21,7 +21,7 @@
#include <stdint.h>
#include "cx.h"
#include "chainConfig.h"
/**
* @brief Decode an RLP encoded field - see
* https://github.com/ethereum/wiki/wiki/RLP
@@ -43,14 +43,17 @@ void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
cx_sha3_t *sha3Context);
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
cx_sha3_t *sha3Context);
cx_sha3_t *sha3Context,
chain_config_t* chain_config);
void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
cx_sha3_t *sha3Context);
cx_sha3_t *sha3Context,
chain_config_t* chain_config);
bool adjustDecimals(char *src, uint32_t srcLength, char *target,
uint32_t targetLength, uint8_t decimals);
__attribute__((no_instrument_function))
inline int allzeroes(uint8_t *buf, int n) {
for (int i = 0; i < n; ++i) {
if (buf[i]) {
@@ -59,7 +62,7 @@ inline int allzeroes(uint8_t *buf, int n) {
}
return 1;
}
__attribute__((no_instrument_function))
inline int ismaxint(uint8_t *buf, int n) {
for (int i = 0; i < n; ++i) {
if (buf[i] != 0xff) {

View File

@@ -325,98 +325,40 @@ void mul128(uint128_t *number1, uint128_t *number2, uint128_t *target) {
add128(&tmp, &tmp2, target);
}
void write_u64_be(uint8_t *buffer, uint64_t value) {
buffer[0] = ((value >> 56) & 0xff);
buffer[1] = ((value >> 48) & 0xff);
buffer[2] = ((value >> 40) & 0xff);
buffer[3] = ((value >> 32) & 0xff);
buffer[4] = ((value >> 24) & 0xff);
buffer[5] = ((value >> 16) & 0xff);
buffer[6] = ((value >> 8) & 0xff);
buffer[7] = (value & 0xff);
}
void read_u64_be(uint8_t *in, uint64_t *out) {
uint8_t *out_ptr = (uint8_t*)out;
*out_ptr++ = in[7];
*out_ptr++ = in[6];
*out_ptr++ = in[5];
*out_ptr++ = in[4];
*out_ptr++ = in[3];
*out_ptr++ = in[2];
*out_ptr++ = in[1];
*out_ptr = in[0];
}
void mul256(uint256_t *number1, uint256_t *number2, uint256_t *target) {
uint128_t top[4];
uint128_t bottom[4];
uint128_t products[4][4];
uint128_t tmp, tmp2, fourth64, third64, second64, first64;
uint256_t target1, target2;
UPPER(top[0]) = 0;
LOWER(top[0]) = UPPER(UPPER_P(number1));
UPPER(top[1]) = 0;
LOWER(top[1]) = LOWER(UPPER_P(number1));
UPPER(top[2]) = 0;
LOWER(top[2]) = UPPER(LOWER_P(number1));
UPPER(top[3]) = 0;
LOWER(top[3]) = LOWER(LOWER_P(number1));
UPPER(bottom[0]) = 0;
LOWER(bottom[0]) = UPPER(UPPER_P(number2));
UPPER(bottom[1]) = 0;
LOWER(bottom[1]) = LOWER(UPPER_P(number2));
UPPER(bottom[2]) = 0;
LOWER(bottom[2]) = UPPER(LOWER_P(number2));
UPPER(bottom[3]) = 0;
LOWER(bottom[3]) = LOWER(LOWER_P(number2));
for (int y = 3; y > -1; y--) {
for (int x = 3; x > -1; x--) {
mul128(&top[x], &bottom[y], &products[3 - x][y]);
}
uint8_t num1[32], num2[32], result[64];
os_memset(&result, 0, sizeof(result));
for(uint8_t i = 0; i<4; i++){
write_u64_be(num1+i*sizeof(uint64_t), number1->elements[i/2].elements[i%2]);
write_u64_be(num2+i*sizeof(uint64_t), number2->elements[i/2].elements[i%2]);
}
cx_math_mult(result, num1, num2, sizeof(num1));
for(uint8_t i = 0; i<4; i++){
read_u64_be(result+32+i*sizeof(uint64_t), &target->elements[i/2].elements[i%2]);
}
UPPER(fourth64) = 0;
LOWER(fourth64) = LOWER(products[0][3]);
UPPER(tmp) = 0;
LOWER(tmp) = LOWER(products[0][2]);
UPPER(tmp2) = 0;
LOWER(tmp2) = UPPER(products[0][3]);
add128(&tmp, &tmp2, &third64);
UPPER(tmp) = 0;
LOWER(tmp) = LOWER(products[0][1]);
UPPER(tmp2) = 0;
LOWER(tmp2) = UPPER(products[0][2]);
add128(&tmp, &tmp2, &second64);
UPPER(tmp) = 0;
LOWER(tmp) = LOWER(products[0][0]);
UPPER(tmp2) = 0;
LOWER(tmp2) = UPPER(products[0][1]);
add128(&tmp, &tmp2, &first64);
UPPER(tmp) = 0;
LOWER(tmp) = LOWER(products[1][3]);
add128(&tmp, &third64, &tmp2);
copy128(&third64, &tmp2);
UPPER(tmp) = 0;
LOWER(tmp) = LOWER(products[1][2]);
add128(&tmp, &second64, &tmp2);
UPPER(tmp) = 0;
LOWER(tmp) = UPPER(products[1][3]);
add128(&tmp, &tmp2, &second64);
UPPER(tmp) = 0;
LOWER(tmp) = LOWER(products[1][1]);
add128(&tmp, &first64, &tmp2);
UPPER(tmp) = 0;
LOWER(tmp) = UPPER(products[1][2]);
add128(&tmp, &tmp2, &first64);
UPPER(tmp) = 0;
LOWER(tmp) = LOWER(products[2][3]);
add128(&tmp, &second64, &tmp2);
copy128(&second64, &tmp2);
UPPER(tmp) = 0;
LOWER(tmp) = LOWER(products[2][2]);
add128(&tmp, &first64, &tmp2);
UPPER(tmp) = 0;
LOWER(tmp) = UPPER(products[2][3]);
add128(&tmp, &tmp2, &first64);
UPPER(tmp) = 0;
LOWER(tmp) = LOWER(products[3][3]);
add128(&tmp, &first64, &tmp2);
copy128(&first64, &tmp2);
clear256(&target1);
shiftl128(&first64, 64, &UPPER(target1));
clear256(&target2);
UPPER(UPPER(target2)) = UPPER(third64);
shiftl128(&third64, 64, &LOWER(target2));
add256(&target1, &target2, target);
clear256(&target1);
copy128(&UPPER(target1), &second64);
add256(&target1, target, &target2);
clear256(&target1);
copy128(&LOWER(target1), &fourth64);
add256(&target1, &target2, target);
}
void divmod128(uint128_t *l, uint128_t *r, uint128_t *retDiv,

View File

@@ -22,6 +22,8 @@
#include <stdint.h>
#include <stdbool.h>
#include "os.h"
#include "cx.h"
typedef struct uint128_t { uint64_t elements[2]; } uint128_t;

View File

@@ -15,7 +15,9 @@ void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t da
uint32_t i;
uint8_t bip32PathLength = *(dataBuffer++);
cx_ecfp_private_key_t privateKey;
reset_app_context();
if(!called_from_swap){
reset_app_context();
}
if ((bip32PathLength < 0x01) ||
(bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
@@ -40,7 +42,7 @@ void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t da
os_memset(&privateKey, 0, sizeof(privateKey));
os_memset(privateKeyData, 0, sizeof(privateKeyData));
io_seproxyhal_io_heartbeat();
getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey, tmpCtx.publicKeyContext.address, &sha3);
getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey, tmpCtx.publicKeyContext.address, &global_sha3, chainConfig);
#ifndef NO_CONSENT
if (p1 == P1_NON_CONFIRM)
#endif // NO_CONSENT

View File

@@ -53,8 +53,8 @@ void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint
workBuffer += 4;
dataLength -= 4;
// Initialize message header + length
cx_keccak_init(&sha3, 256);
cx_hash((cx_hash_t *)&sha3, 0, (uint8_t*)SIGN_MAGIC, sizeof(SIGN_MAGIC) - 1, NULL, 0);
cx_keccak_init(&global_sha3, 256);
cx_hash((cx_hash_t *)&global_sha3, 0, (uint8_t*)SIGN_MAGIC, sizeof(SIGN_MAGIC) - 1, NULL, 0);
for (index = 1; (((index * base) <= tmpCtx.messageSigningContext.remainingLength) &&
(((index * base) / base) == index));
index *= base);
@@ -62,7 +62,7 @@ void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint
tmp[pos++] = '0' + ((tmpCtx.messageSigningContext.remainingLength / index) % base);
}
tmp[pos] = '\0';
cx_hash((cx_hash_t *)&sha3, 0, (uint8_t*)tmp, pos, NULL, 0);
cx_hash((cx_hash_t *)&global_sha3, 0, (uint8_t*)tmp, pos, NULL, 0);
cx_sha256_init(&tmpContent.sha2);
}
else if (p1 != P1_MORE) {
@@ -78,11 +78,11 @@ void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint
if (dataLength > tmpCtx.messageSigningContext.remainingLength) {
THROW(0x6A80);
}
cx_hash((cx_hash_t *)&sha3, 0, workBuffer, dataLength, NULL, 0);
cx_hash((cx_hash_t *)&global_sha3, 0, workBuffer, dataLength, NULL, 0);
cx_hash((cx_hash_t *)&tmpContent.sha2, 0, workBuffer, dataLength, NULL, 0);
tmpCtx.messageSigningContext.remainingLength -= dataLength;
if (tmpCtx.messageSigningContext.remainingLength == 0) {
cx_hash((cx_hash_t *)&sha3, CX_LAST, workBuffer, 0, tmpCtx.messageSigningContext.hash, 32);
cx_hash((cx_hash_t *)&global_sha3, CX_LAST, workBuffer, 0, tmpCtx.messageSigningContext.hash, 32);
cx_hash((cx_hash_t *)&tmpContent.sha2, CX_LAST, workBuffer, 0, hashMessage, 32);
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "%.*H", sizeof(hashMessage), hashMessage);

View File

@@ -40,7 +40,7 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength
}
dataPresent = false;
contractProvisioned = CONTRACT_NONE;
initTx(&txContext, &sha3, &tmpContent.txContent, customProcessor, NULL);
initTx(&txContext, &global_sha3, &tmpContent.txContent, customProcessor, NULL);
}
else
if (p1 != P1_MORE) {
@@ -72,10 +72,10 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength
THROW(0x6A80);
}
*flags |= IO_ASYNCH_REPLY;
if (txResult == USTREAM_FINISHED) {
finalizeParsing(false);
}
*flags |= IO_ASYNCH_REPLY;
}

View File

@@ -17,6 +17,8 @@ static const uint8_t const TOKEN_TRANSFER_ID[] = { 0xa9, 0x05, 0x9c, 0xbb };
#define ALLOWANCE_DATA_SIZE 4 + 32 + 32
static const uint8_t const ALLOWANCE_ID[] = { 0x09, 0x5e, 0xa7, 0xb3 };
#define ERR_SILENT_MODE_CHECK_FAILED 0x6001
#ifdef HAVE_STARKWARE
#define STARKWARE_REGISTER_DATA_SIZE 4 + 32
@@ -130,7 +132,7 @@ customStatus_e customProcessor(txContext_t *context) {
}
else
if ((context->currentFieldLength == STARKWARE_ESCAPE_DATA_SIZE) &&
(os_memcmp(context->workBuffer, STARKWARE_ESCAPE_ID, 4) == 0) &&
(os_memcmp(context->workBuffer, STARKWARE_ESCAPE_ID, 4) == 0) &&
quantumSet) {
contractProvisioned = CONTRACT_STARKWARE_ESCAPE;
}
@@ -143,11 +145,11 @@ customStatus_e customProcessor(txContext_t *context) {
}
// Sanity check
// Also handle exception that only need to process the beginning of the data
if ((contractProvisioned != CONTRACT_NONE) &&
#ifdef HAVE_STARKWARE
if ((contractProvisioned != CONTRACT_NONE) &&
#ifdef HAVE_STARKWARE
(contractProvisioned != CONTRACT_STARKWARE_VERIFY_ESCAPE) &&
(contractProvisioned != CONTRACT_STARKWARE_REGISTER) &&
#endif
#endif
(context->currentFieldLength > sizeof(dataContext.tokenContext.data))) {
PRINTF("Data field overflow - dropping customization\n");
contractProvisioned = CONTRACT_NONE;
@@ -155,7 +157,7 @@ customStatus_e customProcessor(txContext_t *context) {
PRINTF("contractProvisioned %d\n", contractProvisioned);
if (contractProvisioned != CONTRACT_NONE) {
if (context->currentFieldPos < context->currentFieldLength) {
uint32_t copySize = MIN(context->commandLength,
uint32_t copySize = MIN(context->commandLength,
context->currentFieldLength - context->currentFieldPos);
// Handle the case where we only need to handle the beginning of the data parameter
if ((context->currentFieldPos + copySize) < sizeof(dataContext.tokenContext.data)) {
@@ -262,10 +264,32 @@ customStatus_e customProcessor(txContext_t *context) {
return CUSTOM_NOT_HANDLED;
}
void to_uppercase(char* str, unsigned char size){
for (unsigned char i = 0; i < size && str[i] != 0; i++)
{
str[i] = str[i] >= 'a' ? str[i] - ('a' - 'A') : str[i];
}
}
void compareOrCopy(char* preapproved_string, char* parsed_string, bool silent_mode){
if(silent_mode){
/* ETH address are not fundamentally case sensitive but might
have some for checksum purpose, so let's get rid of these diffs */
to_uppercase(preapproved_string, strlen(preapproved_string));
to_uppercase(parsed_string, strlen(parsed_string));
if(os_memcmp(preapproved_string, parsed_string, strlen(preapproved_string))){
THROW(ERR_SILENT_MODE_CHECK_FAILED);
}
}
else{
strcpy(preapproved_string, parsed_string);
}
}
void finalizeParsing(bool direct) {
uint256_t gasPrice, startGas, uint256;
uint32_t i;
uint8_t address[41];
char displayBuffer[50];
uint8_t decimals = WEI_TO_ETHER;
uint8_t *ticker = (uint8_t *)PIC(chainConfig->coinName);
uint8_t *feeTicker = (uint8_t *)PIC(chainConfig->coinName);
@@ -288,7 +312,7 @@ void finalizeParsing(bool direct) {
}
}
// Store the hash
cx_hash((cx_hash_t *)&sha3, CX_LAST, tmpCtx.transactionContext.hash, 0, tmpCtx.transactionContext.hash, 32);
cx_hash((cx_hash_t *)&global_sha3, CX_LAST, tmpCtx.transactionContext.hash, 0, tmpCtx.transactionContext.hash, 32);
#ifdef HAVE_STARKWARE
if ((contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_ETH) ||
(contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_TOKEN) ||
@@ -301,7 +325,7 @@ void finalizeParsing(bool direct) {
if (dataContext.tokenContext.quantumIndex != MAX_TOKEN) {
currentToken = &tmpCtx.transactionContext.tokens[dataContext.tokenContext.quantumIndex];
}
compute_token_id(&sha3,
compute_token_id(&global_sha3,
(currentToken != NULL ? currentToken->address : NULL),
dataContext.tokenContext.quantum, G_io_apdu_buffer + 100);
if (os_memcmp(dataContext.tokenContext.data + tokenIdOffset, G_io_apdu_buffer + 100, 32) != 0) {
@@ -346,20 +370,10 @@ void finalizeParsing(bool direct) {
}
// Add address
if (tmpContent.txContent.destinationLength != 0) {
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3);
/*
addressSummary[0] = '0';
addressSummary[1] = 'x';
os_memmove((unsigned char *)(addressSummary + 2), address, 4);
os_memmove((unsigned char *)(addressSummary + 6), "...", 3);
os_memmove((unsigned char *)(addressSummary + 9), address + 40 - 4, 4);
addressSummary[13] = '\0';
*/
strings.common.fullAddress[0] = '0';
strings.common.fullAddress[1] = 'x';
os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40);
strings.common.fullAddress[42] = '\0';
displayBuffer[0] = '0';
displayBuffer[1] = 'x';
getEthAddressStringFromBinary(tmpContent.txContent.destination, (uint8_t*)displayBuffer+2, &global_sha3, chainConfig);
compareOrCopy(strings.common.fullAddress, displayBuffer, called_from_swap);
}
else
{
@@ -372,28 +386,18 @@ void finalizeParsing(bool direct) {
(contractProvisioned == CONTRACT_ALLOWANCE)) {
// Add amount in ethers or tokens
if ((contractProvisioned == CONTRACT_ALLOWANCE) && ismaxint(tmpContent.txContent.value.value, 32)) {
strcpy((char*)G_io_apdu_buffer, "Unlimited");
i = 0;
tickerOffset = 0;
while (ticker[tickerOffset]) {
displayBuffer[tickerOffset] = ticker[tickerOffset];
tickerOffset++;
}
strcpy(displayBuffer + tickerOffset, "Unlimited");
}
else {
convertUint256BE(tmpContent.txContent.value.value, tmpContent.txContent.value.length, &uint256);
tostring256(&uint256, 10, (char *)(G_io_apdu_buffer + 100), 100);
i = 0;
while (G_io_apdu_buffer[100 + i]) {
i++;
}
adjustDecimals((char *)(G_io_apdu_buffer + 100), i, (char *)G_io_apdu_buffer, 100, decimals);
amountToString(tmpContent.txContent.value.value, tmpContent.txContent.value.length, decimals, (char*)ticker, displayBuffer, sizeof(displayBuffer));
}
i = 0;
tickerOffset = 0;
while (ticker[tickerOffset]) {
strings.common.fullAmount[tickerOffset] = ticker[tickerOffset];
tickerOffset++;
}
while (G_io_apdu_buffer[i]) {
strings.common.fullAmount[tickerOffset + i] = G_io_apdu_buffer[i];
i++;
}
strings.common.fullAmount[tickerOffset + i] = '\0';
compareOrCopy(strings.common.fullAmount, displayBuffer, called_from_swap);
}
// Compute maximum fee
PRINTF("Max fee\n");
@@ -410,75 +414,86 @@ void finalizeParsing(bool direct) {
adjustDecimals((char *)(G_io_apdu_buffer + 100), i, (char *)G_io_apdu_buffer, 100, WEI_TO_ETHER);
i = 0;
tickerOffset=0;
memset(displayBuffer, 0, sizeof(displayBuffer));
while (feeTicker[tickerOffset]) {
strings.common.maxFee[tickerOffset] = feeTicker[tickerOffset];
displayBuffer[tickerOffset] = feeTicker[tickerOffset];
tickerOffset++;
}
tickerOffset++;
while (G_io_apdu_buffer[i]) {
strings.common.maxFee[tickerOffset + i] = G_io_apdu_buffer[i];
displayBuffer[tickerOffset + i] = G_io_apdu_buffer[i];
i++;
}
strings.common.maxFee[tickerOffset + i] = '\0';
displayBuffer[tickerOffset + i] = '\0';
compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap);
bool no_consent = false;
no_consent = called_from_swap;
#ifdef NO_CONSENT
io_seproxyhal_touch_tx_ok(NULL);
#else // NO_CONSENT
no_consent = true;
#endif // NO_CONSENT
if(no_consent){
io_seproxyhal_touch_tx_ok(NULL);
}
else{
#if defined(TARGET_BLUE)
ui_approval_transaction_blue_init();
ui_approval_transaction_blue_init();
#else
#ifdef HAVE_STARKWARE
if (contractProvisioned == CONTRACT_STARKWARE_REGISTER) {
ux_flow_init(0, ux_approval_starkware_register_flow, NULL);
return;
}
else
if (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_TOKEN) {
ux_flow_init(0, ux_approval_starkware_deposit_flow, NULL);
return;
}
else
if (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_ETH) {
ux_flow_init(0, ux_approval_starkware_deposit_flow, NULL);
return;
}
else
if ((contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_CANCEL) ||
(contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_RECLAIM) ||
(contractProvisioned == CONTRACT_STARKWARE_FULL_WITHDRAWAL) ||
(contractProvisioned == CONTRACT_STARKWARE_FREEZE)) {
ux_flow_init(0, ux_approval_starkware_verify_vault_id_flow, NULL);
return;
}
else
if (contractProvisioned == CONTRACT_STARKWARE_WITHDRAW) {
ux_flow_init(0, ux_approval_starkware_withdraw_flow, NULL);
return;
}
else
if (contractProvisioned == CONTRACT_STARKWARE_ESCAPE) {
ux_flow_init(0, ux_approval_starkware_escape_flow, NULL);
return;
}
else
if (contractProvisioned == CONTRACT_STARKWARE_VERIFY_ESCAPE) {
ux_flow_init(0, ux_approval_starkware_verify_escape_flow, NULL);
return;
}
if (contractProvisioned == CONTRACT_STARKWARE_REGISTER) {
ux_flow_init(0, ux_approval_starkware_register_flow, NULL);
return;
}
else
if (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_TOKEN) {
ux_flow_init(0, ux_approval_starkware_deposit_flow, NULL);
return;
}
else
if (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_ETH) {
ux_flow_init(0, ux_approval_starkware_deposit_flow, NULL);
return;
}
else
if ((contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_CANCEL) ||
(contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_RECLAIM) ||
(contractProvisioned == CONTRACT_STARKWARE_FULL_WITHDRAWAL) ||
(contractProvisioned == CONTRACT_STARKWARE_FREEZE)) {
ux_flow_init(0, ux_approval_starkware_verify_vault_id_flow, NULL);
return;
}
else
if (contractProvisioned == CONTRACT_STARKWARE_WITHDRAW) {
ux_flow_init(0, ux_approval_starkware_withdraw_flow, NULL);
return;
}
else
if (contractProvisioned == CONTRACT_STARKWARE_ESCAPE) {
ux_flow_init(0, ux_approval_starkware_escape_flow, NULL);
return;
}
else
if (contractProvisioned == CONTRACT_STARKWARE_VERIFY_ESCAPE) {
ux_flow_init(0, ux_approval_starkware_verify_escape_flow, NULL);
return;
}
#endif
if (contractProvisioned == CONTRACT_ALLOWANCE) {
ux_flow_init(0, ux_approval_allowance_flow, NULL);
return;
if (contractProvisioned == CONTRACT_ALLOWANCE) {
ux_flow_init(0, ux_approval_allowance_flow, NULL);
return;
}
ux_flow_init(0,
((dataPresent && !N_storage.contractDetails) ? ux_approval_tx_data_warning_flow : ux_approval_tx_flow),
NULL);
#endif // #if TARGET_ID
}
ux_flow_init(0,
((dataPresent && !N_storage.contractDetails) ? ux_approval_tx_data_warning_flow : ux_approval_tx_flow),
NULL);
#endif // #if TARGET_ID
#endif // NO_CONSENT
}

View File

@@ -43,9 +43,12 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) {
tx = 65;
G_io_apdu_buffer[tx++] = 0x90;
G_io_apdu_buffer[tx++] = 0x00;
reset_app_context();
// Send back the response, do not restart the event loop
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
if(called_from_swap){
os_sched_exit(0);
}
reset_app_context();
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget

View File

@@ -6,7 +6,7 @@
void prepare_deposit_3() {
uint8_t address[41];
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3);
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig);
strings.common.fullAddress[0] = '0';
strings.common.fullAddress[1] = 'x';
os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40);

View File

@@ -5,7 +5,7 @@
void prepare_escape_3() {
uint8_t address[41];
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3);
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig);
strings.common.fullAddress[0] = '0';
strings.common.fullAddress[1] = 'x';
os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40);

View File

@@ -5,7 +5,7 @@
void prepare_register_3() {
uint8_t address[41];
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3);
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig);
strings.common.fullAddress[0] = '0';
strings.common.fullAddress[1] = 'x';
os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40);
@@ -26,7 +26,7 @@ void prepare_register_4() {
os_memset(&privateKey, 0, sizeof(privateKey));
os_memset(privateKeyData, 0, sizeof(privateKeyData));
io_seproxyhal_io_heartbeat();
getEthAddressStringFromKey(&publicKey, address, &sha3);
getEthAddressStringFromKey(&publicKey, address, &global_sha3, chainConfig);
strings.common.fullAddress[0] = '0';
strings.common.fullAddress[1] = 'x';
os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40);

View File

@@ -5,7 +5,7 @@
void prepare_verify_escape_3() {
uint8_t address[41];
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3);
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig);
strings.common.fullAddress[0] = '0';
strings.common.fullAddress[1] = 'x';
os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40);

View File

@@ -23,7 +23,7 @@ void prepare_verify_vault_id_2() {
void prepare_verify_vault_id_3() {
uint8_t address[41];
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3);
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig);
strings.common.fullAddress[0] = '0';
strings.common.fullAddress[1] = 'x';
os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40);

View File

@@ -7,7 +7,7 @@ void prepare_register_4();
void prepare_withdraw_3() {
uint8_t address[41];
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3);
getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig);
strings.common.fullAddress[0] = '0';
strings.common.fullAddress[1] = 'x';
os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40);

View File

@@ -68,10 +68,10 @@ void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uin
}
// Prepare the Stark parameters
io_seproxyhal_io_heartbeat();
compute_token_id(&sha3, dataBuffer, dataBuffer + 20, dataContext.starkContext.w1);
compute_token_id(&global_sha3, dataBuffer, dataBuffer + 20, dataContext.starkContext.w1);
if (p1 == P1_STARK_ORDER) {
io_seproxyhal_io_heartbeat();
compute_token_id(&sha3, dataBuffer + 20 + 32, dataBuffer + 20 + 32 + 20, dataContext.starkContext.w2);
compute_token_id(&global_sha3, dataBuffer + 20 + 32, dataBuffer + 20 + 32 + 20, dataContext.starkContext.w2);
offset = 20 + 32 + 20 + 32;
}
else {