From df4fe3c0dd001292a84f1d80708e7a1ba40558ba Mon Sep 17 00:00:00 2001 From: pscott Date: Thu, 10 Jun 2021 17:17:47 +0200 Subject: [PATCH] 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 {