From df4fe3c0dd001292a84f1d80708e7a1ba40558ba Mon Sep 17 00:00:00 2001 From: pscott Date: Thu, 10 Jun 2021 17:17:47 +0200 Subject: [PATCH 01/26] Implement support for EIP1559; No settings --- src_common/ethUstream.c | 127 ++++++++++++++++++++++++++- src_common/ethUstream.h | 19 ++++ src_features/signTx/cmd_signTx.c | 3 +- src_features/signTx/logic_signTx.c | 11 ++- src_features/signTx/ui_flow_signTx.c | 2 +- 5 files changed, 155 insertions(+), 7 deletions(-) diff --git a/src_common/ethUstream.c b/src_common/ethUstream.c index dd23d5c..2bba955 100644 --- a/src_common/ethUstream.c +++ b/src_common/ethUstream.c @@ -92,7 +92,7 @@ static void processContent(txContext_t *context) { static void processAccessList(txContext_t *context) { if (!context->currentFieldIsList) { - PRINTF("Invalid type for RLP_DATA\n"); + PRINTF("Invalid type for RLP_ACCESS_LIST\n"); THROW(EXCEPTION); } if (context->currentFieldPos < context->currentFieldLength) { @@ -168,6 +168,30 @@ static void processNonce(txContext_t *context) { } } +static void processMaxPriorityFeePerGas(txContext_t *context) { + PRINTF("PRIORITY\n"); + if (context->currentFieldIsList) { + PRINTF("Invalid type for RLP_MAX_PRIORITY_FEE_PER_GAS\n"); + THROW(EXCEPTION); + } + if (context->currentFieldLength > MAX_INT256) { + PRINTF("Invalid length for RLP_MAX_PRIORITY_FEE_PER_GAS\n"); + THROW(EXCEPTION); + } + if (context->currentFieldPos < context->currentFieldLength) { + uint8_t tmp[100]; + uint32_t copySize = + MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); + // copyTxData(context, NULL, copySize); + copyTxData(context, &tmp, copySize); + } + if (context->currentFieldPos == context->currentFieldLength) { + // context->content->nonce.length = context->currentFieldLength; + context->currentField++; + context->processingField = false; + } +} + static void processStartGas(txContext_t *context) { if (context->currentFieldIsList) { PRINTF("Invalid type for RLP_STARTGAS\n"); @@ -294,6 +318,94 @@ static void processV(txContext_t *context) { } } +static bool processEIP1559Tx(txContext_t *context) { + PRINTF("1559\n"); + switch (context->currentField) { + case EIP1559_RLP_CONTENT: { + uint32_t length = + MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); + PRINTF("content: %.*H\n", length, context->workBuffer); + processContent(context); + PRINTF("flags: %d\n", context->processingFlags); + if ((context->processingFlags & TX_FLAG_TYPE) == 0) { + PRINTF("INCREM\n"); + // context->currentField++; + } + break; + } + case EIP1559_RLP_CHAINID: { + uint32_t length = + MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); + PRINTF("chainid: %.*H\n", length, context->workBuffer); + processChainID(context); + break; + } + case EIP1559_RLP_NONCE: { + uint32_t length = + MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); + PRINTF("nonce: %.*H\n", length, context->workBuffer); + processNonce(context); + break; + } + case EIP1559_RLP_MAX_PRIORITY_FEE_PER_GAS: { + uint32_t length = + MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); + PRINTF("feepergasmax: %.*H\n", length, context->workBuffer); + processMaxPriorityFeePerGas(context); + break; + } + case EIP1559_RLP_MAX_FEE_PER_GAS: { + uint32_t length = + MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); + PRINTF("gasprice: %.*H\n", length, context->workBuffer); + processGasprice(context); + break; + } + case EIP1559_RLP_GASLIMIT: { + uint32_t length = + MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); + PRINTF("gaslimit: %.*H\n", length, context->workBuffer); + processGasLimit(context); + break; + } + case EIP1559_RLP_TO: { + uint32_t length = + MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); + PRINTF("to: %.*H\n", length, context->workBuffer); + processTo(context); + break; + } + case EIP1559_RLP_VALUE: { + uint32_t length = + MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); + PRINTF("value: %.*H\n", length, context->workBuffer); + processValue(context); + break; + } + case EIP1559_RLP_DATA: { + processData(context); + break; + } + case EIP1559_RLP_ACCESS_LIST: { + processAccessList(context); + break; + } + case EIP1559_RLP_YPARITY: { + PRINTF("PARITY\n"); + processV(context); + break; + } + case EIP1559_RLP_SENDER_R: + case EIP1559_RLP_SENDER_S: + processData(context); + break; + default: + PRINTF("Invalid RLP decoder context\n"); + return true; + } + return false; +} + static bool processEIP2930Tx(txContext_t *context) { switch (context->currentField) { case EIP2930_RLP_CONTENT: @@ -333,6 +445,7 @@ static bool processEIP2930Tx(txContext_t *context) { case EIP2930_RLP_SENDER_R: case EIP2930_RLP_SENDER_S: processData(context); + PRINTF("DONE\n"); break; default: PRINTF("Invalid RLP decoder context\n"); @@ -409,6 +522,7 @@ static parserStatus_e parseRLP(txContext_t *context) { PRINTF("Can't decode\n"); return USTREAM_PROCESSING; } + PRINTF("BEFORE: %d\n", context->currentFieldIsList); // Ready to process this field if (!rlpDecodeLength(context->rlpBuffer, context->rlpBufferPos, @@ -418,6 +532,8 @@ static parserStatus_e parseRLP(txContext_t *context) { PRINTF("RLP decode error\n"); return USTREAM_FAULT; } + PRINTF("AFTER: %d\n", context->currentFieldIsList); + // Ready to process this field if (offset == 0) { // Hack for single byte, self encoded context->workBuffer--; @@ -472,7 +588,7 @@ static parserStatus_e processTxInternal(txContext_t *context) { } } if (customStatus == CUSTOM_NOT_HANDLED) { - PRINTF("Current field: %u\n", context->currentField); + PRINTF("Current field: %d\n", context->currentField); switch (context->txType) { bool fault; case LEGACY: @@ -489,6 +605,13 @@ static parserStatus_e processTxInternal(txContext_t *context) { } else { break; } + case EIP1559: + fault = processEIP1559Tx(context); + if (fault) { + return USTREAM_FAULT; + } else { + break; + } default: PRINTF("Transaction type %u is not supported\n", context->txType); return USTREAM_FAULT; diff --git a/src_common/ethUstream.h b/src_common/ethUstream.h index 1a51747..e85c60a 100644 --- a/src_common/ethUstream.h +++ b/src_common/ethUstream.h @@ -80,6 +80,24 @@ typedef enum rlpEIP2930TxField_e { EIP2930_RLP_DONE } rlpEIP2930TxField_e; +typedef enum rlpEIP1559TxField_e { + EIP1559_RLP_NONE = RLP_NONE, + EIP1559_RLP_CONTENT, + EIP1559_RLP_CHAINID, + EIP1559_RLP_NONCE, + EIP1559_RLP_MAX_PRIORITY_FEE_PER_GAS, + EIP1559_RLP_MAX_FEE_PER_GAS, + EIP1559_RLP_GASLIMIT, + EIP1559_RLP_TO, + EIP1559_RLP_VALUE, + EIP1559_RLP_DATA, + EIP1559_RLP_ACCESS_LIST, + EIP1559_RLP_YPARITY, + EIP1559_RLP_SENDER_R, + EIP1559_RLP_SENDER_S, + EIP1559_RLP_DONE +} rlpEIP1559TxField_e; + #define MIN_TX_TYPE 0x00 #define MAX_TX_TYPE 0x7f @@ -87,6 +105,7 @@ typedef enum rlpEIP2930TxField_e { // Valid transaction types should be in [0x00, 0x7f] typedef enum txType_e { EIP2930 = 0x01, + EIP1559 = 0x02, LEGACY = 0xc0 // Legacy tx are greater than or equal to 0xc0. } txType_e; diff --git a/src_features/signTx/cmd_signTx.c b/src_features/signTx/cmd_signTx.c index d4293cc..6db4f4a 100644 --- a/src_features/signTx/cmd_signTx.c +++ b/src_features/signTx/cmd_signTx.c @@ -45,7 +45,7 @@ void handleSign(uint8_t p1, uint8_t txType = *workBuffer; if (txType >= MIN_TX_TYPE && txType <= MAX_TX_TYPE) { // Enumerate through all supported txTypes here... - if (txType == EIP2930) { + if (txType == EIP2930 || txType == EIP1559) { txContext.txType = txType; workBuffer++; dataLength--; @@ -89,6 +89,7 @@ void handleSign(uint8_t p1, THROW(0x6A80); } + PRINTF("FINALIZE\n"); if (txResult == USTREAM_FINISHED) { finalizeParsing(false); } diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 259ee78..0d27cc6 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -29,7 +29,8 @@ uint32_t splitBinaryParameterPart(char *result, uint8_t *parameter) { customStatus_e customProcessor(txContext_t *context) { if (((context->txType == LEGACY && context->currentField == LEGACY_RLP_DATA) || - (context->txType == EIP2930 && context->currentField == EIP2930_RLP_DATA)) && + (context->txType == EIP2930 && context->currentField == EIP2930_RLP_DATA) || + (context->txType == EIP1559 && context->currentField == EIP1559_RLP_DATA)) && (context->currentFieldLength != 0)) { dataPresent = true; // If handling a new contract rather than a function call, abort immediately @@ -245,13 +246,14 @@ void finalizeParsing(bool direct) { tokenDefinition_t *token1 = NULL, *token2 = NULL; bool genericUI = true; + PRINTF("FINALIZING\n"); // Verify the chain if (chainConfig->chainId != 0) { uint32_t id = 0; if (txContext.txType == LEGACY) { id = u32_from_BE(txContext.content->v, txContext.content->vLength, true); - } else if (txContext.txType == EIP2930) { + } else if (txContext.txType == EIP2930 || txContext.txType == EIP1559) { id = u32_from_BE(txContext.content->chainID.value, txContext.content->chainID.length, false); @@ -278,6 +280,7 @@ void finalizeParsing(bool direct) { 32); // Finalize the plugin handling + PRINTF("1\n"); if (dataContext.tokenContext.pluginStatus >= ETH_PLUGIN_RESULT_SUCCESSFUL) { genericUI = false; eth_plugin_prepare_finalize(&pluginFinalize); @@ -357,6 +360,7 @@ void finalizeParsing(bool direct) { } } + PRINTF("2\n"); if (dataPresent && !N_storage.dataAllowed) { reportFinalizeError(direct); if (!direct) { @@ -414,7 +418,7 @@ void finalizeParsing(bool direct) { // the output was truncated. Return the appropriate error code. THROW(0x6502); } - } else if (txContext.txType == EIP2930) { + } else if (txContext.txType == EIP2930 || txContext.txType == EIP1559) { uint256_t chainID; convertUint256BE(tmpContent.txContent.chainID.value, tmpContent.txContent.chainID.length, @@ -426,6 +430,7 @@ void finalizeParsing(bool direct) { return; } } + PRINTF("3\n"); bool no_consent; diff --git a/src_features/signTx/ui_flow_signTx.c b/src_features/signTx/ui_flow_signTx.c index 31de33d..3b7c924 100644 --- a/src_features/signTx/ui_flow_signTx.c +++ b/src_features/signTx/ui_flow_signTx.c @@ -174,7 +174,7 @@ void ux_approve_tx(bool dataPresent) { uint32_t id; if (txContext.txType == LEGACY) { id = u32_from_BE(txContext.content->v, txContext.content->vLength, true); - } else if (txContext.txType == EIP2930) { + } else if (txContext.txType == EIP2930 || txContext.txType == EIP1559) { id = u32_from_BE(txContext.content->chainID.value, txContext.content->chainID.length, false); } else { From bb6f65ad753893734dd6f606f878119d23476d31 Mon Sep 17 00:00:00 2001 From: pscott Date: Thu, 10 Jun 2021 17:36:01 +0200 Subject: [PATCH 02/26] Add comment, remove debug --- src_common/ethUstream.c | 48 ++++++++++-------------------- src_common/ethUstream.h | 8 +++-- src_features/signTx/logic_signTx.c | 1 - 3 files changed, 20 insertions(+), 37 deletions(-) diff --git a/src_common/ethUstream.c b/src_common/ethUstream.c index 2bba955..dc57814 100644 --- a/src_common/ethUstream.c +++ b/src_common/ethUstream.c @@ -322,63 +322,42 @@ static bool processEIP1559Tx(txContext_t *context) { PRINTF("1559\n"); switch (context->currentField) { case EIP1559_RLP_CONTENT: { - uint32_t length = - MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); - PRINTF("content: %.*H\n", length, context->workBuffer); processContent(context); - PRINTF("flags: %d\n", context->processingFlags); if ((context->processingFlags & TX_FLAG_TYPE) == 0) { - PRINTF("INCREM\n"); - // context->currentField++; + context->currentField++; } break; } + // This gets hit only by Wanchain + case EIP1559_RLP_TYPE: { + processType(context); + break; + } case EIP1559_RLP_CHAINID: { - uint32_t length = - MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); - PRINTF("chainid: %.*H\n", length, context->workBuffer); processChainID(context); break; } case EIP1559_RLP_NONCE: { - uint32_t length = - MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); - PRINTF("nonce: %.*H\n", length, context->workBuffer); processNonce(context); break; } case EIP1559_RLP_MAX_PRIORITY_FEE_PER_GAS: { - uint32_t length = - MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); - PRINTF("feepergasmax: %.*H\n", length, context->workBuffer); processMaxPriorityFeePerGas(context); break; } case EIP1559_RLP_MAX_FEE_PER_GAS: { - uint32_t length = - MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); - PRINTF("gasprice: %.*H\n", length, context->workBuffer); processGasprice(context); break; } case EIP1559_RLP_GASLIMIT: { - uint32_t length = - MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); - PRINTF("gaslimit: %.*H\n", length, context->workBuffer); processGasLimit(context); break; } case EIP1559_RLP_TO: { - uint32_t length = - MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); - PRINTF("to: %.*H\n", length, context->workBuffer); processTo(context); break; } case EIP1559_RLP_VALUE: { - uint32_t length = - MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); - PRINTF("value: %.*H\n", length, context->workBuffer); processValue(context); break; } @@ -391,7 +370,6 @@ static bool processEIP1559Tx(txContext_t *context) { break; } case EIP1559_RLP_YPARITY: { - PRINTF("PARITY\n"); processV(context); break; } @@ -414,6 +392,7 @@ static bool processEIP2930Tx(txContext_t *context) { context->currentField++; } break; + // This gets hit only by Wanchain case EIP2930_RLP_TYPE: processType(context); break; @@ -462,6 +441,7 @@ static bool processLegacyTx(txContext_t *context) { context->currentField++; } break; + // This gets hit only by Wanchain case LEGACY_RLP_TYPE: processType(context); break; @@ -522,7 +502,6 @@ static parserStatus_e parseRLP(txContext_t *context) { PRINTF("Can't decode\n"); return USTREAM_PROCESSING; } - PRINTF("BEFORE: %d\n", context->currentFieldIsList); // Ready to process this field if (!rlpDecodeLength(context->rlpBuffer, context->rlpBufferPos, @@ -532,7 +511,6 @@ static parserStatus_e parseRLP(txContext_t *context) { PRINTF("RLP decode error\n"); return USTREAM_FAULT; } - PRINTF("AFTER: %d\n", context->currentFieldIsList); // Ready to process this field if (offset == 0) { // Hack for single byte, self encoded @@ -555,9 +533,13 @@ static parserStatus_e processTxInternal(txContext_t *context) { if (PARSING_IS_DONE(context)) { return USTREAM_FINISHED; } - // Old style transaction - if (((context->txType == LEGACY && context->currentField == LEGACY_RLP_V) || - (context->txType == EIP2930 && context->currentField == EIP2930_RLP_YPARITY)) && + // Old style transaction (pre EIP-155). Transations could just skip `v,r,s` so we needed to cut parsing here. + // commandLength == 0 could happen in two cases : + // 1. We are in an old style transaction : just return `USTREAM_FINISHED`. + // 2. We are at the end of an APDU in a multi-apdu process. This would make us return `USTREAM_FINISHED` preemptively. + // Case number 2 should NOT happen as it is up to `ledgerjs` to correctly decrease the size of the + // APDU (`commandLength`) so that this situation doesn't happen. + if ((context->txType == LEGACY && context->currentField == LEGACY_RLP_V) && (context->commandLength == 0)) { context->content->vLength = 0; return USTREAM_FINISHED; diff --git a/src_common/ethUstream.h b/src_common/ethUstream.h index e85c60a..03f7de2 100644 --- a/src_common/ethUstream.h +++ b/src_common/ethUstream.h @@ -44,12 +44,13 @@ typedef customStatus_e (*ustreamProcess_t)(struct txContext_t *context); #define PARSING_IS_DONE(ctx) \ ((ctx->txType == LEGACY && ctx->currentField == LEGACY_RLP_DONE) || \ - (ctx->txType == EIP2930 && ctx->currentField == EIP2930_RLP_DONE)) + (ctx->txType == EIP2930 && ctx->currentField == EIP2930_RLP_DONE) || \ + (ctx->txType == EIP1559 && ctx->currentField == EIP1559_RLP_DONE)) typedef enum rlpLegacyTxField_e { LEGACY_RLP_NONE = RLP_NONE, LEGACY_RLP_CONTENT, - LEGACY_RLP_TYPE, + LEGACY_RLP_TYPE, // For wanchain LEGACY_RLP_NONCE, LEGACY_RLP_GASPRICE, LEGACY_RLP_STARTGAS, @@ -65,7 +66,7 @@ typedef enum rlpLegacyTxField_e { typedef enum rlpEIP2930TxField_e { EIP2930_RLP_NONE = RLP_NONE, EIP2930_RLP_CONTENT, - EIP2930_RLP_TYPE, + EIP2930_RLP_TYPE, // For wanchain EIP2930_RLP_CHAINID, EIP2930_RLP_NONCE, EIP2930_RLP_GASPRICE, @@ -82,6 +83,7 @@ typedef enum rlpEIP2930TxField_e { typedef enum rlpEIP1559TxField_e { EIP1559_RLP_NONE = RLP_NONE, + EIP1559_RLP_TYPE, // For wanchain EIP1559_RLP_CONTENT, EIP1559_RLP_CHAINID, EIP1559_RLP_NONCE, diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 0d27cc6..344c72c 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -246,7 +246,6 @@ void finalizeParsing(bool direct) { tokenDefinition_t *token1 = NULL, *token2 = NULL; bool genericUI = true; - PRINTF("FINALIZING\n"); // Verify the chain if (chainConfig->chainId != 0) { uint32_t id = 0; From 0bff1de52c58e0bd41350d86202abe49d9be319d Mon Sep 17 00:00:00 2001 From: pscott Date: Fri, 11 Jun 2021 11:37:16 +0200 Subject: [PATCH 03/26] Add setting to display detailed fees --- src/handle_swap_sign_transaction.c | 1 + src/main.c | 2 +- src/shared_context.h | 5 +- src/ui_flow.c | 34 ++++++++++- src_common/ethUstream.c | 40 +++++++++--- src_common/ethUstream.h | 8 ++- src_features/signTx/cmd_signTx.c | 3 +- src_features/signTx/logic_signTx.c | 91 +++++++++++++++++++--------- src_features/signTx/ui_flow_signTx.c | 45 ++++++++++---- 9 files changed, 169 insertions(+), 60 deletions(-) diff --git a/src/handle_swap_sign_transaction.c b/src/handle_swap_sign_transaction.c index 24bb2ed..63a6c36 100644 --- a/src/handle_swap_sign_transaction.c +++ b/src/handle_swap_sign_transaction.c @@ -61,6 +61,7 @@ void handle_swap_sign_transaction(chain_config_t* config) { storage.contractDetails = 0x00; storage.initialized = 0x01; storage.displayNonce = 0x00; + storage.contractDetails = 0x00; nvm_write((void*) &N_storage, (void*) &storage, sizeof(internalStorage_t)); } diff --git a/src/main.c b/src/main.c index e5344eb..d366361 100644 --- a/src/main.c +++ b/src/main.c @@ -49,7 +49,6 @@ strings_t strings; cx_sha3_t global_sha3; uint8_t appState; -bool dataPresent; bool called_from_swap; bool externalPluginIsSet; #ifdef HAVE_STARKWARE @@ -779,6 +778,7 @@ void coin_main(chain_config_t *coin_config) { #endif storage.contractDetails = 0x00; storage.displayNonce = 0x00; + storage.displayFeeDetails = 0x00; storage.initialized = 0x01; nvm_write((void *) &N_storage, (void *) &storage, sizeof(internalStorage_t)); } diff --git a/src/shared_context.h b/src/shared_context.h index f36c131..7b35b21 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -30,6 +30,7 @@ typedef struct internalStorage_t { unsigned char dataAllowed; unsigned char contractDetails; unsigned char displayNonce; + unsigned char displayFeeDetails; uint8_t initialized; } internalStorage_t; @@ -165,7 +166,8 @@ typedef enum { typedef struct txStringProperties_t { char fullAddress[43]; char fullAmount[50]; - char maxFee[50]; + char maxFee[50]; // Used as BaseFee when detailing fees + char priorityFee[50]; char nonce[8]; // 10M tx per account ought to be enough for everybody char chainID[8]; // 10M different chainID ought to be enough for people to find a unique // chainID for their token / chain. @@ -195,7 +197,6 @@ extern cx_sha3_t global_sha3; extern const internalStorage_t N_storage_real; extern bool called_from_swap; -extern bool dataPresent; extern bool externalPluginIsSet; extern uint8_t appState; #ifdef HAVE_STARKWARE diff --git a/src/ui_flow.c b/src/ui_flow.c index 6bac181..67d257b 100644 --- a/src/ui_flow.c +++ b/src/ui_flow.c @@ -5,6 +5,7 @@ void display_settings(const ux_flow_step_t* const start_step); void switch_settings_contract_data(void); void switch_settings_display_data(void); void switch_settings_display_nonce(void); +void switch_settings_display_fee_details(void); ////////////////////////////////////////////////////////////////////// // clang-format off @@ -78,6 +79,15 @@ UX_STEP_CB( .text = strings.common.fullAddress + 26 }); +UX_STEP_CB( + ux_settings_flow_4_step, + bnnn_paging, + switch_settings_display_fee_details(), + { + .title = "Fee Details", + .text = strings.common.fullAddress + 40 + }); + #else UX_STEP_CB( @@ -113,10 +123,21 @@ UX_STEP_CB( strings.common.fullAddress + 26 }); + UX_STEP_CB( + ux_settings_flow_4_step, + bnnn, + switch_settings_display_fee_details(), + { + "Fee Details", + "Display fee details", + "when possible", + strings.common.fullAddress + 40 + }); + #endif UX_STEP_CB( - ux_settings_flow_4_step, + ux_settings_flow_5_step, pb, ui_idle(), { @@ -129,7 +150,8 @@ UX_FLOW(ux_settings_flow, &ux_settings_flow_1_step, &ux_settings_flow_2_step, &ux_settings_flow_3_step, - &ux_settings_flow_4_step); + &ux_settings_flow_4_step, + &ux_settings_flow_5_step); void display_settings(const ux_flow_step_t* const start_step) { strcpy(strings.common.fullAddress, (N_storage.dataAllowed ? "Allowed" : "NOT Allowed")); @@ -137,6 +159,8 @@ void display_settings(const ux_flow_step_t* const start_step) { (N_storage.contractDetails ? "Displayed" : "NOT Displayed")); strcpy(strings.common.fullAddress + 26, (N_storage.displayNonce ? "Displayed" : "NOT Displayed")); + strcpy(strings.common.fullAddress + 40, + (N_storage.displayFeeDetails ? "Displayed" : "NOT Displayed")); ux_flow_init(0, ux_settings_flow, start_step); } @@ -157,3 +181,9 @@ void switch_settings_display_nonce() { nvm_write((void*) &N_storage.displayNonce, (void*) &value, sizeof(uint8_t)); display_settings(&ux_settings_flow_3_step); } + +void switch_settings_display_fee_details() { + uint8_t value = (N_storage.displayFeeDetails ? 0 : 1); + nvm_write((void*) &N_storage.displayFeeDetails, (void*) &value, sizeof(uint8_t)); + display_settings(&ux_settings_flow_4_step); +} \ No newline at end of file diff --git a/src_common/ethUstream.c b/src_common/ethUstream.c index dc57814..7f1643c 100644 --- a/src_common/ethUstream.c +++ b/src_common/ethUstream.c @@ -179,14 +179,12 @@ static void processMaxPriorityFeePerGas(txContext_t *context) { THROW(EXCEPTION); } if (context->currentFieldPos < context->currentFieldLength) { - uint8_t tmp[100]; uint32_t copySize = MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); - // copyTxData(context, NULL, copySize); - copyTxData(context, &tmp, copySize); + copyTxData(context, context->content->maxPriorityFeePerGas.value + context->currentFieldPos, copySize); } if (context->currentFieldPos == context->currentFieldLength) { - // context->content->nonce.length = context->currentFieldLength; + context->content->maxPriorityFeePerGas.length = context->currentFieldLength; context->currentField++; context->processingField = false; } @@ -286,6 +284,26 @@ static void processData(txContext_t *context) { PRINTF("Invalid type for RLP_DATA\n"); THROW(EXCEPTION); } + if (context->currentFieldPos < context->currentFieldLength) { + uint32_t copySize = + MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); + // If there is no data, set dataPresent to false. + if (copySize == 1 && *context->workBuffer == 0x00) { + context->content->dataPresent = false; + } + copyTxData(context, NULL, copySize); + } + if (context->currentFieldPos == context->currentFieldLength) { + context->currentField++; + context->processingField = false; + } +} + +static void processAndDiscard(txContext_t *context) { + if (context->currentFieldIsList) { + PRINTF("Invalid type for Discarded field\n"); + THROW(EXCEPTION); + } if (context->currentFieldPos < context->currentFieldLength) { uint32_t copySize = MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); @@ -319,7 +337,6 @@ static void processV(txContext_t *context) { } static bool processEIP1559Tx(txContext_t *context) { - PRINTF("1559\n"); switch (context->currentField) { case EIP1559_RLP_CONTENT: { processContent(context); @@ -375,7 +392,7 @@ static bool processEIP1559Tx(txContext_t *context) { } case EIP1559_RLP_SENDER_R: case EIP1559_RLP_SENDER_S: - processData(context); + processAndDiscard(context); break; default: PRINTF("Invalid RLP decoder context\n"); @@ -417,14 +434,15 @@ static bool processEIP2930Tx(txContext_t *context) { case EIP2930_RLP_YPARITY: processV(context); break; + case EIP2930_RLP_DATA: + processData(context); + break; case EIP2930_RLP_ACCESS_LIST: processAccessList(context); break; - case EIP2930_RLP_DATA: case EIP2930_RLP_SENDER_R: case EIP2930_RLP_SENDER_S: - processData(context); - PRINTF("DONE\n"); + processAndDiscard(context); break; default: PRINTF("Invalid RLP decoder context\n"); @@ -461,9 +479,11 @@ static bool processLegacyTx(txContext_t *context) { processValue(context); break; case LEGACY_RLP_DATA: + processData(context); + break; case LEGACY_RLP_R: case LEGACY_RLP_S: - processData(context); + processAndDiscard(context); break; case LEGACY_RLP_V: processV(context); diff --git a/src_common/ethUstream.h b/src_common/ethUstream.h index 03f7de2..41fcedf 100644 --- a/src_common/ethUstream.h +++ b/src_common/ethUstream.h @@ -83,8 +83,8 @@ typedef enum rlpEIP2930TxField_e { typedef enum rlpEIP1559TxField_e { EIP1559_RLP_NONE = RLP_NONE, - EIP1559_RLP_TYPE, // For wanchain EIP1559_RLP_CONTENT, + EIP1559_RLP_TYPE, // For wanchain EIP1559_RLP_CHAINID, EIP1559_RLP_NONCE, EIP1559_RLP_MAX_PRIORITY_FEE_PER_GAS, @@ -125,8 +125,9 @@ typedef struct txInt256_t { } txInt256_t; typedef struct txContent_t { - txInt256_t gasprice; - txInt256_t startgas; + txInt256_t gasprice; // Used as MaxFeePerGas when dealing with EIP1559 transactions. + txInt256_t startgas; // Also known as `gasLimit`. + txInt256_t maxPriorityFeePerGas; txInt256_t value; txInt256_t nonce; txInt256_t chainID; @@ -134,6 +135,7 @@ typedef struct txContent_t { uint8_t destinationLength; uint8_t v[4]; uint8_t vLength; + bool dataPresent; } txContent_t; typedef struct txContext_t { diff --git a/src_features/signTx/cmd_signTx.c b/src_features/signTx/cmd_signTx.c index 6db4f4a..c429992 100644 --- a/src_features/signTx/cmd_signTx.c +++ b/src_features/signTx/cmd_signTx.c @@ -38,7 +38,7 @@ void handleSign(uint8_t p1, workBuffer += 4; dataLength -= 4; } - dataPresent = false; + tmpContent.txContent.dataPresent = false; dataContext.tokenContext.pluginStatus = ETH_PLUGIN_RESULT_UNAVAILABLE; // EIP 2718: TransactionType might be present before the TransactionPayload. @@ -89,7 +89,6 @@ void handleSign(uint8_t p1, THROW(0x6A80); } - PRINTF("FINALIZE\n"); if (txResult == USTREAM_FINISHED) { finalizeParsing(false); } diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 344c72c..4c41b1f 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -32,7 +32,7 @@ customStatus_e customProcessor(txContext_t *context) { (context->txType == EIP2930 && context->currentField == EIP2930_RLP_DATA) || (context->txType == EIP1559 && context->currentField == EIP1559_RLP_DATA)) && (context->currentFieldLength != 0)) { - dataPresent = true; + context->content->dataPresent = true; // If handling a new contract rather than a function call, abort immediately if (tmpContent.txContent.destinationLength == 0) { return CUSTOM_NOT_HANDLED; @@ -194,27 +194,31 @@ void reportFinalizeError(bool direct) { } } -void computeFees(char *displayBuffer, uint32_t displayBufferSize) { - uint256_t gasPrice, startGas, uint256; +void computeFees(const txInt256_t *BEgasPrice, const txInt256_t *BEgasLimit, uint256_t *output) { + uint256_t gasPrice = {0}; + uint256_t gasLimit = {0}; + + PRINTF("Gas price %.*H\n", + BEgasPrice->length, + BEgasPrice->value); + PRINTF("Gas limit %.*H\n", + BEgasLimit->length, + BEgasLimit->value); + convertUint256BE(BEgasPrice->value, + BEgasPrice->length, + &gasPrice); + convertUint256BE(BEgasLimit->value, + BEgasLimit->length, + &gasLimit); + mul256(&gasPrice, &gasLimit, output); +} + +void feesToString(const uint256_t *rawFee, char *displayBuffer, uint32_t displayBufferSize) { uint8_t *feeTicker = (uint8_t *) PIC(chainConfig->coinName); uint8_t tickerOffset = 0; uint32_t i; - PRINTF("Max fee\n"); - PRINTF("Gasprice %.*H\n", - tmpContent.txContent.gasprice.length, - tmpContent.txContent.gasprice.value); - PRINTF("Startgas %.*H\n", - tmpContent.txContent.startgas.length, - tmpContent.txContent.startgas.value); - convertUint256BE(tmpContent.txContent.gasprice.value, - tmpContent.txContent.gasprice.length, - &gasPrice); - convertUint256BE(tmpContent.txContent.startgas.value, - tmpContent.txContent.startgas.length, - &startGas); - mul256(&gasPrice, &startGas, &uint256); - tostring256(&uint256, 10, (char *) (G_io_apdu_buffer + 100), 100); + tostring256(rawFee, 10, (char *) (G_io_apdu_buffer + 100), 100); i = 0; while (G_io_apdu_buffer[100 + i]) { i++; @@ -236,6 +240,38 @@ void computeFees(char *displayBuffer, uint32_t displayBufferSize) { i++; } displayBuffer[tickerOffset + i] = '\0'; + PRINTF("Displayed fees: %s\n", displayBuffer); +} + +// Compute the fees, transform it to a string, prepend a ticker to it and copy everything to `displayBuffer`. +void prepareFees(const txInt256_t *BEGasPrice, const txInt256_t *BEGasLimit, char *displayBuffer, uint32_t displayBufferSize) { + uint256_t rawFee = {0}; + computeFees(BEGasPrice, BEGasLimit, &rawFee); + feesToString(&rawFee, displayBuffer, displayBufferSize); +} + +void prepareAndCopyDetailedFees(char *displayBuffer, uint32_t displayBufferSize) { + uint256_t rawPriorityFee = {0}; + uint256_t rawMaxFee = {0}; + uint256_t rawBaseFee = {0}; + + // Compute the priorityFee and the maxFee. + computeFees(&tmpContent.txContent.maxPriorityFeePerGas, &tmpContent.txContent.startgas, &rawPriorityFee); + computeFees(&tmpContent.txContent.gasprice, &tmpContent.txContent.startgas, &rawMaxFee); + // Substract priorityFee from maxFee -> this is the baseFee + minus256(&rawMaxFee, &rawPriorityFee, &rawBaseFee); + + // Transform priorityFee to string (with a ticker). + PRINTF("Computing priority fee\n"); + feesToString(&rawPriorityFee, displayBuffer, displayBufferSize); + // Copy it to destination. + compareOrCopy(strings.common.priorityFee, displayBuffer, called_from_swap); + + PRINTF("Computing base fee\n"); + // Transform priorityFee to string (with a ticker). + feesToString(&rawBaseFee, displayBuffer, displayBufferSize); + // Copy it to destination. + compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap); } void finalizeParsing(bool direct) { @@ -279,7 +315,6 @@ void finalizeParsing(bool direct) { 32); // Finalize the plugin handling - PRINTF("1\n"); if (dataContext.tokenContext.pluginStatus >= ETH_PLUGIN_RESULT_SUCCESSFUL) { genericUI = false; eth_plugin_prepare_finalize(&pluginFinalize); @@ -322,7 +357,7 @@ void finalizeParsing(bool direct) { // Handle the right interface switch (pluginFinalize.uiType) { case ETH_UI_TYPE_GENERIC: - dataPresent = false; + tmpContent.txContent.dataPresent = false; // Add the number of screens + the number of additional screens to get the total // number of screens needed. dataContext.tokenContext.pluginUiMaxItems = @@ -330,7 +365,7 @@ void finalizeParsing(bool direct) { break; case ETH_UI_TYPE_AMOUNT_ADDRESS: genericUI = true; - dataPresent = false; + tmpContent.txContent.dataPresent = false; if ((pluginFinalize.amount == NULL) || (pluginFinalize.address == NULL)) { PRINTF("Incorrect amount/address set by plugin\n"); reportFinalizeError(direct); @@ -359,8 +394,7 @@ void finalizeParsing(bool direct) { } } - PRINTF("2\n"); - if (dataPresent && !N_storage.dataAllowed) { + if (tmpContent.txContent.dataPresent && !N_storage.dataAllowed) { reportFinalizeError(direct); if (!direct) { return; @@ -401,8 +435,12 @@ void finalizeParsing(bool direct) { } // Compute maximum fee if (genericUI) { - computeFees(displayBuffer, sizeof(displayBuffer)); - compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap); + if (N_storage.displayFeeDetails) { + prepareAndCopyDetailedFees(displayBuffer, sizeof(displayBuffer)); + } else { + prepareFees(&tmpContent.txContent.gasprice, &tmpContent.txContent.startgas, displayBuffer, sizeof(displayBuffer)); + compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap); + } } // Prepare chainID field @@ -429,7 +467,6 @@ void finalizeParsing(bool direct) { return; } } - PRINTF("3\n"); bool no_consent; @@ -443,7 +480,7 @@ void finalizeParsing(bool direct) { io_seproxyhal_touch_tx_ok(NULL); } else { if (genericUI) { - ux_approve_tx(dataPresent); + ux_approve_tx(tmpContent.txContent.dataPresent); } else { plugin_ui_start(); } diff --git a/src_features/signTx/ui_flow_signTx.c b/src_features/signTx/ui_flow_signTx.c index 3b7c924..f88e34a 100644 --- a/src_features/signTx/ui_flow_signTx.c +++ b/src_features/signTx/ui_flow_signTx.c @@ -108,6 +108,20 @@ UX_STEP_NOCB( .title = "Address", .text = strings.common.fullAddress, }); +UX_STEP_NOCB( + ux_approval_base_fee_step, + bnnn_paging, + { + .title = "Base Fee", + .text = strings.common.maxFee, + }); +UX_STEP_NOCB( + ux_approval_priority_fee_step, + bnnn_paging, + { + .title = "Priority Fee", + .text = strings.common.priorityFee, + }); UX_STEP_NOCB( ux_approval_fees_step, bnnn_paging, @@ -157,18 +171,18 @@ UX_STEP_NOCB(ux_approval_data_warning_step, }); // clang-format on -const ux_flow_step_t *ux_approval_tx_flow_[10]; +const ux_flow_step_t *ux_approval_tx_flow[12]; void ux_approve_tx(bool dataPresent) { int step = 0; - ux_approval_tx_flow_[step++] = &ux_approval_review_step; - if (dataPresent && !N_storage.contractDetails) { - ux_approval_tx_flow_[step++] = &ux_approval_data_warning_step; + ux_approval_tx_flow[step++] = &ux_approval_review_step; + if (tmpContent.txContent.dataPresent && !N_storage.contractDetails) { + ux_approval_tx_flow[step++] = &ux_approval_data_warning_step; } - ux_approval_tx_flow_[step++] = &ux_approval_amount_step; - ux_approval_tx_flow_[step++] = &ux_approval_address_step; + ux_approval_tx_flow[step++] = &ux_approval_amount_step; + ux_approval_tx_flow[step++] = &ux_approval_address_step; if (N_storage.displayNonce) { - ux_approval_tx_flow_[step++] = &ux_approval_nonce_step; + ux_approval_tx_flow[step++] = &ux_approval_nonce_step; } uint32_t id; @@ -182,12 +196,17 @@ void ux_approve_tx(bool dataPresent) { THROW(0x6501); } if (id != ETHEREUM_MAINNET_CHAINID) { - ux_approval_tx_flow_[step++] = &ux_approval_chainid_step; + ux_approval_tx_flow[step++] = &ux_approval_chainid_step; } - ux_approval_tx_flow_[step++] = &ux_approval_fees_step; - ux_approval_tx_flow_[step++] = &ux_approval_accept_step; - ux_approval_tx_flow_[step++] = &ux_approval_reject_step; - ux_approval_tx_flow_[step++] = FLOW_END_STEP; + if (txContext.txType == EIP1559 && N_storage.displayFeeDetails) { + ux_approval_tx_flow[step++] = &ux_approval_base_fee_step; + ux_approval_tx_flow[step++] = &ux_approval_priority_fee_step; + } else { + ux_approval_tx_flow[step++] = &ux_approval_fees_step; + } + ux_approval_tx_flow[step++] = &ux_approval_accept_step; + ux_approval_tx_flow[step++] = &ux_approval_reject_step; + ux_approval_tx_flow[step++] = FLOW_END_STEP; - ux_flow_init(0, ux_approval_tx_flow_, NULL); + ux_flow_init(0, ux_approval_tx_flow, NULL); } \ No newline at end of file From 27b91e4deaadc2cd1285fedb5da2347cd20dc709 Mon Sep 17 00:00:00 2001 From: pscott Date: Fri, 11 Jun 2021 14:45:45 +0200 Subject: [PATCH 04/26] Bump Plugin interface version to v2 --- src/eth_plugin_handler.c | 2 +- src/eth_plugin_interface.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/eth_plugin_handler.c b/src/eth_plugin_handler.c index da1cac9..13e1e7a 100644 --- a/src/eth_plugin_handler.c +++ b/src/eth_plugin_handler.c @@ -147,7 +147,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { switch (method) { case ETH_PLUGIN_INIT_CONTRACT: ((ethPluginInitContract_t *) parameter)->interfaceVersion = - ETH_PLUGIN_INTERFACE_VERSION_1; + ETH_PLUGIN_INTERFACE_VERSION_2; ((ethPluginInitContract_t *) parameter)->result = ETH_PLUGIN_RESULT_UNAVAILABLE; ((ethPluginInitContract_t *) parameter)->pluginSharedRW = &pluginRW; ((ethPluginInitContract_t *) parameter)->pluginSharedRO = &pluginRO; diff --git a/src/eth_plugin_interface.h b/src/eth_plugin_interface.h index 918645a..dc0e754 100644 --- a/src/eth_plugin_interface.h +++ b/src/eth_plugin_interface.h @@ -9,8 +9,10 @@ #define PLUGIN_ID_LENGTH 30 +// Interface version. To be updated everytime we introduce breaking changes to the plugin interface. typedef enum { - ETH_PLUGIN_INTERFACE_VERSION_1 = 1 // Version 1 + ETH_PLUGIN_INTERFACE_VERSION_1 = 1, // Version 1 + ETH_PLUGIN_INTERFACE_VERSION_2 = 2 // Add dataPresent to txContent } eth_plugin_interface_version_t; typedef enum { From 3fe18f0e188ca2e9599d8ac24cb9619f0fdd0fc4 Mon Sep 17 00:00:00 2001 From: pscott Date: Fri, 11 Jun 2021 14:52:43 +0200 Subject: [PATCH 05/26] Update plugin sdk --- ethereum-plugin-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum-plugin-sdk b/ethereum-plugin-sdk index 75bf9f4..a232fcd 160000 --- a/ethereum-plugin-sdk +++ b/ethereum-plugin-sdk @@ -1 +1 @@ -Subproject commit 75bf9f421ff7c15cfd92c75f2131ffcc622c44b3 +Subproject commit a232fcd3ca8f3f5ee3c23af16b7621c7604c65a7 From 036091bb639d0864ad60f5c919bbd18891f28f9d Mon Sep 17 00:00:00 2001 From: pscott Date: Fri, 11 Jun 2021 20:41:08 +0200 Subject: [PATCH 06/26] Unify plugin ui with standard UI; add prepareFeeDisplay and prepareChainIdDisplay --- doc/ethapp_plugins.asc | 3 + src/eth_plugin_ui.c | 170 +-------------------------- src_features/signTx/feature_signTx.h | 10 ++ src_features/signTx/logic_signTx.c | 81 +++++++------ src_features/signTx/ui_flow_signTx.c | 129 +++++++++++++++++++- 5 files changed, 184 insertions(+), 209 deletions(-) diff --git a/doc/ethapp_plugins.asc b/doc/ethapp_plugins.asc index 0c320d6..5b67b68 100644 --- a/doc/ethapp_plugins.asc +++ b/doc/ethapp_plugins.asc @@ -3,6 +3,9 @@ Ethereum application Plugins : Technical Specifications Ledger Firmware Team Specification version 1.0 - 24th of September 2020 +## 2.0 + - Add field in pluginSharedRO, breaking change. + ## 1.0 - Initial release diff --git a/src/eth_plugin_ui.c b/src/eth_plugin_ui.c index 0f23262..681ef66 100644 --- a/src/eth_plugin_ui.c +++ b/src/eth_plugin_ui.c @@ -5,175 +5,11 @@ #include "ui_callbacks.h" #include "eth_plugin_handler.h" #include "ux.h" - -typedef enum { - - PLUGIN_UI_INSIDE = 0, - PLUGIN_UI_OUTSIDE - -} plugin_ui_state_t; - -void computeFees(char *displayBuffer, uint32_t displayBufferSize); - -void plugin_ui_get_id() { - ethQueryContractID_t pluginQueryContractID; - eth_plugin_prepare_query_contract_ID(&pluginQueryContractID, - strings.tmp.tmp, - sizeof(strings.tmp.tmp), - strings.tmp.tmp2, - sizeof(strings.tmp.tmp2)); - // Query the original contract for ID if it's not an internal alias - if (!eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_ID, (void *) &pluginQueryContractID)) { - PRINTF("Plugin query contract ID call failed\n"); - io_seproxyhal_touch_tx_cancel(NULL); - } -} - -void plugin_ui_get_item() { - ethQueryContractUI_t pluginQueryContractUI; - eth_plugin_prepare_query_contract_UI(&pluginQueryContractUI, - dataContext.tokenContext.pluginUiCurrentItem, - strings.tmp.tmp, - sizeof(strings.tmp.tmp), - strings.tmp.tmp2, - sizeof(strings.tmp.tmp2)); - if (!eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_UI, (void *) &pluginQueryContractUI)) { - PRINTF("Plugin query contract UI call failed\n"); - io_seproxyhal_touch_tx_cancel(NULL); - } -} - -void display_next_plugin_item(bool entering) { - if (entering) { - if (dataContext.tokenContext.pluginUiState == PLUGIN_UI_OUTSIDE) { - dataContext.tokenContext.pluginUiState = PLUGIN_UI_INSIDE; - dataContext.tokenContext.pluginUiCurrentItem = 0; - plugin_ui_get_item(); - ux_flow_next(); - } else { - if (dataContext.tokenContext.pluginUiCurrentItem > 0) { - dataContext.tokenContext.pluginUiCurrentItem--; - plugin_ui_get_item(); - ux_flow_next(); - } else { - dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE; - dataContext.tokenContext.pluginUiCurrentItem = 0; - ux_flow_prev(); - } - } - } else { - if (dataContext.tokenContext.pluginUiState == PLUGIN_UI_OUTSIDE) { - dataContext.tokenContext.pluginUiState = PLUGIN_UI_INSIDE; - plugin_ui_get_item(); - ux_flow_prev(); - } else { - if (dataContext.tokenContext.pluginUiCurrentItem < - dataContext.tokenContext.pluginUiMaxItems - 1) { - dataContext.tokenContext.pluginUiCurrentItem++; - plugin_ui_get_item(); - ux_flow_prev(); - // Reset multi page layout to the first page - G_ux.layout_paging.current = 0; -#ifdef TARGET_NANOS - ux_layout_paging_redisplay_by_addr(G_ux.stack_count - 1); -#else - ux_layout_bnnn_paging_redisplay(0); -#endif - } else { - dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE; - ux_flow_next(); - } - } - } -} - -void plugin_ui_compute_fees() { - computeFees(strings.common.maxFee, sizeof(strings.common.maxFee)); -} - -// clang-format off -UX_FLOW_DEF_NOCB( - ux_plugin_approval_intro_step, - pnn, - { - &C_icon_eye, - "Review", - "contract call", - }); - -UX_STEP_NOCB_INIT( - ux_plugin_approval_id_step, - bnnn_paging, - plugin_ui_get_id(), - { - .title = strings.tmp.tmp, - .text = strings.tmp.tmp2 - }); - -UX_STEP_INIT( - ux_plugin_approval_before_step, - NULL, - NULL, - { - display_next_plugin_item(true); - }); - -UX_FLOW_DEF_NOCB( - ux_plugin_approval_display_step, - bnnn_paging, - { - .title = strings.tmp.tmp, - .text = strings.tmp.tmp2 - }); - -UX_STEP_INIT( - ux_plugin_approval_after_step, - NULL, - NULL, - { - display_next_plugin_item(false); - }); - -UX_STEP_NOCB_INIT( - ux_plugin_approval_fees_step, - bnnn_paging, - plugin_ui_compute_fees(), - { - .title = "Max Fees", - .text = strings.common.maxFee - }); - -UX_FLOW_DEF_VALID( - ux_plugin_approval_ok_step, - pbb, - io_seproxyhal_touch_tx_ok(NULL), - { - &C_icon_validate_14, - "Accept", - "and send", - }); -UX_FLOW_DEF_VALID( - ux_plugin_approval_cancel_step, - pb, - io_seproxyhal_touch_tx_cancel(NULL), - { - &C_icon_crossmark, - "Reject", - }); -// clang-format on - -UX_FLOW(ux_plugin_approval_flow, - &ux_plugin_approval_intro_step, - &ux_plugin_approval_id_step, - &ux_plugin_approval_before_step, - &ux_plugin_approval_display_step, - &ux_plugin_approval_after_step, - &ux_plugin_approval_fees_step, - &ux_plugin_approval_ok_step, - &ux_plugin_approval_cancel_step); +#include "feature_signTx.h" void plugin_ui_start() { dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE; dataContext.tokenContext.pluginUiCurrentItem = 0; - ux_flow_init(0, ux_plugin_approval_flow, NULL); + + ux_approve_tx(true); } diff --git a/src_features/signTx/feature_signTx.h b/src_features/signTx/feature_signTx.h index a25a650..ff9be11 100644 --- a/src_features/signTx/feature_signTx.h +++ b/src_features/signTx/feature_signTx.h @@ -1,4 +1,14 @@ #include "shared_context.h" +typedef enum { + + PLUGIN_UI_INSIDE = 0, + PLUGIN_UI_OUTSIDE + +} plugin_ui_state_t; + customStatus_e customProcessor(txContext_t *context); void finalizeParsing(bool direct); +void prepareFeeDisplay(); +void prepareChainIdDisplay(); +void ux_approve_tx(bool fromPlugin); diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 4c41b1f..dd6f6f8 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -194,7 +194,8 @@ void reportFinalizeError(bool direct) { } } -void computeFees(const txInt256_t *BEgasPrice, const txInt256_t *BEgasLimit, uint256_t *output) { +// Convert `BEgasPrice` and `BEgasLimit` to Uint256 and then stores the multiplication of both in `output`. +static void computeFees(txInt256_t *BEgasPrice, txInt256_t *BEgasLimit, uint256_t *output) { uint256_t gasPrice = {0}; uint256_t gasLimit = {0}; @@ -213,7 +214,7 @@ void computeFees(const txInt256_t *BEgasPrice, const txInt256_t *BEgasLimit, uin mul256(&gasPrice, &gasLimit, output); } -void feesToString(const uint256_t *rawFee, char *displayBuffer, uint32_t displayBufferSize) { +static void feesToString(uint256_t *rawFee, char *displayBuffer, uint32_t displayBufferSize) { uint8_t *feeTicker = (uint8_t *) PIC(chainConfig->coinName); uint8_t tickerOffset = 0; uint32_t i; @@ -244,13 +245,13 @@ void feesToString(const uint256_t *rawFee, char *displayBuffer, uint32_t display } // Compute the fees, transform it to a string, prepend a ticker to it and copy everything to `displayBuffer`. -void prepareFees(const txInt256_t *BEGasPrice, const txInt256_t *BEGasLimit, char *displayBuffer, uint32_t displayBufferSize) { +void prepareAndCopyFees(txInt256_t *BEGasPrice, txInt256_t *BEGasLimit, char *displayBuffer, uint32_t displayBufferSize) { uint256_t rawFee = {0}; computeFees(BEGasPrice, BEGasLimit, &rawFee); feesToString(&rawFee, displayBuffer, displayBufferSize); } -void prepareAndCopyDetailedFees(char *displayBuffer, uint32_t displayBufferSize) { +static void prepareAndCopyDetailedFees() { uint256_t rawPriorityFee = {0}; uint256_t rawMaxFee = {0}; uint256_t rawBaseFee = {0}; @@ -263,15 +264,44 @@ void prepareAndCopyDetailedFees(char *displayBuffer, uint32_t displayBufferSize) // Transform priorityFee to string (with a ticker). PRINTF("Computing priority fee\n"); - feesToString(&rawPriorityFee, displayBuffer, displayBufferSize); - // Copy it to destination. - compareOrCopy(strings.common.priorityFee, displayBuffer, called_from_swap); + feesToString(&rawPriorityFee, strings.common.priorityFee, sizeof(strings.common.priorityFee)); PRINTF("Computing base fee\n"); // Transform priorityFee to string (with a ticker). - feesToString(&rawBaseFee, displayBuffer, displayBufferSize); - // Copy it to destination. - compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap); + feesToString(&rawBaseFee, strings.common.maxFee, sizeof(strings.common.maxFee)); +} + +void prepareFeeDisplay() { + if (N_storage.displayFeeDetails) { + prepareAndCopyDetailedFees(); + } else { + prepareAndCopyFees(&tmpContent.txContent.gasprice, &tmpContent.txContent.startgas, strings.common.maxFee, sizeof(strings.common.maxFee)); + } +} + +uint32_t get_chainID() { + uint32_t chain_id = 0; + + if (txContext.txType == LEGACY) { + chain_id = u32_from_BE(txContext.content->v, txContext.content->vLength, true); + } else if (txContext.txType == EIP2930 || txContext.txType == EIP1559) { + chain_id = u32_from_BE(tmpContent.txContent.chainID.value, tmpContent.txContent.chainID.length, true); + } + else { + PRINTF("Txtype `%u` not supported while generating chainID\n", txContext.txType); + } + PRINTF("ChainID: %d\n", chain_id); + return chain_id; +} + +void prepareChainIdDisplay() { + uint32_t chainID = get_chainID(); + uint8_t res = snprintf(strings.common.chainID, sizeof(strings.common.chainID), "%d", chainID); + if (res >= sizeof(strings.common.chainID)) { + // If the return value is higher or equal to the size passed in as parameter, then + // the output was truncated. Return the appropriate error code. + THROW(0x6502); + } } void finalizeParsing(bool direct) { @@ -435,37 +465,12 @@ void finalizeParsing(bool direct) { } // Compute maximum fee if (genericUI) { - if (N_storage.displayFeeDetails) { - prepareAndCopyDetailedFees(displayBuffer, sizeof(displayBuffer)); - } else { - prepareFees(&tmpContent.txContent.gasprice, &tmpContent.txContent.startgas, displayBuffer, sizeof(displayBuffer)); - compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap); - } + prepareFeeDisplay(); } // Prepare chainID field if (genericUI) { - if (txContext.txType == LEGACY) { - uint32_t id = u32_from_BE(txContext.content->v, txContext.content->vLength, true); - PRINTF("Chain ID: %u\n", id); - uint8_t res = - snprintf(strings.common.chainID, sizeof(strings.common.chainID), "%d", id); - if (res >= sizeof(strings.common.chainID)) { - // If the return value is higher or equal to the size passed in as parameter, then - // the output was truncated. Return the appropriate error code. - THROW(0x6502); - } - } else if (txContext.txType == EIP2930 || txContext.txType == EIP1559) { - uint256_t chainID; - convertUint256BE(tmpContent.txContent.chainID.value, - tmpContent.txContent.chainID.length, - &chainID); - tostring256(&chainID, 10, displayBuffer, sizeof(displayBuffer)); - strncpy(strings.common.chainID, displayBuffer, sizeof(strings.common.chainID)); - } else { - PRINTF("Txtype `%u` not supported while generating chainID\n", txContext.txType); - return; - } + prepareChainIdDisplay(); } bool no_consent; @@ -480,7 +485,7 @@ void finalizeParsing(bool direct) { io_seproxyhal_touch_tx_ok(NULL); } else { if (genericUI) { - ux_approve_tx(tmpContent.txContent.dataPresent); + ux_approve_tx(false); } else { plugin_ui_start(); } diff --git a/src_features/signTx/ui_flow_signTx.c b/src_features/signTx/ui_flow_signTx.c index f88e34a..c1a4fa4 100644 --- a/src_features/signTx/ui_flow_signTx.c +++ b/src_features/signTx/ui_flow_signTx.c @@ -2,6 +2,80 @@ #include "ui_callbacks.h" #include "chainConfig.h" #include "utils.h" +#include "feature_signTx.h" +#include "eth_plugin_handler.h" + +void plugin_ui_get_id() { + ethQueryContractID_t pluginQueryContractID; + eth_plugin_prepare_query_contract_ID(&pluginQueryContractID, + strings.common.fullAddress, + sizeof(strings.common.fullAddress), + strings.common.fullAmount, + sizeof(strings.common.fullAmount)); + // Query the original contract for ID if it's not an internal alias + if (!eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_ID, (void *) &pluginQueryContractID)) { + PRINTF("Plugin query contract ID call failed\n"); + io_seproxyhal_touch_tx_cancel(NULL); + } +} + +void plugin_ui_get_item() { + ethQueryContractUI_t pluginQueryContractUI; + eth_plugin_prepare_query_contract_UI(&pluginQueryContractUI, + dataContext.tokenContext.pluginUiCurrentItem, + strings.common.fullAddress, + sizeof(strings.common.fullAddress), + strings.common.fullAmount, + sizeof(strings.common.fullAmount)); + if (!eth_plugin_call(ETH_PLUGIN_QUERY_CONTRACT_UI, (void *) &pluginQueryContractUI)) { + PRINTF("Plugin query contract UI call failed\n"); + io_seproxyhal_touch_tx_cancel(NULL); + } +} + +void display_next_plugin_item(bool entering) { + if (entering) { + if (dataContext.tokenContext.pluginUiState == PLUGIN_UI_OUTSIDE) { + dataContext.tokenContext.pluginUiState = PLUGIN_UI_INSIDE; + dataContext.tokenContext.pluginUiCurrentItem = 0; + plugin_ui_get_item(); + ux_flow_next(); + } else { + if (dataContext.tokenContext.pluginUiCurrentItem > 0) { + dataContext.tokenContext.pluginUiCurrentItem--; + plugin_ui_get_item(); + ux_flow_next(); + } else { + dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE; + dataContext.tokenContext.pluginUiCurrentItem = 0; + ux_flow_prev(); + } + } + } else { + if (dataContext.tokenContext.pluginUiState == PLUGIN_UI_OUTSIDE) { + dataContext.tokenContext.pluginUiState = PLUGIN_UI_INSIDE; + plugin_ui_get_item(); + ux_flow_prev(); + } else { + if (dataContext.tokenContext.pluginUiCurrentItem < + dataContext.tokenContext.pluginUiMaxItems - 1) { + dataContext.tokenContext.pluginUiCurrentItem++; + plugin_ui_get_item(); + ux_flow_prev(); + // Reset multi page layout to the first page + G_ux.layout_paging.current = 0; +#ifdef TARGET_NANOS + ux_layout_paging_redisplay_by_addr(G_ux.stack_count - 1); +#else + ux_layout_bnnn_paging_redisplay(0); +#endif + } else { + dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE; + ux_flow_next(); + } + } + } +} // clang-format off UX_STEP_NOCB( @@ -108,6 +182,40 @@ UX_STEP_NOCB( .title = "Address", .text = strings.common.fullAddress, }); + +UX_STEP_NOCB_INIT( + ux_plugin_approval_id_step, + bnnn_paging, + plugin_ui_get_id(), + { + .title = strings.common.fullAddress, + .text = strings.common.fullAmount + }); + +UX_STEP_INIT( + ux_plugin_approval_before_step, + NULL, + NULL, + { + display_next_plugin_item(true); + }); + +UX_FLOW_DEF_NOCB( + ux_plugin_approval_display_step, + bnnn_paging, + { + .title = strings.common.fullAddress, + .text = strings.common.fullAmount + }); + +UX_STEP_INIT( + ux_plugin_approval_after_step, + NULL, + NULL, + { + display_next_plugin_item(false); + }); + UX_STEP_NOCB( ux_approval_base_fee_step, bnnn_paging, @@ -136,6 +244,7 @@ UX_STEP_NOCB( .title = "Chain ID", .text = strings.common.chainID, }); + UX_STEP_CB( ux_approval_accept_step, pbb, @@ -171,16 +280,28 @@ UX_STEP_NOCB(ux_approval_data_warning_step, }); // clang-format on -const ux_flow_step_t *ux_approval_tx_flow[12]; +const ux_flow_step_t *ux_approval_tx_flow[15]; -void ux_approve_tx(bool dataPresent) { +void ux_approve_tx(bool fromPlugin) { int step = 0; ux_approval_tx_flow[step++] = &ux_approval_review_step; + if (tmpContent.txContent.dataPresent && !N_storage.contractDetails) { ux_approval_tx_flow[step++] = &ux_approval_data_warning_step; } - ux_approval_tx_flow[step++] = &ux_approval_amount_step; - ux_approval_tx_flow[step++] = &ux_approval_address_step; + + if (fromPlugin) { + prepareChainIdDisplay(); + prepareFeeDisplay(); + ux_approval_tx_flow[step++] = &ux_plugin_approval_id_step; + ux_approval_tx_flow[step++] = &ux_plugin_approval_before_step; + ux_approval_tx_flow[step++] = &ux_plugin_approval_display_step; + ux_approval_tx_flow[step++] = &ux_plugin_approval_after_step; + } else { + ux_approval_tx_flow[step++] = &ux_approval_amount_step; + ux_approval_tx_flow[step++] = &ux_approval_address_step; + } + if (N_storage.displayNonce) { ux_approval_tx_flow[step++] = &ux_approval_nonce_step; } From 638c12473988ea2af9358fadce1cd55fcedb1785 Mon Sep 17 00:00:00 2001 From: pscott Date: Tue, 15 Jun 2021 10:18:32 +0200 Subject: [PATCH 07/26] Add comment --- src_features/signTx/ui_flow_signTx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src_features/signTx/ui_flow_signTx.c b/src_features/signTx/ui_flow_signTx.c index c1a4fa4..6eb729b 100644 --- a/src_features/signTx/ui_flow_signTx.c +++ b/src_features/signTx/ui_flow_signTx.c @@ -286,13 +286,15 @@ void ux_approve_tx(bool fromPlugin) { int step = 0; ux_approval_tx_flow[step++] = &ux_approval_review_step; - if (tmpContent.txContent.dataPresent && !N_storage.contractDetails) { + if (!fromPlugin && tmpContent.txContent.dataPresent && !N_storage.contractDetails) { ux_approval_tx_flow[step++] = &ux_approval_data_warning_step; } if (fromPlugin) { + // If we're coming from a plugin then we need to prepare the display. prepareChainIdDisplay(); prepareFeeDisplay(); + ux_approval_tx_flow[step++] = &ux_plugin_approval_id_step; ux_approval_tx_flow[step++] = &ux_plugin_approval_before_step; ux_approval_tx_flow[step++] = &ux_plugin_approval_display_step; From a944387c1169cdf2888ac70cc72abbfdb52d864e Mon Sep 17 00:00:00 2001 From: pscott Date: Wed, 23 Jun 2021 18:26:59 +0200 Subject: [PATCH 08/26] change wording to available instead of possible --- src/ui_flow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui_flow.c b/src/ui_flow.c index 67d257b..841a100 100644 --- a/src/ui_flow.c +++ b/src/ui_flow.c @@ -130,7 +130,7 @@ UX_STEP_CB( { "Fee Details", "Display fee details", - "when possible", + "when available", strings.common.fullAddress + 40 }); From 0294c5e60fb71dd4ea419a967ec31340c0817dab Mon Sep 17 00:00:00 2001 From: pscott Date: Thu, 24 Jun 2021 18:46:18 +0200 Subject: [PATCH 09/26] Remove detailed fees display --- src/eth_plugin_handler.c | 2 +- src/eth_plugin_interface.h | 1 - src/main.c | 1 - src/shared_context.h | 4 +--- src/ui_flow.c | 34 ++-------------------------- src_common/ethUstream.c | 27 +--------------------- src_common/ethUstream.h | 1 - src_features/signTx/logic_signTx.c | 26 +-------------------- src_features/signTx/ui_flow_signTx.c | 21 +---------------- 9 files changed, 7 insertions(+), 110 deletions(-) diff --git a/src/eth_plugin_handler.c b/src/eth_plugin_handler.c index 13e1e7a..da1cac9 100644 --- a/src/eth_plugin_handler.c +++ b/src/eth_plugin_handler.c @@ -147,7 +147,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) { switch (method) { case ETH_PLUGIN_INIT_CONTRACT: ((ethPluginInitContract_t *) parameter)->interfaceVersion = - ETH_PLUGIN_INTERFACE_VERSION_2; + ETH_PLUGIN_INTERFACE_VERSION_1; ((ethPluginInitContract_t *) parameter)->result = ETH_PLUGIN_RESULT_UNAVAILABLE; ((ethPluginInitContract_t *) parameter)->pluginSharedRW = &pluginRW; ((ethPluginInitContract_t *) parameter)->pluginSharedRO = &pluginRO; diff --git a/src/eth_plugin_interface.h b/src/eth_plugin_interface.h index dc0e754..556e348 100644 --- a/src/eth_plugin_interface.h +++ b/src/eth_plugin_interface.h @@ -12,7 +12,6 @@ // Interface version. To be updated everytime we introduce breaking changes to the plugin interface. typedef enum { ETH_PLUGIN_INTERFACE_VERSION_1 = 1, // Version 1 - ETH_PLUGIN_INTERFACE_VERSION_2 = 2 // Add dataPresent to txContent } eth_plugin_interface_version_t; typedef enum { diff --git a/src/main.c b/src/main.c index d366361..2a67cb5 100644 --- a/src/main.c +++ b/src/main.c @@ -778,7 +778,6 @@ void coin_main(chain_config_t *coin_config) { #endif storage.contractDetails = 0x00; storage.displayNonce = 0x00; - storage.displayFeeDetails = 0x00; storage.initialized = 0x01; nvm_write((void *) &N_storage, (void *) &storage, sizeof(internalStorage_t)); } diff --git a/src/shared_context.h b/src/shared_context.h index 7b35b21..7a884b3 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -30,7 +30,6 @@ typedef struct internalStorage_t { unsigned char dataAllowed; unsigned char contractDetails; unsigned char displayNonce; - unsigned char displayFeeDetails; uint8_t initialized; } internalStorage_t; @@ -166,8 +165,7 @@ typedef enum { typedef struct txStringProperties_t { char fullAddress[43]; char fullAmount[50]; - char maxFee[50]; // Used as BaseFee when detailing fees - char priorityFee[50]; + char maxFee[50]; char nonce[8]; // 10M tx per account ought to be enough for everybody char chainID[8]; // 10M different chainID ought to be enough for people to find a unique // chainID for their token / chain. diff --git a/src/ui_flow.c b/src/ui_flow.c index 841a100..6bac181 100644 --- a/src/ui_flow.c +++ b/src/ui_flow.c @@ -5,7 +5,6 @@ void display_settings(const ux_flow_step_t* const start_step); void switch_settings_contract_data(void); void switch_settings_display_data(void); void switch_settings_display_nonce(void); -void switch_settings_display_fee_details(void); ////////////////////////////////////////////////////////////////////// // clang-format off @@ -79,15 +78,6 @@ UX_STEP_CB( .text = strings.common.fullAddress + 26 }); -UX_STEP_CB( - ux_settings_flow_4_step, - bnnn_paging, - switch_settings_display_fee_details(), - { - .title = "Fee Details", - .text = strings.common.fullAddress + 40 - }); - #else UX_STEP_CB( @@ -123,21 +113,10 @@ UX_STEP_CB( strings.common.fullAddress + 26 }); - UX_STEP_CB( - ux_settings_flow_4_step, - bnnn, - switch_settings_display_fee_details(), - { - "Fee Details", - "Display fee details", - "when available", - strings.common.fullAddress + 40 - }); - #endif UX_STEP_CB( - ux_settings_flow_5_step, + ux_settings_flow_4_step, pb, ui_idle(), { @@ -150,8 +129,7 @@ UX_FLOW(ux_settings_flow, &ux_settings_flow_1_step, &ux_settings_flow_2_step, &ux_settings_flow_3_step, - &ux_settings_flow_4_step, - &ux_settings_flow_5_step); + &ux_settings_flow_4_step); void display_settings(const ux_flow_step_t* const start_step) { strcpy(strings.common.fullAddress, (N_storage.dataAllowed ? "Allowed" : "NOT Allowed")); @@ -159,8 +137,6 @@ void display_settings(const ux_flow_step_t* const start_step) { (N_storage.contractDetails ? "Displayed" : "NOT Displayed")); strcpy(strings.common.fullAddress + 26, (N_storage.displayNonce ? "Displayed" : "NOT Displayed")); - strcpy(strings.common.fullAddress + 40, - (N_storage.displayFeeDetails ? "Displayed" : "NOT Displayed")); ux_flow_init(0, ux_settings_flow, start_step); } @@ -181,9 +157,3 @@ void switch_settings_display_nonce() { nvm_write((void*) &N_storage.displayNonce, (void*) &value, sizeof(uint8_t)); display_settings(&ux_settings_flow_3_step); } - -void switch_settings_display_fee_details() { - uint8_t value = (N_storage.displayFeeDetails ? 0 : 1); - nvm_write((void*) &N_storage.displayFeeDetails, (void*) &value, sizeof(uint8_t)); - display_settings(&ux_settings_flow_4_step); -} \ No newline at end of file diff --git a/src_common/ethUstream.c b/src_common/ethUstream.c index 7f1643c..17f5641 100644 --- a/src_common/ethUstream.c +++ b/src_common/ethUstream.c @@ -168,28 +168,6 @@ static void processNonce(txContext_t *context) { } } -static void processMaxPriorityFeePerGas(txContext_t *context) { - PRINTF("PRIORITY\n"); - if (context->currentFieldIsList) { - PRINTF("Invalid type for RLP_MAX_PRIORITY_FEE_PER_GAS\n"); - THROW(EXCEPTION); - } - if (context->currentFieldLength > MAX_INT256) { - PRINTF("Invalid length for RLP_MAX_PRIORITY_FEE_PER_GAS\n"); - THROW(EXCEPTION); - } - if (context->currentFieldPos < context->currentFieldLength) { - uint32_t copySize = - MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); - copyTxData(context, context->content->maxPriorityFeePerGas.value + context->currentFieldPos, copySize); - } - if (context->currentFieldPos == context->currentFieldLength) { - context->content->maxPriorityFeePerGas.length = context->currentFieldLength; - context->currentField++; - context->processingField = false; - } -} - static void processStartGas(txContext_t *context) { if (context->currentFieldIsList) { PRINTF("Invalid type for RLP_STARTGAS\n"); @@ -358,10 +336,6 @@ static bool processEIP1559Tx(txContext_t *context) { processNonce(context); break; } - case EIP1559_RLP_MAX_PRIORITY_FEE_PER_GAS: { - processMaxPriorityFeePerGas(context); - break; - } case EIP1559_RLP_MAX_FEE_PER_GAS: { processGasprice(context); break; @@ -390,6 +364,7 @@ static bool processEIP1559Tx(txContext_t *context) { processV(context); break; } + case EIP1559_RLP_MAX_PRIORITY_FEE_PER_GAS: case EIP1559_RLP_SENDER_R: case EIP1559_RLP_SENDER_S: processAndDiscard(context); diff --git a/src_common/ethUstream.h b/src_common/ethUstream.h index 41fcedf..4ba337a 100644 --- a/src_common/ethUstream.h +++ b/src_common/ethUstream.h @@ -127,7 +127,6 @@ typedef struct txInt256_t { typedef struct txContent_t { txInt256_t gasprice; // Used as MaxFeePerGas when dealing with EIP1559 transactions. txInt256_t startgas; // Also known as `gasLimit`. - txInt256_t maxPriorityFeePerGas; txInt256_t value; txInt256_t nonce; txInt256_t chainID; diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index dd6f6f8..d35d1dd 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -251,32 +251,8 @@ void prepareAndCopyFees(txInt256_t *BEGasPrice, txInt256_t *BEGasLimit, char *di feesToString(&rawFee, displayBuffer, displayBufferSize); } -static void prepareAndCopyDetailedFees() { - uint256_t rawPriorityFee = {0}; - uint256_t rawMaxFee = {0}; - uint256_t rawBaseFee = {0}; - - // Compute the priorityFee and the maxFee. - computeFees(&tmpContent.txContent.maxPriorityFeePerGas, &tmpContent.txContent.startgas, &rawPriorityFee); - computeFees(&tmpContent.txContent.gasprice, &tmpContent.txContent.startgas, &rawMaxFee); - // Substract priorityFee from maxFee -> this is the baseFee - minus256(&rawMaxFee, &rawPriorityFee, &rawBaseFee); - - // Transform priorityFee to string (with a ticker). - PRINTF("Computing priority fee\n"); - feesToString(&rawPriorityFee, strings.common.priorityFee, sizeof(strings.common.priorityFee)); - - PRINTF("Computing base fee\n"); - // Transform priorityFee to string (with a ticker). - feesToString(&rawBaseFee, strings.common.maxFee, sizeof(strings.common.maxFee)); -} - void prepareFeeDisplay() { - if (N_storage.displayFeeDetails) { - prepareAndCopyDetailedFees(); - } else { - prepareAndCopyFees(&tmpContent.txContent.gasprice, &tmpContent.txContent.startgas, strings.common.maxFee, sizeof(strings.common.maxFee)); - } + prepareAndCopyFees(&tmpContent.txContent.gasprice, &tmpContent.txContent.startgas, strings.common.maxFee, sizeof(strings.common.maxFee)); } uint32_t get_chainID() { diff --git a/src_features/signTx/ui_flow_signTx.c b/src_features/signTx/ui_flow_signTx.c index 6eb729b..f6992f6 100644 --- a/src_features/signTx/ui_flow_signTx.c +++ b/src_features/signTx/ui_flow_signTx.c @@ -216,20 +216,6 @@ UX_STEP_INIT( display_next_plugin_item(false); }); -UX_STEP_NOCB( - ux_approval_base_fee_step, - bnnn_paging, - { - .title = "Base Fee", - .text = strings.common.maxFee, - }); -UX_STEP_NOCB( - ux_approval_priority_fee_step, - bnnn_paging, - { - .title = "Priority Fee", - .text = strings.common.priorityFee, - }); UX_STEP_NOCB( ux_approval_fees_step, bnnn_paging, @@ -321,12 +307,7 @@ void ux_approve_tx(bool fromPlugin) { if (id != ETHEREUM_MAINNET_CHAINID) { ux_approval_tx_flow[step++] = &ux_approval_chainid_step; } - if (txContext.txType == EIP1559 && N_storage.displayFeeDetails) { - ux_approval_tx_flow[step++] = &ux_approval_base_fee_step; - ux_approval_tx_flow[step++] = &ux_approval_priority_fee_step; - } else { - ux_approval_tx_flow[step++] = &ux_approval_fees_step; - } + ux_approval_tx_flow[step++] = &ux_approval_fees_step; ux_approval_tx_flow[step++] = &ux_approval_accept_step; ux_approval_tx_flow[step++] = &ux_approval_reject_step; ux_approval_tx_flow[step++] = FLOW_END_STEP; From 032bd7b7ee21a0334018e16d0971264add69bb36 Mon Sep 17 00:00:00 2001 From: pscott Date: Tue, 29 Jun 2021 16:07:28 +0200 Subject: [PATCH 10/26] clang format --- src_common/ethUstream.c | 11 +++++---- src_common/ethUstream.h | 18 +++++++------- src_features/signTx/logic_signTx.c | 39 +++++++++++++++--------------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src_common/ethUstream.c b/src_common/ethUstream.c index 17f5641..4225f51 100644 --- a/src_common/ethUstream.c +++ b/src_common/ethUstream.c @@ -528,12 +528,13 @@ static parserStatus_e processTxInternal(txContext_t *context) { if (PARSING_IS_DONE(context)) { return USTREAM_FINISHED; } - // Old style transaction (pre EIP-155). Transations could just skip `v,r,s` so we needed to cut parsing here. - // commandLength == 0 could happen in two cases : + // Old style transaction (pre EIP-155). Transations could just skip `v,r,s` so we needed to + // cut parsing here. commandLength == 0 could happen in two cases : // 1. We are in an old style transaction : just return `USTREAM_FINISHED`. - // 2. We are at the end of an APDU in a multi-apdu process. This would make us return `USTREAM_FINISHED` preemptively. - // Case number 2 should NOT happen as it is up to `ledgerjs` to correctly decrease the size of the - // APDU (`commandLength`) so that this situation doesn't happen. + // 2. We are at the end of an APDU in a multi-apdu process. This would make us return + // `USTREAM_FINISHED` preemptively. Case number 2 should NOT happen as it is up to + // `ledgerjs` to correctly decrease the size of the APDU (`commandLength`) so that this + // situation doesn't happen. if ((context->txType == LEGACY && context->currentField == LEGACY_RLP_V) && (context->commandLength == 0)) { context->content->vLength = 0; diff --git a/src_common/ethUstream.h b/src_common/ethUstream.h index 4ba337a..fb05800 100644 --- a/src_common/ethUstream.h +++ b/src_common/ethUstream.h @@ -42,15 +42,15 @@ typedef customStatus_e (*ustreamProcess_t)(struct txContext_t *context); // First variant of every Tx enum. #define RLP_NONE 0 -#define PARSING_IS_DONE(ctx) \ - ((ctx->txType == LEGACY && ctx->currentField == LEGACY_RLP_DONE) || \ - (ctx->txType == EIP2930 && ctx->currentField == EIP2930_RLP_DONE) || \ - (ctx->txType == EIP1559 && ctx->currentField == EIP1559_RLP_DONE)) +#define PARSING_IS_DONE(ctx) \ + ((ctx->txType == LEGACY && ctx->currentField == LEGACY_RLP_DONE) || \ + (ctx->txType == EIP2930 && ctx->currentField == EIP2930_RLP_DONE) || \ + (ctx->txType == EIP1559 && ctx->currentField == EIP1559_RLP_DONE)) typedef enum rlpLegacyTxField_e { LEGACY_RLP_NONE = RLP_NONE, LEGACY_RLP_CONTENT, - LEGACY_RLP_TYPE, // For wanchain + LEGACY_RLP_TYPE, // For wanchain LEGACY_RLP_NONCE, LEGACY_RLP_GASPRICE, LEGACY_RLP_STARTGAS, @@ -66,7 +66,7 @@ typedef enum rlpLegacyTxField_e { typedef enum rlpEIP2930TxField_e { EIP2930_RLP_NONE = RLP_NONE, EIP2930_RLP_CONTENT, - EIP2930_RLP_TYPE, // For wanchain + EIP2930_RLP_TYPE, // For wanchain EIP2930_RLP_CHAINID, EIP2930_RLP_NONCE, EIP2930_RLP_GASPRICE, @@ -84,7 +84,7 @@ typedef enum rlpEIP2930TxField_e { typedef enum rlpEIP1559TxField_e { EIP1559_RLP_NONE = RLP_NONE, EIP1559_RLP_CONTENT, - EIP1559_RLP_TYPE, // For wanchain + EIP1559_RLP_TYPE, // For wanchain EIP1559_RLP_CHAINID, EIP1559_RLP_NONCE, EIP1559_RLP_MAX_PRIORITY_FEE_PER_GAS, @@ -125,8 +125,8 @@ typedef struct txInt256_t { } txInt256_t; typedef struct txContent_t { - txInt256_t gasprice; // Used as MaxFeePerGas when dealing with EIP1559 transactions. - txInt256_t startgas; // Also known as `gasLimit`. + txInt256_t gasprice; // Used as MaxFeePerGas when dealing with EIP1559 transactions. + txInt256_t startgas; // Also known as `gasLimit`. txInt256_t value; txInt256_t nonce; txInt256_t chainID; diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index d35d1dd..45eb058 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -194,23 +194,16 @@ void reportFinalizeError(bool direct) { } } -// Convert `BEgasPrice` and `BEgasLimit` to Uint256 and then stores the multiplication of both in `output`. +// Convert `BEgasPrice` and `BEgasLimit` to Uint256 and then stores the multiplication of both in +// `output`. static void computeFees(txInt256_t *BEgasPrice, txInt256_t *BEgasLimit, uint256_t *output) { uint256_t gasPrice = {0}; uint256_t gasLimit = {0}; - PRINTF("Gas price %.*H\n", - BEgasPrice->length, - BEgasPrice->value); - PRINTF("Gas limit %.*H\n", - BEgasLimit->length, - BEgasLimit->value); - convertUint256BE(BEgasPrice->value, - BEgasPrice->length, - &gasPrice); - convertUint256BE(BEgasLimit->value, - BEgasLimit->length, - &gasLimit); + PRINTF("Gas price %.*H\n", BEgasPrice->length, BEgasPrice->value); + PRINTF("Gas limit %.*H\n", BEgasLimit->length, BEgasLimit->value); + convertUint256BE(BEgasPrice->value, BEgasPrice->length, &gasPrice); + convertUint256BE(BEgasLimit->value, BEgasLimit->length, &gasLimit); mul256(&gasPrice, &gasLimit, output); } @@ -244,15 +237,22 @@ static void feesToString(uint256_t *rawFee, char *displayBuffer, uint32_t displa PRINTF("Displayed fees: %s\n", displayBuffer); } -// Compute the fees, transform it to a string, prepend a ticker to it and copy everything to `displayBuffer`. -void prepareAndCopyFees(txInt256_t *BEGasPrice, txInt256_t *BEGasLimit, char *displayBuffer, uint32_t displayBufferSize) { +// Compute the fees, transform it to a string, prepend a ticker to it and copy everything to +// `displayBuffer`. +void prepareAndCopyFees(txInt256_t *BEGasPrice, + txInt256_t *BEGasLimit, + char *displayBuffer, + uint32_t displayBufferSize) { uint256_t rawFee = {0}; computeFees(BEGasPrice, BEGasLimit, &rawFee); feesToString(&rawFee, displayBuffer, displayBufferSize); } void prepareFeeDisplay() { - prepareAndCopyFees(&tmpContent.txContent.gasprice, &tmpContent.txContent.startgas, strings.common.maxFee, sizeof(strings.common.maxFee)); + prepareAndCopyFees(&tmpContent.txContent.gasprice, + &tmpContent.txContent.startgas, + strings.common.maxFee, + sizeof(strings.common.maxFee)); } uint32_t get_chainID() { @@ -261,9 +261,10 @@ uint32_t get_chainID() { if (txContext.txType == LEGACY) { chain_id = u32_from_BE(txContext.content->v, txContext.content->vLength, true); } else if (txContext.txType == EIP2930 || txContext.txType == EIP1559) { - chain_id = u32_from_BE(tmpContent.txContent.chainID.value, tmpContent.txContent.chainID.length, true); - } - else { + chain_id = u32_from_BE(tmpContent.txContent.chainID.value, + tmpContent.txContent.chainID.length, + true); + } else { PRINTF("Txtype `%u` not supported while generating chainID\n", txContext.txType); } PRINTF("ChainID: %d\n", chain_id); From 1bff0b3b7d0f1c6db16c620c78fd0205f2b29e84 Mon Sep 17 00:00:00 2001 From: pscott Date: Wed, 30 Jun 2021 14:00:35 +0200 Subject: [PATCH 11/26] Add temp eip1559 test (not working) --- tests/src/eip1559.test.js | 168 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 tests/src/eip1559.test.js diff --git a/tests/src/eip1559.test.js b/tests/src/eip1559.test.js new file mode 100644 index 0000000..4643fc9 --- /dev/null +++ b/tests/src/eip1559.test.js @@ -0,0 +1,168 @@ +import "core-js/stable"; +import "regenerator-runtime/runtime"; +import Eth from "@ledgerhq/hw-app-eth"; +import { byContractAddress } from "@ledgerhq/hw-app-eth/erc20"; +import Zemu from "@zondax/zemu"; +import { TransportStatusError } from "@ledgerhq/errors"; +import { expect } from "../jest"; + +const {NANOS_ELF_PATH, NANOX_ELF_PATH, sim_options_nanos, sim_options_nanox, TIMEOUT} = require("generic.js"); + +const ORIGINAL_SNAPSHOT_PATH_PREFIX = "snapshots/eip1559/"; +const SNAPSHOT_PATH_PREFIX = "snapshots/tmp/"; + +const ORIGINAL_SNAPSHOT_PATH_NANOS = ORIGINAL_SNAPSHOT_PATH_PREFIX + "nanos/"; +const ORIGINAL_SNAPSHOT_PATH_NANOX = ORIGINAL_SNAPSHOT_PATH_PREFIX + "nanox/"; + +const SNAPSHOT_PATH_NANOS = SNAPSHOT_PATH_PREFIX + "nanos/"; +const SNAPSHOT_PATH_NANOX = SNAPSHOT_PATH_PREFIX + "nanox/"; + +test("Transfer nanos eip1559", async () => { + jest.setTimeout(TIMEOUT); + const sim = new Zemu(NANOS_ELF_PATH); + + try { + await sim.start(sim_options_nanos); + + let transport = await sim.getTransport(); + let buffer = Buffer.from("02058000002c8000003c800000000000000000000000f88d0101808207d0871000000000000094cccccccccccccccccccccccccccccccccccccccc80a4693c613900000000000000000000000000000000000000000000000000000000000000fac001a0659425c1533f84bacbc9e119863db012ea8e8d49ec9d0ef208254dd67f0bdfa5a043409e4e89855389fe8fafddd4c58616ff", "hex"); + + // Send transaction + let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer); + buffer = Buffer.from("cb3c99990c13e47cf362d63e012b9b", "hex"); + tx = transport.send(0xe0, 0x04, 0x80, 0x00, buffer); + let filename; + + await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()); + // Review tx + filename = "review.png"; + await sim.snapshot(SNAPSHOT_PATH_NANOS + filename); + const review = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); + const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); + expect(review).toEqual(expected_review); + + // Amount 1/3 + filename = "amount_1.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); + const amount_1 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); + const expected_amount_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); + expect(amount_1).toEqual(expected_amount_1); + + // Amount 2/3 + filename = "amount_2.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); + const amount_2 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); + const expected_amount_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); + expect(amount_2).toEqual(expected_amount_2); + + // Amount 3/3 + filename = "amount_3.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); + const amount_3 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); + const expected_amount_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); + expect(amount_3).toEqual(expected_amount_3); + + // Address 1/3 + filename = "address_1.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); + const address_1 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); + const expected_address_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); + expect(address_1).toEqual(expected_address_1); + + // Address 2/3 + filename = "address_2.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); + const address_2 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); + const expected_address_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); + expect(address_2).toEqual(expected_address_2); + + // Address 3/3 + filename = "address_3.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); + const address_3 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); + const expected_address_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); + expect(address_3).toEqual(expected_address_3); + + // Max Fees + filename = "fees.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); + const fees = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); + const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); + expect(fees).toEqual(expected_fees); + + // Accept + filename = "accept.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); + const accept = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); + const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); + expect(accept).toEqual(expected_accept); + + await sim.clickBoth(); + + await expect(tx).resolves.toEqual( + Buffer.from([ 38, 111, 56, 157, 21, 50, 15, 5, 1, 56, 53, 38, 237, 3, 222, 145, 124, 20, 33, 39, 22, 240, 154, 38, 45, 188, 152, 67, 16, 134, 165, 219, 73, 13, 201, 148, 183, 185, 114, 48, 187, 53, 253, 246, 254, 194, 244, 216, 255, 76, 251, 139, 254, 178, 166, 82, 195, 100, 199, 56, 255, 3, 60, 5, 221, 144, 0]) + ); + } finally { + await sim.close(); + } +}); + +test.skip("Transfer nanox", async () => { + jest.setTimeout(TIMEOUT); + const sim = new Zemu(NANOX_ELF_PATH); + + try { + await sim.start(sim_options_nanox); + + let transport = await sim.getTransport(); + let buffer = Buffer.from("058000002C8000003C800000010000000000000000EB44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF6181880018080", "hex"); + + // Send transaction + let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer); + let filename; + + await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()); + // Review tx + filename = "review.png"; + await sim.snapshot(SNAPSHOT_PATH_NANOX + filename); + const review = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename); + const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename); + expect(review).toEqual(expected_review); + + // Amount + filename = "amount.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOX + filename); + const amount = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename); + const expected_amount = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename); + expect(amount).toEqual(expected_amount); + + // Address + filename = "address.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOX + filename); + const address = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename); + const expected_address = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename); + expect(address).toEqual(expected_address); + + // Max Fees + filename = "fees.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOX + filename); + const fees = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename); + const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename); + expect(fees).toEqual(expected_fees); + + // Accept + filename = "accept.png"; + await sim.clickRight(SNAPSHOT_PATH_NANOX + filename); + const accept = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename); + const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename); + expect(accept).toEqual(expected_accept); + + await sim.clickBoth(); + + await expect(tx).resolves.toEqual( + Buffer.from([ 38, 111, 56, 157, 21, 50, 15, 5, 1, 56, 53, 38, 237, 3, 222, 145, 124, 20, 33, 39, 22, 240, 154, 38, 45, 188, 152, 67, 16, 134, 165, 219, 73, 13, 201, 148, 183, 185, 114, 48, 187, 53, 253, 246, 254, 194, 244, 216, 255, 76, 251, 139, 254, 178, 166, 82, 195, 100, 199, 56, 255, 3, 60, 5, 221, 144, 0]) + ); + } finally { + await sim.close(); + } +}); \ No newline at end of file From 5b489f95717e4a28dc4dcb78013bd5409a7c4610 Mon Sep 17 00:00:00 2001 From: pscott Date: Wed, 30 Jun 2021 14:00:46 +0200 Subject: [PATCH 12/26] Add folder for eip1559 tests --- tests/snapshots/eip1559/nanos/accept.png | Bin 0 -> 582 bytes tests/snapshots/eip1559/nanos/address_1.png | Bin 0 -> 809 bytes tests/snapshots/eip1559/nanos/address_2.png | Bin 0 -> 837 bytes tests/snapshots/eip1559/nanos/address_3.png | Bin 0 -> 567 bytes tests/snapshots/eip1559/nanos/amount_1.png | Bin 0 -> 474 bytes tests/snapshots/eip1559/nanos/amount_2.png | Bin 0 -> 759 bytes tests/snapshots/eip1559/nanos/amount_3.png | Bin 0 -> 479 bytes tests/snapshots/eip1559/nanos/fees.png | Bin 0 -> 561 bytes tests/snapshots/eip1559/nanos/review.png | Bin 0 -> 541 bytes tests/snapshots/eip1559/nanox/accept.png | Bin 0 -> 667 bytes tests/snapshots/eip1559/nanox/address.png | Bin 0 -> 1292 bytes tests/snapshots/eip1559/nanox/amount.png | Bin 0 -> 860 bytes tests/snapshots/eip1559/nanox/fees.png | Bin 0 -> 685 bytes tests/snapshots/eip1559/nanox/review.png | Bin 0 -> 633 bytes 14 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/snapshots/eip1559/nanos/accept.png create mode 100644 tests/snapshots/eip1559/nanos/address_1.png create mode 100644 tests/snapshots/eip1559/nanos/address_2.png create mode 100644 tests/snapshots/eip1559/nanos/address_3.png create mode 100644 tests/snapshots/eip1559/nanos/amount_1.png create mode 100644 tests/snapshots/eip1559/nanos/amount_2.png create mode 100644 tests/snapshots/eip1559/nanos/amount_3.png create mode 100644 tests/snapshots/eip1559/nanos/fees.png create mode 100644 tests/snapshots/eip1559/nanos/review.png create mode 100644 tests/snapshots/eip1559/nanox/accept.png create mode 100644 tests/snapshots/eip1559/nanox/address.png create mode 100644 tests/snapshots/eip1559/nanox/amount.png create mode 100644 tests/snapshots/eip1559/nanox/fees.png create mode 100644 tests/snapshots/eip1559/nanox/review.png diff --git a/tests/snapshots/eip1559/nanos/accept.png b/tests/snapshots/eip1559/nanos/accept.png new file mode 100644 index 0000000000000000000000000000000000000000..3158ea690450f2b8c85c12004b002b02e7b02539 GIT binary patch literal 582 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfj3Yx;TbZFupw)IO&lagUi8i zu2=uq*Yz9Se)!g*VK4JBV-C&WKWoz`S-k14IyUoMm0IWFIu4EW+>4RtRSIvkw{qJ) z-k{BNYMKd;QTzYAL~p5OZSof#4llR(=qVMJ($*$Ab77)uTE-4V=fhVFPUOsN*u=_P zev*f``Ha_Lh0T`?P5_w@bmoG=iJGR?wG$oFmOfn9wp(f$o7BG*4~6I6nAJ9Y(#_4S zx*0Q4Cd`zYu+#gQ-puxsHA;+6txb81;;$K;SOc`)`Eb{n3mcS-P1XR-G*4O9=9zYy zWlA>hi9IogRX%T%Vw>52vEj_tR;Wnvk2E8bnCKl>8qOS+%J|{VJNeAR_7fKhJRN>6 zWt_R(#K%Y*B*bf?@cHzid?OPZ*R-q|Qfe~~OJ_JdGiQ7n#BAiBxx@R}2R5LKwiNib zwJkq!XF{bkuSv~rHmSN0W~1w3?WueMPz z$jMOtJF#s}Y?8nbo644w2lP(7Qu7&Lh$$GG`0$>%lOd6E?`G%PjEacEho#sgfuXFQ zeWOb_8W?6gy!z_Ez}=wqxl_z;<{4*T7^Tcp+APW)4b*$#gTTy%593WQI2=|m1}X&# zr~*UES~!4j_tt_NTU!sW)0HX9eYhc;yFK9u$bQ|Tj}*;XgammwB9|D81-LZ`XFR^n$fF;SI`v$~Bw#9iRXBdhZ99sk z8`td4mwb9bhHPRif?hDQUYA`V<=)BC+XvR2WdHhQH%(=F&8$W! zMzihGN~OCp&ZyB>K|(3A9qk4;oWdE&K?p9d1`WGy=_LX@LX2!min2l=M2slbD{MUb5t%PAS0uT7^VLjsV|_GCBElca4UkexH1riZL?{w_s8D zhPh}VMWu?qg17w-P`Ca1BSD&uhCu^u-mehg4xN2^R41JPWs5RGq$;lUv|0~4VA#RtV2sDi0w4xX;L}5VF-pN5>w{FKA#Ksj z(n4Y$PT<%Aoev$v98_+>(id8Y3Br!Sz#gK4J6t=cyPQhMiQAOXUrtXmk-?m1hO!Wp) dMc)c+e?_|s$wq~xc@nMwFF&VHJ)V8j@(=l|VF&;K literal 0 HcmV?d00001 diff --git a/tests/snapshots/eip1559/nanos/address_2.png b/tests/snapshots/eip1559/nanos/address_2.png new file mode 100644 index 0000000000000000000000000000000000000000..93c90c542343a4423166f143ee5f43f335c73b96 GIT binary patch literal 837 zcmXAo4M-DV7{_;A%@R)~MB5oQ6F(yHVLVt$ZA=)^QU zBa$mqOLSqW0}B(ikSSa-LTA~M^?~9*LQSM{U?0zWaUbu!FYohz{?G4uuQ5L_n+PNW zB@zjt%~2P?XoE+-Qws0-{S~ni2_B?XXBJwqm5I{@W!f;+L`=i;zdOFE7GI3q(@a%%ggCfQn@u^+iip^<%vKAXE_sg2^OTwK8cYgpA)QlwvHdYYcoX z2bgK!RAU5Mt$@`d>q?fj?;F7Qi1_QVD(7qn&>7r*=L5+dHSVGAOCb#lr3w}pAa_-p zlo_~48)j3Oa(4=Ih)@|!9sq;O08x*=RR=>ZP7Ur#7=~;jQXTRs>{ZCq#E)j6REz_9 zh=eA{H+q2|PIY6bIx&VnoGuofiBqpCec?p6Uhv)k^ddd4^G&t%9 zY-k2o(470o9Kb|1c*OH30!6??u5JhP6bM<+K|&{NI5fW_YOc}VaBX4v;R9>6F}@>e b9;QD-q}la_C0C<6;P;SdHF@d*Woi9CJYZeG literal 0 HcmV?d00001 diff --git a/tests/snapshots/eip1559/nanos/address_3.png b/tests/snapshots/eip1559/nanos/address_3.png new file mode 100644 index 0000000000000000000000000000000000000000..402c20d84b73864383ebc9f5a2cc87b175f5db3a GIT binary patch literal 567 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfjh}ba4!+V0?Qpu$}+Z;wl?0GvNM-UO}LpM zky5uhal%ZHQK4dSYZ+%cwzcJ7bU5q>gz}StoRy3-c_mXaD%7>#FL-$Sd3dKc15MFpd>Y7XB)^&w=$kU2LncsOmxlb>jgobGRf=9re@@GMm9+yX{PDZj-Jy`?7n3}800mQ0zj@S#rFxit?V zY9vzH*g&X^m)&T0TkK)KXTe7HH&5L>$-{f%jTA&~p9|0|Hc6=omCG4t=4akG$zuex zjEj5ywT3f(ZEfB_i$K!nlAiKNExR6J$vksm;;;I!xRs1EnSr`~8c9mA&1`Oi>s-l} z!Uq&t$T%}xFkqgkf^qF4#+mzpxPBeu%yjPaQWIwCxwW;WGo5l~HoDwus_=QkhYJm7 zN(zlkY;E4uAX2Cbdh_u!?T;G+*9 literal 0 HcmV?d00001 diff --git a/tests/snapshots/eip1559/nanos/amount_2.png b/tests/snapshots/eip1559/nanos/amount_2.png new file mode 100644 index 0000000000000000000000000000000000000000..11ae75e8391d69f363be24e20c136f0ee32b13d0 GIT binary patch literal 759 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfi@&ba4!+V0?Qp&`&v1#O2^* z)#v}j=g8l@cDdkcYoY6pnS>%$F{b` zI|@>Gt&L20W?nQ%abpIlU7F~gmKh->HuL_gLl;l>u%%3EyV!6h!{M18P*ySp$N;L7 zzqH{5k0j70KI!{w8E3k-waKq!oC#Fd$75t7bF@`C)bY?cP=5SXJ5Ka6+Wjt_GC6%9`D!IrY`NDl40?;i1&oe%^$OQc$deoVw}03 zQ{y~P)v7kvXQ8~^XMn+A4Ww2}O}GiP)$MTKnG6sG-b{T(V_>|+T?K~mnM)fkf6z1XW;Sw81BOR1&|&@D?$YFcvsLlQ$7&?QRF zAYZnfnGM9i5S+g#@x&fi2TR*Ey_cPDTi9+vP`{bucKb|_So<*tn4lRvUHx3vIVCg! E0D4U}bN~PV literal 0 HcmV?d00001 diff --git a/tests/snapshots/eip1559/nanos/amount_3.png b/tests/snapshots/eip1559/nanos/amount_3.png new file mode 100644 index 0000000000000000000000000000000000000000..e0420108494b969f9c050ba46e44f5c255fa1f1b GIT binary patch literal 479 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfcCjba4!+V0?Qpu2D;LWW?VAh6@j^#SRf&uFm zFwXq%#B9{w=J;$fTS|sRN*i0sz0}8CQWF+FG?Loq!X}xLVUg+ZOre>_$Ry@yvv#({ z#D$3yB&FD9E@T8D=fj<67CyXCFk$Cv_HcD$6NTao2`Qlbgr7n{X`pTgkimXZd`A1P z6ifi~WzFubWt`c}!~0(r$Oo#noaorrwz{H#mG^YD%?_rS3lo2q%k2qfHc~e-QTUu{ zWWr;l&bxo2L{A6 zpc$$Q&a7aZ=`S^5=FwwDTiG{fTAa{P0E+>AleTGN&Gm*eIc8!R4ry-uX+WpU0lIOs tK)|%jT%F+C5zDr1^vO-0c?+mDU$Ss>;+dSqdccTd@O1TaS?83{1OS_=#2f$s literal 0 HcmV?d00001 diff --git a/tests/snapshots/eip1559/nanos/fees.png b/tests/snapshots/eip1559/nanos/fees.png new file mode 100644 index 0000000000000000000000000000000000000000..8b996b58a1ec0043e05a39e52d99ce49521f5116 GIT binary patch literal 561 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfjh`ba4!+V0?S<_9P{D2Iqr| z`M&&@U&B6g#fK@G39{B^n`3qv9lc+r*7-Ezit)LUYsQ{B#}yaM+3K2ZJNZZvkF(KjQp%**X8vFMuy3Y$pJn*fOlp&zxsVZr@-t_oENk;j%b1Z8clX%t z2@4am9Mas`Bva&;F-ih;PH=qI#$)vU!4dV$9o}tij?bn`m8G<`?Us6%P@Cp96s={P z`Lx+Yp*Z((6tmIk_K6E0-a59FEoBPfj{eKPE=hD0RpVDNPHb6Mw<&;$TB@9Js* literal 0 HcmV?d00001 diff --git a/tests/snapshots/eip1559/nanos/review.png b/tests/snapshots/eip1559/nanos/review.png new file mode 100644 index 0000000000000000000000000000000000000000..2994983f84cf76ab587bac356d5afe297c0e0632 GIT binary patch literal 541 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfcyxba4!+V0?SfW}LV) zm52AlpJ_b2>@)W(0ade0N=>L#7k{_%p*K+Izf)VA1-(C=WRZ-BymEd z+ycg#=gr>vKI=O3DZ$93W?LaYQ1QY>pxO%?Y&v*&<#TnOD>)zbXF6qTB9pT3N&!&M z3dWi9&EBnj=ymuLi`0al9u7OFx80vqnaz8`W+_{Wop8XrwTVif&jYR3;ytm)i1F!7 zQ=gO!i4>qCfqpe|KCDm-Wb*LtR{=T`$TJ28kKEHk+7p0Y?mPqLwy~wK0ofM}OcabW z9iDmf0+pZOF#@XZFL)Sha%TzS%!Lnq%!RyR`IX+l PXlL+r^>bP0l+XkKp5EPW literal 0 HcmV?d00001 diff --git a/tests/snapshots/eip1559/nanox/accept.png b/tests/snapshots/eip1559/nanox/accept.png new file mode 100644 index 0000000000000000000000000000000000000000..7f2b8c89bd1a94620c388b2ac5599a5860918179 GIT binary patch literal 667 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}EWU|>q}ba4!+V0?R!F;Cf*f#Kl2 zz`9HS>x1^Ee)QO$Vfbu^0!v}qD!w`k`M$>q(WeXTJ`~u@;XhuuVeMlEKe= zblsz=UEx}KqN4T7AKeXEai{i!%hS0be`bg5)1I2%Y#ve=7`PK?+@eoir_xu}u(KC@ zO4CxCy1UCWb=8jGnOg6FCRYU^5c7u@_QxF*4>iefJ62pYe>kS>sng- zHXYoyg@4};pf2xLucNL{gFco6P0<5+2g=uDi=Wfg1@u|?!cS|Gf_{o>X-)6)bOl-% zvcd-FmwN}<<71Adht`B0T>=c@AEBb}pEc_PRnFAEv02=qn^cWuW6bfX(Mx8*RNi5Q7S*c4N9CR-H3X_(?fzps@T6PxSxy?d|U z_xbg`x0ve6z0|{$$z`>vm__J(e_?lE0G zAi0bGdZ+lnxBEWNGVl2`{%6UJXQyvpE4Wzn-e|aC?{wb8^_8OsR~Bx4QP|*isOuQt^m>}Nu7q+}3pf1Hn)V>OQKgpB zh<;sTrr2Cmi|ndPr%%kiDa;FspIMGSgx8c~oEeb?2VdjRIbXm66AXWR688v7s$VGQ zIg32k9m?@~Hjc>fF{3znxIq;*l&O)kR!%NCYwSns9?!DZ6L>7=`-P_`{Y*WSg{pk) zm|_M1F@MyG6Hrpr@@Gv&)n`6zF8(02BsC51Yx?1p7xE_TmyI`sa=nz!7r7v8XNS<^ zBBzF}TmnEcfrt%oC~kUya2Z0oMTJy!qYfJ2l!}#;b7MAMW&(X0VT=YeELmkYjqE`e zK`}d#YD1d{lM9av3fVhEhLot-qBcHiBtkW@LA3p-xCm7uHoa={ZZ<$@#AfsyCr!uF z5Bmit9~;EAG+LAg@%Fp63yOCEV$6*-R0lZB=`H$R6;N8TVlxfvjhx&G#2eJZXz`NaB*3)}Kzawuog$Rv*?LaC+eD)~z-shW{cTDt zkNTNFjT*6HIe`&Q>lHDIWI#ONQp3g}5qwIc9dHFTSJbBWQ{wysFCX_vEn5LNKd+Y( zmlh-J)XHzL`0I><-Fa7JJbdZ`CBArEVw<;yU>6vA>;1{jGBpe$kj#vO2#|>c9M~r_ z$qC|&Tr!sN+zV>U-*}b5^fowsq*(_xAVOLOX2%r`MnLVNFi(k+O>aZEhYZrTtU;3C zWboL=GcfqBRlgs!3L6C=`na&FFiLx^8Zo@SKsPX(!4L-$6$O~b0i4X_B4VtclZ^eK zq*@0-Sv?18Er6E%tVM^>kn;5P&P`P1Q%wm(3dM*iB{F0FcRPCS*4V_Zc zqN@M`GKfY!(sUj4@pOJR&b$ly02(@fTid1F9BX+h-GC{QA<57F{)8wvqkcBP|33!U b{Kq5wVK(&fFDI_STh8QkR98&ep6~t})+AOd4F>8ZFrU~~3m(OMCrIK87P&rWPk zUK!WAhI`AilTD;tzH+d&K96(cSJi6wi%BnuFbZNV8l(Lw99lx+yTDUy#dTFh=rC3?0oO*7FWjW6iXi`mcK1=0P z0-J%-%z^;4Kh{^ttwIJK^~^oW-Hl@%mi)gLB%_;Z7(zg6HALM-gk2wUx$4?#12;Ym z{2kU}DKtVUd-nz?=d?@4ep@GpnS0meDF4KrvckpoOMEzPe8%XzVP1zNRjfmJ48*W` zvW)g{P(vfy8LAs1ko4;VGEGn>oms$2Tf^ISon2BZnuaM+tAM$9%;P<+8|JlSpiYDz z%2+7;hei$?b?Bh z!%svsm<3o!-K4kE25p<5Zx!uLhM`cJn|7B;T&&W*&O)tc?o^%D0bHFedDkb8?iP3-ClKDuO)QK*mT?84|K5^y56PspkV$uCQ3?qa`Y; zJ{9Par=qe4=H^B==Vl@!^LZ;kj;!!bT@|o%RY0Zx(Ir3^dOls16tolQUO%ATV2GzG zr%C%S`!wxT$ih#{wL+G0P2CPAS2_W8&IB_(pN1?nS~*9{PYdY0bcr1A-5*nc`p>WU zk*5{1PD^cS`p%CjTK}h=3O%}dMZiyi@z=OFm5v0qO~EJ+&mraOE5jd$QNjB}Kr{|2Y>J3iWH9o~~uyQ5?8%(_b4=t?=e< zuBmU+gI4a4`V#~c$^iz_L47UJ+vmd;7D>gd2+6Sr8g-TN&dq72H>R1<0DTiTY;kjq U6a97!m<$;_UHx3vIVCg!0AW%^y8r+H literal 0 HcmV?d00001 diff --git a/tests/snapshots/eip1559/nanox/review.png b/tests/snapshots/eip1559/nanox/review.png new file mode 100644 index 0000000000000000000000000000000000000000..8794afe436a71131138e8f80fe7d0d4eca0eb076 GIT binary patch literal 633 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}EWU|@3aba4!+V0?S7Zd@yx<8LGD|NL^HOwMbIhRMr6+gQ$n z$QbOfoPT3l5rg{eO>DO>VIn!5Rge5qUD*pZP3XEG70O~b+m^~6IH{zir*(hjjumT?HZ15`uN79ppw7MWhwRj;G6zmJ zX}t>p31G2LNNZm)gL*#D!l%o%LhK@2Pu*plvu7pO)Rj)DzqfKt&HQjsOG`^nG(I#& z>m8U?E?O@7-eGByRLu%5(W#zGlU4=%T;=4N8nkjp$cm5{t&n?;t*5>`I2-DtRW52D z`Y}^0h?Z-ue|C^NaAm;G;F&;qYmldcfNZU0TvK;*O?@A-!benV@~M!8 zpS Date: Wed, 30 Jun 2021 16:51:41 +0200 Subject: [PATCH 13/26] Add 02 preffix to transaction --- tests/src/eip1559.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/eip1559.test.js b/tests/src/eip1559.test.js index 4643fc9..78009d8 100644 --- a/tests/src/eip1559.test.js +++ b/tests/src/eip1559.test.js @@ -25,7 +25,7 @@ test("Transfer nanos eip1559", async () => { await sim.start(sim_options_nanos); let transport = await sim.getTransport(); - let buffer = Buffer.from("02058000002c8000003c800000000000000000000000f88d0101808207d0871000000000000094cccccccccccccccccccccccccccccccccccccccc80a4693c613900000000000000000000000000000000000000000000000000000000000000fac001a0659425c1533f84bacbc9e119863db012ea8e8d49ec9d0ef208254dd67f0bdfa5a043409e4e89855389fe8fafddd4c58616ff", "hex"); + let buffer = Buffer.from("058000002c8000003c80000000000000000000000002f88d0101808207d0871000000000000094cccccccccccccccccccccccccccccccccccccccc80a4693c613900000000000000000000000000000000000000000000000000000000000000fac001a0659425c1533f84bacbc9e119863db012ea8e8d49ec9d0ef208254dd67f0bdfa5a043409e4e89855389fe8fafddd4c58616ff", "hex"); // Send transaction let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer); From aa2415125eae4acdaf23ed6ed43819c1b0e66132 Mon Sep 17 00:00:00 2001 From: pscott Date: Sat, 31 Jul 2021 13:03:56 +0200 Subject: [PATCH 14/26] Remove parsing of sender_r, sender_s and y_parity --- examples/signTx.py | 35 ++++++++++++++++++++++------------- src_common/ethUstream.c | 13 ------------- src_common/ethUstream.h | 6 ------ 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/examples/signTx.py b/examples/signTx.py index 9f0c4a0..5bb7c34 100755 --- a/examples/signTx.py +++ b/examples/signTx.py @@ -37,6 +37,7 @@ except: # Python3 hack import for pyethereum from ethereum.utils import decode_hex, encode_hex, str_to_bytes + def parse_bip32_path(path): if len(path) == 0: return b"" @@ -52,13 +53,18 @@ def parse_bip32_path(path): parser = argparse.ArgumentParser() -parser.add_argument('--nonce', help="Nonce associated to the account", type=int, required=True) -parser.add_argument('--gasprice', help="Network gas price", type=int, required=True) +parser.add_argument( + '--nonce', help="Nonce associated to the account", type=int, required=True) +parser.add_argument('--gasprice', help="Network gas price", + type=int, required=True) parser.add_argument('--startgas', help="startgas", default='21000', type=int) parser.add_argument('--amount', help="Amount to send in ether", required=True) -parser.add_argument('--to', help="Destination address", type=str, required=True) +parser.add_argument('--to', help="Destination address", + type=str, required=True) parser.add_argument('--path', help="BIP 32 path to sign with") parser.add_argument('--data', help="Data to add, hex encoded") +parser.add_argument( + '--chainid', help="Chain ID (1 for Ethereum mainnet, 137 for Polygon, etc)", type=int) parser.add_argument('--descriptor', help="Optional descriptor") args = parser.parse_args() @@ -83,12 +89,15 @@ tx = UnsignedTransaction( ) encodedTx = encode(tx, UnsignedTransaction) +encodedTx = bytearray.fromhex( + "02ef0306843b9aca008504a817c80082520894b2bb2b958afa2e96dab3f3ce7162b87daea39017872386f26fc1000080c0") dongle = getDongle(True) if args.descriptor != None: descriptor = binascii.unhexlify(args.descriptor) - apdu = struct.pack(">BBBBB", 0xE0, 0x0A, 0x00, 0x00, len(descriptor)) + descriptor + apdu = struct.pack(">BBBBB", 0xE0, 0x0A, 0x00, 0x00, + len(descriptor)) + descriptor dongle.exchange(bytes(apdu)) donglePath = parse_bip32_path(args.path) @@ -100,16 +109,16 @@ apdu += donglePath + encodedTx result = dongle.exchange(bytes(apdu)) # Needs to recover (main.c:1121) -if (CHAIN_ID*2 + 35) + 1 > 255: - ecc_parity = result[0] - ((CHAIN_ID*2 + 35) % 256) - v = (CHAIN_ID*2 + 35) + ecc_parity -else: - v = result[0] +# if (CHAIN_ID*2 + 35) + 1 > 255: +# ecc_parity = result[0] - ((CHAIN_ID*2 + 35) % 256) +# v = (CHAIN_ID*2 + 35) + ecc_parity +# else: +# v = result[0] -r = int(binascii.hexlify(result[1:1 + 32]), 16) -s = int(binascii.hexlify(result[1 + 32: 1 + 32 + 32]), 16) +# r = int(binascii.hexlify(result[1:1 + 32]), 16) +# s = int(binascii.hexlify(result[1 + 32: 1 + 32 + 32]), 16) -tx = Transaction(tx.nonce, tx.gasprice, tx.startgas, - tx.to, tx.value, tx.data, v, r, s) +# tx = Transaction(tx.nonce, tx.gasprice, tx.startgas, +# tx.to, tx.value, tx.data, v, r, s) print("Signed transaction", encode_hex(encode(tx))) diff --git a/src_common/ethUstream.c b/src_common/ethUstream.c index 4225f51..8d5c979 100644 --- a/src_common/ethUstream.c +++ b/src_common/ethUstream.c @@ -360,13 +360,7 @@ static bool processEIP1559Tx(txContext_t *context) { processAccessList(context); break; } - case EIP1559_RLP_YPARITY: { - processV(context); - break; - } case EIP1559_RLP_MAX_PRIORITY_FEE_PER_GAS: - case EIP1559_RLP_SENDER_R: - case EIP1559_RLP_SENDER_S: processAndDiscard(context); break; default: @@ -406,19 +400,12 @@ static bool processEIP2930Tx(txContext_t *context) { case EIP2930_RLP_VALUE: processValue(context); break; - case EIP2930_RLP_YPARITY: - processV(context); - break; case EIP2930_RLP_DATA: processData(context); break; case EIP2930_RLP_ACCESS_LIST: processAccessList(context); break; - case EIP2930_RLP_SENDER_R: - case EIP2930_RLP_SENDER_S: - processAndDiscard(context); - break; default: PRINTF("Invalid RLP decoder context\n"); return true; diff --git a/src_common/ethUstream.h b/src_common/ethUstream.h index fb05800..01b9f37 100644 --- a/src_common/ethUstream.h +++ b/src_common/ethUstream.h @@ -75,9 +75,6 @@ typedef enum rlpEIP2930TxField_e { EIP2930_RLP_VALUE, EIP2930_RLP_DATA, EIP2930_RLP_ACCESS_LIST, - EIP2930_RLP_YPARITY, - EIP2930_RLP_SENDER_R, - EIP2930_RLP_SENDER_S, EIP2930_RLP_DONE } rlpEIP2930TxField_e; @@ -94,9 +91,6 @@ typedef enum rlpEIP1559TxField_e { EIP1559_RLP_VALUE, EIP1559_RLP_DATA, EIP1559_RLP_ACCESS_LIST, - EIP1559_RLP_YPARITY, - EIP1559_RLP_SENDER_R, - EIP1559_RLP_SENDER_S, EIP1559_RLP_DONE } rlpEIP1559TxField_e; From d0a540f683d1c4bb4ae67eea4c7a3a05dda14acd Mon Sep 17 00:00:00 2001 From: pscott Date: Sat, 31 Jul 2021 13:33:45 +0200 Subject: [PATCH 15/26] Fix y_parity signature for eip1559 and eip2930 --- src_features/signTx/ui_common_signTx.c | 34 ++++++++++++++++---------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src_features/signTx/ui_common_signTx.c b/src_features/signTx/ui_common_signTx.c index 89b2e91..55ebaa3 100644 --- a/src_features/signTx/ui_common_signTx.c +++ b/src_features/signTx/ui_common_signTx.c @@ -28,20 +28,28 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) { sizeof(signature), &info); explicit_bzero(&privateKey, sizeof(privateKey)); - // Parity is present in the sequence tag in the legacy API - if (tmpContent.txContent.vLength == 0) { - // Legacy API - G_io_apdu_buffer[0] = 27; + if (txContext.txType == EIP1559 || txContext.txType == EIP2930) { + if (info & CX_ECCINFO_PARITY_ODD) { + G_io_apdu_buffer[0] = 1; + } else { + G_io_apdu_buffer[0] = 0; + } } else { - // New API - // Note that this is wrong for a large v, but the client can always recover - G_io_apdu_buffer[0] = (v * 2) + 35; - } - if (info & CX_ECCINFO_PARITY_ODD) { - G_io_apdu_buffer[0]++; - } - if (info & CX_ECCINFO_xGTn) { - G_io_apdu_buffer[0] += 2; + // Parity is present in the sequence tag in the legacy API + if (tmpContent.txContent.vLength == 0) { + // Legacy API + G_io_apdu_buffer[0] = 27; + } else { + // New API + // Note that this is wrong for a large v, but the client can always recover + G_io_apdu_buffer[0] = (v * 2) + 35; + } + if (info & CX_ECCINFO_PARITY_ODD) { + G_io_apdu_buffer[0]++; + } + if (info & CX_ECCINFO_xGTn) { + G_io_apdu_buffer[0] += 2; + } } format_signature_out(signature); tx = 65; From 06075c95863a28f40406d41748ade36d7e1014a5 Mon Sep 17 00:00:00 2001 From: pscott Date: Sat, 31 Jul 2021 14:21:10 +0200 Subject: [PATCH 16/26] Sign txType byte --- src_features/signTx/cmd_signTx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src_features/signTx/cmd_signTx.c b/src_features/signTx/cmd_signTx.c index c429992..7e64235 100644 --- a/src_features/signTx/cmd_signTx.c +++ b/src_features/signTx/cmd_signTx.c @@ -41,11 +41,14 @@ void handleSign(uint8_t p1, tmpContent.txContent.dataPresent = false; dataContext.tokenContext.pluginStatus = ETH_PLUGIN_RESULT_UNAVAILABLE; + initTx(&txContext, &global_sha3, &tmpContent.txContent, customProcessor, NULL); + // EIP 2718: TransactionType might be present before the TransactionPayload. uint8_t txType = *workBuffer; if (txType >= MIN_TX_TYPE && txType <= MAX_TX_TYPE) { // Enumerate through all supported txTypes here... if (txType == EIP2930 || txType == EIP1559) { + cx_hash((cx_hash_t *) &global_sha3, 0, workBuffer, 1, NULL, 0); txContext.txType = txType; workBuffer++; dataLength--; @@ -56,7 +59,6 @@ void handleSign(uint8_t p1, } else { txContext.txType = LEGACY; } - initTx(&txContext, &global_sha3, &tmpContent.txContent, customProcessor, NULL); } else if (p1 != P1_MORE) { THROW(0x6B00); } From 8d24d911176f0633b0ff3742ebdd890a0ca84476 Mon Sep 17 00:00:00 2001 From: pscott Date: Tue, 3 Aug 2021 12:08:43 +0200 Subject: [PATCH 17/26] Bump version 1.8.9-rc1 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 93bd78d..71c3caa 100755 --- a/Makefile +++ b/Makefile @@ -30,8 +30,8 @@ APP_LOAD_PARAMS += --path "1517992542'/1101353413'" APPVERSION_M=1 APPVERSION_N=8 -APPVERSION_P=8 -APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) +APPVERSION_P=9 +APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-rc1 APP_LOAD_FLAGS= --appFlags 0x240 --dep Ethereum:$(APPVERSION) ifeq ($(CHAIN),) From 087af9c0fe2e137047aeac4a9233a9048f837ef9 Mon Sep 17 00:00:00 2001 From: pscott Date: Tue, 3 Aug 2021 12:09:42 +0200 Subject: [PATCH 18/26] Add EIP1559 to changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e3da2a..56ad1db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [1.8.9](https://github.com/ledgerhq/app-ethereum/compare/1.8.8...1.8.0) - 2021-8-03 + +### Added + +- Added support for EIP-1559 and EIP-2930 style transactions. + ## [1.8.8](https://github.com/ledgerhq/app-ethereum/compare/1.8.7...1.8.8) - 2021-7-21 ### Added From 2e4ddb8d691a96accb75ab7b246946d644fe5996 Mon Sep 17 00:00:00 2001 From: pscott Date: Tue, 3 Aug 2021 12:14:05 +0200 Subject: [PATCH 19/26] Update plugin sdk --- ethereum-plugin-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum-plugin-sdk b/ethereum-plugin-sdk index b5325d0..51c4cad 160000 --- a/ethereum-plugin-sdk +++ b/ethereum-plugin-sdk @@ -1 +1 @@ -Subproject commit b5325d0f08af7f233e22d766183fb70cdb8ead59 +Subproject commit 51c4cad6297a99a220eb09e6d30d229ac02d469c From f07a5941259f3d4605bb0dba8837af582421371e Mon Sep 17 00:00:00 2001 From: pscott Date: Tue, 3 Aug 2021 12:27:09 +0200 Subject: [PATCH 20/26] bump to 1.9.0 --- CHANGELOG.md | 2 +- Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56ad1db..7936fb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [1.8.9](https://github.com/ledgerhq/app-ethereum/compare/1.8.8...1.8.0) - 2021-8-03 +## [1.9.0](https://github.com/ledgerhq/app-ethereum/compare/1.8.8...1.9.0) - 2021-8-03 ### Added diff --git a/Makefile b/Makefile index 71c3caa..226baf4 100755 --- a/Makefile +++ b/Makefile @@ -29,8 +29,8 @@ APP_LOAD_PARAMS += --path "45'" APP_LOAD_PARAMS += --path "1517992542'/1101353413'" APPVERSION_M=1 -APPVERSION_N=8 -APPVERSION_P=9 +APPVERSION_N=9 +APPVERSION_P=0 APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-rc1 APP_LOAD_FLAGS= --appFlags 0x240 --dep Ethereum:$(APPVERSION) From 448ef70ab1a5835a418743702df4732b9601021f Mon Sep 17 00:00:00 2001 From: pscott Date: Wed, 4 Aug 2021 17:00:12 +0200 Subject: [PATCH 21/26] Fix approval test --- tests/snapshots/approve/nanos/review.png | Bin 544 -> 541 bytes tests/snapshots/approve/nanox/review.png | Bin 627 -> 633 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/snapshots/approve/nanos/review.png b/tests/snapshots/approve/nanos/review.png index a99bc5a34cf591709351905b31000f355ca7adfc..2994983f84cf76ab587bac356d5afe297c0e0632 100644 GIT binary patch delta 515 zcmZ3$GM8n7O8pa07srqa#d-)aI=}p;W5$U)Q+aq#{F%nX%RY0z5>Pd}q|}5;b@6vA zA9@3Y{yVj`IX>$@dBNbsoX&f0~If9 z1ggET!KS00hgUvV=ed&eVSlDmwk9$u`>qrKHLYNrIp6Hv+J|0;Ke0$n`03%Wb9&qT zNtM~WCv29orPv7vyjz>7^!Yr{el6Y;dyE*L-Zb?|$&g3^x)SJHBj>{k#Xu$x?|v1a zJApi7U;xQIJ)}JW=;_WgU~U^*3fs)inll#+OcabW9iDmf0@a`3F#>AnFL)Sha%TzS z%!Lnq%MG3VehCL@zM7hA(G6-@XUbT}RuSZ!_EMkYK)?QP9xTtFcp u$*FNVGgoK%wvBUc9V^O`KD`pi`Nlhc*G1Qt@+-X=fWXt$&t;ucLK6VfBiuv) delta 518 zcmbQsvVdiRO8s+B7srqa#My! zD$|Ms*YCI#x?W}Doc4yIt75TVy@XC%=G0u&o)#<^aL@5@-h0O(aJ26pncg;_mt|+B@A{x8HQ{EaLt2(YTK%M%QWG58*iy<;K)Qe;%Nb|x z21-wyDK+oyp`z6f6Q$x#9xIy9W5lo6d`A05gx}jkyC*D6oa6}htSOICx#=AcUs8%~ zrYy+rg%3kHG)`yc>MY;3an7w{MOo6PR{}ZTxcQEp58QWiJ|6=Rc)I$ztaD0e0s!HO B=DYv^ diff --git a/tests/snapshots/approve/nanox/review.png b/tests/snapshots/approve/nanox/review.png index bc99f6190d36ae1e877cae6492a622dbe767e7c9..8794afe436a71131138e8f80fe7d0d4eca0eb076 100644 GIT binary patch delta 543 zcmey&@{?tPN|1x6i(^OyXBcn zD|^AF30?OCBTq8U(OHxfv~%^0kTAoD38%ufw54gwZcjm)VWvwkexbJ=D^7&t#=_Hf!mwdZeK!0LR$NZ8PxNE7Cv3B z6=E0Jdg`t*GEnl6=Jy3N3=XkYyGo>+<_|tb_UM`DzFCmAPC6TTE;bX zH`mnnAuD`DwI-hmS@_9IZqLlF`6~iuYMDvwQ52nOzjP7Mutl3T9druO+Va#`lCxWbscO9iCeiQV?#$*_oruUN4oWY4M{(jj+3LqcM--T~pgMz5nLKLSLx zv?hBU4O#eUvMr-z{r=UDE{CkRV_Q+IHN7ibYrpr?%PaOs)o@Jhs$UcoxbRc{ijWmC zAzC5#t~T>84KiH$M{8=A=hI->11GnwIk;^L3i`Hx#SE=|-3QrM{a7DTvx)t_$I&H4 zD`$i(>$0BeeH7?Vp#G3MD}6-QYw2mN*HW9>Wt}kf{hNd4feVYm7aE1G@X-ox?ec0p zHTTpKqfj59w?wt#R|f11o~gBOH#_&LAHiDpP9_9uY1KD%owAn5@vi>hyCTF#OA8p% x>sNt;a;g`|${j22tOSZr? Date: Wed, 4 Aug 2021 17:41:06 +0200 Subject: [PATCH 22/26] Update eip1559 test --- tests/snapshots/eip1559/nanos/address_1.png | Bin 809 -> 724 bytes tests/snapshots/eip1559/nanos/address_2.png | Bin 837 -> 727 bytes tests/snapshots/eip1559/nanos/address_3.png | Bin 567 -> 544 bytes tests/snapshots/eip1559/nanos/amount.png | Bin 0 -> 414 bytes tests/snapshots/eip1559/nanos/amount_1.png | Bin 474 -> 0 bytes tests/snapshots/eip1559/nanos/amount_2.png | Bin 759 -> 0 bytes tests/snapshots/eip1559/nanos/amount_3.png | Bin 479 -> 0 bytes tests/snapshots/eip1559/nanos/fees.png | Bin 561 -> 536 bytes tests/snapshots/eip1559/nanox/address.png | Bin 1292 -> 1102 bytes tests/snapshots/eip1559/nanox/amount.png | Bin 860 -> 514 bytes tests/snapshots/eip1559/nanox/fees.png | Bin 685 -> 659 bytes tests/src/eip1559.test.js | 44 +++++++------------- 12 files changed, 15 insertions(+), 29 deletions(-) create mode 100644 tests/snapshots/eip1559/nanos/amount.png delete mode 100644 tests/snapshots/eip1559/nanos/amount_1.png delete mode 100644 tests/snapshots/eip1559/nanos/amount_2.png delete mode 100644 tests/snapshots/eip1559/nanos/amount_3.png diff --git a/tests/snapshots/eip1559/nanos/address_1.png b/tests/snapshots/eip1559/nanos/address_1.png index f979f716022e2492f86f9dcc9ba56e7622cefd3e..54bb773b34b38cb33bd849717935e6c229d6bd1b 100644 GIT binary patch literal 724 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfh&bba4!+V0?S{uVL2>G+bBEczgQS8wM9?v{*R`3O`WQJMRxvgKQ=j!_*5B={zSeN&ih-$uv8hhVGPabqw$?MEGtEsE zKJPc-F`CT7d*aTiV{3uZCoX(Ymde<1sbJ~DXsHR2Cls6y+gcX#OV!N*s$U4SC@sU` z*~Q#D%#tY+c5+Hei5Z#L>=NF7rQwWI8(YeRg%5p=OlrD#cqgB^U~m#dfrQIU6*gzg z0NI=8>97;1_8~9ti9e!1+{Konmm8Di@a#hZ(ETb4_5e-)a6oE8<;IVT7-t@Cp1knk z(PP|_QhfaD7-x!0uRnRApdtY1WwixBO=%YmPSkiEc6t`e%RO^tqT=UdpmTx`JEdhs zobUk(m4o~W^yrlh6J|KDbc>h|)nfrl` zcV#x}W=jzRhHMD4(e{!@)+rehDSZFu^&Sqs{i6>QR*4rssPgWXs`CZLSuBvTZ%JY} zkhxwcz;1CO$jOpYKoaC7U|d4I0tr-T*j@m649UyDK!=MwQ)W8#Ff&(X-mPN~S0YjM YRzJ-wTc@vh4NR>Jp00i_>zopr0H6ao#sB~S literal 809 zcmXAoe@GKy7{|9(n~5hP67E%TxlI3%nCJX45Or=&tu&RQiKdN?buLSBQL_Z+{y3DG zY?{iUh`Q9wa0@{cM3O;Vb=jO)DH9u$bQ|Tj}*;XgammwB9|D81-LZ`XFR^n$fF;SI`v$~Bw#9iRXBdhZ99sk z8`td4mwb9bhHPRif?hDQUYA`V<=)BC+XvR2WdHhQH%(=F&8$W! zMzihGN~OCp&ZyB>K|(3A9qk4;oWdE&K?p9d1`WGy=_LX@LX2!min2l=M2slbD{MUb5t%PAS0uT7^VLjsV|_GCBElca4UkexH1riZL?{w_s8D zhPh}VMWu?qg17w-P`Ca1BSD&uhCu^u-mehg4xN2^R41JPWs5RGq$;lUv|0~4VA#RtV2sDi0w4xX;L}5VF-pN5>w{FKA#Ksj z(n4Y$PT<%Aoev$v98_+>(id8Y3Br!Sz#gK4J6t=cyPQhMiQAOXUrtXmk-?m1hO!Wp) dMc)c+e?_|s$wq~xc@nMwFF&VHJ)V8j@(=l|VF&;K diff --git a/tests/snapshots/eip1559/nanos/address_2.png b/tests/snapshots/eip1559/nanos/address_2.png index 93c90c542343a4423166f143ee5f43f335c73b96..21eac94e3f0922d047db08bc1a9766a1b7464fb0 100644 GIT binary patch literal 727 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfh&Yba4!+V0?QpFi**o!R6p| z-RFP#=g3>G*fJ&NSnt8zaT1pWAIaNJJo0es3iUZJmZ(p%*u%&8bcwFj%T5)(^@)$? z&MT;qYt~TZ-M)hBN)y4rv)PQuIs|oDZuQn<{+v$hT=`O93iauL$IV&|2^R zVJ66&Kr^|uj58hE+T<@f9Bysn<}J^3NXv3aQ*7qpJ^!RP{lbUGDS9V(cu(*cIWrr@ zXE{8}-};d!WrE`~#gvSQ6Bi0XnT_g=8J`A9P1tz>Y{5(^F_6;kHcyb#+uA&zIWYrW z<IRYt)FGeX0{Z*{SnMY z>C)-ECuHg@C8f@polD8E_*2AtVovTJb?3tmrvqJL%lLFL8!&KmAl?J|ZB?RTap+;E zXL-EbGgkxM5q#JwEi2+g%+(DOeog}hsZc=PMS~MD84^HUJVxf35-E9?3{KQUA66)y z+~)Yq2}mzYoUqgLu)^oydpp|C=*^5Z+AXCv(=ja^7_2AWWPv@DHsR(~gOfZ)yHm$=cz4*dORVpi@C12zEKhHekE~?E?B|W#S}Bpi>qm0%IN& xzhIyFz$8FAz!4uW7{I5W4YLSp--k>87`Qx)LV8x^?g1uP22WQ%mvv4FO#qscFB1R& literal 837 zcmXAo4M-DV7{_;A%@R)~MB5oQ6F(yHVLVt$ZA=)^QU zBa$mqOLSqW0}B(ikSSa-LTA~M^?~9*LQSM{U?0zWaUbu!FYohz{?G4uuQ5L_n+PNW zB@zjt%~2P?XoE+-Qws0-{S~ni2_B?XXBJwqm5I{@W!f;+L`=i;zdOFE7GI3q(@a%%ggCfQn@u^+iip^<%vKAXE_sg2^OTwK8cYgpA)QlwvHdYYcoX z2bgK!RAU5Mt$@`d>q?fj?;F7Qi1_QVD(7qn&>7r*=L5+dHSVGAOCb#lr3w}pAa_-p zlo_~48)j3Oa(4=Ih)@|!9sq;O08x*=RR=>ZP7Ur#7=~;jQXTRs>{ZCq#E)j6REz_9 zh=eA{H+q2|PIY6bIx&VnoGuofiBqpCec?p6Uhv)k^ddd4^G&t%9 zY-k2o(470o9Kb|1c*OH30!6??u5JhP6bM<+K|&{NI5fW_YOc}VaBX4v;R9>6F}@>e b9;QD-q}la_C0C<6;P;SdHF@d*Woi9CJYZeG diff --git a/tests/snapshots/eip1559/nanos/address_3.png b/tests/snapshots/eip1559/nanos/address_3.png index 402c20d84b73864383ebc9f5a2cc87b175f5db3a..4baa24f1db931a6dd3de32ed9a8ac67dae78bde4 100644 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfcy%ba4!+V0?SfyXdw9gY!Z5 zX$Ak8lN&cITcjCWWY=vm>Euf>`%?AJr%_jAt>5mNe56R0>C`&iTOc7RGrJdkPlH&d zlwW8#lW(fDbn$f6?LaiO8J`9+8=Y2{n(z~Z^?^cLKCWP#`7|XZqe5lD9aDwPb0V0H%B9PBPw1$tJ0HG# zY%UM)>64}k#oIql1hPDVfitn;6G)5W;l?xDFE*S}W=#FLxy|vJPu?8Y!z#umKA>QO zQ77h{?KKA3&p5Lg=qZrz9iDNSP4m7Tp_iNdvzj+udBGerB5%- m)tSC+W6Z5%MVUa(UxuqEuX(?*T)zPr^9-J@elF{r5}E*nW84=2 delta 542 zcmZ3$vYlmuO8q}i7srqa#5-MRavChU~y;ofWDvJJbB^6yoY{mZKn^KDim-3FqMaQ zdNa@zZN{g8%trF78G+s@1G;2lW&NteNk2JwPuN6Nx;?v)GH=pPWl-Sc`#+mGRT<)* zXY);bjNCVUdI@yl#FvS+xHer0Av8;>so5O})! KxvX}o!hf34QCcU z1QI|=`H7aM3e7ycCt}V%$da01dE&x`n!LwdQq$^_A9tnr@t%Hewr&aIOmQO*mxf>GDejlYUNYo0)s3^NjrD%8Le*4;pO+qF(Dv ti<5tXjZ9=x-Z?o$E;Ef-W`=~maWAm$h-~?4p9~Cl22WQ%mvv4FO#qnAt;GNU literal 0 HcmV?d00001 diff --git a/tests/snapshots/eip1559/nanos/amount_1.png b/tests/snapshots/eip1559/nanos/amount_1.png deleted file mode 100644 index 4cd3e38bacb6946307a7e132d42d79b6a8ebee6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 474 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfcCkba4!+V0?QpFmH|ngUi9| z9sB+_{$AW1P?mCS+mi@SvBM#q_jgS^QlkH=t=H_XN762S#?;GVxga5a?);L&CE84< zBux}PE1M`7o4iT6m+8>f=9re@@GMm9+yX{PDZj-Jy`?7n3}800mQ0zj@S#rFxit?V zY9vzH*g&X^m)&T0TkK)KXTe7HH&5L>$-{f%jTA&~p9|0|Hc6=omCG4t=4akG$zuex zjEj5ywT3f(ZEfB_i$K!nlAiKNExR6J$vksm;;;I!xRs1EnSr`~8c9mA&1`Oi>s-l} z!Uq&t$T%}xFkqgkf^qF4#+mzpxPBeu%yjPaQWIwCxwW;WGo5l~HoDwus_=QkhYJm7 zN(zlkY;E4uAX2Cbdh_u!?T;G+*9 diff --git a/tests/snapshots/eip1559/nanos/amount_2.png b/tests/snapshots/eip1559/nanos/amount_2.png deleted file mode 100644 index 11ae75e8391d69f363be24e20c136f0ee32b13d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 759 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfi@&ba4!+V0?Qp&`&v1#O2^* z)#v}j=g8l@cDdkcYoY6pnS>%$F{b` zI|@>Gt&L20W?nQ%abpIlU7F~gmKh->HuL_gLl;l>u%%3EyV!6h!{M18P*ySp$N;L7 zzqH{5k0j70KI!{w8E3k-waKq!oC#Fd$75t7bF@`C)bY?cP=5SXJ5Ka6+Wjt_GC6%9`D!IrY`NDl40?;i1&oe%^$OQc$deoVw}03 zQ{y~P)v7kvXQ8~^XMn+A4Ww2}O}GiP)$MTKnG6sG-b{T(V_>|+T?K~mnM)fkf6z1XW;Sw81BOR1&|&@D?$YFcvsLlQ$7&?QRF zAYZnfnGM9i5S+g#@x&fi2TR*Ey_cPDTi9+vP`{bucKb|_So<*tn4lRvUHx3vIVCg! E0D4U}bN~PV diff --git a/tests/snapshots/eip1559/nanos/amount_3.png b/tests/snapshots/eip1559/nanos/amount_3.png deleted file mode 100644 index e0420108494b969f9c050ba46e44f5c255fa1f1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 479 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfcCjba4!+V0?Qpu2D;LWW?VAh6@j^#SRf&uFm zFwXq%#B9{w=J;$fTS|sRN*i0sz0}8CQWF+FG?Loq!X}xLVUg+ZOre>_$Ry@yvv#({ z#D$3yB&FD9E@T8D=fj<67CyXCFk$Cv_HcD$6NTao2`Qlbgr7n{X`pTgkimXZd`A1P z6ifi~WzFubWt`c}!~0(r$Oo#noaorrwz{H#mG^YD%?_rS3lo2q%k2qfHc~e-QTUu{ zWWr;l&bxo2L{A6 zpc$$Q&a7aZ=`S^5=FwwDTiG{fTAa{P0E+>AleTGN&Gm*eIc8!R4ry-uX+WpU0lIOs tK)|%jT%F+C5zDr1^vO-0c?+mDU$Ss>;+dSqdccTd@O1TaS?83{1OS_=#2f$s diff --git a/tests/snapshots/eip1559/nanos/fees.png b/tests/snapshots/eip1559/nanos/fees.png index 8b996b58a1ec0043e05a39e52d99ce49521f5116..5512e8a2199b8d4bd1e3b58cfe135b88ddbfe566 100644 GIT binary patch literal 536 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfiWtba4!+V0?QpFz>bpgUi9| zEWiJ;zw75Sj5J=f!7-!B;c&a{e zVd8{Jue6LGMl+YE%$roHU~HoB`JLFh1&op@85Nw8Qupqjx@l6Q4YHw`hu3=M!bJ7Y z?^vc(^PccgztnJMZ!4Ik?0k4{Ycxnq)%oz+R(=pm-T82PE5DJ6k2=sz?XA%u*42hH zx{Ocbn2q$W767fX0lEd`%4hbb3dI*7US$Wm((y2uyC;U(=zG|_i9h2{fK~n!qE zX~BgmHD{)aty{)8^X2xb<(D>0{yC-1KieVgSMt-jCu(K_jr~%|9e&ZkfLoC^vkzqU5VG@uU@KI^eedAUh!nRoOIz1+lITUuXU d0&;${=Ev__*(Gr1Ffhg$JYD@<);T3K0RUH=-2?yt delta 536 zcmbQivXNziO8pN{7srqa#jcMVZ9GQr z9~@E7+~M8U=J;&7R9Q+}+it0MSq{%+=TxX0neZ5upXA}auU0($OstW4N*f!I5nJYi;Cwm>1-Y zxoj!#vLsUKRwhoknF;an%EU=C!A|vjcHC5<`0Wu}qxzmRVAcQEfc-Abdx8fI83i*N zHJ`a+aI)Tq_rxEKnbl^~oUK3R@J>FHpIKqed*Thyv*(K*-Avi%o3{L6s)@qqXpn#B zB_>zSVN1ya^1IBY9nWxhc6Uz2wl>da3sW*AQkJo$ut@^rz!MmJX_FR$oH!%pU+7_# w&pJ$}iXx;>FU-|x-?mZa*0G`tAm=aZo{l4er(5S9^thYBWz%(9Q*6||rGlfW)@C&ZBn zw-Nxj9Y=GuIlwQ5?Ele_b{OG8C_`nr_3$I%pDxIGmrB!Q#>jR~z}^A&MKV>miugV1w9>Ni1O-eiwKz z329J65kQ>K@30N}%rmxFXoubCDzE|tV5?zILVUH}PXAMp^O$d+2oT$GKC?-Mx(KF%X4CuB<+Q`^CYX%ZYN3QgeFRgqBDFyhdrnvB{7I7i z?B+FiNMGg|`MgONYJ)u#oywp-i6V5HScOP=FU1y~O6IoqoSB{WTm2y1f)Jx|$^RV0 zwajlG0Ua=3lp~o=|E;@q4Fp3s@-DG@=m?c%yLBX>AN~Wjp!H_} literal 1292 zcmZuxe@q)y9PdQOJiD3waYH1Ve@tESFd?l576K7k8fb0cdVL4OG-$e9&}29P6&lD` z&@w$zk>Ev02=qn^cWuW6bfX(Mx8*RNi5Q7S*c4N9CR-H3X_(?fzps@T6PxSxy?d|U z_xbg`x0ve6z0|{$$z`>vm__J(e_?lE0G zAi0bGdZ+lnxBEWNGVl2`{%6UJXQyvpE4Wzn-e|aC?{wb8^_8OsR~Bx4QP|*isOuQt^m>}Nu7q+}3pf1Hn)V>OQKgpB zh<;sTrr2Cmi|ndPr%%kiDa;FspIMGSgx8c~oEeb?2VdjRIbXm66AXWR688v7s$VGQ zIg32k9m?@~Hjc>fF{3znxIq;*l&O)kR!%NCYwSns9?!DZ6L>7=`-P_`{Y*WSg{pk) zm|_M1F@MyG6Hrpr@@Gv&)n`6zF8(02BsC51Yx?1p7xE_TmyI`sa=nz!7r7v8XNS<^ zBBzF}TmnEcfrt%oC~kUya2Z0oMTJy!qYfJ2l!}#;b7MAMW&(X0VT=YeELmkYjqE`e zK`}d#YD1d{lM9av3fVhEhLot-qBcHiBtkW@LA3p-xCm7uHoa={ZZ<$@#AfsyCr!uF z5Bmit9~;EAG+LAg@%Fp63yOCEV$6*-R0lZB=`H$R6;N8TVlxfvjhx&G#2eJZXz`NaB*3)}Kzawuog$Rv*?LaC+eD)~z-shW{cTDt zkNTNFjT*6HIe`&Q>lHDIWI#ONQp3g}5qwIc9dHFTSJbBWQ{wysFCX_vEn5LNKd+Y( zmlh-J)XHzL`0I><-Fa7JJbdZ`CBArEVw<;yU>6vA>;1{jGBpe$kj#vO2#|>c9M~r_ z$qC|&Tr!sN+zV>U-*}b5^fowsq*(_xAVOLOX2%r`MnLVNFi(k+O>aZEhYZrTtU;3C zWboL=GcfqBRlgs!3L6C=`na&FFiLx^8Zo@SKsPX(!4L-$6$O~b0i4X_B4VtclZ^eK zq*@0-Sv?18Er6E%tVM^>kn;5P&P`P1Q%wm(3dM*iB{F0FcRPCS*4V_Zc zqN@M`GKfY!(sUj4@pOJR&b$ly02(@fTid1F9BX+h-GC{QA<57F{)8wvqkcBP|33!U b{Kq5wVK(&fFDI_STh8QkR98&ep6~t}Ay>Eakt!T9#z!Q49m0;~uB zHJ^R*R6gjq)8qyYfo|IqoA}hySBb@MyBpPg@${{-H`nrRuiYw9tCNttJy$w=``c?# zJ#t;$xyLh78KoDmP1+LHbFE7{C{XhMx*d{JC!hN7{C_t1Y4>+T<|GY%X5d)G zCQWFWAMn#<>0)v7B}R4bg~D3PRa71>`4sEPFuuz>6P`9(ty_G5tcTXw^ z2;AAtn$xqb>td8)l(t*;(TuecYxh=gOkJ%a6LL@W;etsm+EZ0(76EM!-cvC_WsmnE zM^#SyrIT8ky@cj10I3z28Z5NWdFf_x{z)zSrvjDxK@77C*r_ZkI`#fE7SX9HcY05$ zbKlqz;CZM*ZmLR*sJND=#Q7;KQ&&Ig_7Xa_8R)@~8qcOv6=qXa=5%$dtmsJ(@;r2v r$;>Sp>>|;{TOpx_>`c-H|1p?eKRYLH)yE6KxMlEk^>bP0l+XkK`wrXi literal 860 zcmYjQTSydP6dp4y7PY4}P4h)+;nyzf%X%Tp(M4BnFXKN7YAJ(@1Zt_6E{U49fg5VE zj3jtryfwQk(poJ_nh34oJQ^5Yve+D{2a{a`lT16~lJzkEz&YRf&v(A_{cU<}Mu_Z; zj39^*O=da;|7Q5EoeY9=VX>)+AOd4F>8ZFrU~~3m(OMCrIK87P&rWPk zUK!WAhI`AilTD;tzH+d&K96(cSJi6wi%BnuFbZNV8l(Lw99lx+yTDUy#dTFh=rC3?0oO*7FWjW6iXi`mcK1=0P z0-J%-%z^;4Kh{^ttwIJK^~^oW-Hl@%mi)gLB%_;Z7(zg6HALM-gk2wUx$4?#12;Ym z{2kU}DKtVUd-nz?=d?@4ep@GpnS0meDF4KrvckpoOMEzPe8%XzVP1zNRjfmJ48*W` zvW)g{P(vfy8LAs1ko4;VGEGn>oms$2Tf^ISon2BZnuaM+tAM$9%;P<+8|JlSpiYDz z%2+7;hei$?b?Bh z!%svsm<3o!-K4kE25p<5Zx!uLhM`cJn|7B;T&&W*&O)tc?o^%!ba4!+V0?S9u~*uhf#IO7 z)7+f@s=2yd9e)(XAKL$8=~L{UWBH??-lDHLSNHhe#`eb#{}srv-?rj=aPIKmy5|); z>}8H0+}3vR=-E(KKWl~V!Os!>Io~|J2 zz{*hbdk#m#L$tKirq(YiT4fO$6FNt0Uy$L-J&UCE{gysj5>&WqM#!?R|IMdDk9t0x z>2-9a)6=Uwb;6?mU5_p?3ay!bDmn{R1vSOK0=!%%o6@NThfmSRj3N>6A19Wb<=wuN0lUCjy zfvM?Q!L6sx2Yg)Pl)5TlrdG%@uBj{0n3b%}M?+TR)bIM}q~)h|Kk#F$sMhUxkmh>t zr>l~F?>ndj^mf(1zarr0RiNVile~cT2CbYC;->|))pKc5kmbq{ zAFcgSt*16K?D0bHFedDkb8?iP3-ClKDuO)QK*mT?84|K5^y56PspkV$uCQ3?qa`Y; zJ{9Par=qe4=H^B==Vl@!^LZ;kj;!!bT@|o%RY0Zx(Ir3^dOls16tolQUO%ATV2GzG zr%C%S`!wxT$ih#{wL+G0P2CPAS2_W8&IB_(pN1?nS~*9{PYdY0bcr1A-5*nc`p>WU zk*5{1PD^cS`p%CjTK}h=3O%}dMZiyi@z=OFm5v0qO~EJ+&mraOE5jd$QNjB}Kr{|2Y>J3iWH9o~~uyQ5?8%(_b4=t?=e< zuBmU+gI4a4`V#~c$^iz_L47UJ+vmd;7D>gd2+6Sr8g-TN&dq72H>R1<0DTiTY;kjq U6a97!m<$;_UHx3vIVCg!0AW%^y8r+H diff --git a/tests/src/eip1559.test.js b/tests/src/eip1559.test.js index 78009d8..d102d3c 100644 --- a/tests/src/eip1559.test.js +++ b/tests/src/eip1559.test.js @@ -9,7 +9,7 @@ import { expect } from "../jest"; const {NANOS_ELF_PATH, NANOX_ELF_PATH, sim_options_nanos, sim_options_nanox, TIMEOUT} = require("generic.js"); const ORIGINAL_SNAPSHOT_PATH_PREFIX = "snapshots/eip1559/"; -const SNAPSHOT_PATH_PREFIX = "snapshots/tmp/"; +const SNAPSHOT_PATH_PREFIX = "snapshots/eip1559/"; const ORIGINAL_SNAPSHOT_PATH_NANOS = ORIGINAL_SNAPSHOT_PATH_PREFIX + "nanos/"; const ORIGINAL_SNAPSHOT_PATH_NANOX = ORIGINAL_SNAPSHOT_PATH_PREFIX + "nanox/"; @@ -25,12 +25,12 @@ test("Transfer nanos eip1559", async () => { await sim.start(sim_options_nanos); let transport = await sim.getTransport(); - let buffer = Buffer.from("058000002c8000003c80000000000000000000000002f88d0101808207d0871000000000000094cccccccccccccccccccccccccccccccccccccccc80a4693c613900000000000000000000000000000000000000000000000000000000000000fac001a0659425c1533f84bacbc9e119863db012ea8e8d49ec9d0ef208254dd67f0bdfa5a043409e4e89855389fe8fafddd4c58616ff", "hex"); + + // From this test: https://github.com/ethereum/tests/blob/5d534e37b80e9310e8c7751f805ca481a451123e/GeneralStateTests/stEIP1559/outOfFunds.json#L35 + let buffer = Buffer.from("058000002c8000003c80000000000000000000000002f87001018502540be4008502540be40086246139ca800094cccccccccccccccccccccccccccccccccccccccc8000c001a0e07fb8a64ea3786c9a6649e54429e2786af3ea31c6d06165346678cf8ce44f9ba00e4a0526db1e905b7164a858fd5ebd2f1759e22e6955499448bd276a6aa62830", "hex"); // Send transaction let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer); - buffer = Buffer.from("cb3c99990c13e47cf362d63e012b9b", "hex"); - tx = transport.send(0xe0, 0x04, 0x80, 0x00, buffer); let filename; await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()); @@ -41,26 +41,12 @@ test("Transfer nanos eip1559", async () => { const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); expect(review).toEqual(expected_review); - // Amount 1/3 - filename = "amount_1.png"; + // Amount + filename = "amount.png"; await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); - const amount_1 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); - const expected_amount_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); - expect(amount_1).toEqual(expected_amount_1); - - // Amount 2/3 - filename = "amount_2.png"; - await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); - const amount_2 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); - const expected_amount_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); - expect(amount_2).toEqual(expected_amount_2); - - // Amount 3/3 - filename = "amount_3.png"; - await sim.clickRight(SNAPSHOT_PATH_NANOS + filename); - const amount_3 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); - const expected_amount_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); - expect(amount_3).toEqual(expected_amount_3); + const amount = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename); + const expected_amount = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename); + expect(amount).toEqual(expected_amount); // Address 1/3 filename = "address_1.png"; @@ -100,14 +86,13 @@ test("Transfer nanos eip1559", async () => { await sim.clickBoth(); await expect(tx).resolves.toEqual( - Buffer.from([ 38, 111, 56, 157, 21, 50, 15, 5, 1, 56, 53, 38, 237, 3, 222, 145, 124, 20, 33, 39, 22, 240, 154, 38, 45, 188, 152, 67, 16, 134, 165, 219, 73, 13, 201, 148, 183, 185, 114, 48, 187, 53, 253, 246, 254, 194, 244, 216, 255, 76, 251, 139, 254, 178, 166, 82, 195, 100, 199, 56, 255, 3, 60, 5, 221, 144, 0]) - ); + Buffer.from([1, 61, 109, 250, 188, 108, 82, 55, 75, 250, 52, 203, 44, 67, 56, 86, 160, 188, 217, 72, 72, 112, 221, 27, 80, 36, 159, 113, 100, 165, 252, 224, 82, 5, 72, 167, 116, 221, 11, 99, 147, 13, 131, 203, 46, 26, 131, 111, 227, 239, 36, 68, 78, 139, 117, 139, 0, 88, 93, 154, 7, 108, 14, 152, 168, 144, 0])); } finally { await sim.close(); } }); -test.skip("Transfer nanox", async () => { +test("Transfer nanox", async () => { jest.setTimeout(TIMEOUT); const sim = new Zemu(NANOX_ELF_PATH); @@ -115,7 +100,9 @@ test.skip("Transfer nanox", async () => { await sim.start(sim_options_nanox); let transport = await sim.getTransport(); - let buffer = Buffer.from("058000002C8000003C800000010000000000000000EB44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF6181880018080", "hex"); + + // From this test: https://github.com/ethereum/tests/blob/5d534e37b80e9310e8c7751f805ca481a451123e/GeneralStateTests/stEIP1559/outOfFunds.json#L35 + let buffer = Buffer.from("058000002c8000003c80000000000000000000000002f87001018502540be4008502540be40086246139ca800094cccccccccccccccccccccccccccccccccccccccc8000c001a0e07fb8a64ea3786c9a6649e54429e2786af3ea31c6d06165346678cf8ce44f9ba00e4a0526db1e905b7164a858fd5ebd2f1759e22e6955499448bd276a6aa62830", "hex"); // Send transaction let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer); @@ -160,8 +147,7 @@ test.skip("Transfer nanox", async () => { await sim.clickBoth(); await expect(tx).resolves.toEqual( - Buffer.from([ 38, 111, 56, 157, 21, 50, 15, 5, 1, 56, 53, 38, 237, 3, 222, 145, 124, 20, 33, 39, 22, 240, 154, 38, 45, 188, 152, 67, 16, 134, 165, 219, 73, 13, 201, 148, 183, 185, 114, 48, 187, 53, 253, 246, 254, 194, 244, 216, 255, 76, 251, 139, 254, 178, 166, 82, 195, 100, 199, 56, 255, 3, 60, 5, 221, 144, 0]) - ); + Buffer.from([1, 61, 109, 250, 188, 108, 82, 55, 75, 250, 52, 203, 44, 67, 56, 86, 160, 188, 217, 72, 72, 112, 221, 27, 80, 36, 159, 113, 100, 165, 252, 224, 82, 5, 72, 167, 116, 221, 11, 99, 147, 13, 131, 203, 46, 26, 131, 111, 227, 239, 36, 68, 78, 139, 117, 139, 0, 88, 93, 154, 7, 108, 14, 152, 168, 144, 0])); } finally { await sim.close(); } From d04dcd8dc68e42c7400751684197821308f5a68a Mon Sep 17 00:00:00 2001 From: pscott Date: Wed, 4 Aug 2021 17:42:09 +0200 Subject: [PATCH 23/26] Add printf for txtype; Fix txtype init --- src_common/ethUstream.c | 3 --- src_features/signTx/cmd_signTx.c | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src_common/ethUstream.c b/src_common/ethUstream.c index a67ec71..fc091cc 100644 --- a/src_common/ethUstream.c +++ b/src_common/ethUstream.c @@ -31,10 +31,7 @@ void initTx(txContext_t *context, txContent_t *content, ustreamProcess_t customProcessor, void *extra) { - uint8_t save = context->txType; - memset(context, 0, sizeof(txContext_t)); - context->txType = save; context->sha3 = sha3; context->content = content; context->customProcessor = customProcessor; diff --git a/src_features/signTx/cmd_signTx.c b/src_features/signTx/cmd_signTx.c index 7e64235..4e4fdbe 100644 --- a/src_features/signTx/cmd_signTx.c +++ b/src_features/signTx/cmd_signTx.c @@ -59,6 +59,7 @@ void handleSign(uint8_t p1, } else { txContext.txType = LEGACY; } + PRINTF("TxType: %d\n", txContext.txType); } else if (p1 != P1_MORE) { THROW(0x6B00); } From 51244a6b8ae88968bd631cc81ee391962c2cf665 Mon Sep 17 00:00:00 2001 From: pscott Date: Wed, 4 Aug 2021 17:56:30 +0200 Subject: [PATCH 24/26] rc2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 226baf4..8a3e747 100755 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ APP_LOAD_PARAMS += --path "1517992542'/1101353413'" APPVERSION_M=1 APPVERSION_N=9 APPVERSION_P=0 -APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-rc1 +APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-rc2 APP_LOAD_FLAGS= --appFlags 0x240 --dep Ethereum:$(APPVERSION) ifeq ($(CHAIN),) From e301ff1b8365d7084746cf5d69782953fd293737 Mon Sep 17 00:00:00 2001 From: pscott <30843220+pscott@users.noreply.github.com> Date: Wed, 4 Aug 2021 19:12:16 +0200 Subject: [PATCH 25/26] Remove update of plugin.asc --- doc/ethapp_plugins.asc | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/ethapp_plugins.asc b/doc/ethapp_plugins.asc index 33b079d..e1233fa 100644 --- a/doc/ethapp_plugins.asc +++ b/doc/ethapp_plugins.asc @@ -3,8 +3,6 @@ Ethereum application Plugins : Technical Specifications Ledger Firmware Team Specification version 1.0 - 24th of September 2020 -## 2.0 - - Add field in pluginSharedRO, breaking change. ## 1.0 - Initial release From 12ebced7bf65f0aa808f3afec73aa40ad80aeff9 Mon Sep 17 00:00:00 2001 From: pscott Date: Thu, 5 Aug 2021 10:42:43 +0200 Subject: [PATCH 26/26] Update to 1.9.0 --- CHANGELOG.md | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7936fb3..0ba57b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [1.9.0](https://github.com/ledgerhq/app-ethereum/compare/1.8.8...1.9.0) - 2021-8-03 +## [1.9.0](https://github.com/ledgerhq/app-ethereum/compare/1.8.8...1.9.0) - 2021-8-05 ### Added diff --git a/Makefile b/Makefile index 8a3e747..0dcbd5a 100755 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ APP_LOAD_PARAMS += --path "1517992542'/1101353413'" APPVERSION_M=1 APPVERSION_N=9 APPVERSION_P=0 -APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-rc2 +APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) APP_LOAD_FLAGS= --appFlags 0x240 --dep Ethereum:$(APPVERSION) ifeq ($(CHAIN),)