Merge pull request #117 from LedgerHQ/format-and-basic-CI
Add clang-format and basic CI
This commit is contained in:
20
.clang-format
Normal file
20
.clang-format
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
BasedOnStyle: Google
|
||||
IndentWidth: 4
|
||||
---
|
||||
Language: Cpp
|
||||
ColumnLimit: 100
|
||||
PointerAlignment: Right
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
SortIncludes: false
|
||||
SpaceAfterCStyleCast: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
---
|
||||
36
.github/workflows/ci-workflow.yml
vendored
Normal file
36
.github/workflows/ci-workflow.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Compilation & tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
job_build_debug:
|
||||
name: Build debug
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: docker://ledgerhq/ledger-app-builder:1.6.1-2
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build an altcoin
|
||||
run: |
|
||||
make DEBUG=1 CHAIN=ethereum_classic
|
||||
|
||||
- name: Upload altcoin binary
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ethereum-classic-app-debug
|
||||
path: bin
|
||||
|
||||
- name: Build Ethereum
|
||||
run: |
|
||||
make clean
|
||||
make DEBUG=1
|
||||
|
||||
- name: Upload app binary
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ethereum-app-debug
|
||||
path: bin
|
||||
19
.github/workflows/lint-workflow.yml
vendored
Normal file
19
.github/workflows/lint-workflow.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Code style check
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
job_lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Lint
|
||||
uses: DoozyX/clang-format-lint-action@v0.11
|
||||
with:
|
||||
source: "./"
|
||||
extensions: "h,c"
|
||||
clangFormatVersion: 10
|
||||
@@ -1,76 +1,135 @@
|
||||
#include "shared_context.h"
|
||||
|
||||
#define APP_FLAG_DATA_ALLOWED 0x01
|
||||
#define APP_FLAG_DATA_ALLOWED 0x01
|
||||
#define APP_FLAG_EXTERNAL_TOKEN_NEEDED 0x02
|
||||
#define APP_FLAG_STARKWARE 0x04
|
||||
#define APP_FLAG_STARKWARE_V2 0x08
|
||||
#define APP_FLAG_STARKWARE 0x04
|
||||
#define APP_FLAG_STARKWARE_V2 0x08
|
||||
|
||||
#define CLA 0xE0
|
||||
#define INS_GET_PUBLIC_KEY 0x02
|
||||
#define INS_SIGN 0x04
|
||||
#define INS_GET_APP_CONFIGURATION 0x06
|
||||
#define INS_SIGN_PERSONAL_MESSAGE 0x08
|
||||
#define CLA 0xE0
|
||||
#define INS_GET_PUBLIC_KEY 0x02
|
||||
#define INS_SIGN 0x04
|
||||
#define INS_GET_APP_CONFIGURATION 0x06
|
||||
#define INS_SIGN_PERSONAL_MESSAGE 0x08
|
||||
#define INS_PROVIDE_ERC20_TOKEN_INFORMATION 0x0A
|
||||
#define INS_SIGN_EIP_712_MESSAGE 0x0C
|
||||
#define INS_GET_ETH2_PUBLIC_KEY 0x0E
|
||||
#define INS_SET_ETH2_WITHDRAWAL_INDEX 0x10
|
||||
#define P1_CONFIRM 0x01
|
||||
#define P1_NON_CONFIRM 0x00
|
||||
#define P2_NO_CHAINCODE 0x00
|
||||
#define P2_CHAINCODE 0x01
|
||||
#define P1_FIRST 0x00
|
||||
#define P1_MORE 0x80
|
||||
#define INS_SIGN_EIP_712_MESSAGE 0x0C
|
||||
#define INS_GET_ETH2_PUBLIC_KEY 0x0E
|
||||
#define INS_SET_ETH2_WITHDRAWAL_INDEX 0x10
|
||||
#define P1_CONFIRM 0x01
|
||||
#define P1_NON_CONFIRM 0x00
|
||||
#define P2_NO_CHAINCODE 0x00
|
||||
#define P2_CHAINCODE 0x01
|
||||
#define P1_FIRST 0x00
|
||||
#define P1_MORE 0x80
|
||||
|
||||
#define COMMON_CLA 0xB0
|
||||
#define COMMON_CLA 0xB0
|
||||
#define COMMON_INS_GET_WALLET_ID 0x04
|
||||
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
#define STARKWARE_CLA 0xF0
|
||||
#define STARKWARE_INS_GET_PUBLIC_KEY 0x02
|
||||
#define STARKWARE_INS_SIGN_MESSAGE 0x04
|
||||
#define STARKWARE_CLA 0xF0
|
||||
#define STARKWARE_INS_GET_PUBLIC_KEY 0x02
|
||||
#define STARKWARE_INS_SIGN_MESSAGE 0x04
|
||||
#define STARKWARE_INS_PROVIDE_QUANTUM 0x08
|
||||
#define STARKWARE_INS_UNSAFE_SIGN 0x0A
|
||||
#define STARKWARE_INS_UNSAFE_SIGN 0x0A
|
||||
|
||||
#define P1_STARK_ORDER 0x01
|
||||
#define P1_STARK_TRANSFER 0x02
|
||||
#define P1_STARK_ORDER_V2 0x03
|
||||
#define P1_STARK_TRANSFER_V2 0x04
|
||||
#define P1_STARK_ORDER 0x01
|
||||
#define P1_STARK_TRANSFER 0x02
|
||||
#define P1_STARK_ORDER_V2 0x03
|
||||
#define P1_STARK_TRANSFER_V2 0x04
|
||||
#define P1_STARK_CONDITIONAL_TRANSFER 0x05
|
||||
|
||||
#define STARK_ORDER_TYPE 0
|
||||
#define STARK_TRANSFER_TYPE 1
|
||||
#define STARK_ORDER_TYPE 0
|
||||
#define STARK_TRANSFER_TYPE 1
|
||||
#define STARK_CONDITIONAL_TRANSFER_TYPE 2
|
||||
|
||||
#endif
|
||||
|
||||
#define OFFSET_CLA 0
|
||||
#define OFFSET_INS 1
|
||||
#define OFFSET_P1 2
|
||||
#define OFFSET_P2 3
|
||||
#define OFFSET_LC 4
|
||||
#define OFFSET_CLA 0
|
||||
#define OFFSET_INS 1
|
||||
#define OFFSET_P1 2
|
||||
#define OFFSET_P2 3
|
||||
#define OFFSET_LC 4
|
||||
#define OFFSET_CDATA 5
|
||||
|
||||
void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleProvideErc20TokenInformation(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleSign(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleGetAppConfiguration(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleSignEIP712Message(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleGetPublicKey(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
void handleSign(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
void handleGetAppConfiguration(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
void handleSignPersonalMessage(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
void handleSignEIP712Message(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
|
||||
#ifdef HAVE_ETH2
|
||||
|
||||
void handleGetEth2PublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleSetEth2WinthdrawalIndex(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleGetEth2PublicKey(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
void handleSetEth2WinthdrawalIndex(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
void handleStarkwareGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleStarkwareProvideQuantum(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleStarkwareUnsafeSign(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx);
|
||||
void handleStarkwareGetPublicKey(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
void handleStarkwareSignMessage(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
void handleStarkwareProvideQuantum(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
void handleStarkwareUnsafeSign(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
45
src/base64.c
45
src/base64.c
@@ -2,16 +2,16 @@
|
||||
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
|
||||
*
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
@@ -19,7 +19,7 @@
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/* ====================================================================
|
||||
@@ -172,41 +172,34 @@ int Base64decode(char *bufplain, const char *bufcoded)
|
||||
|
||||
#endif
|
||||
|
||||
static const char basis_64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
int Base64encode_len(int len)
|
||||
{
|
||||
int Base64encode_len(int len) {
|
||||
return ((len + 2) / 3 * 4) + 1;
|
||||
}
|
||||
|
||||
int Base64encode(char *encoded, const char *string, int len)
|
||||
{
|
||||
int Base64encode(char *encoded, const char *string, int len) {
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
p = encoded;
|
||||
for (i = 0; i < len - 2; i += 3) {
|
||||
*p++ = basis_64[(string[i] >> 2) & 0x3F];
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4) |
|
||||
((int) (string[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
|
||||
((int) (string[i + 2] & 0xC0) >> 6)];
|
||||
*p++ = basis_64[string[i + 2] & 0x3F];
|
||||
*p++ = basis_64[(string[i] >> 2) & 0x3F];
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = basis_64[((string[i + 1] & 0xF) << 2) | ((int) (string[i + 2] & 0xC0) >> 6)];
|
||||
*p++ = basis_64[string[i + 2] & 0x3F];
|
||||
}
|
||||
if (i < len) {
|
||||
*p++ = basis_64[(string[i] >> 2) & 0x3F];
|
||||
if (i == (len - 1)) {
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4)];
|
||||
*p++ = basis_64[(string[i] >> 2) & 0x3F];
|
||||
if (i == (len - 1)) {
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4)];
|
||||
*p++ = '=';
|
||||
} else {
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
|
||||
}
|
||||
*p++ = '=';
|
||||
}
|
||||
else {
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4) |
|
||||
((int) (string[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
|
||||
}
|
||||
*p++ = '=';
|
||||
}
|
||||
|
||||
*p++ = '\0';
|
||||
return p - encoded;
|
||||
|
||||
14
src/base64.h
14
src/base64.h
@@ -2,16 +2,16 @@
|
||||
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
|
||||
*
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
@@ -19,7 +19,7 @@
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/* ====================================================================
|
||||
@@ -79,8 +79,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _BASE64_H_
|
||||
#define _BASE64_H_
|
||||
|
||||
@@ -89,7 +87,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
int Base64encode_len(int len);
|
||||
int Base64encode(char * coded_dst, const char *plain_src,int len_plain_src);
|
||||
int Base64encode(char *coded_dst, const char *plain_src, int len_plain_src);
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -102,4 +100,4 @@ int Base64decode(char * plain_dst, const char *coded_src);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_BASE64_H_
|
||||
#endif //_BASE64_H_
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef _CHAIN_CONFIG_H_
|
||||
#define _CHAIN_CONFIG_H_
|
||||
@@ -23,42 +23,42 @@
|
||||
#include "os.h"
|
||||
|
||||
typedef enum chain_kind_e {
|
||||
CHAIN_KIND_ETHEREUM,
|
||||
CHAIN_KIND_ETHEREUM_CLASSIC,
|
||||
CHAIN_KIND_EXPANSE,
|
||||
CHAIN_KIND_POA,
|
||||
CHAIN_KIND_RSK,
|
||||
CHAIN_KIND_UBIQ,
|
||||
CHAIN_KIND_WANCHAIN,
|
||||
CHAIN_KIND_KUSD,
|
||||
CHAIN_KIND_PIRL,
|
||||
CHAIN_KIND_AKROMA,
|
||||
CHAIN_KIND_MUSICOIN,
|
||||
CHAIN_KIND_CALLISTO,
|
||||
CHAIN_KIND_ETHERSOCIAL,
|
||||
CHAIN_KIND_ELLAISM,
|
||||
CHAIN_KIND_ETHER1,
|
||||
CHAIN_KIND_ETHERGEM,
|
||||
CHAIN_KIND_ATHEIOS,
|
||||
CHAIN_KIND_GOCHAIN,
|
||||
CHAIN_KIND_MIX,
|
||||
CHAIN_KIND_REOSC,
|
||||
CHAIN_KIND_HPB,
|
||||
CHAIN_KIND_TOMOCHAIN,
|
||||
CHAIN_KIND_TOBALABA,
|
||||
CHAIN_KIND_DEXON,
|
||||
CHAIN_KIND_VOLTA,
|
||||
CHAIN_KIND_EWC,
|
||||
CHAIN_KIND_ARTIS_SIGMA1,
|
||||
CHAIN_KIND_ARTIS_TAU1,
|
||||
CHAIN_KIND_WEBCHAIN,
|
||||
CHAIN_KIND_THUNDERCORE
|
||||
CHAIN_KIND_ETHEREUM,
|
||||
CHAIN_KIND_ETHEREUM_CLASSIC,
|
||||
CHAIN_KIND_EXPANSE,
|
||||
CHAIN_KIND_POA,
|
||||
CHAIN_KIND_RSK,
|
||||
CHAIN_KIND_UBIQ,
|
||||
CHAIN_KIND_WANCHAIN,
|
||||
CHAIN_KIND_KUSD,
|
||||
CHAIN_KIND_PIRL,
|
||||
CHAIN_KIND_AKROMA,
|
||||
CHAIN_KIND_MUSICOIN,
|
||||
CHAIN_KIND_CALLISTO,
|
||||
CHAIN_KIND_ETHERSOCIAL,
|
||||
CHAIN_KIND_ELLAISM,
|
||||
CHAIN_KIND_ETHER1,
|
||||
CHAIN_KIND_ETHERGEM,
|
||||
CHAIN_KIND_ATHEIOS,
|
||||
CHAIN_KIND_GOCHAIN,
|
||||
CHAIN_KIND_MIX,
|
||||
CHAIN_KIND_REOSC,
|
||||
CHAIN_KIND_HPB,
|
||||
CHAIN_KIND_TOMOCHAIN,
|
||||
CHAIN_KIND_TOBALABA,
|
||||
CHAIN_KIND_DEXON,
|
||||
CHAIN_KIND_VOLTA,
|
||||
CHAIN_KIND_EWC,
|
||||
CHAIN_KIND_ARTIS_SIGMA1,
|
||||
CHAIN_KIND_ARTIS_TAU1,
|
||||
CHAIN_KIND_WEBCHAIN,
|
||||
CHAIN_KIND_THUNDERCORE
|
||||
} chain_kind_t;
|
||||
|
||||
typedef struct chain_config_s {
|
||||
char coinName[10]; // ticker
|
||||
uint32_t chainId;
|
||||
chain_kind_t kind;
|
||||
char coinName[10]; // ticker
|
||||
uint32_t chainId;
|
||||
chain_kind_t kind;
|
||||
} chain_config_t;
|
||||
|
||||
#endif /* _CHAIN_CONFIG_H_ */
|
||||
|
||||
@@ -5,248 +5,267 @@
|
||||
#include "base64.h"
|
||||
|
||||
void eth_plugin_prepare_init(ethPluginInitContract_t *init, uint8_t *selector, uint32_t dataSize) {
|
||||
memset((uint8_t*)init, 0, sizeof(ethPluginInitContract_t));
|
||||
init->selector = selector;
|
||||
init->dataSize = dataSize;
|
||||
memset((uint8_t *) init, 0, sizeof(ethPluginInitContract_t));
|
||||
init->selector = selector;
|
||||
init->dataSize = dataSize;
|
||||
}
|
||||
|
||||
void eth_plugin_prepare_provide_parameter(ethPluginProvideParameter_t *provideParameter, uint8_t *parameter, uint32_t parameterOffset) {
|
||||
memset((uint8_t*)provideParameter, 0, sizeof(ethPluginProvideParameter_t));
|
||||
provideParameter->parameter = parameter;
|
||||
provideParameter->parameterOffset = parameterOffset;
|
||||
void eth_plugin_prepare_provide_parameter(ethPluginProvideParameter_t *provideParameter,
|
||||
uint8_t *parameter,
|
||||
uint32_t parameterOffset) {
|
||||
memset((uint8_t *) provideParameter, 0, sizeof(ethPluginProvideParameter_t));
|
||||
provideParameter->parameter = parameter;
|
||||
provideParameter->parameterOffset = parameterOffset;
|
||||
}
|
||||
|
||||
void eth_plugin_prepare_finalize(ethPluginFinalize_t *finalize) {
|
||||
memset((uint8_t*)finalize, 0, sizeof(ethPluginFinalize_t));
|
||||
memset((uint8_t *) finalize, 0, sizeof(ethPluginFinalize_t));
|
||||
}
|
||||
|
||||
void eth_plugin_prepare_provide_token(ethPluginProvideToken_t *provideToken, tokenDefinition_t *token1, tokenDefinition_t *token2) {
|
||||
memset((uint8_t*)provideToken, 0, sizeof(ethPluginProvideToken_t));
|
||||
provideToken->token1 = token1;
|
||||
provideToken->token2 = token2;
|
||||
void eth_plugin_prepare_provide_token(ethPluginProvideToken_t *provideToken,
|
||||
tokenDefinition_t *token1,
|
||||
tokenDefinition_t *token2) {
|
||||
memset((uint8_t *) provideToken, 0, sizeof(ethPluginProvideToken_t));
|
||||
provideToken->token1 = token1;
|
||||
provideToken->token2 = token2;
|
||||
}
|
||||
|
||||
void eth_plugin_prepare_query_contract_ID(ethQueryContractID_t *queryContractID, char *name, uint32_t nameLength, char *version, uint32_t versionLength) {
|
||||
memset((uint8_t*)queryContractID, 0, sizeof(ethQueryContractID_t));
|
||||
queryContractID->name = name;
|
||||
queryContractID->nameLength = nameLength;
|
||||
queryContractID->version = version;
|
||||
queryContractID->versionLength = versionLength;
|
||||
void eth_plugin_prepare_query_contract_ID(ethQueryContractID_t *queryContractID,
|
||||
char *name,
|
||||
uint32_t nameLength,
|
||||
char *version,
|
||||
uint32_t versionLength) {
|
||||
memset((uint8_t *) queryContractID, 0, sizeof(ethQueryContractID_t));
|
||||
queryContractID->name = name;
|
||||
queryContractID->nameLength = nameLength;
|
||||
queryContractID->version = version;
|
||||
queryContractID->versionLength = versionLength;
|
||||
}
|
||||
|
||||
void eth_plugin_prepare_query_contract_UI(ethQueryContractUI_t *queryContractUI, uint8_t screenIndex, char *title, uint32_t titleLength, char *msg, uint32_t msgLength) {
|
||||
memset((uint8_t*)queryContractUI, 0, sizeof(ethQueryContractUI_t));
|
||||
queryContractUI->screenIndex = screenIndex;
|
||||
queryContractUI->title = title;
|
||||
queryContractUI->titleLength = titleLength;
|
||||
queryContractUI->msg = msg;
|
||||
queryContractUI->msgLength = msgLength;
|
||||
void eth_plugin_prepare_query_contract_UI(ethQueryContractUI_t *queryContractUI,
|
||||
uint8_t screenIndex,
|
||||
char *title,
|
||||
uint32_t titleLength,
|
||||
char *msg,
|
||||
uint32_t msgLength) {
|
||||
memset((uint8_t *) queryContractUI, 0, sizeof(ethQueryContractUI_t));
|
||||
queryContractUI->screenIndex = screenIndex;
|
||||
queryContractUI->title = title;
|
||||
queryContractUI->titleLength = titleLength;
|
||||
queryContractUI->msg = msg;
|
||||
queryContractUI->msgLength = msgLength;
|
||||
}
|
||||
|
||||
int eth_plugin_perform_init(uint8_t *contractAddress, ethPluginInitContract_t *init) {
|
||||
uint8_t i;
|
||||
const uint8_t **selectors;
|
||||
dataContext.tokenContext.pluginAvailable = 0;
|
||||
// Handle hardcoded plugin list
|
||||
PRINTF("Selector %.*H\n", 4, init->selector);
|
||||
for (i=0;; i++) {
|
||||
uint8_t j;
|
||||
selectors = PIC(INTERNAL_ETH_PLUGINS[i].selectors);
|
||||
if (selectors == NULL) {
|
||||
break;
|
||||
}
|
||||
for (j=0; ((j<INTERNAL_ETH_PLUGINS[i].num_selectors) && (contractAddress != NULL)); j++) {
|
||||
if (memcmp(init->selector, PIC(selectors[j]), SELECTOR_SIZE) == 0) {
|
||||
if ((INTERNAL_ETH_PLUGINS[i].availableCheck == NULL) ||
|
||||
((PluginAvailableCheck)PIC(INTERNAL_ETH_PLUGINS[i].availableCheck))()) {
|
||||
strcpy(dataContext.tokenContext.pluginName, INTERNAL_ETH_PLUGINS[i].alias);
|
||||
dataContext.tokenContext.pluginAvailable = 1;
|
||||
contractAddress = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uint8_t i;
|
||||
const uint8_t **selectors;
|
||||
dataContext.tokenContext.pluginAvailable = 0;
|
||||
// Handle hardcoded plugin list
|
||||
PRINTF("Selector %.*H\n", 4, init->selector);
|
||||
for (i = 0;; i++) {
|
||||
uint8_t j;
|
||||
selectors = PIC(INTERNAL_ETH_PLUGINS[i].selectors);
|
||||
if (selectors == NULL) {
|
||||
break;
|
||||
}
|
||||
for (j = 0; ((j < INTERNAL_ETH_PLUGINS[i].num_selectors) && (contractAddress != NULL));
|
||||
j++) {
|
||||
if (memcmp(init->selector, PIC(selectors[j]), SELECTOR_SIZE) == 0) {
|
||||
if ((INTERNAL_ETH_PLUGINS[i].availableCheck == NULL) ||
|
||||
((PluginAvailableCheck) PIC(INTERNAL_ETH_PLUGINS[i].availableCheck))()) {
|
||||
strcpy(dataContext.tokenContext.pluginName, INTERNAL_ETH_PLUGINS[i].alias);
|
||||
dataContext.tokenContext.pluginAvailable = 1;
|
||||
contractAddress = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do not handle a plugin if running in swap mode
|
||||
if (called_from_swap && (contractAddress != NULL)) {
|
||||
PRINTF("eth_plug_init aborted in swap mode\n");
|
||||
return 0;
|
||||
}
|
||||
for (;;) {
|
||||
PRINTF("eth_plugin_init\n");
|
||||
if (contractAddress != NULL) {
|
||||
PRINTF("Trying address %.*H\n", 20, contractAddress);
|
||||
}
|
||||
else {
|
||||
PRINTF("Trying alias %s\n", dataContext.tokenContext.pluginName);
|
||||
}
|
||||
int status = eth_plugin_call(contractAddress, ETH_PLUGIN_INIT_CONTRACT, (void*)init);
|
||||
if (!status) {
|
||||
return 0;
|
||||
}
|
||||
if (status == ETH_PLUGIN_RESULT_OK) {
|
||||
break;
|
||||
}
|
||||
if (status == ETH_PLUGIN_RESULT_OK_ALIAS) {
|
||||
contractAddress = NULL;
|
||||
}
|
||||
}
|
||||
PRINTF("eth_plugin_init ok %s\n", dataContext.tokenContext.pluginName);
|
||||
dataContext.tokenContext.pluginAvailable = 1;
|
||||
return 1;
|
||||
// Do not handle a plugin if running in swap mode
|
||||
if (called_from_swap && (contractAddress != NULL)) {
|
||||
PRINTF("eth_plug_init aborted in swap mode\n");
|
||||
return 0;
|
||||
}
|
||||
for (;;) {
|
||||
PRINTF("eth_plugin_init\n");
|
||||
if (contractAddress != NULL) {
|
||||
PRINTF("Trying address %.*H\n", 20, contractAddress);
|
||||
} else {
|
||||
PRINTF("Trying alias %s\n", dataContext.tokenContext.pluginName);
|
||||
}
|
||||
int status = eth_plugin_call(contractAddress, ETH_PLUGIN_INIT_CONTRACT, (void *) init);
|
||||
if (!status) {
|
||||
return 0;
|
||||
}
|
||||
if (status == ETH_PLUGIN_RESULT_OK) {
|
||||
break;
|
||||
}
|
||||
if (status == ETH_PLUGIN_RESULT_OK_ALIAS) {
|
||||
contractAddress = NULL;
|
||||
}
|
||||
}
|
||||
PRINTF("eth_plugin_init ok %s\n", dataContext.tokenContext.pluginName);
|
||||
dataContext.tokenContext.pluginAvailable = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int eth_plugin_call(uint8_t *contractAddress, int method, void *parameter) {
|
||||
ethPluginSharedRW_t pluginRW;
|
||||
ethPluginSharedRO_t pluginRO;
|
||||
char tmp[PLUGIN_ID_LENGTH];
|
||||
char *alias;
|
||||
uint8_t i;
|
||||
uint8_t internalPlugin = 0;
|
||||
ethPluginSharedRW_t pluginRW;
|
||||
ethPluginSharedRO_t pluginRO;
|
||||
char tmp[PLUGIN_ID_LENGTH];
|
||||
char *alias;
|
||||
uint8_t i;
|
||||
uint8_t internalPlugin = 0;
|
||||
|
||||
pluginRW.sha3 = &global_sha3;
|
||||
pluginRO.txContent = &tmpContent.txContent;
|
||||
pluginRW.sha3 = &global_sha3;
|
||||
pluginRO.txContent = &tmpContent.txContent;
|
||||
|
||||
if (contractAddress == NULL) {
|
||||
if (!dataContext.tokenContext.pluginAvailable) {
|
||||
PRINTF("Cached plugin call but no plugin available\n");
|
||||
return 0;
|
||||
}
|
||||
alias = dataContext.tokenContext.pluginName;
|
||||
}
|
||||
else {
|
||||
Base64encode(tmp, (char*)contractAddress, 20);
|
||||
alias = tmp;
|
||||
}
|
||||
if (contractAddress == NULL) {
|
||||
if (!dataContext.tokenContext.pluginAvailable) {
|
||||
PRINTF("Cached plugin call but no plugin available\n");
|
||||
return 0;
|
||||
}
|
||||
alias = dataContext.tokenContext.pluginName;
|
||||
} else {
|
||||
Base64encode(tmp, (char *) contractAddress, 20);
|
||||
alias = tmp;
|
||||
}
|
||||
|
||||
// Prepare the call
|
||||
// Prepare the call
|
||||
|
||||
switch(method) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT:
|
||||
((ethPluginInitContract_t*)parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethPluginInitContract_t*)parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethPluginInitContract_t*)parameter)->pluginContext = (uint8_t*)&dataContext.tokenContext.pluginContext;
|
||||
((ethPluginInitContract_t*)parameter)->pluginContextLength = sizeof(dataContext.tokenContext.pluginContext);
|
||||
((ethPluginInitContract_t*)parameter)->alias = dataContext.tokenContext.pluginName;
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER:
|
||||
((ethPluginProvideParameter_t*)parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethPluginProvideParameter_t*)parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethPluginProvideParameter_t*)parameter)->pluginContext = (uint8_t*)&dataContext.tokenContext.pluginContext;
|
||||
break;
|
||||
case ETH_PLUGIN_FINALIZE:
|
||||
((ethPluginFinalize_t*)parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethPluginFinalize_t*)parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethPluginFinalize_t*)parameter)->pluginContext = (uint8_t*)&dataContext.tokenContext.pluginContext;
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_TOKEN:
|
||||
((ethPluginProvideToken_t*)parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethPluginProvideToken_t*)parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethPluginProvideToken_t*)parameter)->pluginContext = (uint8_t*)&dataContext.tokenContext.pluginContext;
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID:
|
||||
((ethQueryContractID_t*)parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethQueryContractID_t*)parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethQueryContractID_t*)parameter)->pluginContext = (uint8_t*)&dataContext.tokenContext.pluginContext;
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI:
|
||||
((ethQueryContractUI_t*)parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethQueryContractUI_t*)parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethQueryContractUI_t*)parameter)->pluginContext = (uint8_t*)&dataContext.tokenContext.pluginContext;
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unknown plugin method %d\n", method);
|
||||
return 0;
|
||||
}
|
||||
switch (method) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT:
|
||||
((ethPluginInitContract_t *) parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethPluginInitContract_t *) parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethPluginInitContract_t *) parameter)->pluginContext =
|
||||
(uint8_t *) &dataContext.tokenContext.pluginContext;
|
||||
((ethPluginInitContract_t *) parameter)->pluginContextLength =
|
||||
sizeof(dataContext.tokenContext.pluginContext);
|
||||
((ethPluginInitContract_t *) parameter)->alias = dataContext.tokenContext.pluginName;
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER:
|
||||
((ethPluginProvideParameter_t *) parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethPluginProvideParameter_t *) parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethPluginProvideParameter_t *) parameter)->pluginContext =
|
||||
(uint8_t *) &dataContext.tokenContext.pluginContext;
|
||||
break;
|
||||
case ETH_PLUGIN_FINALIZE:
|
||||
((ethPluginFinalize_t *) parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethPluginFinalize_t *) parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethPluginFinalize_t *) parameter)->pluginContext =
|
||||
(uint8_t *) &dataContext.tokenContext.pluginContext;
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_TOKEN:
|
||||
((ethPluginProvideToken_t *) parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethPluginProvideToken_t *) parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethPluginProvideToken_t *) parameter)->pluginContext =
|
||||
(uint8_t *) &dataContext.tokenContext.pluginContext;
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID:
|
||||
((ethQueryContractID_t *) parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethQueryContractID_t *) parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethQueryContractID_t *) parameter)->pluginContext =
|
||||
(uint8_t *) &dataContext.tokenContext.pluginContext;
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI:
|
||||
((ethQueryContractUI_t *) parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethQueryContractUI_t *) parameter)->pluginSharedRO = &pluginRO;
|
||||
((ethQueryContractUI_t *) parameter)->pluginContext =
|
||||
(uint8_t *) &dataContext.tokenContext.pluginContext;
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unknown plugin method %d\n", method);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Perform the call
|
||||
// Perform the call
|
||||
|
||||
for (i=0;; i++) {
|
||||
if (INTERNAL_ETH_PLUGINS[i].alias[0] == 0) {
|
||||
break;
|
||||
}
|
||||
if (strcmp(alias, INTERNAL_ETH_PLUGINS[i].alias) == 0) {
|
||||
internalPlugin = 1;
|
||||
((PluginCall)PIC(INTERNAL_ETH_PLUGINS[i].impl))(method, parameter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0;; i++) {
|
||||
if (INTERNAL_ETH_PLUGINS[i].alias[0] == 0) {
|
||||
break;
|
||||
}
|
||||
if (strcmp(alias, INTERNAL_ETH_PLUGINS[i].alias) == 0) {
|
||||
internalPlugin = 1;
|
||||
((PluginCall) PIC(INTERNAL_ETH_PLUGINS[i].impl))(method, parameter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!internalPlugin) {
|
||||
uint32_t params[3];
|
||||
params[0] = (uint32_t)alias;
|
||||
params[1] = method;
|
||||
params[2] = (uint32_t)parameter;
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
os_lib_call(params);
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
PRINTF("Plugin call exception for %s\n", alias);
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
}
|
||||
if (!internalPlugin) {
|
||||
uint32_t params[3];
|
||||
params[0] = (uint32_t) alias;
|
||||
params[1] = method;
|
||||
params[2] = (uint32_t) parameter;
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
os_lib_call(params);
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
PRINTF("Plugin call exception for %s\n", alias);
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
}
|
||||
|
||||
// Check the call result
|
||||
// Check the call result
|
||||
|
||||
switch(method) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT:
|
||||
switch (((ethPluginInitContract_t*)parameter)->result) {
|
||||
case ETH_PLUGIN_RESULT_OK:
|
||||
if (contractAddress != NULL) {
|
||||
strcpy(dataContext.tokenContext.pluginName, alias);
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_RESULT_OK_ALIAS:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER:
|
||||
switch (((ethPluginProvideParameter_t*)parameter)->result) {
|
||||
case ETH_PLUGIN_RESULT_OK:
|
||||
case ETH_PLUGIN_RESULT_FALLBACK:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_FINALIZE:
|
||||
switch (((ethPluginFinalize_t*)parameter)->result) {
|
||||
case ETH_PLUGIN_RESULT_OK:
|
||||
case ETH_PLUGIN_RESULT_FALLBACK:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_TOKEN:
|
||||
switch (((ethPluginProvideToken_t*)parameter)->result) {
|
||||
case ETH_PLUGIN_RESULT_OK:
|
||||
case ETH_PLUGIN_RESULT_FALLBACK:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID:
|
||||
if (((ethQueryContractID_t*)parameter)->result != ETH_PLUGIN_RESULT_OK) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI:
|
||||
if (((ethQueryContractUI_t*)parameter)->result != ETH_PLUGIN_RESULT_OK) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
switch (method) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT:
|
||||
switch (((ethPluginInitContract_t *) parameter)->result) {
|
||||
case ETH_PLUGIN_RESULT_OK:
|
||||
if (contractAddress != NULL) {
|
||||
strcpy(dataContext.tokenContext.pluginName, alias);
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_RESULT_OK_ALIAS:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER:
|
||||
switch (((ethPluginProvideParameter_t *) parameter)->result) {
|
||||
case ETH_PLUGIN_RESULT_OK:
|
||||
case ETH_PLUGIN_RESULT_FALLBACK:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_FINALIZE:
|
||||
switch (((ethPluginFinalize_t *) parameter)->result) {
|
||||
case ETH_PLUGIN_RESULT_OK:
|
||||
case ETH_PLUGIN_RESULT_FALLBACK:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_TOKEN:
|
||||
switch (((ethPluginProvideToken_t *) parameter)->result) {
|
||||
case ETH_PLUGIN_RESULT_OK:
|
||||
case ETH_PLUGIN_RESULT_FALLBACK:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID:
|
||||
if (((ethQueryContractID_t *) parameter)->result != ETH_PLUGIN_RESULT_OK) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI:
|
||||
if (((ethQueryContractUI_t *) parameter)->result != ETH_PLUGIN_RESULT_OK) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,24 @@
|
||||
#include "eth_plugin_interface.h"
|
||||
|
||||
void eth_plugin_prepare_init(ethPluginInitContract_t *init, uint8_t *selector, uint32_t dataSize);
|
||||
void eth_plugin_prepare_provide_parameter(ethPluginProvideParameter_t *provideParameter, uint8_t *parameter, uint32_t parameterOffset);
|
||||
void eth_plugin_prepare_provide_parameter(ethPluginProvideParameter_t *provideParameter,
|
||||
uint8_t *parameter,
|
||||
uint32_t parameterOffset);
|
||||
void eth_plugin_prepare_finalize(ethPluginFinalize_t *finalize);
|
||||
void eth_plugin_prepare_provide_token(ethPluginProvideToken_t *provideToken, tokenDefinition_t *token1, tokenDefinition_t *token2);
|
||||
void eth_plugin_prepare_query_contract_ID(ethQueryContractID_t *queryContractID, char *name, uint32_t nameLength, char *version, uint32_t versionLength);
|
||||
void eth_plugin_prepare_query_contract_UI(ethQueryContractUI_t *queryContractUI, uint8_t screenIndex, char *title, uint32_t titleLength, char *msg, uint32_t msgLength);
|
||||
void eth_plugin_prepare_provide_token(ethPluginProvideToken_t *provideToken,
|
||||
tokenDefinition_t *token1,
|
||||
tokenDefinition_t *token2);
|
||||
void eth_plugin_prepare_query_contract_ID(ethQueryContractID_t *queryContractID,
|
||||
char *name,
|
||||
uint32_t nameLength,
|
||||
char *version,
|
||||
uint32_t versionLength);
|
||||
void eth_plugin_prepare_query_contract_UI(ethQueryContractUI_t *queryContractUI,
|
||||
uint8_t screenIndex,
|
||||
char *title,
|
||||
uint32_t titleLength,
|
||||
char *msg,
|
||||
uint32_t msgLength);
|
||||
|
||||
int eth_plugin_perform_init(uint8_t *contractAddress, ethPluginInitContract_t *init);
|
||||
// NULL for cached address, or base contract address
|
||||
@@ -17,4 +30,3 @@ int compound_plugin_call(uint8_t *contractAddress, int method, void *parameter);
|
||||
void plugin_ui_start(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -11,123 +11,116 @@
|
||||
|
||||
typedef enum {
|
||||
|
||||
ETH_PLUGIN_INIT_CONTRACT = 0x0101,
|
||||
ETH_PLUGIN_PROVIDE_PARAMETER = 0x0102,
|
||||
ETH_PLUGIN_FINALIZE = 0x0103,
|
||||
ETH_PLUGIN_PROVIDE_TOKEN = 0x0104,
|
||||
ETH_PLUGIN_QUERY_CONTRACT_ID = 0x0105,
|
||||
ETH_PLUGIN_QUERY_CONTRACT_UI = 0x0106
|
||||
ETH_PLUGIN_INIT_CONTRACT = 0x0101,
|
||||
ETH_PLUGIN_PROVIDE_PARAMETER = 0x0102,
|
||||
ETH_PLUGIN_FINALIZE = 0x0103,
|
||||
ETH_PLUGIN_PROVIDE_TOKEN = 0x0104,
|
||||
ETH_PLUGIN_QUERY_CONTRACT_ID = 0x0105,
|
||||
ETH_PLUGIN_QUERY_CONTRACT_UI = 0x0106
|
||||
|
||||
} eth_plugin_msg_t;
|
||||
|
||||
typedef enum {
|
||||
|
||||
ETH_PLUGIN_RESULT_ERROR = 0x00,
|
||||
ETH_PLUGIN_RESULT_OK = 0x01,
|
||||
ETH_PLUGIN_RESULT_OK_ALIAS = 0x02,
|
||||
ETH_PLUGIN_RESULT_FALLBACK = 0x03
|
||||
ETH_PLUGIN_RESULT_ERROR = 0x00,
|
||||
ETH_PLUGIN_RESULT_OK = 0x01,
|
||||
ETH_PLUGIN_RESULT_OK_ALIAS = 0x02,
|
||||
ETH_PLUGIN_RESULT_FALLBACK = 0x03
|
||||
|
||||
} eth_plugin_result_t;
|
||||
|
||||
typedef enum {
|
||||
|
||||
ETH_UI_TYPE_AMOUNT_ADDRESS = 0x01,
|
||||
ETH_UI_TYPE_GENERIC = 0x02
|
||||
ETH_UI_TYPE_AMOUNT_ADDRESS = 0x01,
|
||||
ETH_UI_TYPE_GENERIC = 0x02
|
||||
|
||||
} eth_ui_type_t;
|
||||
|
||||
typedef void (*PluginCall)(int, void*);
|
||||
typedef void (*PluginCall)(int, void *);
|
||||
|
||||
// Shared objects, read-write
|
||||
|
||||
typedef struct ethPluginSharedRW_t {
|
||||
|
||||
cx_sha3_t *sha3;
|
||||
cx_sha3_t *sha3;
|
||||
|
||||
} ethPluginSharedRW_t;
|
||||
|
||||
// Shared objects, read-only
|
||||
|
||||
typedef struct ethPluginSharedRO_t {
|
||||
|
||||
txContent_t *txContent;
|
||||
txContent_t *txContent;
|
||||
|
||||
} ethPluginSharedRO_t;
|
||||
|
||||
|
||||
// Init Contract
|
||||
|
||||
typedef struct ethPluginInitContract_t {
|
||||
// in
|
||||
|
||||
// in
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
uint32_t pluginContextLength;
|
||||
uint8_t *selector; // 4 bytes selector
|
||||
uint32_t dataSize;
|
||||
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
uint32_t pluginContextLength;
|
||||
uint8_t *selector; // 4 bytes selector
|
||||
uint32_t dataSize;
|
||||
char *alias; // 29 bytes alias if ETH_PLUGIN_RESULT_OK_ALIAS set
|
||||
|
||||
char *alias; // 29 bytes alias if ETH_PLUGIN_RESULT_OK_ALIAS set
|
||||
|
||||
uint8_t result;
|
||||
uint8_t result;
|
||||
|
||||
} ethPluginInitContract_t;
|
||||
|
||||
// Provide parameter
|
||||
|
||||
typedef struct ethPluginProvideParameter_t {
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
uint8_t *parameter; // 32 bytes parameter
|
||||
uint32_t parameterOffset;
|
||||
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
uint8_t *parameter; // 32 bytes parameter
|
||||
uint32_t parameterOffset;
|
||||
|
||||
uint8_t result;
|
||||
uint8_t result;
|
||||
|
||||
} ethPluginProvideParameter_t;
|
||||
|
||||
// Finalize
|
||||
|
||||
typedef struct ethPluginFinalize_t {
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
uint8_t *tokenLookup1; // set by the plugin if a token should be looked up
|
||||
uint8_t *tokenLookup2;
|
||||
|
||||
uint8_t *tokenLookup1; // set by the plugin if a token should be looked up
|
||||
uint8_t *tokenLookup2;
|
||||
uint8_t *amount; // set an uint256 pointer if uiType is UI_AMOUNT_ADDRESS
|
||||
uint8_t *address; // set to a 20 bytes address pointer if uiType is UI_AMOUNT_ADDRESS
|
||||
|
||||
uint8_t *amount; // set an uint256 pointer if uiType is UI_AMOUNT_ADDRESS
|
||||
uint8_t *address; // set to a 20 bytes address pointer if uiType is UI_AMOUNT_ADDRESS
|
||||
|
||||
uint8_t uiType;
|
||||
uint8_t numScreens; // ignored if uiType is UI_AMOUNT_ADDRESS
|
||||
uint8_t result;
|
||||
uint8_t uiType;
|
||||
uint8_t numScreens; // ignored if uiType is UI_AMOUNT_ADDRESS
|
||||
uint8_t result;
|
||||
|
||||
} ethPluginFinalize_t;
|
||||
|
||||
// If uiType is UI_AMOUNT_ADDRESS, the amount and address provided by the plugin will be used
|
||||
// If tokenLookup1 is set, the amount is provided for this token
|
||||
|
||||
// if uiType is UI_TYPE_GENERIC, the ETH application provides tokens if requested then prompts
|
||||
// if uiType is UI_TYPE_GENERIC, the ETH application provides tokens if requested then prompts
|
||||
// for each UI field
|
||||
// The first field is forced by the ETH app to be the name + version of the plugin handling the request
|
||||
// The last field is the fee amount
|
||||
// The first field is forced by the ETH app to be the name + version of the plugin handling the
|
||||
// request The last field is the fee amount
|
||||
|
||||
// Provide token
|
||||
// Provide token
|
||||
|
||||
typedef struct ethPluginProvideToken_t {
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
tokenDefinition_t *token1; // set by the ETH application, to be saved by the plugin
|
||||
tokenDefinition_t *token2;
|
||||
|
||||
tokenDefinition_t *token1; // set by the ETH application, to be saved by the plugin
|
||||
tokenDefinition_t *token2;
|
||||
|
||||
uint8_t result;
|
||||
uint8_t result;
|
||||
|
||||
} ethPluginProvideToken_t;
|
||||
|
||||
@@ -136,36 +129,33 @@ typedef struct ethPluginProvideToken_t {
|
||||
// This is always called on the non aliased contract
|
||||
|
||||
typedef struct ethQueryContractID_t {
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
char *name;
|
||||
uint32_t nameLength;
|
||||
char *version;
|
||||
uint32_t versionLength;
|
||||
|
||||
char *name;
|
||||
uint32_t nameLength;
|
||||
char *version;
|
||||
uint32_t versionLength;
|
||||
|
||||
uint8_t result;
|
||||
uint8_t result;
|
||||
|
||||
} ethQueryContractID_t;
|
||||
|
||||
// Query Contract UI
|
||||
|
||||
typedef struct ethQueryContractUI_t {
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
uint8_t screenIndex;
|
||||
char *title;
|
||||
uint32_t titleLength;
|
||||
char *msg;
|
||||
uint32_t msgLength;
|
||||
|
||||
ethPluginSharedRW_t *pluginSharedRW;
|
||||
ethPluginSharedRO_t *pluginSharedRO;
|
||||
uint8_t *pluginContext;
|
||||
uint8_t screenIndex;
|
||||
char *title;
|
||||
uint32_t titleLength;
|
||||
char *msg;
|
||||
uint32_t msgLength;
|
||||
|
||||
uint8_t result;
|
||||
uint8_t result;
|
||||
|
||||
} ethQueryContractUI_t;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,138 +3,118 @@
|
||||
bool erc20_plugin_available_check(void);
|
||||
bool erc721_plugin_available_check(void);
|
||||
|
||||
void erc20_plugin_call(int message, void *parameters);
|
||||
void erc721_plugin_call(int message, void *parameters);
|
||||
void compound_plugin_call(int message, void *parameters);
|
||||
void erc20_plugin_call(int message, void* parameters);
|
||||
void erc721_plugin_call(int message, void* parameters);
|
||||
void compound_plugin_call(int message, void* parameters);
|
||||
#ifdef HAVE_STARKWARE
|
||||
void starkware_plugin_call(int message, void *parameters);
|
||||
void starkware_plugin_call(int message, void* parameters);
|
||||
#endif
|
||||
#ifdef HAVE_ETH2
|
||||
void eth2_plugin_call(int message, void *parameters);
|
||||
void eth2_plugin_call(int message, void* parameters);
|
||||
#endif
|
||||
|
||||
static const uint8_t const ERC20_TRANSFER_SELECTOR[SELECTOR_SIZE] = { 0xa9, 0x05, 0x9c, 0xbb };
|
||||
static const uint8_t const ERC20_APPROVE_SELECTOR[SELECTOR_SIZE] = { 0x09, 0x5e, 0xa7, 0xb3 };
|
||||
static const uint8_t const ERC20_TRANSFER_SELECTOR[SELECTOR_SIZE] = {0xa9, 0x05, 0x9c, 0xbb};
|
||||
static const uint8_t const ERC20_APPROVE_SELECTOR[SELECTOR_SIZE] = {0x09, 0x5e, 0xa7, 0xb3};
|
||||
|
||||
const uint8_t* const ERC20_SELECTORS[NUM_ERC20_SELECTORS] = {
|
||||
ERC20_TRANSFER_SELECTOR, ERC20_APPROVE_SELECTOR
|
||||
};
|
||||
const uint8_t* const ERC20_SELECTORS[NUM_ERC20_SELECTORS] = {ERC20_TRANSFER_SELECTOR,
|
||||
ERC20_APPROVE_SELECTOR};
|
||||
|
||||
static const uint8_t const ERC721_APPROVE_SELECTOR[SELECTOR_SIZE] = {0x09, 0x5e, 0xa7, 0xb3};
|
||||
|
||||
static const uint8_t const ERC721_APPROVE_SELECTOR[SELECTOR_SIZE] = { 0x09, 0x5e, 0xa7, 0xb3 };
|
||||
const uint8_t* const ERC721_SELECTORS[NUM_ERC721_SELECTORS] = {ERC721_APPROVE_SELECTOR};
|
||||
|
||||
const uint8_t* const ERC721_SELECTORS[NUM_ERC721_SELECTORS] = {
|
||||
ERC721_APPROVE_SELECTOR
|
||||
};
|
||||
|
||||
static const uint8_t const COMPOUND_REDEEM_UNDERLYING_SELECTOR[SELECTOR_SIZE] = { 0x85, 0x2a, 0x12, 0xe3 };
|
||||
static const uint8_t const COMPOUND_REDEEM_SELECTOR[SELECTOR_SIZE] = { 0xdb, 0x00, 0x6a, 0x75 };
|
||||
static const uint8_t const COMPOUND_MINT_SELECTOR[SELECTOR_SIZE] = { 0xa0, 0x71, 0x2d, 0x68 };
|
||||
static const uint8_t const CETH_MINT_SELECTOR[SELECTOR_SIZE] = { 0x12, 0x49, 0xc5, 0x8b };
|
||||
static const uint8_t const COMPOUND_REDEEM_UNDERLYING_SELECTOR[SELECTOR_SIZE] = {0x85,
|
||||
0x2a,
|
||||
0x12,
|
||||
0xe3};
|
||||
static const uint8_t const COMPOUND_REDEEM_SELECTOR[SELECTOR_SIZE] = {0xdb, 0x00, 0x6a, 0x75};
|
||||
static const uint8_t const COMPOUND_MINT_SELECTOR[SELECTOR_SIZE] = {0xa0, 0x71, 0x2d, 0x68};
|
||||
static const uint8_t const CETH_MINT_SELECTOR[SELECTOR_SIZE] = {0x12, 0x49, 0xc5, 0x8b};
|
||||
|
||||
const uint8_t* const COMPOUND_SELECTORS[NUM_COMPOUND_SELECTORS] = {
|
||||
COMPOUND_REDEEM_UNDERLYING_SELECTOR, COMPOUND_REDEEM_SELECTOR,
|
||||
COMPOUND_MINT_SELECTOR, CETH_MINT_SELECTOR
|
||||
};
|
||||
COMPOUND_REDEEM_UNDERLYING_SELECTOR,
|
||||
COMPOUND_REDEEM_SELECTOR,
|
||||
COMPOUND_MINT_SELECTOR,
|
||||
CETH_MINT_SELECTOR};
|
||||
|
||||
#ifdef HAVE_ETH2
|
||||
|
||||
static const uint8_t const ETH2_DEPOSIT_SELECTOR[SELECTOR_SIZE] = { 0x22, 0x89, 0x51, 0x18 };
|
||||
static const uint8_t const ETH2_DEPOSIT_SELECTOR[SELECTOR_SIZE] = {0x22, 0x89, 0x51, 0x18};
|
||||
|
||||
const uint8_t* const ETH2_SELECTORS[NUM_ETH2_SELECTORS] = {
|
||||
ETH2_DEPOSIT_SELECTOR
|
||||
};
|
||||
const uint8_t* const ETH2_SELECTORS[NUM_ETH2_SELECTORS] = {ETH2_DEPOSIT_SELECTOR};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
static const uint8_t const STARKWARE_REGISTER_ID[SELECTOR_SIZE] = { 0xdd, 0x24, 0x14, 0xd4 };
|
||||
static const uint8_t const STARKWARE_DEPOSIT_TOKEN_ID[SELECTOR_SIZE] = { 0x25, 0x05, 0xc3, 0xd9 };
|
||||
static const uint8_t const STARKWARE_DEPOSIT_ETH_ID[SELECTOR_SIZE] = { 0x00, 0xae, 0xef, 0x8a };
|
||||
static const uint8_t const STARKWARE_DEPOSIT_CANCEL_ID[SELECTOR_SIZE] = { 0x7d, 0xf7, 0xdc, 0x04 };
|
||||
static const uint8_t const STARKWARE_DEPOSIT_RECLAIM_ID[SELECTOR_SIZE] = { 0xae, 0x87, 0x38, 0x16 };
|
||||
static const uint8_t const STARKWARE_WITHDRAW_ID[SELECTOR_SIZE] = { 0x44, 0x1a, 0x3e, 0x70 };
|
||||
static const uint8_t const STARKWARE_FULL_WITHDRAWAL_ID[SELECTOR_SIZE] = { 0xa9, 0x33, 0x10, 0xc4 };
|
||||
static const uint8_t const STARKWARE_FREEZE_ID[SELECTOR_SIZE] = { 0x93, 0xc1, 0xe4, 0x66 };
|
||||
static const uint8_t const STARKWARE_ESCAPE_ID[SELECTOR_SIZE] = { 0x9e, 0x3a, 0xda, 0xc4 };
|
||||
static const uint8_t const STARKWARE_VERIFY_ESCAPE_ID[SELECTOR_SIZE] = { 0x2d, 0xd5, 0x30, 0x06 };
|
||||
|
||||
static const uint8_t const STARKWARE_WITHDRAW_TO_ID[SELECTOR_SIZE] = { 0x14, 0xcd, 0x70, 0xe4 };
|
||||
static const uint8_t const STARKWARE_DEPOSIT_NFT_ID[SELECTOR_SIZE] = { 0xae, 0x1c, 0xdd, 0xe6 };
|
||||
static const uint8_t const STARKWARE_DEPOSIT_NFT_RECLAIM_ID[SELECTOR_SIZE] = { 0xfc, 0xb0, 0x58, 0x22 };
|
||||
static const uint8_t const STARKWARE_WITHDRAW_AND_MINT_ID[SELECTOR_SIZE] = { 0xd9, 0x14, 0x43, 0xb7 };
|
||||
static const uint8_t const STARKWARE_WITHDRAW_NFT_ID[SELECTOR_SIZE] = { 0x01, 0x9b, 0x41, 0x7a };
|
||||
static const uint8_t const STARKWARE_WITHDRAW_NFT_TO_ID[SELECTOR_SIZE] = { 0xeb, 0xef, 0x0f, 0xd0 };
|
||||
static const uint8_t const STARKWARE_REGISTER_ID[SELECTOR_SIZE] = {0xdd, 0x24, 0x14, 0xd4};
|
||||
static const uint8_t const STARKWARE_DEPOSIT_TOKEN_ID[SELECTOR_SIZE] = {0x25, 0x05, 0xc3, 0xd9};
|
||||
static const uint8_t const STARKWARE_DEPOSIT_ETH_ID[SELECTOR_SIZE] = {0x00, 0xae, 0xef, 0x8a};
|
||||
static const uint8_t const STARKWARE_DEPOSIT_CANCEL_ID[SELECTOR_SIZE] = {0x7d, 0xf7, 0xdc, 0x04};
|
||||
static const uint8_t const STARKWARE_DEPOSIT_RECLAIM_ID[SELECTOR_SIZE] = {0xae, 0x87, 0x38, 0x16};
|
||||
static const uint8_t const STARKWARE_WITHDRAW_ID[SELECTOR_SIZE] = {0x44, 0x1a, 0x3e, 0x70};
|
||||
static const uint8_t const STARKWARE_FULL_WITHDRAWAL_ID[SELECTOR_SIZE] = {0xa9, 0x33, 0x10, 0xc4};
|
||||
static const uint8_t const STARKWARE_FREEZE_ID[SELECTOR_SIZE] = {0x93, 0xc1, 0xe4, 0x66};
|
||||
static const uint8_t const STARKWARE_ESCAPE_ID[SELECTOR_SIZE] = {0x9e, 0x3a, 0xda, 0xc4};
|
||||
static const uint8_t const STARKWARE_VERIFY_ESCAPE_ID[SELECTOR_SIZE] = {0x2d, 0xd5, 0x30, 0x06};
|
||||
|
||||
static const uint8_t const STARKWARE_WITHDRAW_TO_ID[SELECTOR_SIZE] = {0x14, 0xcd, 0x70, 0xe4};
|
||||
static const uint8_t const STARKWARE_DEPOSIT_NFT_ID[SELECTOR_SIZE] = {0xae, 0x1c, 0xdd, 0xe6};
|
||||
static const uint8_t const STARKWARE_DEPOSIT_NFT_RECLAIM_ID[SELECTOR_SIZE] = {0xfc,
|
||||
0xb0,
|
||||
0x58,
|
||||
0x22};
|
||||
static const uint8_t const STARKWARE_WITHDRAW_AND_MINT_ID[SELECTOR_SIZE] = {0xd9, 0x14, 0x43, 0xb7};
|
||||
static const uint8_t const STARKWARE_WITHDRAW_NFT_ID[SELECTOR_SIZE] = {0x01, 0x9b, 0x41, 0x7a};
|
||||
static const uint8_t const STARKWARE_WITHDRAW_NFT_TO_ID[SELECTOR_SIZE] = {0xeb, 0xef, 0x0f, 0xd0};
|
||||
|
||||
const uint8_t* const STARKWARE_SELECTORS[NUM_STARKWARE_SELECTORS] = {
|
||||
STARKWARE_REGISTER_ID, STARKWARE_DEPOSIT_TOKEN_ID, STARKWARE_DEPOSIT_ETH_ID,
|
||||
STARKWARE_DEPOSIT_CANCEL_ID, STARKWARE_DEPOSIT_RECLAIM_ID, STARKWARE_WITHDRAW_ID,
|
||||
STARKWARE_FULL_WITHDRAWAL_ID, STARKWARE_FREEZE_ID, STARKWARE_ESCAPE_ID,
|
||||
STARKWARE_VERIFY_ESCAPE_ID, STARKWARE_WITHDRAW_TO_ID, STARKWARE_DEPOSIT_NFT_ID,
|
||||
STARKWARE_DEPOSIT_NFT_RECLAIM_ID, STARKWARE_WITHDRAW_AND_MINT_ID, STARKWARE_WITHDRAW_NFT_ID,
|
||||
STARKWARE_WITHDRAW_NFT_TO_ID
|
||||
};
|
||||
STARKWARE_REGISTER_ID,
|
||||
STARKWARE_DEPOSIT_TOKEN_ID,
|
||||
STARKWARE_DEPOSIT_ETH_ID,
|
||||
STARKWARE_DEPOSIT_CANCEL_ID,
|
||||
STARKWARE_DEPOSIT_RECLAIM_ID,
|
||||
STARKWARE_WITHDRAW_ID,
|
||||
STARKWARE_FULL_WITHDRAWAL_ID,
|
||||
STARKWARE_FREEZE_ID,
|
||||
STARKWARE_ESCAPE_ID,
|
||||
STARKWARE_VERIFY_ESCAPE_ID,
|
||||
STARKWARE_WITHDRAW_TO_ID,
|
||||
STARKWARE_DEPOSIT_NFT_ID,
|
||||
STARKWARE_DEPOSIT_NFT_RECLAIM_ID,
|
||||
STARKWARE_WITHDRAW_AND_MINT_ID,
|
||||
STARKWARE_WITHDRAW_NFT_ID,
|
||||
STARKWARE_WITHDRAW_NFT_TO_ID};
|
||||
|
||||
#endif
|
||||
|
||||
// All internal alias names start with 'minus'
|
||||
|
||||
const internalEthPlugin_t const INTERNAL_ETH_PLUGINS[] = {
|
||||
{
|
||||
erc20_plugin_available_check,
|
||||
ERC20_SELECTORS,
|
||||
NUM_ERC20_SELECTORS,
|
||||
"-erc20",
|
||||
erc20_plugin_call
|
||||
},
|
||||
const internalEthPlugin_t const INTERNAL_ETH_PLUGINS[] = {
|
||||
{erc20_plugin_available_check,
|
||||
ERC20_SELECTORS,
|
||||
NUM_ERC20_SELECTORS,
|
||||
"-erc20",
|
||||
erc20_plugin_call},
|
||||
|
||||
{
|
||||
erc721_plugin_available_check,
|
||||
ERC721_SELECTORS,
|
||||
NUM_ERC721_SELECTORS,
|
||||
"-er721",
|
||||
erc721_plugin_call
|
||||
},
|
||||
{erc721_plugin_available_check,
|
||||
ERC721_SELECTORS,
|
||||
NUM_ERC721_SELECTORS,
|
||||
"-er721",
|
||||
erc721_plugin_call},
|
||||
|
||||
{
|
||||
NULL,
|
||||
COMPOUND_SELECTORS,
|
||||
NUM_COMPOUND_SELECTORS,
|
||||
"-cmpd",
|
||||
compound_plugin_call
|
||||
},
|
||||
{NULL, COMPOUND_SELECTORS, NUM_COMPOUND_SELECTORS, "-cmpd", compound_plugin_call},
|
||||
|
||||
#ifdef HAVE_ETH2
|
||||
|
||||
{
|
||||
NULL,
|
||||
ETH2_SELECTORS,
|
||||
NUM_ETH2_SELECTORS,
|
||||
"-eth2",
|
||||
eth2_plugin_call
|
||||
},
|
||||
{NULL, ETH2_SELECTORS, NUM_ETH2_SELECTORS, "-eth2", eth2_plugin_call},
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
{
|
||||
NULL,
|
||||
STARKWARE_SELECTORS,
|
||||
10,
|
||||
"-strk",
|
||||
starkware_plugin_call
|
||||
},
|
||||
{NULL, STARKWARE_SELECTORS, 10, "-strk", starkware_plugin_call},
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
"",
|
||||
NULL
|
||||
}
|
||||
};
|
||||
{NULL, NULL, 0, "", NULL}};
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
typedef bool (*PluginAvailableCheck)(void);
|
||||
|
||||
typedef struct internalEthPlugin_t {
|
||||
PluginAvailableCheck availableCheck;
|
||||
const uint8_t **selectors;
|
||||
uint8_t num_selectors;
|
||||
char alias[7];
|
||||
PluginCall impl;
|
||||
PluginAvailableCheck availableCheck;
|
||||
const uint8_t** selectors;
|
||||
uint8_t num_selectors;
|
||||
char alias[7];
|
||||
PluginCall impl;
|
||||
} internalEthPlugin_t;
|
||||
|
||||
#define NUM_ERC20_SELECTORS 2
|
||||
|
||||
@@ -7,86 +7,94 @@
|
||||
|
||||
typedef enum {
|
||||
|
||||
PLUGIN_UI_INSIDE = 0,
|
||||
PLUGIN_UI_OUTSIDE
|
||||
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(
|
||||
(dataContext.tokenContext.pluginName[0] == '-' ? NULL : tmpContent.txContent.destination),
|
||||
ETH_PLUGIN_QUERY_CONTRACT_ID, (void*)&pluginQueryContractID)) {
|
||||
PRINTF("Plugin query contract ID call failed\n");
|
||||
io_seproxyhal_touch_tx_cancel(NULL);
|
||||
}
|
||||
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(
|
||||
(dataContext.tokenContext.pluginName[0] == '-' ? NULL
|
||||
: tmpContent.txContent.destination),
|
||||
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(NULL, ETH_PLUGIN_QUERY_CONTRACT_UI, (void*)&pluginQueryContractUI)) {
|
||||
PRINTF("Plugin query contract UI call failed\n");
|
||||
io_seproxyhal_touch_tx_cancel(NULL);
|
||||
}
|
||||
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(NULL, 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();
|
||||
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(G_ux.stack_count - 1);
|
||||
#else
|
||||
ux_layout_bnnn_paging_redisplay(0);
|
||||
#endif
|
||||
} else {
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE;
|
||||
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(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));
|
||||
computeFees(strings.common.maxFee, sizeof(strings.common.maxFee));
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
UX_FLOW_DEF_NOCB(
|
||||
ux_plugin_approval_intro_step,
|
||||
pnn,
|
||||
@@ -155,21 +163,20 @@ UX_FLOW_DEF_VALID(
|
||||
&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
|
||||
);
|
||||
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);
|
||||
|
||||
void plugin_ui_start() {
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE;
|
||||
dataContext.tokenContext.pluginUiCurrentItem = 0;
|
||||
ux_flow_init(0, ux_plugin_approval_flow, NULL);
|
||||
dataContext.tokenContext.pluginUiState = PLUGIN_UI_OUTSIDE;
|
||||
dataContext.tokenContext.pluginUiCurrentItem = 0;
|
||||
ux_flow_init(0, ux_plugin_approval_flow, NULL);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
#define ZERO(x) memset(x, 0, sizeof(x))
|
||||
|
||||
void handle_check_address(check_address_parameters_t* params, chain_config_t* chain_config) {
|
||||
PRINTF("Params on the address %d\n",(unsigned int)params);
|
||||
PRINTF("Address to check %s\n",params->address_to_check);
|
||||
PRINTF("Params on the address %d\n", (unsigned int) params);
|
||||
PRINTF("Address to check %s\n", params->address_to_check);
|
||||
PRINTF("Inside handle_check_address\n");
|
||||
params->result = 0;
|
||||
if (params->address_to_check == 0) {
|
||||
@@ -17,27 +17,23 @@ void handle_check_address(check_address_parameters_t* params, chain_config_t* ch
|
||||
}
|
||||
|
||||
uint8_t i;
|
||||
uint8_t *bip32_path_ptr = params->address_parameters;
|
||||
uint8_t* bip32_path_ptr = params->address_parameters;
|
||||
uint8_t bip32PathLength = *(bip32_path_ptr++);
|
||||
cx_sha3_t local_sha3;
|
||||
|
||||
// Common memory is used for locals that are not used concurrently
|
||||
union group1
|
||||
{
|
||||
union group1 {
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
char address[51];
|
||||
} locals_union1;
|
||||
union group2
|
||||
{
|
||||
union group2 {
|
||||
uint8_t privateKeyData[32];
|
||||
cx_ecfp_public_key_t publicKey;
|
||||
} locals_union2;
|
||||
|
||||
|
||||
if ((bip32PathLength < 0x01) ||
|
||||
(bip32PathLength > MAX_BIP32_PATH) ||
|
||||
(bip32PathLength*4 != params->address_parameters_length - 1)) {
|
||||
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH) ||
|
||||
(bip32PathLength * 4 != params->address_parameters_length - 1)) {
|
||||
PRINTF("Invalid path\n");
|
||||
return;
|
||||
}
|
||||
@@ -45,22 +41,34 @@ void handle_check_address(check_address_parameters_t* params, chain_config_t* ch
|
||||
locals_union1.bip32Path[i] = U4BE(bip32_path_ptr, 0);
|
||||
bip32_path_ptr += 4;
|
||||
}
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1, locals_union1.bip32Path, bip32PathLength, locals_union2.privateKeyData, NULL);
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1,
|
||||
locals_union1.bip32Path,
|
||||
bip32PathLength,
|
||||
locals_union2.privateKeyData,
|
||||
NULL);
|
||||
ZERO(&locals_union1);
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, locals_union2.privateKeyData, 32, &locals_union1.privateKey);
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1,
|
||||
locals_union2.privateKeyData,
|
||||
32,
|
||||
&locals_union1.privateKey);
|
||||
ZERO(&locals_union2);
|
||||
cx_ecfp_generate_pair(CX_CURVE_256K1, &locals_union2.publicKey, &locals_union1.privateKey, 1);
|
||||
ZERO(&locals_union1);
|
||||
getEthAddressStringFromKey(&locals_union2.publicKey, (uint8_t*)locals_union1.address, &local_sha3, chain_config);
|
||||
getEthAddressStringFromKey(&locals_union2.publicKey,
|
||||
(uint8_t*) locals_union1.address,
|
||||
&local_sha3,
|
||||
chain_config);
|
||||
ZERO(&locals_union2);
|
||||
|
||||
uint8_t offset_0x = 0;
|
||||
if(memcmp(params->address_to_check, "0x", 2) == 0){
|
||||
if (memcmp(params->address_to_check, "0x", 2) == 0) {
|
||||
offset_0x = 2;
|
||||
}
|
||||
|
||||
if ((strlen(locals_union1.address) != strlen(params->address_to_check + offset_0x)) ||
|
||||
memcmp(locals_union1.address, params->address_to_check + offset_0x, strlen(locals_union1.address)) != 0) {
|
||||
memcmp(locals_union1.address,
|
||||
params->address_to_check + offset_0x,
|
||||
strlen(locals_union1.address)) != 0) {
|
||||
PRINTF("Addresses doesn't match\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "swap_lib_calls.h"
|
||||
#include "chainConfig.h"
|
||||
|
||||
void handle_check_address(check_address_parameters_t* check_address_params, chain_config_t* chain_config);
|
||||
void handle_check_address(check_address_parameters_t* check_address_params,
|
||||
chain_config_t* chain_config);
|
||||
|
||||
#endif // _HANDLE_CHECK_ADDRESS_H_
|
||||
#endif // _HANDLE_CHECK_ADDRESS_H_
|
||||
@@ -6,8 +6,8 @@
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void handle_get_printable_amount( get_printable_amount_parameters_t* params, chain_config_t *config) {
|
||||
void handle_get_printable_amount(get_printable_amount_parameters_t* params,
|
||||
chain_config_t* config) {
|
||||
uint8_t decimals;
|
||||
char ticker[MAX_TICKER_LEN];
|
||||
memset(params->printable_amount, 0, sizeof(params->printable_amount));
|
||||
@@ -15,19 +15,27 @@ void handle_get_printable_amount( get_printable_amount_parameters_t* params, cha
|
||||
PRINTF("Amount is too big, 32 bytes max but buffer has %u bytes", params->amount_length);
|
||||
os_lib_end();
|
||||
}
|
||||
if(!parse_swap_config(params->coin_configuration, params->coin_configuration_length, ticker, &decimals)){
|
||||
if (!parse_swap_config(params->coin_configuration,
|
||||
params->coin_configuration_length,
|
||||
ticker,
|
||||
&decimals)) {
|
||||
PRINTF("Error while parsing config\n");
|
||||
os_lib_end();
|
||||
}
|
||||
|
||||
// If the amount is a fee, its value is nominated in ETH even if we're doing an ERC20 swap
|
||||
if(params->is_fee){
|
||||
if (params->is_fee) {
|
||||
uint8_t ticker_len = strnlen(config->coinName, sizeof(config->coinName));
|
||||
memcpy(ticker, config->coinName, ticker_len);
|
||||
ticker[ticker_len] = ' ';
|
||||
ticker[ticker_len+1] = '\0';
|
||||
ticker[ticker_len + 1] = '\0';
|
||||
decimals = WEI_TO_ETHER;
|
||||
}
|
||||
|
||||
amountToString(params->amount, params->amount_length, decimals, ticker, params->printable_amount, sizeof(params->printable_amount));
|
||||
amountToString(params->amount,
|
||||
params->amount_length,
|
||||
decimals,
|
||||
ticker,
|
||||
params->printable_amount,
|
||||
sizeof(params->printable_amount));
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "swap_lib_calls.h"
|
||||
#include "chainConfig.h"
|
||||
|
||||
void handle_get_printable_amount(get_printable_amount_parameters_t* get_printable_amount_params, chain_config_t *config);
|
||||
void handle_get_printable_amount(get_printable_amount_parameters_t* get_printable_amount_params,
|
||||
chain_config_t* config);
|
||||
|
||||
#endif // _HANDLE_GET_PRINTABLE_AMOUNT_H_
|
||||
#endif // _HANDLE_GET_PRINTABLE_AMOUNT_H_
|
||||
@@ -4,13 +4,15 @@
|
||||
#include "shared_context.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
void copy_transaction_parameters(create_transaction_parameters_t* sign_transaction_params, chain_config_t *config) {
|
||||
void copy_transaction_parameters(create_transaction_parameters_t* sign_transaction_params,
|
||||
chain_config_t* config) {
|
||||
// first copy parameters to stack, and then to global data.
|
||||
// We need this "trick" as the input data position can overlap with app-ethereum globals
|
||||
txStringProperties_t stack_data;
|
||||
memset(&stack_data, 0, sizeof(stack_data));
|
||||
strncpy(stack_data.fullAddress, sign_transaction_params->destination_address, sizeof(stack_data.fullAddress));
|
||||
strncpy(stack_data.fullAddress,
|
||||
sign_transaction_params->destination_address,
|
||||
sizeof(stack_data.fullAddress));
|
||||
if ((stack_data.fullAddress[sizeof(stack_data.fullAddress) - 1] != '\0') ||
|
||||
(sign_transaction_params->amount_length > 32) ||
|
||||
(sign_transaction_params->fee_amount_length > 8)) {
|
||||
@@ -19,21 +21,35 @@ void copy_transaction_parameters(create_transaction_parameters_t* sign_transacti
|
||||
|
||||
uint8_t decimals;
|
||||
char ticker[MAX_TICKER_LEN];
|
||||
if(!parse_swap_config(sign_transaction_params->coin_configuration, sign_transaction_params->coin_configuration_length, ticker, &decimals)){
|
||||
if (!parse_swap_config(sign_transaction_params->coin_configuration,
|
||||
sign_transaction_params->coin_configuration_length,
|
||||
ticker,
|
||||
&decimals)) {
|
||||
PRINTF("Error while parsing config\n");
|
||||
os_lib_end();
|
||||
}
|
||||
amountToString(sign_transaction_params->amount, sign_transaction_params->amount_length, decimals, ticker, stack_data.fullAmount, sizeof(stack_data.fullAmount));
|
||||
amountToString(sign_transaction_params->amount,
|
||||
sign_transaction_params->amount_length,
|
||||
decimals,
|
||||
ticker,
|
||||
stack_data.fullAmount,
|
||||
sizeof(stack_data.fullAmount));
|
||||
|
||||
// If the amount is a fee, its value is nominated in ETH even if we're doing an ERC20 swap
|
||||
strcpy(ticker, config->coinName);
|
||||
decimals = WEI_TO_ETHER;
|
||||
amountToString(sign_transaction_params->fee_amount, sign_transaction_params->fee_amount_length, decimals, ticker, stack_data.maxFee, sizeof(stack_data.maxFee));
|
||||
amountToString(sign_transaction_params->fee_amount,
|
||||
sign_transaction_params->fee_amount_length,
|
||||
decimals,
|
||||
ticker,
|
||||
stack_data.maxFee,
|
||||
sizeof(stack_data.maxFee));
|
||||
|
||||
memcpy(&strings.common, &stack_data, sizeof(stack_data));
|
||||
}
|
||||
|
||||
void handle_swap_sign_transaction(create_transaction_parameters_t* sign_transaction_params, chain_config_t *config) {
|
||||
void handle_swap_sign_transaction(create_transaction_parameters_t* sign_transaction_params,
|
||||
chain_config_t* config) {
|
||||
copy_transaction_parameters(sign_transaction_params, config);
|
||||
chainConfig = config;
|
||||
reset_app_context();
|
||||
@@ -41,25 +57,25 @@ void handle_swap_sign_transaction(create_transaction_parameters_t* sign_transact
|
||||
io_seproxyhal_init();
|
||||
|
||||
if (N_storage.initialized != 0x01) {
|
||||
internalStorage_t storage;
|
||||
storage.dataAllowed = 0x00;
|
||||
storage.contractDetails = 0x00;
|
||||
storage.initialized = 0x01;
|
||||
nvm_write((void*)&N_storage, (void*)&storage, sizeof(internalStorage_t));
|
||||
internalStorage_t storage;
|
||||
storage.dataAllowed = 0x00;
|
||||
storage.contractDetails = 0x00;
|
||||
storage.initialized = 0x01;
|
||||
nvm_write((void*) &N_storage, (void*) &storage, sizeof(internalStorage_t));
|
||||
}
|
||||
|
||||
UX_INIT();
|
||||
USB_power(0);
|
||||
USB_power(1);
|
||||
//ui_idle();
|
||||
// ui_idle();
|
||||
PRINTF("USB power ON/OFF\n");
|
||||
#ifdef TARGET_NANOX
|
||||
// grab the current plane mode setting
|
||||
G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
|
||||
#endif // TARGET_NANOX
|
||||
#endif // TARGET_NANOX
|
||||
#ifdef HAVE_BLE
|
||||
BLE_power(0, NULL);
|
||||
BLE_power(1, "Nano X");
|
||||
#endif // HAVE_BLE
|
||||
#endif // HAVE_BLE
|
||||
app_main();
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "swap_lib_calls.h"
|
||||
#include "chainConfig.h"
|
||||
|
||||
void handle_swap_sign_transaction(create_transaction_parameters_t* get_printable_amount_params, chain_config_t *config);
|
||||
void handle_swap_sign_transaction(create_transaction_parameters_t* get_printable_amount_params,
|
||||
chain_config_t* config);
|
||||
|
||||
#endif // _HANDLE_SWAP_SIGN_TRANSACTION_H_
|
||||
#endif // _HANDLE_SWAP_SIGN_TRANSACTION_H_
|
||||
603
src/main.c
603
src/main.c
@@ -1,19 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
#include "shared_context.h"
|
||||
#include "apdu_constants.h"
|
||||
@@ -67,23 +67,23 @@ const internalStorage_t N_storage_real;
|
||||
chain_config_t *chainConfig;
|
||||
|
||||
void reset_app_context() {
|
||||
//PRINTF("!!RESET_APP_CONTEXT\n");
|
||||
appState = APP_STATE_IDLE;
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
|
||||
called_from_swap = false;
|
||||
// PRINTF("!!RESET_APP_CONTEXT\n");
|
||||
appState = APP_STATE_IDLE;
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
|
||||
called_from_swap = false;
|
||||
#ifdef HAVE_STARKWARE
|
||||
quantumSet = false;
|
||||
quantumSet = false;
|
||||
#endif
|
||||
#ifdef HAVE_ETH2
|
||||
eth2WithdrawalIndex = 0;
|
||||
eth2WithdrawalIndex = 0;
|
||||
#endif
|
||||
memset((uint8_t*)&txContext, 0, sizeof(txContext));
|
||||
memset((uint8_t*)&tmpContent, 0, sizeof(tmpContent));
|
||||
memset((uint8_t *) &txContext, 0, sizeof(txContext));
|
||||
memset((uint8_t *) &tmpContent, 0, sizeof(tmpContent));
|
||||
}
|
||||
|
||||
void ui_idle(void) {
|
||||
// reserve a display stack slot if none yet
|
||||
if(G_ux.stack_count == 0) {
|
||||
if (G_ux.stack_count == 0) {
|
||||
ux_stack_push();
|
||||
}
|
||||
ux_flow_init(0, ux_idle_flow, NULL);
|
||||
@@ -92,24 +92,24 @@ void ui_idle(void) {
|
||||
unsigned int io_seproxyhal_touch_exit(const bagl_element_t *e) {
|
||||
// Go back to the dashboard
|
||||
os_sched_exit(0);
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
#if defined(TARGET_NANOS)
|
||||
unsigned int ui_address_nanos_button(unsigned int button_mask, unsigned int button_mask_counter) {
|
||||
switch(button_mask) {
|
||||
case BUTTON_EVT_RELEASED|BUTTON_LEFT: // CANCEL
|
||||
io_seproxyhal_touch_address_cancel(NULL);
|
||||
switch (button_mask) {
|
||||
case BUTTON_EVT_RELEASED | BUTTON_LEFT: // CANCEL
|
||||
io_seproxyhal_touch_address_cancel(NULL);
|
||||
break;
|
||||
|
||||
case BUTTON_EVT_RELEASED|BUTTON_RIGHT: { // OK
|
||||
io_seproxyhal_touch_address_ok(NULL);
|
||||
break;
|
||||
case BUTTON_EVT_RELEASED | BUTTON_RIGHT: { // OK
|
||||
io_seproxyhal_touch_address_ok(NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif // #if defined(TARGET_NANOS)
|
||||
#endif // #if defined(TARGET_NANOS)
|
||||
|
||||
void io_seproxyhal_send_status(uint32_t sw) {
|
||||
G_io_apdu_buffer[0] = ((sw >> 8) & 0xff);
|
||||
@@ -117,60 +117,59 @@ void io_seproxyhal_send_status(uint32_t sw) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||
}
|
||||
|
||||
void format_signature_out(const uint8_t* signature) {
|
||||
memset(G_io_apdu_buffer + 1, 0x00, 64);
|
||||
uint8_t offset = 1;
|
||||
uint8_t xoffset = 4; //point to r value
|
||||
//copy r
|
||||
uint8_t xlength = signature[xoffset-1];
|
||||
if (xlength == 33) {
|
||||
xlength = 32;
|
||||
xoffset ++;
|
||||
}
|
||||
memmove(G_io_apdu_buffer+offset+32-xlength, signature+xoffset, xlength);
|
||||
offset += 32;
|
||||
xoffset += xlength +2; //move over rvalue and TagLEn
|
||||
//copy s value
|
||||
xlength = signature[xoffset-1];
|
||||
if (xlength == 33) {
|
||||
xlength = 32;
|
||||
xoffset ++;
|
||||
}
|
||||
memmove(G_io_apdu_buffer+offset+32-xlength, signature+xoffset, xlength);
|
||||
void format_signature_out(const uint8_t *signature) {
|
||||
memset(G_io_apdu_buffer + 1, 0x00, 64);
|
||||
uint8_t offset = 1;
|
||||
uint8_t xoffset = 4; // point to r value
|
||||
// copy r
|
||||
uint8_t xlength = signature[xoffset - 1];
|
||||
if (xlength == 33) {
|
||||
xlength = 32;
|
||||
xoffset++;
|
||||
}
|
||||
memmove(G_io_apdu_buffer + offset + 32 - xlength, signature + xoffset, xlength);
|
||||
offset += 32;
|
||||
xoffset += xlength + 2; // move over rvalue and TagLEn
|
||||
// copy s value
|
||||
xlength = signature[xoffset - 1];
|
||||
if (xlength == 33) {
|
||||
xlength = 32;
|
||||
xoffset++;
|
||||
}
|
||||
memmove(G_io_apdu_buffer + offset + 32 - xlength, signature + xoffset, xlength);
|
||||
}
|
||||
|
||||
unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) {
|
||||
switch (channel & ~(IO_FLAGS)) {
|
||||
case CHANNEL_KEYBOARD:
|
||||
break;
|
||||
case CHANNEL_KEYBOARD:
|
||||
break;
|
||||
|
||||
// multiplexed io exchange over a SPI channel and TLV encapsulated protocol
|
||||
case CHANNEL_SPI:
|
||||
if (tx_len) {
|
||||
io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
|
||||
// multiplexed io exchange over a SPI channel and TLV encapsulated protocol
|
||||
case CHANNEL_SPI:
|
||||
if (tx_len) {
|
||||
io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
|
||||
|
||||
if (channel & IO_RESET_AFTER_REPLIED) {
|
||||
reset();
|
||||
if (channel & IO_RESET_AFTER_REPLIED) {
|
||||
reset();
|
||||
}
|
||||
return 0; // nothing received from the master so far (it's a tx
|
||||
// transaction)
|
||||
} else {
|
||||
return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0);
|
||||
}
|
||||
return 0; // nothing received from the master so far (it's a tx
|
||||
// transaction)
|
||||
} else {
|
||||
return io_seproxyhal_spi_recv(G_io_apdu_buffer,
|
||||
sizeof(G_io_apdu_buffer), 0);
|
||||
}
|
||||
|
||||
default:
|
||||
THROW(INVALID_PARAMETER);
|
||||
default:
|
||||
THROW(INVALID_PARAMETER);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
tokenDefinition_t* getKnownToken(uint8_t *contractAddress) {
|
||||
tokenDefinition_t *getKnownToken(uint8_t *contractAddress) {
|
||||
tokenDefinition_t *currentToken = NULL;
|
||||
#ifdef HAVE_TOKENS_LIST
|
||||
uint32_t numTokens = 0;
|
||||
uint32_t i;
|
||||
switch(chainConfig->kind) {
|
||||
switch (chainConfig->kind) {
|
||||
case CHAIN_KIND_AKROMA:
|
||||
numTokens = NUM_TOKENS_AKROMA;
|
||||
break;
|
||||
@@ -262,97 +261,97 @@ tokenDefinition_t* getKnownToken(uint8_t *contractAddress) {
|
||||
numTokens = NUM_TOKENS_THUNDERCORE;
|
||||
break;
|
||||
}
|
||||
for (i=0; i<numTokens; i++) {
|
||||
switch(chainConfig->kind) {
|
||||
for (i = 0; i < numTokens; i++) {
|
||||
switch (chainConfig->kind) {
|
||||
case CHAIN_KIND_AKROMA:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_AKROMA[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_AKROMA[i]);
|
||||
break;
|
||||
case CHAIN_KIND_ETHEREUM:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_ETHEREUM[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_ETHEREUM[i]);
|
||||
break;
|
||||
case CHAIN_KIND_ETHEREUM_CLASSIC:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_ETHEREUM_CLASSIC[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_ETHEREUM_CLASSIC[i]);
|
||||
break;
|
||||
case CHAIN_KIND_PIRL:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_PIRL[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_PIRL[i]);
|
||||
break;
|
||||
case CHAIN_KIND_POA:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_POA[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_POA[i]);
|
||||
break;
|
||||
case CHAIN_KIND_ARTIS_SIGMA1:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_ARTIS_SIGMA1[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_ARTIS_SIGMA1[i]);
|
||||
break;
|
||||
case CHAIN_KIND_ARTIS_TAU1:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_ARTIS_TAU1[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_ARTIS_TAU1[i]);
|
||||
break;
|
||||
case CHAIN_KIND_RSK:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_RSK[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_RSK[i]);
|
||||
break;
|
||||
case CHAIN_KIND_EXPANSE:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_EXPANSE[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_EXPANSE[i]);
|
||||
break;
|
||||
case CHAIN_KIND_UBIQ:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_UBIQ[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_UBIQ[i]);
|
||||
break;
|
||||
case CHAIN_KIND_WANCHAIN:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_WANCHAIN[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_WANCHAIN[i]);
|
||||
break;
|
||||
case CHAIN_KIND_KUSD:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_KUSD[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_KUSD[i]);
|
||||
break;
|
||||
case CHAIN_KIND_MUSICOIN:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_MUSICOIN[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_MUSICOIN[i]);
|
||||
break;
|
||||
case CHAIN_KIND_CALLISTO:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_CALLISTO[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_CALLISTO[i]);
|
||||
break;
|
||||
case CHAIN_KIND_ETHERSOCIAL:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_ETHERSOCIAL[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_ETHERSOCIAL[i]);
|
||||
break;
|
||||
case CHAIN_KIND_ELLAISM:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_ELLAISM[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_ELLAISM[i]);
|
||||
break;
|
||||
case CHAIN_KIND_ETHER1:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_ETHER1[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_ETHER1[i]);
|
||||
break;
|
||||
case CHAIN_KIND_ETHERGEM:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_ETHERGEM[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_ETHERGEM[i]);
|
||||
break;
|
||||
case CHAIN_KIND_ATHEIOS:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_ATHEIOS[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_ATHEIOS[i]);
|
||||
break;
|
||||
case CHAIN_KIND_GOCHAIN:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_GOCHAIN[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_GOCHAIN[i]);
|
||||
break;
|
||||
case CHAIN_KIND_MIX:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_MIX[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_MIX[i]);
|
||||
break;
|
||||
case CHAIN_KIND_REOSC:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_REOSC[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_REOSC[i]);
|
||||
break;
|
||||
case CHAIN_KIND_HPB:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_HPB[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_HPB[i]);
|
||||
break;
|
||||
case CHAIN_KIND_TOMOCHAIN:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_TOMOCHAIN[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_TOMOCHAIN[i]);
|
||||
break;
|
||||
case CHAIN_KIND_TOBALABA:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_TOBALABA[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_TOBALABA[i]);
|
||||
break;
|
||||
case CHAIN_KIND_DEXON:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_DEXON[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_DEXON[i]);
|
||||
break;
|
||||
case CHAIN_KIND_VOLTA:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_VOLTA[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_VOLTA[i]);
|
||||
break;
|
||||
case CHAIN_KIND_EWC:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_EWC[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_EWC[i]);
|
||||
break;
|
||||
case CHAIN_KIND_WEBCHAIN:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_WEBCHAIN[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_WEBCHAIN[i]);
|
||||
break;
|
||||
case CHAIN_KIND_THUNDERCORE:
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_THUNDERCORE[i]);
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_THUNDERCORE[i]);
|
||||
break
|
||||
}
|
||||
if (memcmp(currentToken->address, tmpContent.txContent.destination, 20) == 0) {
|
||||
@@ -360,91 +359,151 @@ tokenDefinition_t* getKnownToken(uint8_t *contractAddress) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for(size_t i=0; i<MAX_TOKEN; i++){
|
||||
currentToken = &tmpCtx.transactionContext.tokens[i];
|
||||
if (tmpCtx.transactionContext.tokenSet[i] && (memcmp(currentToken->address, contractAddress, 20) == 0)) {
|
||||
PRINTF("Token found at index %d\n", i);
|
||||
return currentToken;
|
||||
}
|
||||
for (size_t i = 0; i < MAX_TOKEN; i++) {
|
||||
currentToken = &tmpCtx.transactionContext.tokens[i];
|
||||
if (tmpCtx.transactionContext.tokenSet[i] &&
|
||||
(memcmp(currentToken->address, contractAddress, 20) == 0)) {
|
||||
PRINTF("Token found at index %d\n", i);
|
||||
return currentToken;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void handleApdu(unsigned int *flags, unsigned int *tx) {
|
||||
unsigned short sw = 0;
|
||||
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
unsigned short sw = 0;
|
||||
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
if (G_io_apdu_buffer[OFFSET_CLA] == STARKWARE_CLA) {
|
||||
switch(G_io_apdu_buffer[OFFSET_INS]) {
|
||||
case STARKWARE_INS_GET_PUBLIC_KEY:
|
||||
handleStarkwareGetPublicKey(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
case STARKWARE_INS_SIGN_MESSAGE:
|
||||
handleStarkwareSignMessage(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
case STARKWARE_INS_PROVIDE_QUANTUM:
|
||||
handleStarkwareProvideQuantum(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
case STARKWARE_INS_UNSAFE_SIGN:
|
||||
handleStarkwareUnsafeSign(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
default:
|
||||
THROW(0x6D00);
|
||||
break;
|
||||
}
|
||||
CLOSE_TRY;
|
||||
return;
|
||||
}
|
||||
if (G_io_apdu_buffer[OFFSET_CLA] == STARKWARE_CLA) {
|
||||
switch (G_io_apdu_buffer[OFFSET_INS]) {
|
||||
case STARKWARE_INS_GET_PUBLIC_KEY:
|
||||
handleStarkwareGetPublicKey(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
case STARKWARE_INS_SIGN_MESSAGE:
|
||||
handleStarkwareSignMessage(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
case STARKWARE_INS_PROVIDE_QUANTUM:
|
||||
handleStarkwareProvideQuantum(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
case STARKWARE_INS_UNSAFE_SIGN:
|
||||
handleStarkwareUnsafeSign(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
default:
|
||||
THROW(0x6D00);
|
||||
break;
|
||||
}
|
||||
CLOSE_TRY;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (G_io_apdu_buffer[OFFSET_CLA] != CLA) {
|
||||
THROW(0x6E00);
|
||||
}
|
||||
if (G_io_apdu_buffer[OFFSET_CLA] != CLA) {
|
||||
THROW(0x6E00);
|
||||
}
|
||||
|
||||
switch (G_io_apdu_buffer[OFFSET_INS]) {
|
||||
case INS_GET_PUBLIC_KEY:
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
|
||||
handleGetPublicKey(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
switch (G_io_apdu_buffer[OFFSET_INS]) {
|
||||
case INS_GET_PUBLIC_KEY:
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
|
||||
handleGetPublicKey(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
|
||||
case INS_PROVIDE_ERC20_TOKEN_INFORMATION:
|
||||
handleProvideErc20TokenInformation(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
case INS_PROVIDE_ERC20_TOKEN_INFORMATION:
|
||||
handleProvideErc20TokenInformation(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
|
||||
case INS_SIGN:
|
||||
handleSign(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
case INS_SIGN:
|
||||
handleSign(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
|
||||
case INS_GET_APP_CONFIGURATION:
|
||||
handleGetAppConfiguration(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
case INS_GET_APP_CONFIGURATION:
|
||||
handleGetAppConfiguration(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
|
||||
case INS_SIGN_PERSONAL_MESSAGE:
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
|
||||
handleSignPersonalMessage(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
case INS_SIGN_PERSONAL_MESSAGE:
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
|
||||
handleSignPersonalMessage(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
|
||||
case INS_SIGN_EIP_712_MESSAGE:
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
|
||||
handleSignEIP712Message(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
case INS_SIGN_EIP_712_MESSAGE:
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
|
||||
handleSignEIP712Message(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_ETH2
|
||||
|
||||
case INS_GET_ETH2_PUBLIC_KEY:
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
|
||||
handleGetEth2PublicKey(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
case INS_GET_ETH2_PUBLIC_KEY:
|
||||
memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN);
|
||||
handleGetEth2PublicKey(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
|
||||
case INS_SET_ETH2_WITHDRAWAL_INDEX:
|
||||
handleSetEth2WithdrawalIndex(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
||||
break;
|
||||
case INS_SET_ETH2_WITHDRAWAL_INDEX:
|
||||
handleSetEth2WithdrawalIndex(G_io_apdu_buffer[OFFSET_P1],
|
||||
G_io_apdu_buffer[OFFSET_P2],
|
||||
G_io_apdu_buffer + OFFSET_CDATA,
|
||||
G_io_apdu_buffer[OFFSET_LC],
|
||||
flags,
|
||||
tx);
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -453,40 +512,40 @@ void handleApdu(unsigned int *flags, unsigned int *tx) {
|
||||
goto return_to_dashboard;
|
||||
#endif
|
||||
|
||||
default:
|
||||
THROW(0x6D00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
CATCH(EXCEPTION_IO_RESET) {
|
||||
THROW(EXCEPTION_IO_RESET);
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
switch (e & 0xF000) {
|
||||
case 0x6000:
|
||||
// Wipe the transaction context and report the exception
|
||||
sw = e;
|
||||
reset_app_context();
|
||||
break;
|
||||
case 0x9000:
|
||||
// All is well
|
||||
sw = e;
|
||||
break;
|
||||
default:
|
||||
// Internal error
|
||||
sw = 0x6800 | (e & 0x7FF);
|
||||
reset_app_context();
|
||||
break;
|
||||
default:
|
||||
THROW(0x6D00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Unexpected exception => report
|
||||
G_io_apdu_buffer[*tx] = sw >> 8;
|
||||
G_io_apdu_buffer[*tx + 1] = sw;
|
||||
*tx += 2;
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
CATCH(EXCEPTION_IO_RESET) {
|
||||
THROW(EXCEPTION_IO_RESET);
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
switch (e & 0xF000) {
|
||||
case 0x6000:
|
||||
// Wipe the transaction context and report the exception
|
||||
sw = e;
|
||||
reset_app_context();
|
||||
break;
|
||||
case 0x9000:
|
||||
// All is well
|
||||
sw = e;
|
||||
break;
|
||||
default:
|
||||
// Internal error
|
||||
sw = 0x6800 | (e & 0x7FF);
|
||||
reset_app_context();
|
||||
break;
|
||||
}
|
||||
// Unexpected exception => report
|
||||
G_io_apdu_buffer[*tx] = sw >> 8;
|
||||
G_io_apdu_buffer[*tx + 1] = sw;
|
||||
*tx += 2;
|
||||
}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
}
|
||||
|
||||
void app_main(void) {
|
||||
@@ -506,8 +565,8 @@ void app_main(void) {
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
rx = tx;
|
||||
tx = 0; // ensure no race in catch_other if io_exchange throws
|
||||
// an error
|
||||
tx = 0; // ensure no race in catch_other if io_exchange throws
|
||||
// an error
|
||||
rx = io_exchange(CHANNEL_APDU | flags, rx);
|
||||
flags = 0;
|
||||
|
||||
@@ -525,20 +584,20 @@ void app_main(void) {
|
||||
}
|
||||
CATCH_OTHER(e) {
|
||||
switch (e & 0xF000) {
|
||||
case 0x6000:
|
||||
// Wipe the transaction context and report the exception
|
||||
sw = e;
|
||||
reset_app_context();
|
||||
break;
|
||||
case 0x9000:
|
||||
// All is well
|
||||
sw = e;
|
||||
break;
|
||||
default:
|
||||
// Internal error
|
||||
sw = 0x6800 | (e & 0x7FF);
|
||||
reset_app_context();
|
||||
break;
|
||||
case 0x6000:
|
||||
// Wipe the transaction context and report the exception
|
||||
sw = e;
|
||||
reset_app_context();
|
||||
break;
|
||||
case 0x9000:
|
||||
// All is well
|
||||
sw = e;
|
||||
break;
|
||||
default:
|
||||
// Internal error
|
||||
sw = 0x6800 | (e & 0x7FF);
|
||||
reset_app_context();
|
||||
break;
|
||||
}
|
||||
if (e != 0x9000) {
|
||||
flags &= ~IO_ASYNCH_REPLY;
|
||||
@@ -554,13 +613,13 @@ void app_main(void) {
|
||||
END_TRY;
|
||||
}
|
||||
|
||||
//return_to_dashboard:
|
||||
// return_to_dashboard:
|
||||
return;
|
||||
}
|
||||
|
||||
// override point, but nothing more to do
|
||||
void io_seproxyhal_display(const bagl_element_t *element) {
|
||||
io_seproxyhal_display_default((bagl_element_t *)element);
|
||||
io_seproxyhal_display_default((bagl_element_t *) element);
|
||||
}
|
||||
|
||||
unsigned char io_event(unsigned char channel) {
|
||||
@@ -569,26 +628,28 @@ unsigned char io_event(unsigned char channel) {
|
||||
|
||||
// can't have more than one tag in the reply, not supported yet.
|
||||
switch (G_io_seproxyhal_spi_buffer[0]) {
|
||||
case SEPROXYHAL_TAG_FINGER_EVENT:
|
||||
UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer);
|
||||
break;
|
||||
case SEPROXYHAL_TAG_FINGER_EVENT:
|
||||
UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer);
|
||||
break;
|
||||
|
||||
case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT:
|
||||
UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer);
|
||||
break;
|
||||
case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT:
|
||||
UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer);
|
||||
break;
|
||||
|
||||
case SEPROXYHAL_TAG_STATUS_EVENT:
|
||||
if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID && !(U4BE(G_io_seproxyhal_spi_buffer, 3) & SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) {
|
||||
THROW(EXCEPTION_IO_RESET);
|
||||
}
|
||||
// no break is intentional
|
||||
default:
|
||||
UX_DEFAULT_EVENT();
|
||||
break;
|
||||
case SEPROXYHAL_TAG_STATUS_EVENT:
|
||||
if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID &&
|
||||
!(U4BE(G_io_seproxyhal_spi_buffer, 3) &
|
||||
SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) {
|
||||
THROW(EXCEPTION_IO_RESET);
|
||||
}
|
||||
// no break is intentional
|
||||
default:
|
||||
UX_DEFAULT_EVENT();
|
||||
break;
|
||||
|
||||
case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
|
||||
UX_DISPLAYED_EVENT({});
|
||||
break;
|
||||
case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
|
||||
UX_DISPLAYED_EVENT({});
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case SEPROXYHAL_TAG_TICKER_EVENT:
|
||||
@@ -609,21 +670,17 @@ unsigned char io_event(unsigned char channel) {
|
||||
}
|
||||
|
||||
void app_exit() {
|
||||
|
||||
BEGIN_TRY_L(exit) {
|
||||
TRY_L(exit) {
|
||||
os_sched_exit(-1);
|
||||
}
|
||||
FINALLY_L(exit) {
|
||||
|
||||
}
|
||||
}
|
||||
END_TRY_L(exit);
|
||||
}
|
||||
|
||||
|
||||
void coin_main_with_config(chain_config_t *config) {
|
||||
|
||||
chainConfig = config;
|
||||
reset_app_context();
|
||||
tmpCtx.transactionContext.currentTokenIndex = 0;
|
||||
@@ -638,14 +695,14 @@ void coin_main_with_config(chain_config_t *config) {
|
||||
#ifdef TARGET_NANOX
|
||||
// grab the current plane mode setting
|
||||
G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
|
||||
#endif // TARGET_NANOX
|
||||
#endif // TARGET_NANOX
|
||||
|
||||
if (N_storage.initialized != 0x01) {
|
||||
internalStorage_t storage;
|
||||
storage.dataAllowed = 0x00;
|
||||
storage.contractDetails = 0x00;
|
||||
storage.initialized = 0x01;
|
||||
nvm_write((void*)&N_storage, (void*)&storage, sizeof(internalStorage_t));
|
||||
nvm_write((void *) &N_storage, (void *) &storage, sizeof(internalStorage_t));
|
||||
}
|
||||
|
||||
USB_power(0);
|
||||
@@ -656,7 +713,7 @@ void coin_main_with_config(chain_config_t *config) {
|
||||
#ifdef HAVE_BLE
|
||||
BLE_power(0, NULL);
|
||||
BLE_power(1, "Nano X");
|
||||
#endif // HAVE_BLE
|
||||
#endif // HAVE_BLE
|
||||
|
||||
app_main();
|
||||
}
|
||||
@@ -690,30 +747,37 @@ void coin_main() {
|
||||
coin_main_with_config(&coin_config);
|
||||
}
|
||||
|
||||
void library_main_with_config(chain_config_t *config, unsigned int command, unsigned int* call_parameters) {
|
||||
void library_main_with_config(chain_config_t *config,
|
||||
unsigned int command,
|
||||
unsigned int *call_parameters) {
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
check_api_level(CX_COMPAT_APILEVEL);
|
||||
PRINTF("Inside a library \n");
|
||||
switch (command) {
|
||||
case CHECK_ADDRESS:
|
||||
handle_check_address((check_address_parameters_t*)call_parameters, config);
|
||||
break;
|
||||
handle_check_address((check_address_parameters_t *) call_parameters, config);
|
||||
break;
|
||||
case SIGN_TRANSACTION:
|
||||
handle_swap_sign_transaction((create_transaction_parameters_t*)call_parameters, config);
|
||||
break;
|
||||
handle_swap_sign_transaction(
|
||||
(create_transaction_parameters_t *) call_parameters,
|
||||
config);
|
||||
break;
|
||||
case GET_PRINTABLE_AMOUNT:
|
||||
handle_get_printable_amount((get_printable_amount_parameters_t*)call_parameters, config);
|
||||
break;
|
||||
handle_get_printable_amount(
|
||||
(get_printable_amount_parameters_t *) call_parameters,
|
||||
config);
|
||||
break;
|
||||
}
|
||||
os_lib_end();
|
||||
}
|
||||
FINALLY {}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
}
|
||||
|
||||
void library_main(unsigned int call_id, unsigned int* call_parameters) {
|
||||
void library_main(unsigned int call_id, unsigned int *call_parameters) {
|
||||
chain_config_t coin_config;
|
||||
init_coin_config(&coin_config);
|
||||
library_main_with_config(&coin_config, call_id, call_parameters);
|
||||
@@ -736,22 +800,22 @@ __attribute__((section(".boot"))) int main(int arg0) {
|
||||
libcall_params[4] = 0;
|
||||
if (arg0) {
|
||||
// call as a library
|
||||
libcall_params[2] = ((unsigned int *)arg0)[1];
|
||||
libcall_params[4] = ((unsigned int *)arg0)[3]; // library arguments
|
||||
libcall_params[2] = ((unsigned int *) arg0)[1];
|
||||
libcall_params[4] = ((unsigned int *) arg0)[3]; // library arguments
|
||||
os_lib_call(&libcall_params);
|
||||
((unsigned int *)arg0)[0] = libcall_params[1];
|
||||
((unsigned int *) arg0)[0] = libcall_params[1];
|
||||
os_lib_end();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// launch coin application
|
||||
libcall_params[1] = 0x100; // use the Init call, as we won't exit
|
||||
libcall_params[1] = 0x100; // use the Init call, as we won't exit
|
||||
os_lib_call(&libcall_params);
|
||||
}
|
||||
}
|
||||
FINALLY {}
|
||||
FINALLY {
|
||||
}
|
||||
}
|
||||
END_TRY;
|
||||
// no return
|
||||
// no return
|
||||
#else
|
||||
// exit critical section
|
||||
__asm volatile("cpsie i");
|
||||
@@ -765,12 +829,12 @@ __attribute__((section(".boot"))) int main(int arg0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (((unsigned int *)arg0)[0] != 0x100) {
|
||||
if (((unsigned int *) arg0)[0] != 0x100) {
|
||||
app_exit();
|
||||
return 0;
|
||||
}
|
||||
unsigned int command = ((unsigned int *)arg0)[1];
|
||||
chain_config_t * chain_config = ((unsigned int *)arg0)[2];
|
||||
unsigned int command = ((unsigned int *) arg0)[1];
|
||||
chain_config_t *chain_config = ((unsigned int *) arg0)[2];
|
||||
switch (command) {
|
||||
case RUN_APPLICATION:
|
||||
// coin application launched from dashboard
|
||||
@@ -778,25 +842,18 @@ __attribute__((section(".boot"))) int main(int arg0) {
|
||||
app_exit();
|
||||
else
|
||||
coin_main_with_config(chain_config);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
if (chain_config == NULL)
|
||||
// Called as standalone eth library
|
||||
library_main(command, ((unsigned int *)arg0)[3]);// called as bitcoin library
|
||||
library_main(command, ((unsigned int *) arg0)[3]); // called as bitcoin library
|
||||
else
|
||||
// Called as a library from an altcoin
|
||||
library_main_with_config(chain_config, command, ((unsigned int *)arg0)[3]);// called as coin library
|
||||
break;
|
||||
library_main_with_config(chain_config,
|
||||
command,
|
||||
((unsigned int *) arg0)[3]); // called as coin library
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
#include "poorstream.h"
|
||||
|
||||
void poorstream_init(poorstream_t *stream, uint8_t *buffer) {
|
||||
memset((void*)stream, 0, sizeof(poorstream_t));
|
||||
stream->pointer = buffer;
|
||||
memset((void *) stream, 0, sizeof(poorstream_t));
|
||||
stream->pointer = buffer;
|
||||
}
|
||||
|
||||
void poorstream_flush(poorstream_t *stream) {
|
||||
//PRINTF("Flush\n");
|
||||
// PRINTF("Flush\n");
|
||||
*(stream->pointer + 0) = (stream->accumulator >> 56);
|
||||
*(stream->pointer + 1) = (stream->accumulator >> 48);
|
||||
*(stream->pointer + 2) = (stream->accumulator >> 40);
|
||||
@@ -23,12 +23,12 @@ void poorstream_write_bits(poorstream_t *stream, uint64_t bits, uint32_t num_bit
|
||||
stream->offset += num_bits;
|
||||
if (stream->offset < 64) {
|
||||
stream->accumulator |= (bits << (64 - stream->offset));
|
||||
//PRINTF("ACC |= << %d\n", (64 - stream->offset));
|
||||
// PRINTF("ACC |= << %d\n", (64 - stream->offset));
|
||||
} else {
|
||||
stream->offset -= 64;
|
||||
stream->mask = ((1 << (num_bits - stream->offset)) - 1);
|
||||
//PRINTF("Mask %lx\n", stream->mask);
|
||||
//PRINTF("Offset %d\n", stream->offset);
|
||||
// PRINTF("Mask %lx\n", stream->mask);
|
||||
// PRINTF("Offset %d\n", stream->offset);
|
||||
stream->accumulator |= ((bits >> stream->offset) & stream->mask);
|
||||
poorstream_flush(stream);
|
||||
stream->accumulator = 0;
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
#include "os.h"
|
||||
|
||||
typedef struct poorstream_t {
|
||||
uint8_t *pointer;
|
||||
uint32_t offset;
|
||||
uint64_t mask;
|
||||
uint64_t accumulator;
|
||||
uint8_t *pointer;
|
||||
uint32_t offset;
|
||||
uint64_t mask;
|
||||
uint64_t accumulator;
|
||||
} poorstream_t;
|
||||
|
||||
void poorstream_init(poorstream_t *stream, uint8_t *buffer);
|
||||
|
||||
@@ -22,24 +22,24 @@
|
||||
|
||||
#define WEI_TO_ETHER 18
|
||||
|
||||
#define N_storage (*(volatile internalStorage_t*) PIC(&N_storage_real))
|
||||
#define N_storage (*(volatile internalStorage_t *) PIC(&N_storage_real))
|
||||
|
||||
typedef struct internalStorage_t {
|
||||
unsigned char dataAllowed;
|
||||
unsigned char contractDetails;
|
||||
uint8_t initialized;
|
||||
unsigned char dataAllowed;
|
||||
unsigned char contractDetails;
|
||||
uint8_t initialized;
|
||||
} internalStorage_t;
|
||||
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
typedef enum starkQuantumType_e {
|
||||
|
||||
STARK_QUANTUM_LEGACY = 0x00,
|
||||
STARK_QUANTUM_ETH,
|
||||
STARK_QUANTUM_ERC20,
|
||||
STARK_QUANTUM_ERC721,
|
||||
STARK_QUANTUM_MINTABLE_ERC20,
|
||||
STARK_QUANTUM_MINTABLE_ERC721
|
||||
STARK_QUANTUM_LEGACY = 0x00,
|
||||
STARK_QUANTUM_ETH,
|
||||
STARK_QUANTUM_ERC20,
|
||||
STARK_QUANTUM_ERC721,
|
||||
STARK_QUANTUM_MINTABLE_ERC20,
|
||||
STARK_QUANTUM_MINTABLE_ERC721
|
||||
|
||||
} starkQuantumType_e;
|
||||
|
||||
@@ -47,11 +47,11 @@ typedef enum starkQuantumType_e {
|
||||
|
||||
typedef struct tokenContext_t {
|
||||
char pluginName[PLUGIN_ID_LENGTH];
|
||||
uint8_t pluginAvailable;
|
||||
uint8_t pluginAvailable;
|
||||
|
||||
uint8_t data[32];
|
||||
uint8_t fieldIndex;
|
||||
uint8_t fieldOffset;
|
||||
uint8_t fieldOffset;
|
||||
|
||||
uint8_t pluginUiMaxItems;
|
||||
uint8_t pluginUiCurrentItem;
|
||||
@@ -98,7 +98,6 @@ typedef struct messageSigningContext712_t {
|
||||
uint8_t messageHash[32];
|
||||
} messageSigningContext712_t;
|
||||
|
||||
|
||||
typedef union {
|
||||
publicKeyContext_t publicKeyContext;
|
||||
transactionContext_t transactionContext;
|
||||
@@ -107,22 +106,22 @@ typedef union {
|
||||
} tmpCtx_t;
|
||||
|
||||
typedef union {
|
||||
txContent_t txContent;
|
||||
cx_sha256_t sha2;
|
||||
char tmp[100];
|
||||
txContent_t txContent;
|
||||
cx_sha256_t sha2;
|
||||
char tmp[100];
|
||||
} tmpContent_t;
|
||||
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
typedef struct starkContext_t {
|
||||
uint8_t w1[32];
|
||||
uint8_t w2[32];
|
||||
uint8_t w3[32];
|
||||
uint8_t w4[32];
|
||||
uint8_t conditional;
|
||||
uint8_t transferDestination[32];
|
||||
uint8_t fact[32];
|
||||
uint8_t conditionAddress[20];
|
||||
uint8_t w1[32];
|
||||
uint8_t w2[32];
|
||||
uint8_t w3[32];
|
||||
uint8_t w4[32];
|
||||
uint8_t conditional;
|
||||
uint8_t transferDestination[32];
|
||||
uint8_t fact[32];
|
||||
uint8_t conditionAddress[20];
|
||||
} starkContext_t;
|
||||
|
||||
#endif
|
||||
@@ -134,27 +133,23 @@ typedef union {
|
||||
#endif
|
||||
} dataContext_t;
|
||||
|
||||
typedef enum {
|
||||
APP_STATE_IDLE,
|
||||
APP_STATE_SIGNING_TX,
|
||||
APP_STATE_SIGNING_MESSAGE
|
||||
} app_state_t;
|
||||
typedef enum { APP_STATE_IDLE, APP_STATE_SIGNING_TX, APP_STATE_SIGNING_MESSAGE } app_state_t;
|
||||
|
||||
typedef enum {
|
||||
CONTRACT_NONE,
|
||||
CONTRACT_ERC20,
|
||||
CONTRACT_ALLOWANCE,
|
||||
CONTRACT_NONE,
|
||||
CONTRACT_ERC20,
|
||||
CONTRACT_ALLOWANCE,
|
||||
#ifdef HAVE_STARKWARE
|
||||
CONTRACT_STARKWARE_REGISTER,
|
||||
CONTRACT_STARKWARE_DEPOSIT_TOKEN,
|
||||
CONTRACT_STARKWARE_DEPOSIT_ETH,
|
||||
CONTRACT_STARKWARE_WITHDRAW,
|
||||
CONTRACT_STARKWARE_DEPOSIT_CANCEL,
|
||||
CONTRACT_STARKWARE_DEPOSIT_RECLAIM,
|
||||
CONTRACT_STARKWARE_FULL_WITHDRAWAL,
|
||||
CONTRACT_STARKWARE_FREEZE,
|
||||
CONTRACT_STARKWARE_ESCAPE,
|
||||
CONTRACT_STARKWARE_VERIFY_ESCAPE
|
||||
CONTRACT_STARKWARE_REGISTER,
|
||||
CONTRACT_STARKWARE_DEPOSIT_TOKEN,
|
||||
CONTRACT_STARKWARE_DEPOSIT_ETH,
|
||||
CONTRACT_STARKWARE_WITHDRAW,
|
||||
CONTRACT_STARKWARE_DEPOSIT_CANCEL,
|
||||
CONTRACT_STARKWARE_DEPOSIT_RECLAIM,
|
||||
CONTRACT_STARKWARE_FULL_WITHDRAWAL,
|
||||
CONTRACT_STARKWARE_FREEZE,
|
||||
CONTRACT_STARKWARE_ESCAPE,
|
||||
CONTRACT_STARKWARE_VERIFY_ESCAPE
|
||||
#endif
|
||||
} contract_call_t;
|
||||
|
||||
@@ -196,5 +191,4 @@ extern uint32_t eth2WithdrawalIndex;
|
||||
|
||||
void reset_app_context(void);
|
||||
|
||||
#endif // __SHARED_CONTEXT_H__
|
||||
|
||||
#endif // __SHARED_CONTEXT_H__
|
||||
|
||||
@@ -5,18 +5,17 @@
|
||||
#include "ui_callbacks.h"
|
||||
#include "utils.h"
|
||||
|
||||
static unsigned char const C_cx_Stark256_n[] = {
|
||||
//n: 0x0800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xb7, 0x81, 0x12, 0x6d, 0xca, 0xe7, 0xb2, 0x32, 0x1e, 0x66, 0xa2, 0x41, 0xad, 0xc6, 0x4d, 0x2f};
|
||||
|
||||
// C_cx_secp256k1_n - (C_cx_secp256k1_n % C_cx_Stark256_n)
|
||||
static unsigned char const STARK_DERIVE_BIAS[] = {
|
||||
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
|
||||
0x38, 0xa1, 0x3b, 0x4b, 0x92, 0x0e, 0x94, 0x11, 0xae, 0x6d, 0xa5, 0xf4, 0x0b, 0x03, 0x58, 0xb1
|
||||
};
|
||||
static unsigned char const C_cx_Stark256_n[] = {
|
||||
// n: 0x0800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xb7, 0x81, 0x12, 0x6d, 0xca, 0xe7, 0xb2, 0x32, 0x1e, 0x66, 0xa2, 0x41, 0xad, 0xc6, 0x4d, 0x2f};
|
||||
|
||||
void starkDerivePrivateKey(uint32_t *bip32Path, uint32_t bip32PathLength, uint8_t *privateKeyData) {
|
||||
// C_cx_secp256k1_n - (C_cx_secp256k1_n % C_cx_Stark256_n)
|
||||
static unsigned char const STARK_DERIVE_BIAS[] = {
|
||||
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
|
||||
0x38, 0xa1, 0x3b, 0x4b, 0x92, 0x0e, 0x94, 0x11, 0xae, 0x6d, 0xa5, 0xf4, 0x0b, 0x03, 0x58, 0xb1};
|
||||
|
||||
void starkDerivePrivateKey(uint32_t *bip32Path, uint32_t bip32PathLength, uint8_t *privateKeyData) {
|
||||
#if 0
|
||||
// Sanity check
|
||||
if (bip32Path[0] != STARK_BIP32_PATH_0) {
|
||||
@@ -29,59 +28,62 @@ void starkDerivePrivateKey(uint32_t *bip32Path, uint32_t bip32PathLength, uint8_
|
||||
cx_math_modm(privateKeyData, 32, C_cx_Stark256_n, 32);
|
||||
PRINTF("Private key after processing %.*H\n", 32, privateKeyData);
|
||||
#else
|
||||
uint8_t tmp[33];
|
||||
uint8_t index = 0;
|
||||
// Sanity check
|
||||
if ((bip32PathLength < 2) || (bip32Path[0] != STARK_BIP32_PATH_0) || (bip32Path[1] != STARK_BIP32_PATH_1)) {
|
||||
PRINTF("Invalid Stark derivation path %d %d\n", bip32Path[0], bip32Path[1]);
|
||||
THROW(0x6a80);
|
||||
}
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1, bip32Path, bip32PathLength, tmp, NULL);
|
||||
PRINTF("Private key before processing %.*H\n", 32, tmp);
|
||||
for(;;) {
|
||||
tmp[32] = index;
|
||||
cx_hash_sha256(tmp, 33, privateKeyData, 32);
|
||||
PRINTF("Key hash %.*H\n", 32, privateKeyData);
|
||||
if (cx_math_cmp(privateKeyData, STARK_DERIVE_BIAS, 32) < 0) {
|
||||
cx_math_modm(privateKeyData, 32, C_cx_Stark256_n, 32);
|
||||
break;
|
||||
uint8_t tmp[33];
|
||||
uint8_t index = 0;
|
||||
// Sanity check
|
||||
if ((bip32PathLength < 2) || (bip32Path[0] != STARK_BIP32_PATH_0) ||
|
||||
(bip32Path[1] != STARK_BIP32_PATH_1)) {
|
||||
PRINTF("Invalid Stark derivation path %d %d\n", bip32Path[0], bip32Path[1]);
|
||||
THROW(0x6a80);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
PRINTF("Key result %.*H\n", 32, privateKeyData);
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1, bip32Path, bip32PathLength, tmp, NULL);
|
||||
PRINTF("Private key before processing %.*H\n", 32, tmp);
|
||||
for (;;) {
|
||||
tmp[32] = index;
|
||||
cx_hash_sha256(tmp, 33, privateKeyData, 32);
|
||||
PRINTF("Key hash %.*H\n", 32, privateKeyData);
|
||||
if (cx_math_cmp(privateKeyData, STARK_DERIVE_BIAS, 32) < 0) {
|
||||
cx_math_modm(privateKeyData, 32, C_cx_Stark256_n, 32);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
PRINTF("Key result %.*H\n", 32, privateKeyData);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void stark_get_amount_string(uint8_t *contractAddress, uint8_t *quantum256, uint8_t *amount64, char *tmp100, char *target100) {
|
||||
uint256_t amountPre, quantum, amount;
|
||||
uint8_t decimals;
|
||||
char *ticker = (char*)PIC(chainConfig->coinName);
|
||||
void stark_get_amount_string(uint8_t *contractAddress,
|
||||
uint8_t *quantum256,
|
||||
uint8_t *amount64,
|
||||
char *tmp100,
|
||||
char *target100) {
|
||||
uint256_t amountPre, quantum, amount;
|
||||
uint8_t decimals;
|
||||
char *ticker = (char *) PIC(chainConfig->coinName);
|
||||
|
||||
PRINTF("stark_get_amount_string %.*H\n", 20, contractAddress);
|
||||
PRINTF("stark_get_amount_string %.*H\n", 20, contractAddress);
|
||||
|
||||
if (allzeroes(contractAddress, 20)) {
|
||||
decimals = WEI_TO_ETHER;
|
||||
PRINTF("stark_get_amount_string - ETH\n");
|
||||
}
|
||||
else {
|
||||
tokenDefinition_t *token = getKnownToken(contractAddress);
|
||||
if (token == NULL) { // caught earlier
|
||||
THROW(0x6A80);
|
||||
if (allzeroes(contractAddress, 20)) {
|
||||
decimals = WEI_TO_ETHER;
|
||||
PRINTF("stark_get_amount_string - ETH\n");
|
||||
} else {
|
||||
tokenDefinition_t *token = getKnownToken(contractAddress);
|
||||
if (token == NULL) { // caught earlier
|
||||
THROW(0x6A80);
|
||||
}
|
||||
decimals = token->decimals;
|
||||
ticker = (char *) token->ticker;
|
||||
PRINTF("stark_get_amount_string - decimals %d ticker %s\n", decimals, ticker);
|
||||
}
|
||||
decimals = token->decimals;
|
||||
ticker = (char*)token->ticker;
|
||||
PRINTF("stark_get_amount_string - decimals %d ticker %s\n", decimals, ticker);
|
||||
}
|
||||
convertUint256BE(amount64, 8, &amountPre);
|
||||
readu256BE(quantum256, &quantum);
|
||||
mul256(&amountPre, &quantum, &amount);
|
||||
tostring256(&amount, 10, tmp100, 100);
|
||||
PRINTF("stark_get_amount_string - mul256 %s\n", tmp100);
|
||||
strcpy(target100, ticker);
|
||||
adjustDecimals(tmp100, strlen(tmp100), target100 + strlen(ticker), 100, decimals);
|
||||
PRINTF("get_amount_string %s\n", target100);
|
||||
convertUint256BE(amount64, 8, &amountPre);
|
||||
readu256BE(quantum256, &quantum);
|
||||
mul256(&amountPre, &quantum, &amount);
|
||||
tostring256(&amount, 10, tmp100, 100);
|
||||
PRINTF("stark_get_amount_string - mul256 %s\n", tmp100);
|
||||
strcpy(target100, ticker);
|
||||
adjustDecimals(tmp100, strlen(tmp100), target100 + strlen(ticker), 100, decimals);
|
||||
PRINTF("get_amount_string %s\n", target100);
|
||||
}
|
||||
|
||||
|
||||
#endif // HAVE_STARK
|
||||
#endif // HAVE_STARK
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
#include "os.h"
|
||||
#include "cx.h"
|
||||
|
||||
|
||||
/* EC points */
|
||||
#define FIELD_ELEMENT_SIZE (32)
|
||||
#define EC_POINT_SIZE (2 * FIELD_ELEMENT_SIZE + 1)
|
||||
#define EC_POINT_SIZE (2 * FIELD_ELEMENT_SIZE + 1)
|
||||
typedef unsigned char FieldElement[FIELD_ELEMENT_SIZE];
|
||||
typedef unsigned char ECPoint[EC_POINT_SIZE];
|
||||
|
||||
void pedersen(FieldElement res, /* out */
|
||||
FieldElement a, FieldElement b);
|
||||
FieldElement a,
|
||||
FieldElement b);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -8,16 +8,14 @@
|
||||
|
||||
#define SIGNATURE_MAX_LEN (72)
|
||||
|
||||
static const ECPoint PEDERSEN_SHIFT[] = { {
|
||||
static const ECPoint PEDERSEN_SHIFT[] = {{
|
||||
0x04,
|
||||
|
||||
0x04, 0x9e, 0xe3, 0xeb, 0xa8, 0xc1, 0x60, 0x07, 0x00, 0xee, 0x1b,
|
||||
0x87, 0xeb, 0x59, 0x9f, 0x16, 0x71, 0x6b, 0x0b, 0x10, 0x22, 0x94,
|
||||
0x77, 0x33, 0x55, 0x1f, 0xde, 0x40, 0x50, 0xca, 0x68, 0x04,
|
||||
0x04, 0x9e, 0xe3, 0xeb, 0xa8, 0xc1, 0x60, 0x07, 0x00, 0xee, 0x1b, 0x87, 0xeb, 0x59, 0x9f, 0x16,
|
||||
0x71, 0x6b, 0x0b, 0x10, 0x22, 0x94, 0x77, 0x33, 0x55, 0x1f, 0xde, 0x40, 0x50, 0xca, 0x68, 0x04,
|
||||
|
||||
0x03, 0xca, 0x0c, 0xfe, 0x4b, 0x3b, 0xc6, 0xdd, 0xf3, 0x46, 0xd4,
|
||||
0x9d, 0x06, 0xea, 0x0e, 0xd3, 0x4e, 0x62, 0x10, 0x62, 0xc0, 0xe0,
|
||||
0x56, 0xc1, 0xd0, 0x40, 0x5d, 0x26, 0x6e, 0x10, 0x26, 0x8a,
|
||||
0x03, 0xca, 0x0c, 0xfe, 0x4b, 0x3b, 0xc6, 0xdd, 0xf3, 0x46, 0xd4, 0x9d, 0x06, 0xea, 0x0e, 0xd3,
|
||||
0x4e, 0x62, 0x10, 0x62, 0xc0, 0xe0, 0x56, 0xc1, 0xd0, 0x40, 0x5d, 0x26, 0x6e, 0x10, 0x26, 0x8a,
|
||||
}};
|
||||
|
||||
static const ECPoint PEDERSEN_POINTS[4] = {
|
||||
@@ -78,15 +76,16 @@ void accum_ec_mul(ECPoint *hash, uint8_t *buf, int len, int pedersen_idx) {
|
||||
}
|
||||
|
||||
void pedersen(FieldElement res, /* out */
|
||||
FieldElement a, FieldElement b) {
|
||||
FieldElement a,
|
||||
FieldElement b) {
|
||||
ECPoint hash;
|
||||
|
||||
memcpy(hash, PEDERSEN_SHIFT, sizeof(hash));
|
||||
|
||||
|
||||
accum_ec_mul(&hash, a, 1, 1);
|
||||
accum_ec_mul(&hash, a+1, FIELD_ELEMENT_SIZE-1, 0);
|
||||
accum_ec_mul(&hash, a + 1, FIELD_ELEMENT_SIZE - 1, 0);
|
||||
accum_ec_mul(&hash, b, 1, 3);
|
||||
accum_ec_mul(&hash, b+1, FIELD_ELEMENT_SIZE-1, 2);
|
||||
accum_ec_mul(&hash, b + 1, FIELD_ELEMENT_SIZE - 1, 2);
|
||||
|
||||
memcpy(res, hash + 1, FIELD_ELEMENT_SIZE);
|
||||
}
|
||||
@@ -116,31 +115,43 @@ int stark_sign(uint8_t *signature, /* out */
|
||||
PRINTF("Pedersen hash 2 %.*H\n", 32, hash);
|
||||
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
int signatureLength = cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
|
||||
hash, sizeof(hash), signature, SIGNATURE_MAX_LEN, &info);
|
||||
int signatureLength = cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
hash,
|
||||
sizeof(hash),
|
||||
signature,
|
||||
SIGNATURE_MAX_LEN,
|
||||
&info);
|
||||
PRINTF("Stark signature %.*H\n", signatureLength, signature);
|
||||
return signatureLength;
|
||||
}
|
||||
|
||||
// ERC20Token(address)
|
||||
static const uint8_t ERC20_SELECTOR[] = { 0xf4, 0x72, 0x61, 0xb0 };
|
||||
static const uint8_t ERC20_SELECTOR[] = {0xf4, 0x72, 0x61, 0xb0};
|
||||
// ETH()
|
||||
static const uint8_t ETH_SELECTOR[] = { 0x83, 0x22, 0xff, 0xf2 };
|
||||
static const uint8_t ETH_SELECTOR[] = {0x83, 0x22, 0xff, 0xf2};
|
||||
// ERC721Token(address, uint256)
|
||||
static const uint8_t ERC721_SELECTOR[] = { 0x02, 0x57, 0x17, 0x92 };
|
||||
static const uint8_t ERC721_SELECTOR[] = {0x02, 0x57, 0x17, 0x92};
|
||||
// MintableERC20Token(address)
|
||||
static const uint8_t MINTABLE_ERC20_SELECTOR[] = { 0x68, 0x64, 0x6e, 0x2d };
|
||||
static const uint8_t MINTABLE_ERC20_SELECTOR[] = {0x68, 0x64, 0x6e, 0x2d};
|
||||
// MintableERC721Token(address,uint256)
|
||||
static const uint8_t MINTABLE_ERC721_SELECTOR[] = { 0xb8, 0xb8, 0x66, 0x72 };
|
||||
static const char NFT_ASSET_ID_PREFIX[] = { 'N', 'F', 'T', ':', 0 };
|
||||
static const char MINTABLE_ASSET_ID_PREFIX[] = { 'M', 'I', 'N', 'T', 'A', 'B', 'L', 'E', ':', 0 };
|
||||
static const uint8_t MINTABLE_ERC721_SELECTOR[] = {0xb8, 0xb8, 0x66, 0x72};
|
||||
static const char NFT_ASSET_ID_PREFIX[] = {'N', 'F', 'T', ':', 0};
|
||||
static const char MINTABLE_ASSET_ID_PREFIX[] = {'M', 'I', 'N', 'T', 'A', 'B', 'L', 'E', ':', 0};
|
||||
|
||||
void compute_token_id(cx_sha3_t *sha3, uint8_t *contractAddress, uint8_t quantumType, uint8_t *quantum, uint8_t *mintingBlob, bool assetTypeOnly, uint8_t *output) {
|
||||
void compute_token_id(cx_sha3_t *sha3,
|
||||
uint8_t *contractAddress,
|
||||
uint8_t quantumType,
|
||||
uint8_t *quantum,
|
||||
uint8_t *mintingBlob,
|
||||
bool assetTypeOnly,
|
||||
uint8_t *output) {
|
||||
uint8_t tmp[36];
|
||||
cx_keccak_init(sha3, 256);
|
||||
if ((contractAddress != NULL) && (!allzeroes(contractAddress, 20))) {
|
||||
const uint8_t *selector = NULL;
|
||||
switch(quantumType) {
|
||||
switch (quantumType) {
|
||||
case STARK_QUANTUM_ERC20:
|
||||
case STARK_QUANTUM_LEGACY:
|
||||
selector = ERC20_SELECTOR;
|
||||
@@ -162,29 +173,27 @@ void compute_token_id(cx_sha3_t *sha3, uint8_t *contractAddress, uint8_t quantum
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
memmove(tmp, selector, 4);
|
||||
memmove(tmp + 16, contractAddress, 20);
|
||||
cx_hash((cx_hash_t*)sha3, 0, tmp, sizeof(tmp), NULL, 0);
|
||||
}
|
||||
else {
|
||||
cx_hash((cx_hash_t *) sha3, 0, tmp, sizeof(tmp), NULL, 0);
|
||||
} else {
|
||||
PRINTF("compute_token_id for ETH\n");
|
||||
cx_hash((cx_hash_t*)sha3, 0, ETH_SELECTOR, sizeof(ETH_SELECTOR), NULL, 0);
|
||||
cx_hash((cx_hash_t *) sha3, 0, ETH_SELECTOR, sizeof(ETH_SELECTOR), NULL, 0);
|
||||
}
|
||||
if ((quantumType == STARK_QUANTUM_ERC721) || (quantumType == STARK_QUANTUM_MINTABLE_ERC721)) {
|
||||
if ((quantumType == STARK_QUANTUM_ERC721) || (quantumType == STARK_QUANTUM_MINTABLE_ERC721)) {
|
||||
memset(tmp, 0, 32);
|
||||
tmp[31] = 1;
|
||||
PRINTF("compute_token_id quantum %.*H\n", 32, tmp);
|
||||
cx_hash((cx_hash_t*)sha3, CX_LAST, tmp, 32, output, 32);
|
||||
}
|
||||
else {
|
||||
cx_hash((cx_hash_t *) sha3, CX_LAST, tmp, 32, output, 32);
|
||||
} else {
|
||||
PRINTF("compute_token_id quantum %.*H\n", 32, quantum);
|
||||
cx_hash((cx_hash_t*)sha3, CX_LAST, quantum, 32, output, 32);
|
||||
cx_hash((cx_hash_t *) sha3, CX_LAST, quantum, 32, output, 32);
|
||||
}
|
||||
if (!assetTypeOnly && ((quantumType != STARK_QUANTUM_LEGACY) &&
|
||||
(quantumType != STARK_QUANTUM_ETH) &&
|
||||
(quantumType != STARK_QUANTUM_ERC20))) {
|
||||
if (!assetTypeOnly &&
|
||||
((quantumType != STARK_QUANTUM_LEGACY) && (quantumType != STARK_QUANTUM_ETH) &&
|
||||
(quantumType != STARK_QUANTUM_ERC20))) {
|
||||
const char *prefix = NULL;
|
||||
output[0] &= 0x03;
|
||||
cx_keccak_init(sha3, 256);
|
||||
switch(quantumType) {
|
||||
switch (quantumType) {
|
||||
case STARK_QUANTUM_ERC721:
|
||||
prefix = NFT_ASSET_ID_PREFIX;
|
||||
break;
|
||||
@@ -196,18 +205,18 @@ void compute_token_id(cx_sha3_t *sha3, uint8_t *contractAddress, uint8_t quantum
|
||||
PRINTF("Unsupported non default quantum type %d\n", quantumType);
|
||||
return;
|
||||
}
|
||||
cx_hash((cx_hash_t*)sha3, 0, (const uint8_t*)prefix, strlen(prefix), NULL, 0);
|
||||
cx_hash((cx_hash_t*)sha3, 0, output, 32, NULL, 0);
|
||||
cx_hash((cx_hash_t*)sha3, CX_LAST, mintingBlob, 32, output, 32);
|
||||
cx_hash((cx_hash_t *) sha3, 0, (const uint8_t *) prefix, strlen(prefix), NULL, 0);
|
||||
cx_hash((cx_hash_t *) sha3, 0, output, 32, NULL, 0);
|
||||
cx_hash((cx_hash_t *) sha3, CX_LAST, mintingBlob, 32, output, 32);
|
||||
}
|
||||
if (!assetTypeOnly && ((quantumType == STARK_QUANTUM_MINTABLE_ERC20) || (quantumType == STARK_QUANTUM_MINTABLE_ERC721))) {
|
||||
if (!assetTypeOnly && ((quantumType == STARK_QUANTUM_MINTABLE_ERC20) ||
|
||||
(quantumType == STARK_QUANTUM_MINTABLE_ERC721))) {
|
||||
output[0] = 0x04;
|
||||
output[1] = 0x00;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
output[0] &= 0x03;
|
||||
}
|
||||
PRINTF("compute_token_id computed token %.*H\n", 32, output);
|
||||
}
|
||||
|
||||
#endif // HAVE_STARK
|
||||
#endif // HAVE_STARK
|
||||
|
||||
@@ -9,11 +9,21 @@
|
||||
#include "cx.h"
|
||||
#include "stark_crypto.h"
|
||||
|
||||
void compute_token_id(cx_sha3_t *sha3, uint8_t *contractAddress, uint8_t quantumType, uint8_t *quantum, uint8_t *mintingBlob, bool assetTypeOnly, uint8_t *output);
|
||||
void compute_token_id(cx_sha3_t *sha3,
|
||||
uint8_t *contractAddress,
|
||||
uint8_t quantumType,
|
||||
uint8_t *quantum,
|
||||
uint8_t *mintingBlob,
|
||||
bool assetTypeOnly,
|
||||
uint8_t *output);
|
||||
|
||||
void starkDerivePrivateKey(uint32_t *bip32Path, uint32_t bip32PathLength, uint8_t *privateKeyData);
|
||||
|
||||
void stark_get_amount_string(uint8_t *contractAddress, uint8_t *quantum256, uint8_t *amount64, char *tmp100, char *target100);
|
||||
void stark_get_amount_string(uint8_t *contractAddress,
|
||||
uint8_t *quantum256,
|
||||
uint8_t *amount64,
|
||||
char *tmp100,
|
||||
char *target100);
|
||||
|
||||
int stark_sign(uint8_t *signature, /* out */
|
||||
uint8_t *privateKeyData,
|
||||
@@ -23,4 +33,3 @@ int stark_sign(uint8_t *signature, /* out */
|
||||
FieldElement condition);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ typedef struct check_address_parameters_s {
|
||||
// fields and serialization format depends on spesific coin app
|
||||
unsigned char* address_parameters;
|
||||
unsigned char address_parameters_length;
|
||||
char *address_to_check;
|
||||
char *extra_id_to_check;
|
||||
char* address_to_check;
|
||||
char* extra_id_to_check;
|
||||
// OUT
|
||||
int result;
|
||||
} check_address_parameters_t;
|
||||
@@ -45,8 +45,8 @@ typedef struct create_transaction_parameters_s {
|
||||
unsigned char amount_length;
|
||||
unsigned char* fee_amount;
|
||||
unsigned char fee_amount_length;
|
||||
char *destination_address;
|
||||
char *destination_address_extra_id;
|
||||
char* destination_address;
|
||||
char* destination_address_extra_id;
|
||||
} create_transaction_parameters_t;
|
||||
|
||||
#endif
|
||||
|
||||
5616
src/tokens.c
5616
src/tokens.c
File diff suppressed because it is too large
Load Diff
92
src/tokens.h
92
src/tokens.h
@@ -1,26 +1,26 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef _TOKENS_H_
|
||||
#define _TOKENS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_TICKER_LEN 12 // 10 characters + ' ' + '\0'
|
||||
#define MAX_TICKER_LEN 12 // 10 characters + ' ' + '\0'
|
||||
|
||||
typedef struct tokenDefinition_t {
|
||||
#ifdef HAVE_CONTRACT_NAME_IN_DESCRIPTOR
|
||||
@@ -33,7 +33,7 @@ typedef struct tokenDefinition_t {
|
||||
|
||||
#ifdef HAVE_TOKENS_EXTRA_LIST
|
||||
|
||||
#define NUM_TOKENS_EXTRA 4
|
||||
#define NUM_TOKENS_EXTRA 4
|
||||
|
||||
extern tokenDefinition_t const TOKENS_EXTRA[NUM_TOKENS_EXTRA];
|
||||
|
||||
@@ -41,36 +41,36 @@ extern tokenDefinition_t const TOKENS_EXTRA[NUM_TOKENS_EXTRA];
|
||||
|
||||
#ifdef HAVE_TOKENS_LIST
|
||||
|
||||
#define NUM_TOKENS_AKROMA 0
|
||||
#define NUM_TOKENS_ELLAISM 1
|
||||
#define NUM_TOKENS_ETHEREUM 1102
|
||||
#define NUM_TOKENS_AKROMA 0
|
||||
#define NUM_TOKENS_ELLAISM 1
|
||||
#define NUM_TOKENS_ETHEREUM 1102
|
||||
#define NUM_TOKENS_ETHEREUM_CLASSIC 4
|
||||
#define NUM_TOKENS_ETHERSOCIAL 0
|
||||
#define NUM_TOKENS_ETHER1 0
|
||||
#define NUM_TOKENS_PIRL 0
|
||||
#define NUM_TOKENS_POA 0
|
||||
#define NUM_TOKENS_RSK 0
|
||||
#define NUM_TOKENS_UBIQ 6
|
||||
#define NUM_TOKENS_EXPANSE 0
|
||||
#define NUM_TOKENS_WANCHAIN 0
|
||||
#define NUM_TOKENS_KUSD 0
|
||||
#define NUM_TOKENS_MUSICOIN 0
|
||||
#define NUM_TOKENS_CALLISTO 0
|
||||
#define NUM_TOKENS_ETHERGEM 0
|
||||
#define NUM_TOKENS_ATHEIOS 0
|
||||
#define NUM_TOKENS_GOCHAIN 0
|
||||
#define NUM_TOKENS_MIX 0
|
||||
#define NUM_TOKENS_REOSC 0
|
||||
#define NUM_TOKENS_HPB 0
|
||||
#define NUM_TOKENS_TOMOCHAIN 0
|
||||
#define NUM_TOKENS_TOBALABA 0
|
||||
#define NUM_TOKENS_DEXON 0
|
||||
#define NUM_TOKENS_VOLTA 0
|
||||
#define NUM_TOKENS_EWC 0
|
||||
#define NUM_TOKENS_ARTIS_SIGMA1 0
|
||||
#define NUM_TOKENS_ARTIS_TAU1 0
|
||||
#define NUM_TOKENS_WEBCHAIN 0
|
||||
#define NUM_TOKENS_THUNDERCORE 0
|
||||
#define NUM_TOKENS_ETHERSOCIAL 0
|
||||
#define NUM_TOKENS_ETHER1 0
|
||||
#define NUM_TOKENS_PIRL 0
|
||||
#define NUM_TOKENS_POA 0
|
||||
#define NUM_TOKENS_RSK 0
|
||||
#define NUM_TOKENS_UBIQ 6
|
||||
#define NUM_TOKENS_EXPANSE 0
|
||||
#define NUM_TOKENS_WANCHAIN 0
|
||||
#define NUM_TOKENS_KUSD 0
|
||||
#define NUM_TOKENS_MUSICOIN 0
|
||||
#define NUM_TOKENS_CALLISTO 0
|
||||
#define NUM_TOKENS_ETHERGEM 0
|
||||
#define NUM_TOKENS_ATHEIOS 0
|
||||
#define NUM_TOKENS_GOCHAIN 0
|
||||
#define NUM_TOKENS_MIX 0
|
||||
#define NUM_TOKENS_REOSC 0
|
||||
#define NUM_TOKENS_HPB 0
|
||||
#define NUM_TOKENS_TOMOCHAIN 0
|
||||
#define NUM_TOKENS_TOBALABA 0
|
||||
#define NUM_TOKENS_DEXON 0
|
||||
#define NUM_TOKENS_VOLTA 0
|
||||
#define NUM_TOKENS_EWC 0
|
||||
#define NUM_TOKENS_ARTIS_SIGMA1 0
|
||||
#define NUM_TOKENS_ARTIS_TAU1 0
|
||||
#define NUM_TOKENS_WEBCHAIN 0
|
||||
#define NUM_TOKENS_THUNDERCORE 0
|
||||
|
||||
extern tokenDefinition_t const TOKENS_AKROMA[NUM_TOKENS_AKROMA];
|
||||
extern tokenDefinition_t const TOKENS_ELLAISM[NUM_TOKENS_ELLAISM];
|
||||
|
||||
@@ -17,7 +17,6 @@ unsigned int io_seproxyhal_touch_eth2_address_ok(const bagl_element_t *e);
|
||||
void ui_idle(void);
|
||||
|
||||
void io_seproxyhal_send_status(uint32_t sw);
|
||||
void format_signature_out(const uint8_t* signature);
|
||||
void format_signature_out(const uint8_t *signature);
|
||||
void finalizeParsing(bool direct);
|
||||
tokenDefinition_t* getKnownToken(uint8_t *contractAddress);
|
||||
|
||||
tokenDefinition_t *getKnownToken(uint8_t *contractAddress);
|
||||
|
||||
@@ -6,6 +6,7 @@ void switch_settings_contract_data(void);
|
||||
void switch_settings_display_data(void);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_idle_flow_1_step,
|
||||
nn, //pnn,
|
||||
@@ -37,16 +38,18 @@ UX_STEP_CB(
|
||||
&C_icon_dashboard_x,
|
||||
"Quit",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_idle_flow,
|
||||
&ux_idle_flow_1_step,
|
||||
&ux_idle_flow_2_step,
|
||||
&ux_idle_flow_3_step,
|
||||
&ux_idle_flow_4_step,
|
||||
FLOW_LOOP
|
||||
);
|
||||
&ux_idle_flow_1_step,
|
||||
&ux_idle_flow_2_step,
|
||||
&ux_idle_flow_3_step,
|
||||
&ux_idle_flow_4_step,
|
||||
FLOW_LOOP);
|
||||
|
||||
#if defined(TARGET_NANOS)
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_CB(
|
||||
ux_settings_flow_1_step,
|
||||
bnnn_paging,
|
||||
@@ -99,28 +102,28 @@ UX_STEP_CB(
|
||||
&C_icon_back_x,
|
||||
"Back",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_settings_flow,
|
||||
&ux_settings_flow_1_step,
|
||||
&ux_settings_flow_2_step,
|
||||
&ux_settings_flow_3_step
|
||||
);
|
||||
&ux_settings_flow_1_step,
|
||||
&ux_settings_flow_2_step,
|
||||
&ux_settings_flow_3_step);
|
||||
|
||||
void display_settings() {
|
||||
strcpy(strings.common.fullAddress, (N_storage.dataAllowed ? "Allowed" : "NOT Allowed"));
|
||||
strcpy(strings.common.fullAddress + 20, (N_storage.contractDetails ? "Displayed" : "NOT Displayed"));
|
||||
ux_flow_init(0, ux_settings_flow, NULL);
|
||||
strcpy(strings.common.fullAddress, (N_storage.dataAllowed ? "Allowed" : "NOT Allowed"));
|
||||
strcpy(strings.common.fullAddress + 20,
|
||||
(N_storage.contractDetails ? "Displayed" : "NOT Displayed"));
|
||||
ux_flow_init(0, ux_settings_flow, NULL);
|
||||
}
|
||||
|
||||
void switch_settings_contract_data() {
|
||||
uint8_t value = (N_storage.dataAllowed ? 0 : 1);
|
||||
nvm_write((void*)&N_storage.dataAllowed, (void*)&value, sizeof(uint8_t));
|
||||
display_settings();
|
||||
uint8_t value = (N_storage.dataAllowed ? 0 : 1);
|
||||
nvm_write((void*) &N_storage.dataAllowed, (void*) &value, sizeof(uint8_t));
|
||||
display_settings();
|
||||
}
|
||||
|
||||
void switch_settings_display_data() {
|
||||
uint8_t value = (N_storage.contractDetails ? 0 : 1);
|
||||
nvm_write((void*)&N_storage.contractDetails, (void*)&value, sizeof(uint8_t));
|
||||
display_settings();
|
||||
uint8_t value = (N_storage.contractDetails ? 0 : 1);
|
||||
nvm_write((void*) &N_storage.contractDetails, (void*) &value, sizeof(uint8_t));
|
||||
display_settings();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,55 +2,54 @@
|
||||
|
||||
#include "os_io_seproxyhal.h"
|
||||
|
||||
extern const ux_flow_step_t * const ux_idle_flow [];
|
||||
extern const ux_flow_step_t* const ux_idle_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_settings_flow [];
|
||||
extern const ux_flow_step_t* const ux_settings_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_display_public_flow [];
|
||||
extern const ux_flow_step_t* const ux_display_public_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_confirm_selector_flow [];
|
||||
extern const ux_flow_step_t* const ux_confirm_selector_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_confirm_parameter_flow [];
|
||||
extern const ux_flow_step_t* const ux_confirm_parameter_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_approval_tx_flow [];
|
||||
extern const ux_flow_step_t* const ux_approval_tx_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_approval_tx_data_warning_flow [];
|
||||
extern const ux_flow_step_t* const ux_approval_tx_data_warning_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_approval_allowance_flow [];
|
||||
extern const ux_flow_step_t* const ux_approval_allowance_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_sign_flow [];
|
||||
extern const ux_flow_step_t* const ux_sign_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_sign_712_v0_flow [];
|
||||
extern const ux_flow_step_t* const ux_sign_712_v0_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_display_public_eth2_flow [];
|
||||
extern const ux_flow_step_t* const ux_display_public_eth2_flow[];
|
||||
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
extern const ux_flow_step_t * const ux_display_stark_public_flow [];
|
||||
extern const ux_flow_step_t* const ux_display_stark_public_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_stark_limit_order_flow [];
|
||||
extern const ux_flow_step_t* const ux_stark_limit_order_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_stark_transfer_flow [];
|
||||
extern const ux_flow_step_t* const ux_stark_transfer_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_stark_self_transfer_flow [];
|
||||
extern const ux_flow_step_t* const ux_stark_self_transfer_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_stark_transfer_conditional_flow [];
|
||||
extern const ux_flow_step_t* const ux_stark_transfer_conditional_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_stark_self_transfer_conditional_flow [];
|
||||
extern const ux_flow_step_t* const ux_stark_self_transfer_conditional_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_approval_starkware_register_flow [];
|
||||
extern const ux_flow_step_t* const ux_approval_starkware_register_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_approval_starkware_deposit_flow [];
|
||||
extern const ux_flow_step_t* const ux_approval_starkware_deposit_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_approval_starkware_withdraw_flow [];
|
||||
extern const ux_flow_step_t* const ux_approval_starkware_withdraw_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_approval_starkware_verify_vault_id_flow [];
|
||||
extern const ux_flow_step_t* const ux_approval_starkware_verify_vault_id_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_approval_starkware_escape_flow [];
|
||||
extern const ux_flow_step_t* const ux_approval_starkware_escape_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_approval_starkware_verify_escape_flow [];
|
||||
extern const ux_flow_step_t* const ux_approval_starkware_verify_escape_flow[];
|
||||
|
||||
extern const ux_flow_step_t * const ux_stark_unsafe_sign_flow [];
|
||||
extern const ux_flow_step_t* const ux_stark_unsafe_sign_flow[];
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
97
src/utils.c
97
src/utils.c
@@ -1,19 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@@ -23,16 +23,16 @@
|
||||
#include "uint256.h"
|
||||
#include "tokens.h"
|
||||
|
||||
static const unsigned char hex_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
static const unsigned char hex_digits[] =
|
||||
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
|
||||
void array_hexstr(char *strbuf, const void *bin, unsigned int len) {
|
||||
while (len--) {
|
||||
*strbuf++ = hex_digits[((*((char *)bin)) >> 4) & 0xF];
|
||||
*strbuf++ = hex_digits[(*((char *)bin)) & 0xF];
|
||||
bin = (const void *)((unsigned int)bin + 1);
|
||||
*strbuf++ = hex_digits[((*((char *) bin)) >> 4) & 0xF];
|
||||
*strbuf++ = hex_digits[(*((char *) bin)) & 0xF];
|
||||
bin = (const void *) ((unsigned int) bin + 1);
|
||||
}
|
||||
*strbuf = 0; // EOS
|
||||
*strbuf = 0; // EOS
|
||||
}
|
||||
|
||||
void convertUint256BE(uint8_t *data, uint32_t length, uint256_t *target) {
|
||||
@@ -45,7 +45,7 @@ void convertUint256BE(uint8_t *data, uint32_t length, uint256_t *target) {
|
||||
int local_strchr(char *string, char ch) {
|
||||
unsigned int length = strlen(string);
|
||||
unsigned int i;
|
||||
for (i=0; i<length; i++) {
|
||||
for (i = 0; i < length; i++) {
|
||||
if (string[i] == ch) {
|
||||
return i;
|
||||
}
|
||||
@@ -56,30 +56,27 @@ int local_strchr(char *string, char ch) {
|
||||
uint32_t getV(txContent_t *txContent) {
|
||||
uint32_t v = 0;
|
||||
if (txContent->vLength == 1) {
|
||||
v = txContent->v[0];
|
||||
}
|
||||
else
|
||||
if (txContent->vLength == 2) {
|
||||
v = (txContent->v[0] << 8) | txContent->v[1];
|
||||
}
|
||||
else
|
||||
if (txContent->vLength == 3) {
|
||||
v = (txContent->v[0] << 16) | (txContent->v[1] << 8) | txContent->v[2];
|
||||
}
|
||||
else
|
||||
if (txContent->vLength == 4) {
|
||||
v = (txContent->v[0] << 24) | (txContent->v[1] << 16) |
|
||||
(txContent->v[2] << 8) | txContent->v[3];
|
||||
}
|
||||
else
|
||||
if (txContent->vLength != 0) {
|
||||
v = txContent->v[0];
|
||||
} else if (txContent->vLength == 2) {
|
||||
v = (txContent->v[0] << 8) | txContent->v[1];
|
||||
} else if (txContent->vLength == 3) {
|
||||
v = (txContent->v[0] << 16) | (txContent->v[1] << 8) | txContent->v[2];
|
||||
} else if (txContent->vLength == 4) {
|
||||
v = (txContent->v[0] << 24) | (txContent->v[1] << 16) | (txContent->v[2] << 8) |
|
||||
txContent->v[3];
|
||||
} else if (txContent->vLength != 0) {
|
||||
PRINTF("Unexpected v format\n");
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void amountToString(uint8_t* amount, uint8_t amount_size, uint8_t decimals, char* ticker, char* out_buffer, uint8_t out_buffer_size){
|
||||
void amountToString(uint8_t *amount,
|
||||
uint8_t amount_size,
|
||||
uint8_t decimals,
|
||||
char *ticker,
|
||||
char *out_buffer,
|
||||
uint8_t out_buffer_size) {
|
||||
uint256_t amount_256;
|
||||
char tmp_buffer[100];
|
||||
convertUint256BE(amount, amount_size, &amount_256);
|
||||
@@ -90,25 +87,29 @@ void amountToString(uint8_t* amount, uint8_t amount_size, uint8_t decimals, char
|
||||
|
||||
memcpy(out_buffer, ticker, MIN(out_buffer_size, ticker_len));
|
||||
|
||||
adjustDecimals(tmp_buffer, amount_len, out_buffer + ticker_len, out_buffer_size - ticker_len -1, decimals);
|
||||
out_buffer[out_buffer_size-1] = '\0';
|
||||
adjustDecimals(tmp_buffer,
|
||||
amount_len,
|
||||
out_buffer + ticker_len,
|
||||
out_buffer_size - ticker_len - 1,
|
||||
decimals);
|
||||
out_buffer[out_buffer_size - 1] = '\0';
|
||||
}
|
||||
|
||||
bool parse_swap_config(uint8_t* config, uint8_t config_len, char* ticker, uint8_t* decimals){
|
||||
bool parse_swap_config(uint8_t *config, uint8_t config_len, char *ticker, uint8_t *decimals) {
|
||||
uint8_t ticker_len, offset = 0;
|
||||
if (config_len == 0){
|
||||
if (config_len == 0) {
|
||||
return false;
|
||||
}
|
||||
ticker_len = config[offset++];
|
||||
if(ticker_len == 0 || ticker_len > MAX_TICKER_LEN - 2 || config_len - offset < ticker_len){
|
||||
if (ticker_len == 0 || ticker_len > MAX_TICKER_LEN - 2 || config_len - offset < ticker_len) {
|
||||
return false;
|
||||
}
|
||||
memcpy(ticker, config+offset, ticker_len);
|
||||
memcpy(ticker, config + offset, ticker_len);
|
||||
offset += ticker_len;
|
||||
ticker[ticker_len] = ' ';
|
||||
ticker[ticker_len+1] = '\0';
|
||||
ticker[ticker_len + 1] = '\0';
|
||||
|
||||
if(config_len - offset < 1){
|
||||
if (config_len - offset < 1) {
|
||||
return false;
|
||||
}
|
||||
*decimals = config[offset];
|
||||
|
||||
45
src/utils.h
45
src/utils.h
@@ -1,19 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
@@ -22,15 +22,20 @@
|
||||
|
||||
#include "uint256.h"
|
||||
|
||||
void array_hexstr(char *strbuf, const void *bin, unsigned int len);
|
||||
void array_hexstr(char* strbuf, const void* bin, unsigned int len);
|
||||
|
||||
void convertUint256BE(uint8_t *data, uint32_t length, uint256_t *target);
|
||||
void convertUint256BE(uint8_t* data, uint32_t length, uint256_t* target);
|
||||
|
||||
int local_strchr(char *string, char ch);
|
||||
int local_strchr(char* string, char ch);
|
||||
|
||||
uint32_t getV(txContent_t *txContent);
|
||||
uint32_t getV(txContent_t* txContent);
|
||||
|
||||
void amountToString(uint8_t* amount, uint8_t amount_len, uint8_t decimals, char* ticker, char* out_buffer, uint8_t out_buffer_size);
|
||||
void amountToString(uint8_t* amount,
|
||||
uint8_t amount_len,
|
||||
uint8_t decimals,
|
||||
char* ticker,
|
||||
char* out_buffer,
|
||||
uint8_t out_buffer_size);
|
||||
|
||||
bool parse_swap_config(uint8_t* config, uint8_t config_len, char* ticker, uint8_t* decimals);
|
||||
|
||||
|
||||
@@ -1,31 +1,34 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ethUstream.h"
|
||||
#include "ethUtils.h"
|
||||
|
||||
#define MAX_INT256 32
|
||||
#define MAX_INT256 32
|
||||
#define MAX_ADDRESS 20
|
||||
#define MAX_V 4
|
||||
#define MAX_V 4
|
||||
|
||||
void initTx(txContext_t *context, cx_sha3_t *sha3, txContent_t *content,
|
||||
ustreamProcess_t customProcessor, void *extra) {
|
||||
void initTx(txContext_t *context,
|
||||
cx_sha3_t *sha3,
|
||||
txContent_t *content,
|
||||
ustreamProcess_t customProcessor,
|
||||
void *extra) {
|
||||
memset(context, 0, sizeof(txContext_t));
|
||||
context->sha3 = sha3;
|
||||
context->content = content;
|
||||
@@ -48,7 +51,7 @@ uint8_t readTxByte(txContext_t *context) {
|
||||
context->currentFieldPos++;
|
||||
}
|
||||
if (!(context->processingField && context->fieldSingleByte)) {
|
||||
cx_hash((cx_hash_t*)context->sha3, 0, &data, 1, NULL, 0);
|
||||
cx_hash((cx_hash_t *) context->sha3, 0, &data, 1, NULL, 0);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@@ -62,7 +65,7 @@ void copyTxData(txContext_t *context, uint8_t *out, uint32_t length) {
|
||||
memmove(out, context->workBuffer, length);
|
||||
}
|
||||
if (!(context->processingField && context->fieldSingleByte)) {
|
||||
cx_hash((cx_hash_t*)context->sha3, 0, context->workBuffer, length, NULL, 0);
|
||||
cx_hash((cx_hash_t *) context->sha3, 0, context->workBuffer, length, NULL, 0);
|
||||
}
|
||||
context->workBuffer += length;
|
||||
context->commandLength -= length;
|
||||
@@ -82,7 +85,6 @@ static void processContent(txContext_t *context) {
|
||||
context->processingField = false;
|
||||
}
|
||||
|
||||
|
||||
static void processType(txContext_t *context) {
|
||||
if (context->currentFieldIsList) {
|
||||
PRINTF("Invalid type for RLP_TYPE\n");
|
||||
@@ -93,8 +95,8 @@ static void processType(txContext_t *context) {
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize = MIN(context->commandLength,
|
||||
context->currentFieldLength - context->currentFieldPos);
|
||||
uint32_t copySize =
|
||||
MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, NULL, copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
@@ -113,8 +115,8 @@ static void processNonce(txContext_t *context) {
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize = MIN(context->commandLength,
|
||||
context->currentFieldLength - context->currentFieldPos);
|
||||
uint32_t copySize =
|
||||
MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, NULL, copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
@@ -129,16 +131,13 @@ static void processStartGas(txContext_t *context) {
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldLength > MAX_INT256) {
|
||||
PRINTF("Invalid length for RLP_STARTGAS %d\n",
|
||||
context->currentFieldLength);
|
||||
PRINTF("Invalid length for RLP_STARTGAS %d\n", context->currentFieldLength);
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize = MIN(context->commandLength,
|
||||
context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context,
|
||||
context->content->startgas.value + context->currentFieldPos,
|
||||
copySize);
|
||||
uint32_t copySize =
|
||||
MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, context->content->startgas.value + context->currentFieldPos, copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->content->startgas.length = context->currentFieldLength;
|
||||
@@ -157,11 +156,9 @@ static void processGasprice(txContext_t *context) {
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize = MIN(context->commandLength,
|
||||
context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context,
|
||||
context->content->gasprice.value + context->currentFieldPos,
|
||||
copySize);
|
||||
uint32_t copySize =
|
||||
MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, context->content->gasprice.value + context->currentFieldPos, copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->content->gasprice.length = context->currentFieldLength;
|
||||
@@ -180,11 +177,9 @@ static void processValue(txContext_t *context) {
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize = MIN(context->commandLength,
|
||||
context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context,
|
||||
context->content->value.value + context->currentFieldPos,
|
||||
copySize);
|
||||
uint32_t copySize =
|
||||
MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, context->content->value.value + context->currentFieldPos, copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->content->value.length = context->currentFieldLength;
|
||||
@@ -203,11 +198,9 @@ static void processTo(txContext_t *context) {
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize = MIN(context->commandLength,
|
||||
context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context,
|
||||
context->content->destination + context->currentFieldPos,
|
||||
copySize);
|
||||
uint32_t copySize =
|
||||
MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, context->content->destination + context->currentFieldPos, copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->content->destinationLength = context->currentFieldLength;
|
||||
@@ -222,8 +215,8 @@ static void processData(txContext_t *context) {
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize = MIN(context->commandLength,
|
||||
context->currentFieldLength - context->currentFieldPos);
|
||||
uint32_t copySize =
|
||||
MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, NULL, copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
@@ -242,11 +235,9 @@ static void processV(txContext_t *context) {
|
||||
THROW(EXCEPTION);
|
||||
}
|
||||
if (context->currentFieldPos < context->currentFieldLength) {
|
||||
uint32_t copySize = MIN(context->commandLength,
|
||||
context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context,
|
||||
context->content->v + context->currentFieldPos,
|
||||
copySize);
|
||||
uint32_t copySize =
|
||||
MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos);
|
||||
copyTxData(context, context->content->v + context->currentFieldPos, copySize);
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->content->vLength = context->currentFieldLength;
|
||||
@@ -255,7 +246,6 @@ static void processV(txContext_t *context) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static parserStatus_e processTxInternal(txContext_t *context) {
|
||||
for (;;) {
|
||||
customStatus_e customStatus = CUSTOM_NOT_HANDLED;
|
||||
@@ -277,10 +267,8 @@ static parserStatus_e processTxInternal(txContext_t *context) {
|
||||
while (context->commandLength != 0) {
|
||||
bool valid;
|
||||
// Feed the RLP buffer until the length can be decoded
|
||||
context->rlpBuffer[context->rlpBufferPos++] =
|
||||
readTxByte(context);
|
||||
if (rlpCanDecode(context->rlpBuffer, context->rlpBufferPos,
|
||||
&valid)) {
|
||||
context->rlpBuffer[context->rlpBufferPos++] = readTxByte(context);
|
||||
if (rlpCanDecode(context->rlpBuffer, context->rlpBufferPos, &valid)) {
|
||||
// Can decode now, if valid
|
||||
if (!valid) {
|
||||
PRINTF("RLP pre-decode error\n");
|
||||
@@ -300,8 +288,10 @@ static parserStatus_e processTxInternal(txContext_t *context) {
|
||||
return USTREAM_PROCESSING;
|
||||
}
|
||||
// Ready to process this field
|
||||
if (!rlpDecodeLength(context->rlpBuffer, context->rlpBufferPos,
|
||||
&context->currentFieldLength, &offset,
|
||||
if (!rlpDecodeLength(context->rlpBuffer,
|
||||
context->rlpBufferPos,
|
||||
&context->currentFieldLength,
|
||||
&offset,
|
||||
&context->currentFieldIsList)) {
|
||||
PRINTF("RLP decode error\n");
|
||||
return USTREAM_FAULT;
|
||||
@@ -320,7 +310,7 @@ static parserStatus_e processTxInternal(txContext_t *context) {
|
||||
}
|
||||
if (context->customProcessor != NULL) {
|
||||
customStatus = context->customProcessor(context);
|
||||
switch(customStatus) {
|
||||
switch (customStatus) {
|
||||
case CUSTOM_NOT_HANDLED:
|
||||
case CUSTOM_HANDLED:
|
||||
break;
|
||||
@@ -336,48 +326,50 @@ static parserStatus_e processTxInternal(txContext_t *context) {
|
||||
}
|
||||
if (customStatus == CUSTOM_NOT_HANDLED) {
|
||||
switch (context->currentField) {
|
||||
case TX_RLP_CONTENT:
|
||||
processContent(context);
|
||||
if ((context->processingFlags & TX_FLAG_TYPE) == 0) {
|
||||
context->currentField++;
|
||||
}
|
||||
break;
|
||||
case TX_RLP_TYPE:
|
||||
processType(context);
|
||||
break;
|
||||
case TX_RLP_NONCE:
|
||||
processNonce(context);
|
||||
break;
|
||||
case TX_RLP_GASPRICE:
|
||||
processGasprice(context);
|
||||
break;
|
||||
case TX_RLP_STARTGAS:
|
||||
processStartGas(context);
|
||||
break;
|
||||
case TX_RLP_VALUE:
|
||||
processValue(context);
|
||||
break;
|
||||
case TX_RLP_TO:
|
||||
processTo(context);
|
||||
break;
|
||||
case TX_RLP_DATA:
|
||||
case TX_RLP_R:
|
||||
case TX_RLP_S:
|
||||
processData(context);
|
||||
break;
|
||||
case TX_RLP_V:
|
||||
processV(context);
|
||||
break;
|
||||
default:
|
||||
PRINTF("Invalid RLP decoder context\n");
|
||||
return USTREAM_FAULT;
|
||||
case TX_RLP_CONTENT:
|
||||
processContent(context);
|
||||
if ((context->processingFlags & TX_FLAG_TYPE) == 0) {
|
||||
context->currentField++;
|
||||
}
|
||||
break;
|
||||
case TX_RLP_TYPE:
|
||||
processType(context);
|
||||
break;
|
||||
case TX_RLP_NONCE:
|
||||
processNonce(context);
|
||||
break;
|
||||
case TX_RLP_GASPRICE:
|
||||
processGasprice(context);
|
||||
break;
|
||||
case TX_RLP_STARTGAS:
|
||||
processStartGas(context);
|
||||
break;
|
||||
case TX_RLP_VALUE:
|
||||
processValue(context);
|
||||
break;
|
||||
case TX_RLP_TO:
|
||||
processTo(context);
|
||||
break;
|
||||
case TX_RLP_DATA:
|
||||
case TX_RLP_R:
|
||||
case TX_RLP_S:
|
||||
processData(context);
|
||||
break;
|
||||
case TX_RLP_V:
|
||||
processV(context);
|
||||
break;
|
||||
default:
|
||||
PRINTF("Invalid RLP decoder context\n");
|
||||
return USTREAM_FAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parserStatus_e processTx(txContext_t *context, uint8_t *buffer,
|
||||
uint32_t length, uint32_t processingFlags) {
|
||||
parserStatus_e processTx(txContext_t *context,
|
||||
uint8_t *buffer,
|
||||
uint32_t length,
|
||||
uint32_t processingFlags) {
|
||||
parserStatus_e result;
|
||||
BEGIN_TRY {
|
||||
TRY {
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef _ETHUSTREAM_H_
|
||||
#define _ETHUSTREAM_H_
|
||||
@@ -94,10 +94,15 @@ typedef struct txContext_t {
|
||||
void *extra;
|
||||
} txContext_t;
|
||||
|
||||
void initTx(txContext_t *context, cx_sha3_t *sha3, txContent_t *content,
|
||||
ustreamProcess_t customProcessor, void *extra);
|
||||
parserStatus_e processTx(txContext_t *context, uint8_t *buffer,
|
||||
uint32_t length, uint32_t processingFlags);
|
||||
void initTx(txContext_t *context,
|
||||
cx_sha3_t *sha3,
|
||||
txContent_t *content,
|
||||
ustreamProcess_t customProcessor,
|
||||
void *extra);
|
||||
parserStatus_e processTx(txContext_t *context,
|
||||
uint8_t *buffer,
|
||||
uint32_t length,
|
||||
uint32_t processingFlags);
|
||||
parserStatus_e continueTx(txContext_t *context);
|
||||
void copyTxData(txContext_t *context, uint8_t *out, uint32_t length);
|
||||
uint8_t readTxByte(txContext_t *context);
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Utilities for an Ethereum Hardware Wallet logic
|
||||
@@ -40,7 +40,7 @@ bool rlpCanDecode(uint8_t *buffer, uint32_t bufferLength, bool *valid) {
|
||||
return false;
|
||||
}
|
||||
if (*buffer > 0xbb) {
|
||||
*valid = false; // arbitrary 32 bits length limitation
|
||||
*valid = false; // arbitrary 32 bits length limitation
|
||||
return true;
|
||||
}
|
||||
} else if (*buffer <= 0xf7) {
|
||||
@@ -49,7 +49,7 @@ bool rlpCanDecode(uint8_t *buffer, uint32_t bufferLength, bool *valid) {
|
||||
return false;
|
||||
}
|
||||
if (*buffer > 0xfb) {
|
||||
*valid = false; // arbitrary 32 bits length limitation
|
||||
*valid = false; // arbitrary 32 bits length limitation
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -57,8 +57,11 @@ bool rlpCanDecode(uint8_t *buffer, uint32_t bufferLength, bool *valid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rlpDecodeLength(uint8_t *buffer, uint32_t bufferLength,
|
||||
uint32_t *fieldLength, uint32_t *offset, bool *list) {
|
||||
bool rlpDecodeLength(uint8_t *buffer,
|
||||
uint32_t bufferLength,
|
||||
uint32_t *fieldLength,
|
||||
uint32_t *offset,
|
||||
bool *list) {
|
||||
if (*buffer <= 0x7f) {
|
||||
*offset = 0;
|
||||
*fieldLength = 1;
|
||||
@@ -71,22 +74,21 @@ bool rlpDecodeLength(uint8_t *buffer, uint32_t bufferLength,
|
||||
*offset = 1 + (*buffer - 0xb7);
|
||||
*list = false;
|
||||
switch (*buffer) {
|
||||
case 0xb8:
|
||||
*fieldLength = *(buffer + 1);
|
||||
break;
|
||||
case 0xb9:
|
||||
*fieldLength = (*(buffer + 1) << 8) + *(buffer + 2);
|
||||
break;
|
||||
case 0xba:
|
||||
*fieldLength =
|
||||
(*(buffer + 1) << 16) + (*(buffer + 2) << 8) + *(buffer + 3);
|
||||
break;
|
||||
case 0xbb:
|
||||
*fieldLength = (*(buffer + 1) << 24) + (*(buffer + 2) << 16) +
|
||||
(*(buffer + 3) << 8) + *(buffer + 4);
|
||||
break;
|
||||
default:
|
||||
return false; // arbitrary 32 bits length limitation
|
||||
case 0xb8:
|
||||
*fieldLength = *(buffer + 1);
|
||||
break;
|
||||
case 0xb9:
|
||||
*fieldLength = (*(buffer + 1) << 8) + *(buffer + 2);
|
||||
break;
|
||||
case 0xba:
|
||||
*fieldLength = (*(buffer + 1) << 16) + (*(buffer + 2) << 8) + *(buffer + 3);
|
||||
break;
|
||||
case 0xbb:
|
||||
*fieldLength = (*(buffer + 1) << 24) + (*(buffer + 2) << 16) +
|
||||
(*(buffer + 3) << 8) + *(buffer + 4);
|
||||
break;
|
||||
default:
|
||||
return false; // arbitrary 32 bits length limitation
|
||||
}
|
||||
} else if (*buffer <= 0xf7) {
|
||||
*offset = 1;
|
||||
@@ -96,43 +98,39 @@ bool rlpDecodeLength(uint8_t *buffer, uint32_t bufferLength,
|
||||
*offset = 1 + (*buffer - 0xf7);
|
||||
*list = true;
|
||||
switch (*buffer) {
|
||||
case 0xf8:
|
||||
*fieldLength = *(buffer + 1);
|
||||
break;
|
||||
case 0xf9:
|
||||
*fieldLength = (*(buffer + 1) << 8) + *(buffer + 2);
|
||||
break;
|
||||
case 0xfa:
|
||||
*fieldLength =
|
||||
(*(buffer + 1) << 16) + (*(buffer + 2) << 8) + *(buffer + 3);
|
||||
break;
|
||||
case 0xfb:
|
||||
*fieldLength = (*(buffer + 1) << 24) + (*(buffer + 2) << 16) +
|
||||
(*(buffer + 3) << 8) + *(buffer + 4);
|
||||
break;
|
||||
default:
|
||||
return false; // arbitrary 32 bits length limitation
|
||||
case 0xf8:
|
||||
*fieldLength = *(buffer + 1);
|
||||
break;
|
||||
case 0xf9:
|
||||
*fieldLength = (*(buffer + 1) << 8) + *(buffer + 2);
|
||||
break;
|
||||
case 0xfa:
|
||||
*fieldLength = (*(buffer + 1) << 16) + (*(buffer + 2) << 8) + *(buffer + 3);
|
||||
break;
|
||||
case 0xfb:
|
||||
*fieldLength = (*(buffer + 1) << 24) + (*(buffer + 2) << 16) +
|
||||
(*(buffer + 3) << 8) + *(buffer + 4);
|
||||
break;
|
||||
default:
|
||||
return false; // arbitrary 32 bits length limitation
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
|
||||
cx_sha3_t *sha3Context) {
|
||||
void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3_t *sha3Context) {
|
||||
uint8_t hashAddress[32];
|
||||
cx_keccak_init(sha3Context, 256);
|
||||
cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32);
|
||||
cx_hash((cx_hash_t *) sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32);
|
||||
memmove(out, hashAddress + 12, 20);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CHECKSUM_1
|
||||
|
||||
static const uint8_t const HEXDIGITS[] = "0123456789ABCDEF";
|
||||
|
||||
static const uint8_t const MASK[] = {0x80, 0x40, 0x20, 0x10,
|
||||
0x08, 0x04, 0x02, 0x01};
|
||||
static const uint8_t const MASK[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
|
||||
|
||||
char convertDigit(uint8_t *address, uint8_t index, uint8_t *hash) {
|
||||
unsigned char digit = address[index / 2];
|
||||
@@ -153,21 +151,25 @@ char convertDigit(uint8_t *address, uint8_t index, uint8_t *hash) {
|
||||
}
|
||||
}
|
||||
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
|
||||
cx_sha3_t *sha3Context, chain_config_t* chain_config) {
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey,
|
||||
uint8_t *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t *chain_config) {
|
||||
uint8_t hashAddress[32];
|
||||
cx_keccak_init(sha3Context, 256);
|
||||
cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32);
|
||||
cx_hash((cx_hash_t *) sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32);
|
||||
getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context, chain_config);
|
||||
}
|
||||
|
||||
void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
cx_sha3_t *sha3Context, chain_config_t* chain_config) {
|
||||
void getEthAddressStringFromBinary(uint8_t *address,
|
||||
uint8_t *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t *chain_config) {
|
||||
UNUSED(chain_config);
|
||||
uint8_t hashChecksum[32];
|
||||
uint8_t i;
|
||||
cx_keccak_init(sha3Context, 256);
|
||||
cx_hash((cx_hash_t*)sha3Context, CX_LAST, address, 20, hashChecksum, 32);
|
||||
cx_hash((cx_hash_t *) sha3Context, CX_LAST, address, 20, hashChecksum, 32);
|
||||
for (i = 0; i < 40; i++) {
|
||||
out[i] = convertDigit(address, i, hashChecksum);
|
||||
}
|
||||
@@ -178,20 +180,22 @@ void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
|
||||
static const uint8_t const HEXDIGITS[] = "0123456789abcdef";
|
||||
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
|
||||
cx_sha3_t *sha3Context, chain_config_t* chain_config) {
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey,
|
||||
uint8_t *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t *chain_config) {
|
||||
uint8_t hashAddress[32];
|
||||
cx_keccak_init(sha3Context, 256);
|
||||
cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32);
|
||||
cx_hash((cx_hash_t *) sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32);
|
||||
getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context, chain_config);
|
||||
}
|
||||
|
||||
void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
cx_sha3_t *sha3Context, chain_config_t* chain_config) {
|
||||
|
||||
void getEthAddressStringFromBinary(uint8_t *address,
|
||||
uint8_t *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t *chain_config) {
|
||||
// save some precious stack space
|
||||
union locals_union
|
||||
{
|
||||
union locals_union {
|
||||
uint8_t hashChecksum[32];
|
||||
uint8_t tmp[51];
|
||||
} locals_union;
|
||||
@@ -199,15 +203,18 @@ void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
uint8_t i;
|
||||
bool eip1191 = false;
|
||||
uint32_t offset = 0;
|
||||
switch(chain_config->chainId) {
|
||||
switch (chain_config->chainId) {
|
||||
case 30:
|
||||
case 31:
|
||||
eip1191 = true;
|
||||
break;
|
||||
}
|
||||
if (eip1191) {
|
||||
snprintf((char*)locals_union.tmp, sizeof(locals_union.tmp), "%d0x", chain_config->chainId);
|
||||
offset = strlen((char*)locals_union.tmp);
|
||||
snprintf((char *) locals_union.tmp,
|
||||
sizeof(locals_union.tmp),
|
||||
"%d0x",
|
||||
chain_config->chainId);
|
||||
offset = strlen((char *) locals_union.tmp);
|
||||
}
|
||||
for (i = 0; i < 20; i++) {
|
||||
uint8_t digit = address[i];
|
||||
@@ -215,7 +222,12 @@ void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
locals_union.tmp[offset + 2 * i + 1] = HEXDIGITS[digit & 0x0f];
|
||||
}
|
||||
cx_keccak_init(sha3Context, 256);
|
||||
cx_hash((cx_hash_t*)sha3Context, CX_LAST, locals_union.tmp, offset + 40, locals_union.hashChecksum, 32);
|
||||
cx_hash((cx_hash_t *) sha3Context,
|
||||
CX_LAST,
|
||||
locals_union.tmp,
|
||||
offset + 40,
|
||||
locals_union.hashChecksum,
|
||||
32);
|
||||
for (i = 0; i < 40; i++) {
|
||||
uint8_t digit = address[i / 2];
|
||||
if ((i % 2) == 0) {
|
||||
@@ -225,13 +237,11 @@ void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
}
|
||||
if (digit < 10) {
|
||||
out[i] = HEXDIGITS[digit];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
int v = (locals_union.hashChecksum[i / 2] >> (4 * (1 - i % 2))) & 0x0f;
|
||||
if (v >= 8) {
|
||||
out[i] = HEXDIGITS[digit] - 'a' + 'A';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
out[i] = HEXDIGITS[digit];
|
||||
}
|
||||
}
|
||||
@@ -241,14 +251,17 @@ void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
|
||||
#endif
|
||||
|
||||
bool adjustDecimals(char *src, uint32_t srcLength, char *target,
|
||||
uint32_t targetLength, uint8_t decimals) {
|
||||
bool adjustDecimals(char *src,
|
||||
uint32_t srcLength,
|
||||
char *target,
|
||||
uint32_t targetLength,
|
||||
uint8_t decimals) {
|
||||
uint32_t startOffset;
|
||||
uint32_t lastZeroOffset = 0;
|
||||
uint32_t offset = 0;
|
||||
if ((srcLength == 1) && (*src == '0')) {
|
||||
if (targetLength < 2) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
target[0] = '0';
|
||||
target[1] = '\0';
|
||||
@@ -285,7 +298,7 @@ bool adjustDecimals(char *src, uint32_t srcLength, char *target,
|
||||
while (sourceOffset < srcLength) {
|
||||
target[offset++] = src[sourceOffset++];
|
||||
}
|
||||
target[offset] = '\0';
|
||||
target[offset] = '\0';
|
||||
}
|
||||
for (uint32_t i = startOffset; i < offset; i++) {
|
||||
if (target[i] == '0') {
|
||||
@@ -299,7 +312,7 @@ bool adjustDecimals(char *src, uint32_t srcLength, char *target,
|
||||
if (lastZeroOffset != 0) {
|
||||
target[lastZeroOffset] = '\0';
|
||||
if (target[lastZeroOffset - 1] == '.') {
|
||||
target[lastZeroOffset - 1] = '\0';
|
||||
target[lastZeroOffset - 1] = '\0';
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef _ETHUTILS_H_
|
||||
#define _ETHUTILS_H_
|
||||
@@ -34,42 +34,47 @@
|
||||
* string
|
||||
* @return true if the RLP header is consistent
|
||||
*/
|
||||
bool rlpDecodeLength(uint8_t *buffer, uint32_t bufferLength,
|
||||
uint32_t *fieldLength, uint32_t *offset, bool *list);
|
||||
bool rlpDecodeLength(uint8_t *buffer,
|
||||
uint32_t bufferLength,
|
||||
uint32_t *fieldLength,
|
||||
uint32_t *offset,
|
||||
bool *list);
|
||||
|
||||
bool rlpCanDecode(uint8_t *buffer, uint32_t bufferLength, bool *valid);
|
||||
|
||||
void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
|
||||
cx_sha3_t *sha3Context);
|
||||
void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3_t *sha3Context);
|
||||
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out,
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey,
|
||||
uint8_t *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t* chain_config);
|
||||
chain_config_t *chain_config);
|
||||
|
||||
void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t* chain_config);
|
||||
void getEthAddressStringFromBinary(uint8_t *address,
|
||||
uint8_t *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t *chain_config);
|
||||
|
||||
bool adjustDecimals(char *src, uint32_t srcLength, char *target,
|
||||
uint32_t targetLength, uint8_t decimals);
|
||||
bool adjustDecimals(char *src,
|
||||
uint32_t srcLength,
|
||||
char *target,
|
||||
uint32_t targetLength,
|
||||
uint8_t decimals);
|
||||
|
||||
__attribute__((no_instrument_function))
|
||||
inline int allzeroes(uint8_t *buf, int n) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (buf[i]) {
|
||||
return 0;
|
||||
__attribute__((no_instrument_function)) inline int allzeroes(uint8_t *buf, int n) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (buf[i]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
__attribute__((no_instrument_function))
|
||||
inline int ismaxint(uint8_t *buf, int n) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (buf[i] != 0xff) {
|
||||
return 0;
|
||||
__attribute__((no_instrument_function)) inline int ismaxint(uint8_t *buf, int n) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (buf[i] != 0xff) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* _ETHUTILS_H_ */
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
// Adapted from https://github.com/calccrypto/uint256_t
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
static const char HEXDIGITS[] = "0123456789abcdef";
|
||||
|
||||
static uint64_t readUint64BE(uint8_t *buffer) {
|
||||
return (((uint64_t)buffer[0]) << 56) | (((uint64_t)buffer[1]) << 48) |
|
||||
(((uint64_t)buffer[2]) << 40) | (((uint64_t)buffer[3]) << 32) |
|
||||
(((uint64_t)buffer[4]) << 24) | (((uint64_t)buffer[5]) << 16) |
|
||||
(((uint64_t)buffer[6]) << 8) | (((uint64_t)buffer[7]));
|
||||
return (((uint64_t) buffer[0]) << 56) | (((uint64_t) buffer[1]) << 48) |
|
||||
(((uint64_t) buffer[2]) << 40) | (((uint64_t) buffer[3]) << 32) |
|
||||
(((uint64_t) buffer[4]) << 24) | (((uint64_t) buffer[5]) << 16) |
|
||||
(((uint64_t) buffer[6]) << 8) | (((uint64_t) buffer[7]));
|
||||
}
|
||||
|
||||
void readu128BE(uint8_t *buffer, uint128_t *target) {
|
||||
@@ -78,8 +78,7 @@ void shiftl128(uint128_t *number, uint32_t value, uint128_t *target) {
|
||||
} else if (value == 0) {
|
||||
copy128(target, number);
|
||||
} else if (value < 64) {
|
||||
UPPER_P(target) =
|
||||
(UPPER_P(number) << value) + (LOWER_P(number) >> (64 - value));
|
||||
UPPER_P(target) = (UPPER_P(number) << value) + (LOWER_P(number) >> (64 - value));
|
||||
LOWER_P(target) = (LOWER_P(number) << value);
|
||||
} else if ((128 > value) && (value > 64)) {
|
||||
UPPER_P(target) = LOWER_P(number) << (value - 64);
|
||||
@@ -125,8 +124,7 @@ void shiftr128(uint128_t *number, uint32_t value, uint128_t *target) {
|
||||
} else if (value < 64) {
|
||||
uint128_t result;
|
||||
UPPER(result) = UPPER_P(number) >> value;
|
||||
LOWER(result) =
|
||||
(UPPER_P(number) << (64 - value)) + (LOWER_P(number) >> value);
|
||||
LOWER(result) = (UPPER_P(number) << (64 - value)) + (LOWER_P(number) >> value);
|
||||
copy128(target, &result);
|
||||
} else if ((128 > value) && (value > 64)) {
|
||||
LOWER_P(target) = UPPER_P(number) >> (value - 64);
|
||||
@@ -202,8 +200,7 @@ uint32_t bits256(uint256_t *number) {
|
||||
}
|
||||
|
||||
bool equal128(uint128_t *number1, uint128_t *number2) {
|
||||
return (UPPER_P(number1) == UPPER_P(number2)) &&
|
||||
(LOWER_P(number1) == LOWER_P(number2));
|
||||
return (UPPER_P(number1) == UPPER_P(number2)) && (LOWER_P(number1) == LOWER_P(number2));
|
||||
}
|
||||
|
||||
bool equal256(uint256_t *number1, uint256_t *number2) {
|
||||
@@ -234,9 +231,8 @@ bool gte256(uint256_t *number1, uint256_t *number2) {
|
||||
}
|
||||
|
||||
void add128(uint128_t *number1, uint128_t *number2, uint128_t *target) {
|
||||
UPPER_P(target) =
|
||||
UPPER_P(number1) + UPPER_P(number2) +
|
||||
((LOWER_P(number1) + LOWER_P(number2)) < LOWER_P(number1));
|
||||
UPPER_P(target) = UPPER_P(number1) + UPPER_P(number2) +
|
||||
((LOWER_P(number1) + LOWER_P(number2)) < LOWER_P(number1));
|
||||
LOWER_P(target) = LOWER_P(number1) + LOWER_P(number2);
|
||||
}
|
||||
|
||||
@@ -254,9 +250,8 @@ void add256(uint256_t *number1, uint256_t *number2, uint256_t *target) {
|
||||
}
|
||||
|
||||
void minus128(uint128_t *number1, uint128_t *number2, uint128_t *target) {
|
||||
UPPER_P(target) =
|
||||
UPPER_P(number1) - UPPER_P(number2) -
|
||||
((LOWER_P(number1) - LOWER_P(number2)) > LOWER_P(number1));
|
||||
UPPER_P(target) = UPPER_P(number1) - UPPER_P(number2) -
|
||||
((LOWER_P(number1) - LOWER_P(number2)) > LOWER_P(number1));
|
||||
LOWER_P(target) = LOWER_P(number1) - LOWER_P(number2);
|
||||
}
|
||||
|
||||
@@ -284,9 +279,12 @@ void or256(uint256_t *number1, uint256_t *number2, uint256_t *target) {
|
||||
}
|
||||
|
||||
void mul128(uint128_t *number1, uint128_t *number2, uint128_t *target) {
|
||||
uint64_t top[4] = {UPPER_P(number1) >> 32, UPPER_P(number1) & 0xffffffff,
|
||||
LOWER_P(number1) >> 32, LOWER_P(number1) & 0xffffffff};
|
||||
uint64_t bottom[4] = {UPPER_P(number2) >> 32, UPPER_P(number2) & 0xffffffff,
|
||||
uint64_t top[4] = {UPPER_P(number1) >> 32,
|
||||
UPPER_P(number1) & 0xffffffff,
|
||||
LOWER_P(number1) >> 32,
|
||||
LOWER_P(number1) & 0xffffffff};
|
||||
uint64_t bottom[4] = {UPPER_P(number2) >> 32,
|
||||
UPPER_P(number2) & 0xffffffff,
|
||||
LOWER_P(number2) >> 32,
|
||||
LOWER_P(number2) & 0xffffffff};
|
||||
uint64_t products[4][4];
|
||||
@@ -337,7 +335,7 @@ void write_u64_be(uint8_t *buffer, uint64_t value) {
|
||||
}
|
||||
|
||||
void read_u64_be(uint8_t *in, uint64_t *out) {
|
||||
uint8_t *out_ptr = (uint8_t*)out;
|
||||
uint8_t *out_ptr = (uint8_t *) out;
|
||||
*out_ptr++ = in[7];
|
||||
*out_ptr++ = in[6];
|
||||
*out_ptr++ = in[5];
|
||||
@@ -351,18 +349,17 @@ void read_u64_be(uint8_t *in, uint64_t *out) {
|
||||
void mul256(uint256_t *number1, uint256_t *number2, uint256_t *target) {
|
||||
uint8_t num1[32], num2[32], result[64];
|
||||
memset(&result, 0, sizeof(result));
|
||||
for(uint8_t i = 0; i<4; i++){
|
||||
write_u64_be(num1+i*sizeof(uint64_t), number1->elements[i/2].elements[i%2]);
|
||||
write_u64_be(num2+i*sizeof(uint64_t), number2->elements[i/2].elements[i%2]);
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
write_u64_be(num1 + i * sizeof(uint64_t), number1->elements[i / 2].elements[i % 2]);
|
||||
write_u64_be(num2 + i * sizeof(uint64_t), number2->elements[i / 2].elements[i % 2]);
|
||||
}
|
||||
cx_math_mult(result, num1, num2, sizeof(num1));
|
||||
for(uint8_t i = 0; i<4; i++){
|
||||
read_u64_be(result+32+i*sizeof(uint64_t), &target->elements[i/2].elements[i%2]);
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
read_u64_be(result + 32 + i * sizeof(uint64_t), &target->elements[i / 2].elements[i % 2]);
|
||||
}
|
||||
}
|
||||
|
||||
void divmod128(uint128_t *l, uint128_t *r, uint128_t *retDiv,
|
||||
uint128_t *retMod) {
|
||||
void divmod128(uint128_t *l, uint128_t *r, uint128_t *retDiv, uint128_t *retMod) {
|
||||
uint128_t copyd, adder, resDiv, resMod;
|
||||
uint128_t one;
|
||||
UPPER(one) = 0;
|
||||
@@ -393,8 +390,7 @@ void divmod128(uint128_t *l, uint128_t *r, uint128_t *retDiv,
|
||||
}
|
||||
}
|
||||
|
||||
void divmod256(uint256_t *l, uint256_t *r, uint256_t *retDiv,
|
||||
uint256_t *retMod) {
|
||||
void divmod256(uint256_t *l, uint256_t *r, uint256_t *retDiv, uint256_t *retMod) {
|
||||
uint256_t copyd, adder, resDiv, resMod;
|
||||
uint256_t one;
|
||||
clear256(&one);
|
||||
@@ -436,8 +432,7 @@ static void reverseString(char *str, uint32_t length) {
|
||||
}
|
||||
}
|
||||
|
||||
bool tostring128(uint128_t *number, uint32_t baseParam, char *out,
|
||||
uint32_t outLength) {
|
||||
bool tostring128(uint128_t *number, uint32_t baseParam, char *out, uint32_t outLength) {
|
||||
uint128_t rDiv;
|
||||
uint128_t rMod;
|
||||
uint128_t base;
|
||||
@@ -454,15 +449,14 @@ bool tostring128(uint128_t *number, uint32_t baseParam, char *out,
|
||||
return false;
|
||||
}
|
||||
divmod128(&rDiv, &base, &rDiv, &rMod);
|
||||
out[offset++] = HEXDIGITS[(uint8_t)LOWER(rMod)];
|
||||
out[offset++] = HEXDIGITS[(uint8_t) LOWER(rMod)];
|
||||
} while (!zero128(&rDiv));
|
||||
out[offset] = '\0';
|
||||
reverseString(out, offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tostring256(uint256_t *number, uint32_t baseParam, char *out,
|
||||
uint32_t outLength) {
|
||||
bool tostring256(uint256_t *number, uint32_t baseParam, char *out, uint32_t outLength) {
|
||||
uint256_t rDiv;
|
||||
uint256_t rMod;
|
||||
uint256_t base;
|
||||
@@ -480,7 +474,7 @@ bool tostring256(uint256_t *number, uint32_t baseParam, char *out,
|
||||
return false;
|
||||
}
|
||||
divmod256(&rDiv, &base, &rDiv, &rMod);
|
||||
out[offset++] = HEXDIGITS[(uint8_t)LOWER(LOWER(rMod))];
|
||||
out[offset++] = HEXDIGITS[(uint8_t) LOWER(LOWER(rMod))];
|
||||
} while (!zero256(&rDiv));
|
||||
out[offset] = '\0';
|
||||
reverseString(out, offset);
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*******************************************************************************
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
* Ledger Ethereum App
|
||||
* (c) 2016-2019 Ledger
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
********************************************************************************/
|
||||
|
||||
// Adapted from https://github.com/calccrypto/uint256_t
|
||||
|
||||
@@ -25,14 +25,18 @@
|
||||
#include "os.h"
|
||||
#include "cx.h"
|
||||
|
||||
typedef struct uint128_t { uint64_t elements[2]; } uint128_t;
|
||||
typedef struct uint128_t {
|
||||
uint64_t elements[2];
|
||||
} uint128_t;
|
||||
|
||||
typedef struct uint256_t { uint128_t elements[2]; } uint256_t;
|
||||
typedef struct uint256_t {
|
||||
uint128_t elements[2];
|
||||
} uint256_t;
|
||||
|
||||
#define UPPER_P(x) x->elements[0]
|
||||
#define LOWER_P(x) x->elements[1]
|
||||
#define UPPER(x) x.elements[0]
|
||||
#define LOWER(x) x.elements[1]
|
||||
#define UPPER(x) x.elements[0]
|
||||
#define LOWER(x) x.elements[1]
|
||||
|
||||
void readu128BE(uint8_t *buffer, uint128_t *target);
|
||||
void readu256BE(uint8_t *buffer, uint256_t *target);
|
||||
@@ -64,9 +68,7 @@ void mul128(uint128_t *number1, uint128_t *number2, uint128_t *target);
|
||||
void mul256(uint256_t *number1, uint256_t *number2, uint256_t *target);
|
||||
void divmod128(uint128_t *l, uint128_t *r, uint128_t *div, uint128_t *mod);
|
||||
void divmod256(uint256_t *l, uint256_t *r, uint256_t *div, uint256_t *mod);
|
||||
bool tostring128(uint128_t *number, uint32_t base, char *out,
|
||||
uint32_t outLength);
|
||||
bool tostring256(uint256_t *number, uint32_t base, char *out,
|
||||
uint32_t outLength);
|
||||
bool tostring128(uint128_t *number, uint32_t base, char *out, uint32_t outLength);
|
||||
bool tostring256(uint256_t *number, uint32_t base, char *out, uint32_t outLength);
|
||||
|
||||
#endif /* _UINT256_H_ */
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "shared_context.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(ux_approval_allowance_1_step,
|
||||
pnn,
|
||||
{
|
||||
@@ -59,14 +60,13 @@ UX_STEP_CB(
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_approval_allowance_flow,
|
||||
&ux_approval_allowance_1_step,
|
||||
&ux_approval_allowance_2_step,
|
||||
&ux_approval_allowance_3_step,
|
||||
&ux_approval_allowance_4_step,
|
||||
&ux_approval_allowance_5_step,
|
||||
&ux_approval_allowance_6_step,
|
||||
&ux_approval_allowance_7_step
|
||||
);
|
||||
|
||||
&ux_approval_allowance_1_step,
|
||||
&ux_approval_allowance_2_step,
|
||||
&ux_approval_allowance_3_step,
|
||||
&ux_approval_allowance_4_step,
|
||||
&ux_approval_allowance_5_step,
|
||||
&ux_approval_allowance_6_step,
|
||||
&ux_approval_allowance_7_step);
|
||||
|
||||
@@ -3,24 +3,28 @@
|
||||
|
||||
#include "ui_flow.h"
|
||||
|
||||
void handleGetAppConfiguration(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
UNUSED(p1);
|
||||
UNUSED(p2);
|
||||
UNUSED(workBuffer);
|
||||
UNUSED(dataLength);
|
||||
UNUSED(flags);
|
||||
G_io_apdu_buffer[0] = (N_storage.dataAllowed ? APP_FLAG_DATA_ALLOWED : 0x00);
|
||||
void handleGetAppConfiguration(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *workBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
UNUSED(p1);
|
||||
UNUSED(p2);
|
||||
UNUSED(workBuffer);
|
||||
UNUSED(dataLength);
|
||||
UNUSED(flags);
|
||||
G_io_apdu_buffer[0] = (N_storage.dataAllowed ? APP_FLAG_DATA_ALLOWED : 0x00);
|
||||
#ifndef HAVE_TOKENS_LIST
|
||||
G_io_apdu_buffer[0] |= APP_FLAG_EXTERNAL_TOKEN_NEEDED;
|
||||
G_io_apdu_buffer[0] |= APP_FLAG_EXTERNAL_TOKEN_NEEDED;
|
||||
#endif
|
||||
#ifdef HAVE_STARKWARE
|
||||
G_io_apdu_buffer[0] |= APP_FLAG_STARKWARE;
|
||||
G_io_apdu_buffer[0] |= APP_FLAG_STARKWARE_V2;
|
||||
G_io_apdu_buffer[0] |= APP_FLAG_STARKWARE;
|
||||
G_io_apdu_buffer[0] |= APP_FLAG_STARKWARE_V2;
|
||||
#endif
|
||||
G_io_apdu_buffer[1] = LEDGER_MAJOR_VERSION;
|
||||
G_io_apdu_buffer[2] = LEDGER_MINOR_VERSION;
|
||||
G_io_apdu_buffer[3] = LEDGER_PATCH_VERSION;
|
||||
*tx = 4;
|
||||
THROW(0x9000);
|
||||
G_io_apdu_buffer[1] = LEDGER_MAJOR_VERSION;
|
||||
G_io_apdu_buffer[2] = LEDGER_MINOR_VERSION;
|
||||
G_io_apdu_buffer[3] = LEDGER_PATCH_VERSION;
|
||||
*tx = 4;
|
||||
THROW(0x9000);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,75 +6,81 @@
|
||||
#include "ui_flow.h"
|
||||
#include "feature_getEth2PublicKey.h"
|
||||
|
||||
static const uint8_t BLS12_381_FIELD_MODULUS[] = { 0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, 0x43, 0x4b, 0xac, 0xd7, 0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, 0x67, 0x30, 0xd2, 0xa0, 0xf6, 0xb0, 0xf6, 0x24, 0x1e, 0xab, 0xff, 0xfe, 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xab };
|
||||
static const uint8_t BLS12_381_FIELD_MODULUS[] = {
|
||||
0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, 0x43, 0x4b, 0xac, 0xd7,
|
||||
0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, 0x67, 0x30, 0xd2, 0xa0, 0xf6, 0xb0, 0xf6, 0x24,
|
||||
0x1e, 0xab, 0xff, 0xfe, 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xab};
|
||||
|
||||
void getEth2PublicKey(uint32_t *bip32Path, uint8_t bip32PathLength, uint8_t *out) {
|
||||
uint8_t privateKeyData[32];
|
||||
cx_ecfp_256_extended_private_key_t privateKey;
|
||||
cx_ecfp_384_public_key_t publicKey;
|
||||
uint8_t yFlag = 0;
|
||||
uint8_t tmp[96];
|
||||
uint8_t privateKeyData[32];
|
||||
cx_ecfp_256_extended_private_key_t privateKey;
|
||||
cx_ecfp_384_public_key_t publicKey;
|
||||
uint8_t yFlag = 0;
|
||||
uint8_t tmp[96];
|
||||
|
||||
io_seproxyhal_io_heartbeat();
|
||||
os_perso_derive_eip2333(CX_CURVE_BLS12_381_G1, bip32Path, bip32PathLength, privateKeyData);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
memset(tmp, 0, 48);
|
||||
memmove(tmp + 16, privateKeyData, 32);
|
||||
cx_ecfp_init_private_key(CX_CURVE_BLS12_381_G1, tmp, 48, &privateKey);
|
||||
cx_ecfp_generate_pair(CX_CURVE_BLS12_381_G1, &publicKey, &privateKey, 1);
|
||||
explicit_bzero(tmp, 96);
|
||||
explicit_bzero((void*)&privateKey, sizeof(cx_ecfp_256_extended_private_key_t));
|
||||
tmp[47] = 2;
|
||||
cx_math_mult(tmp, publicKey.W + 1 + 48, tmp, 48);
|
||||
if (cx_math_cmp(tmp + 48, BLS12_381_FIELD_MODULUS, 48) > 0) {
|
||||
yFlag = 0x20;
|
||||
}
|
||||
publicKey.W[1] &= 0x1f;
|
||||
publicKey.W[1] |= 0x80 | yFlag;
|
||||
memmove(out, publicKey.W + 1, 48);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
os_perso_derive_eip2333(CX_CURVE_BLS12_381_G1, bip32Path, bip32PathLength, privateKeyData);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
memset(tmp, 0, 48);
|
||||
memmove(tmp + 16, privateKeyData, 32);
|
||||
cx_ecfp_init_private_key(CX_CURVE_BLS12_381_G1, tmp, 48, &privateKey);
|
||||
cx_ecfp_generate_pair(CX_CURVE_BLS12_381_G1, &publicKey, &privateKey, 1);
|
||||
explicit_bzero(tmp, 96);
|
||||
explicit_bzero((void *) &privateKey, sizeof(cx_ecfp_256_extended_private_key_t));
|
||||
tmp[47] = 2;
|
||||
cx_math_mult(tmp, publicKey.W + 1 + 48, tmp, 48);
|
||||
if (cx_math_cmp(tmp + 48, BLS12_381_FIELD_MODULUS, 48) > 0) {
|
||||
yFlag = 0x20;
|
||||
}
|
||||
publicKey.W[1] &= 0x1f;
|
||||
publicKey.W[1] |= 0x80 | yFlag;
|
||||
memmove(out, publicKey.W + 1, 48);
|
||||
}
|
||||
|
||||
void handleGetEth2PublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
UNUSED(dataLength);
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = *(dataBuffer++);
|
||||
void handleGetEth2PublicKey(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
UNUSED(dataLength);
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = *(dataBuffer++);
|
||||
|
||||
if(!called_from_swap){
|
||||
reset_app_context();
|
||||
}
|
||||
if ((bip32PathLength < 0x01) ||
|
||||
(bip32PathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (p2 != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
bip32Path[i] = U4BE(dataBuffer, 0);
|
||||
dataBuffer += 4;
|
||||
}
|
||||
getEth2PublicKey(bip32Path, bip32PathLength, tmpCtx.publicKeyContext.publicKey.W);
|
||||
if (!called_from_swap) {
|
||||
reset_app_context();
|
||||
}
|
||||
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (p2 != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
bip32Path[i] = U4BE(dataBuffer, 0);
|
||||
dataBuffer += 4;
|
||||
}
|
||||
getEth2PublicKey(bip32Path, bip32PathLength, tmpCtx.publicKeyContext.publicKey.W);
|
||||
|
||||
#ifndef NO_CONSENT
|
||||
if (p1 == P1_NON_CONFIRM)
|
||||
#endif // NO_CONSENT
|
||||
{
|
||||
*tx = set_result_get_eth2_publicKey();
|
||||
THROW(0x9000);
|
||||
}
|
||||
if (p1 == P1_NON_CONFIRM)
|
||||
#endif // NO_CONSENT
|
||||
{
|
||||
*tx = set_result_get_eth2_publicKey();
|
||||
THROW(0x9000);
|
||||
}
|
||||
#ifndef NO_CONSENT
|
||||
else
|
||||
{
|
||||
ux_flow_init(0, ux_display_public_eth2_flow, NULL);
|
||||
else {
|
||||
ux_flow_init(0, ux_display_public_eth2_flow, NULL);
|
||||
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
#endif // NO_CONSENT
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
#endif // NO_CONSENT
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "shared_context.h"
|
||||
|
||||
uint32_t set_result_get_eth2_publicKey(void);
|
||||
|
||||
|
||||
@@ -10,4 +10,3 @@ uint32_t set_result_get_eth2_publicKey() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ unsigned int io_seproxyhal_touch_eth2_address_ok(const bagl_element_t *e) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
void prepare_eth2_public_key() {
|
||||
snprintf(strings.tmp.tmp, 100, "0x%.*H", 48, tmpCtx.publicKeyContext.publicKey.W);
|
||||
snprintf(strings.tmp.tmp, 100, "0x%.*H", 48, tmpCtx.publicKeyContext.publicKey.W);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_display_public_eth2_flow_1_step,
|
||||
pnn,
|
||||
@@ -39,12 +40,12 @@ UX_STEP_CB(
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_display_public_eth2_flow,
|
||||
&ux_display_public_eth2_flow_1_step,
|
||||
&ux_display_public_eth2_flow_2_step,
|
||||
&ux_display_public_eth2_flow_3_step,
|
||||
&ux_display_public_eth2_flow_4_step
|
||||
);
|
||||
&ux_display_public_eth2_flow_1_step,
|
||||
&ux_display_public_eth2_flow_2_step,
|
||||
&ux_display_public_eth2_flow_3_step,
|
||||
&ux_display_public_eth2_flow_4_step);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,56 +4,70 @@
|
||||
#include "ui_flow.h"
|
||||
#include "feature_getPublicKey.h"
|
||||
|
||||
void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
UNUSED(dataLength);
|
||||
uint8_t privateKeyData[32];
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = *(dataBuffer++);
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
if(!called_from_swap){
|
||||
reset_app_context();
|
||||
}
|
||||
if ((bip32PathLength < 0x01) ||
|
||||
(bip32PathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if ((p2 != P2_CHAINCODE) && (p2 != P2_NO_CHAINCODE)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
bip32Path[i] = U4BE(dataBuffer, 0);
|
||||
dataBuffer += 4;
|
||||
}
|
||||
tmpCtx.publicKeyContext.getChaincode = (p2 == P2_CHAINCODE);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1, bip32Path, bip32PathLength, privateKeyData, (tmpCtx.publicKeyContext.getChaincode ? tmpCtx.publicKeyContext.chainCode : NULL));
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_generate_pair(CX_CURVE_256K1, &tmpCtx.publicKeyContext.publicKey, &privateKey, 1);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
io_seproxyhal_io_heartbeat();
|
||||
getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey, tmpCtx.publicKeyContext.address, &global_sha3, chainConfig);
|
||||
void handleGetPublicKey(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
UNUSED(dataLength);
|
||||
uint8_t privateKeyData[32];
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = *(dataBuffer++);
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
if (!called_from_swap) {
|
||||
reset_app_context();
|
||||
}
|
||||
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if ((p2 != P2_CHAINCODE) && (p2 != P2_NO_CHAINCODE)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
bip32Path[i] = U4BE(dataBuffer, 0);
|
||||
dataBuffer += 4;
|
||||
}
|
||||
tmpCtx.publicKeyContext.getChaincode = (p2 == P2_CHAINCODE);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
os_perso_derive_node_bip32(
|
||||
CX_CURVE_256K1,
|
||||
bip32Path,
|
||||
bip32PathLength,
|
||||
privateKeyData,
|
||||
(tmpCtx.publicKeyContext.getChaincode ? tmpCtx.publicKeyContext.chainCode : NULL));
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_generate_pair(CX_CURVE_256K1, &tmpCtx.publicKeyContext.publicKey, &privateKey, 1);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
io_seproxyhal_io_heartbeat();
|
||||
getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey,
|
||||
tmpCtx.publicKeyContext.address,
|
||||
&global_sha3,
|
||||
chainConfig);
|
||||
#ifndef NO_CONSENT
|
||||
if (p1 == P1_NON_CONFIRM)
|
||||
#endif // NO_CONSENT
|
||||
{
|
||||
*tx = set_result_get_publicKey();
|
||||
THROW(0x9000);
|
||||
}
|
||||
if (p1 == P1_NON_CONFIRM)
|
||||
#endif // NO_CONSENT
|
||||
{
|
||||
*tx = set_result_get_publicKey();
|
||||
THROW(0x9000);
|
||||
}
|
||||
#ifndef NO_CONSENT
|
||||
else
|
||||
{
|
||||
snprintf(strings.common.fullAddress, sizeof(strings.common.fullAddress), "0x%.*s", 40, tmpCtx.publicKeyContext.address);
|
||||
ux_flow_init(0, ux_display_public_flow, NULL);
|
||||
else {
|
||||
snprintf(strings.common.fullAddress,
|
||||
sizeof(strings.common.fullAddress),
|
||||
"0x%.*s",
|
||||
40,
|
||||
tmpCtx.publicKeyContext.address);
|
||||
ux_flow_init(0, ux_display_public_flow, NULL);
|
||||
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
#endif // NO_CONSENT
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
#endif // NO_CONSENT
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "shared_context.h"
|
||||
|
||||
uint32_t set_result_get_publicKey(void);
|
||||
|
||||
|
||||
@@ -9,9 +9,8 @@ uint32_t set_result_get_publicKey() {
|
||||
memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.address, 40);
|
||||
tx += 40;
|
||||
if (tmpCtx.publicKeyContext.getChaincode) {
|
||||
memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.chainCode, 32);
|
||||
tx += 32;
|
||||
memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.chainCode, 32);
|
||||
tx += 32;
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ unsigned int io_seproxyhal_touch_address_ok(const bagl_element_t *e) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_address_cancel(const bagl_element_t *e) {
|
||||
@@ -22,6 +22,5 @@ unsigned int io_seproxyhal_touch_address_cancel(const bagl_element_t *e) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "shared_context.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_display_public_flow_1_step,
|
||||
pnn,
|
||||
@@ -32,10 +33,10 @@ UX_STEP_CB(
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_display_public_flow,
|
||||
&ux_display_public_flow_1_step,
|
||||
&ux_display_public_flow_2_step,
|
||||
&ux_display_public_flow_3_step,
|
||||
&ux_display_public_flow_4_step
|
||||
);
|
||||
&ux_display_public_flow_1_step,
|
||||
&ux_display_public_flow_2_step,
|
||||
&ux_display_public_flow_3_step,
|
||||
&ux_display_public_flow_4_step);
|
||||
|
||||
@@ -3,172 +3,212 @@
|
||||
#include "ui_flow.h"
|
||||
|
||||
static const uint8_t const TOKEN_SIGNATURE_PUBLIC_KEY[] = {
|
||||
// production key 2019-01-11 03:07PM (erc20signer)
|
||||
0x04,
|
||||
// production key 2019-01-11 03:07PM (erc20signer)
|
||||
0x04,
|
||||
|
||||
0x5e,0x6c,0x10,0x20,0xc1,0x4d,0xc4,0x64,
|
||||
0x42,0xfe,0x89,0xf9,0x7c,0x0b,0x68,0xcd,
|
||||
0xb1,0x59,0x76,0xdc,0x24,0xf2,0x4c,0x31,
|
||||
0x6e,0x7b,0x30,0xfe,0x4e,0x8c,0xc7,0x6b,
|
||||
0x5e, 0x6c, 0x10, 0x20, 0xc1, 0x4d, 0xc4, 0x64, 0x42, 0xfe, 0x89, 0xf9, 0x7c, 0x0b, 0x68, 0xcd,
|
||||
0xb1, 0x59, 0x76, 0xdc, 0x24, 0xf2, 0x4c, 0x31, 0x6e, 0x7b, 0x30, 0xfe, 0x4e, 0x8c, 0xc7, 0x6b,
|
||||
|
||||
0x14,0x89,0x15,0x0c,0x21,0x51,0x4e,0xbf,
|
||||
0x44,0x0f,0xf5,0xde,0xa5,0x39,0x3d,0x83,
|
||||
0xde,0x53,0x58,0xcd,0x09,0x8f,0xce,0x8f,
|
||||
0xd0,0xf8,0x1d,0xaa,0x94,0x97,0x91,0x83
|
||||
};
|
||||
0x14, 0x89, 0x15, 0x0c, 0x21, 0x51, 0x4e, 0xbf, 0x44, 0x0f, 0xf5, 0xde, 0xa5, 0x39, 0x3d, 0x83,
|
||||
0xde, 0x53, 0x58, 0xcd, 0x09, 0x8f, 0xce, 0x8f, 0xd0, 0xf8, 0x1d, 0xaa, 0x94, 0x97, 0x91, 0x83};
|
||||
|
||||
#ifdef HAVE_CONTRACT_NAME_IN_DESCRIPTOR
|
||||
|
||||
void handleProvideErc20TokenInformation(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
UNUSED(p1);
|
||||
UNUSED(p2);
|
||||
UNUSED(flags);
|
||||
uint32_t offset = 0;
|
||||
uint8_t tickerLength, contractNameLength;
|
||||
uint32_t chainId;
|
||||
uint8_t hash[32];
|
||||
cx_sha256_t sha256;
|
||||
cx_ecfp_public_key_t tokenKey;
|
||||
void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *workBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
UNUSED(p1);
|
||||
UNUSED(p2);
|
||||
UNUSED(flags);
|
||||
uint32_t offset = 0;
|
||||
uint8_t tickerLength, contractNameLength;
|
||||
uint32_t chainId;
|
||||
uint8_t hash[32];
|
||||
cx_sha256_t sha256;
|
||||
cx_ecfp_public_key_t tokenKey;
|
||||
|
||||
cx_sha256_init(&sha256);
|
||||
cx_sha256_init(&sha256);
|
||||
|
||||
tmpCtx.transactionContext.currentTokenIndex = (tmpCtx.transactionContext.currentTokenIndex + 1) % MAX_TOKEN;
|
||||
tokenDefinition_t* token = &tmpCtx.transactionContext.tokens[tmpCtx.transactionContext.currentTokenIndex];
|
||||
tmpCtx.transactionContext.currentTokenIndex =
|
||||
(tmpCtx.transactionContext.currentTokenIndex + 1) % MAX_TOKEN;
|
||||
tokenDefinition_t *token =
|
||||
&tmpCtx.transactionContext.tokens[tmpCtx.transactionContext.currentTokenIndex];
|
||||
|
||||
if (dataLength < 1) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
tickerLength = workBuffer[offset++];
|
||||
dataLength--;
|
||||
if ((tickerLength + 2) >= sizeof(token->ticker)) { // +2 because ' \0' is appended to ticker
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (dataLength < tickerLength + 1) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_hash((cx_hash_t*)&sha256, 0, workBuffer + offset, tickerLength, NULL, 0);
|
||||
memmove(token->ticker, workBuffer + offset, tickerLength);
|
||||
token->ticker[tickerLength] = ' ';
|
||||
token->ticker[tickerLength + 1] = '\0';
|
||||
offset += tickerLength;
|
||||
dataLength -= tickerLength;
|
||||
if (dataLength < 1) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
tickerLength = workBuffer[offset++];
|
||||
dataLength--;
|
||||
if ((tickerLength + 2) >= sizeof(token->ticker)) { // +2 because ' \0' is appended to ticker
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (dataLength < tickerLength + 1) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_hash((cx_hash_t *) &sha256, 0, workBuffer + offset, tickerLength, NULL, 0);
|
||||
memmove(token->ticker, workBuffer + offset, tickerLength);
|
||||
token->ticker[tickerLength] = ' ';
|
||||
token->ticker[tickerLength + 1] = '\0';
|
||||
offset += tickerLength;
|
||||
dataLength -= tickerLength;
|
||||
|
||||
contractNameLength = workBuffer[offset++];
|
||||
dataLength--;
|
||||
if (dataLength < contractNameLength + 20 + 4 + 4) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_hash((cx_hash_t*)&sha256, CX_LAST, workBuffer + offset, contractNameLength + 20 + 4 + 4, hash, 32);
|
||||
memmove(token->contractName, workBuffer + offset, MIN(contractNameLength, sizeof(token->contractName)-1));
|
||||
token->contractName[MIN(contractNameLength, sizeof(token->contractName)-1)] = '\0';
|
||||
offset += contractNameLength;
|
||||
dataLength -= contractNameLength;
|
||||
contractNameLength = workBuffer[offset++];
|
||||
dataLength--;
|
||||
if (dataLength < contractNameLength + 20 + 4 + 4) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_hash((cx_hash_t *) &sha256,
|
||||
CX_LAST,
|
||||
workBuffer + offset,
|
||||
contractNameLength + 20 + 4 + 4,
|
||||
hash,
|
||||
32);
|
||||
memmove(token->contractName,
|
||||
workBuffer + offset,
|
||||
MIN(contractNameLength, sizeof(token->contractName) - 1));
|
||||
token->contractName[MIN(contractNameLength, sizeof(token->contractName) - 1)] = '\0';
|
||||
offset += contractNameLength;
|
||||
dataLength -= contractNameLength;
|
||||
|
||||
memmove(token->address, workBuffer + offset, 20);
|
||||
offset += 20;
|
||||
dataLength -= 20;
|
||||
token->decimals = U4BE(workBuffer, offset);
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
chainId = U4BE(workBuffer, offset);
|
||||
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
|
||||
PRINTF("ChainId token mismatch\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
cx_ecfp_init_public_key(CX_CURVE_256K1, TOKEN_SIGNATURE_PUBLIC_KEY, sizeof(TOKEN_SIGNATURE_PUBLIC_KEY), &tokenKey);
|
||||
if (!cx_ecdsa_verify(&tokenKey, CX_LAST, CX_SHA256, hash, 32, workBuffer + offset, dataLength)) {
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentTokenIndex] = 1;
|
||||
THROW(0x9000);
|
||||
memmove(token->address, workBuffer + offset, 20);
|
||||
offset += 20;
|
||||
dataLength -= 20;
|
||||
token->decimals = U4BE(workBuffer, offset);
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
chainId = U4BE(workBuffer, offset);
|
||||
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
|
||||
PRINTF("ChainId token mismatch\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
cx_ecfp_init_public_key(CX_CURVE_256K1,
|
||||
TOKEN_SIGNATURE_PUBLIC_KEY,
|
||||
sizeof(TOKEN_SIGNATURE_PUBLIC_KEY),
|
||||
&tokenKey);
|
||||
if (!cx_ecdsa_verify(&tokenKey,
|
||||
CX_LAST,
|
||||
CX_SHA256,
|
||||
hash,
|
||||
32,
|
||||
workBuffer + offset,
|
||||
dataLength)) {
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentTokenIndex] = 1;
|
||||
THROW(0x9000);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void handleProvideErc20TokenInformation(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
UNUSED(p1);
|
||||
UNUSED(p2);
|
||||
UNUSED(flags);
|
||||
uint32_t offset = 0;
|
||||
uint8_t tickerLength;
|
||||
uint32_t chainId;
|
||||
uint8_t hash[32];
|
||||
cx_ecfp_public_key_t tokenKey;
|
||||
void handleProvideErc20TokenInformation(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *workBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
UNUSED(p1);
|
||||
UNUSED(p2);
|
||||
UNUSED(flags);
|
||||
uint32_t offset = 0;
|
||||
uint8_t tickerLength;
|
||||
uint32_t chainId;
|
||||
uint8_t hash[32];
|
||||
cx_ecfp_public_key_t tokenKey;
|
||||
|
||||
tmpCtx.transactionContext.currentTokenIndex =
|
||||
(tmpCtx.transactionContext.currentTokenIndex + 1) % MAX_TOKEN;
|
||||
tokenDefinition_t *token =
|
||||
&tmpCtx.transactionContext.tokens[tmpCtx.transactionContext.currentTokenIndex];
|
||||
|
||||
tmpCtx.transactionContext.currentTokenIndex = (tmpCtx.transactionContext.currentTokenIndex + 1) % MAX_TOKEN;
|
||||
tokenDefinition_t* token = &tmpCtx.transactionContext.tokens[tmpCtx.transactionContext.currentTokenIndex];
|
||||
PRINTF("Provisioning currentTokenIndex %d\n", tmpCtx.transactionContext.currentTokenIndex);
|
||||
|
||||
PRINTF("Provisioning currentTokenIndex %d\n", tmpCtx.transactionContext.currentTokenIndex);
|
||||
|
||||
if (dataLength < 1) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
tickerLength = workBuffer[offset++];
|
||||
dataLength--;
|
||||
if ((tickerLength + 1) >= sizeof(token->ticker)) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (dataLength < tickerLength + 20 + 4 + 4) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32);
|
||||
memmove(token->ticker, workBuffer + offset, tickerLength);
|
||||
token->ticker[tickerLength] = ' ';
|
||||
token->ticker[tickerLength + 1] = '\0';
|
||||
offset += tickerLength;
|
||||
dataLength -= tickerLength;
|
||||
memmove(token->address, workBuffer + offset, 20);
|
||||
offset += 20;
|
||||
dataLength -= 20;
|
||||
token->decimals = U4BE(workBuffer, offset);
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
chainId = U4BE(workBuffer, offset);
|
||||
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
|
||||
PRINTF("ChainId token mismatch\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
if (dataLength < 1) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
tickerLength = workBuffer[offset++];
|
||||
dataLength--;
|
||||
if ((tickerLength + 1) >= sizeof(token->ticker)) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (dataLength < tickerLength + 20 + 4 + 4) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32);
|
||||
memmove(token->ticker, workBuffer + offset, tickerLength);
|
||||
token->ticker[tickerLength] = ' ';
|
||||
token->ticker[tickerLength + 1] = '\0';
|
||||
offset += tickerLength;
|
||||
dataLength -= tickerLength;
|
||||
memmove(token->address, workBuffer + offset, 20);
|
||||
offset += 20;
|
||||
dataLength -= 20;
|
||||
token->decimals = U4BE(workBuffer, offset);
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
chainId = U4BE(workBuffer, offset);
|
||||
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
|
||||
PRINTF("ChainId token mismatch\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
offset += 4;
|
||||
dataLength -= 4;
|
||||
|
||||
#ifdef HAVE_TOKENS_EXTRA_LIST
|
||||
tokenDefinition_t *currentToken = NULL;
|
||||
uint32_t index;
|
||||
for (index=0; index < NUM_TOKENS_EXTRA; index++) {
|
||||
currentToken = (tokenDefinition_t *)PIC(&TOKENS_EXTRA[index]);
|
||||
if (memcmp(currentToken->address, token->address, 20) == 0) {
|
||||
strcpy((char*)token->ticker, (char*)currentToken->ticker);
|
||||
token->decimals = currentToken->decimals;
|
||||
break;
|
||||
}
|
||||
for (index = 0; index < NUM_TOKENS_EXTRA; index++) {
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_EXTRA[index]);
|
||||
if (memcmp(currentToken->address, token->address, 20) == 0) {
|
||||
strcpy((char *) token->ticker, (char *) currentToken->ticker);
|
||||
token->decimals = currentToken->decimals;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < NUM_TOKENS_EXTRA) {
|
||||
PRINTF("Descriptor whitelisted\n");
|
||||
}
|
||||
else {
|
||||
cx_ecfp_init_public_key(CX_CURVE_256K1, TOKEN_SIGNATURE_PUBLIC_KEY, sizeof(TOKEN_SIGNATURE_PUBLIC_KEY), &tokenKey);
|
||||
if (!cx_ecdsa_verify(&tokenKey, CX_LAST, CX_SHA256, hash, 32, workBuffer + offset, dataLength)) {
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
PRINTF("Descriptor whitelisted\n");
|
||||
} else {
|
||||
cx_ecfp_init_public_key(CX_CURVE_256K1,
|
||||
TOKEN_SIGNATURE_PUBLIC_KEY,
|
||||
sizeof(TOKEN_SIGNATURE_PUBLIC_KEY),
|
||||
&tokenKey);
|
||||
if (!cx_ecdsa_verify(&tokenKey,
|
||||
CX_LAST,
|
||||
CX_SHA256,
|
||||
hash,
|
||||
32,
|
||||
workBuffer + offset,
|
||||
dataLength)) {
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
cx_ecfp_init_public_key(CX_CURVE_256K1, TOKEN_SIGNATURE_PUBLIC_KEY, sizeof(TOKEN_SIGNATURE_PUBLIC_KEY), &tokenKey);
|
||||
if (!cx_ecdsa_verify(&tokenKey, CX_LAST, CX_SHA256, hash, 32, workBuffer + offset, dataLength)) {
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_ecfp_init_public_key(CX_CURVE_256K1,
|
||||
TOKEN_SIGNATURE_PUBLIC_KEY,
|
||||
sizeof(TOKEN_SIGNATURE_PUBLIC_KEY),
|
||||
&tokenKey);
|
||||
if (!cx_ecdsa_verify(&tokenKey,
|
||||
CX_LAST,
|
||||
CX_SHA256,
|
||||
hash,
|
||||
32,
|
||||
workBuffer + offset,
|
||||
dataLength)) {
|
||||
PRINTF("Invalid token signature\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
#endif
|
||||
|
||||
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentTokenIndex] = 1;
|
||||
THROW(0x9000);
|
||||
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentTokenIndex] = 1;
|
||||
THROW(0x9000);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,19 +3,23 @@
|
||||
#include "shared_context.h"
|
||||
#include "apdu_constants.h"
|
||||
|
||||
void handleSetEth2WithdrawalIndex(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
if (dataLength != 4) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
|
||||
void handleSetEth2WithdrawalIndex(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
if (dataLength != 4) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
if ((p1 != 0) || (p2 != 0)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
|
||||
if ((p1 != 0) || (p2 != 0)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
eth2WithdrawalIndex = U4BE(dataBuffer, 0);
|
||||
|
||||
eth2WithdrawalIndex = U4BE(dataBuffer, 0);
|
||||
|
||||
THROW(0x9000);
|
||||
THROW(0x9000);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,94 +3,113 @@
|
||||
#include "utils.h"
|
||||
#include "ui_flow.h"
|
||||
|
||||
static const char const SIGN_MAGIC[] = "\x19"
|
||||
"Ethereum Signed Message:\n";
|
||||
static const char const SIGN_MAGIC[] =
|
||||
"\x19"
|
||||
"Ethereum Signed Message:\n";
|
||||
|
||||
void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
UNUSED(tx);
|
||||
uint8_t hashMessage[32];
|
||||
if (p1 == P1_FIRST) {
|
||||
char tmp[11];
|
||||
uint32_t index;
|
||||
uint32_t base = 10;
|
||||
uint8_t pos = 0;
|
||||
uint32_t i;
|
||||
if (dataLength < 1) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
appState = APP_STATE_SIGNING_MESSAGE;
|
||||
tmpCtx.messageSigningContext.pathLength = workBuffer[0];
|
||||
if ((tmpCtx.messageSigningContext.pathLength < 0x01) ||
|
||||
(tmpCtx.messageSigningContext.pathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
workBuffer++;
|
||||
dataLength--;
|
||||
for (i = 0; i < tmpCtx.messageSigningContext.pathLength; i++) {
|
||||
if (dataLength < 4) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
void handleSignPersonalMessage(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *workBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
UNUSED(tx);
|
||||
uint8_t hashMessage[32];
|
||||
if (p1 == P1_FIRST) {
|
||||
char tmp[11];
|
||||
uint32_t index;
|
||||
uint32_t base = 10;
|
||||
uint8_t pos = 0;
|
||||
uint32_t i;
|
||||
if (dataLength < 1) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
tmpCtx.messageSigningContext.bip32Path[i] = U4BE(workBuffer, 0);
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
appState = APP_STATE_SIGNING_MESSAGE;
|
||||
tmpCtx.messageSigningContext.pathLength = workBuffer[0];
|
||||
if ((tmpCtx.messageSigningContext.pathLength < 0x01) ||
|
||||
(tmpCtx.messageSigningContext.pathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
workBuffer++;
|
||||
dataLength--;
|
||||
for (i = 0; i < tmpCtx.messageSigningContext.pathLength; i++) {
|
||||
if (dataLength < 4) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
tmpCtx.messageSigningContext.bip32Path[i] = U4BE(workBuffer, 0);
|
||||
workBuffer += 4;
|
||||
dataLength -= 4;
|
||||
}
|
||||
if (dataLength < 4) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
tmpCtx.messageSigningContext.remainingLength = U4BE(workBuffer, 0);
|
||||
workBuffer += 4;
|
||||
dataLength -= 4;
|
||||
}
|
||||
if (dataLength < 4) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
tmpCtx.messageSigningContext.remainingLength = U4BE(workBuffer, 0);
|
||||
workBuffer += 4;
|
||||
dataLength -= 4;
|
||||
// Initialize message header + length
|
||||
cx_keccak_init(&global_sha3, 256);
|
||||
cx_hash((cx_hash_t *)&global_sha3, 0, (uint8_t*)SIGN_MAGIC, sizeof(SIGN_MAGIC) - 1, NULL, 0);
|
||||
for (index = 1; (((index * base) <= tmpCtx.messageSigningContext.remainingLength) &&
|
||||
// Initialize message header + length
|
||||
cx_keccak_init(&global_sha3, 256);
|
||||
cx_hash((cx_hash_t *) &global_sha3,
|
||||
0,
|
||||
(uint8_t *) SIGN_MAGIC,
|
||||
sizeof(SIGN_MAGIC) - 1,
|
||||
NULL,
|
||||
0);
|
||||
for (index = 1; (((index * base) <= tmpCtx.messageSigningContext.remainingLength) &&
|
||||
(((index * base) / base) == index));
|
||||
index *= base);
|
||||
for (; index; index /= base) {
|
||||
tmp[pos++] = '0' + ((tmpCtx.messageSigningContext.remainingLength / index) % base);
|
||||
index *= base)
|
||||
;
|
||||
for (; index; index /= base) {
|
||||
tmp[pos++] = '0' + ((tmpCtx.messageSigningContext.remainingLength / index) % base);
|
||||
}
|
||||
tmp[pos] = '\0';
|
||||
cx_hash((cx_hash_t *) &global_sha3, 0, (uint8_t *) tmp, pos, NULL, 0);
|
||||
cx_sha256_init(&tmpContent.sha2);
|
||||
} else if (p1 != P1_MORE) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
tmp[pos] = '\0';
|
||||
cx_hash((cx_hash_t *)&global_sha3, 0, (uint8_t*)tmp, pos, NULL, 0);
|
||||
cx_sha256_init(&tmpContent.sha2);
|
||||
}
|
||||
else if (p1 != P1_MORE) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (p2 != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if ((p1 == P1_MORE) && (appState != APP_STATE_SIGNING_MESSAGE)) {
|
||||
PRINTF("Signature not initialized\n");
|
||||
THROW(0x6985);
|
||||
}
|
||||
if (dataLength > tmpCtx.messageSigningContext.remainingLength) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_hash((cx_hash_t *)&global_sha3, 0, workBuffer, dataLength, NULL, 0);
|
||||
cx_hash((cx_hash_t *)&tmpContent.sha2, 0, workBuffer, dataLength, NULL, 0);
|
||||
tmpCtx.messageSigningContext.remainingLength -= dataLength;
|
||||
if (tmpCtx.messageSigningContext.remainingLength == 0) {
|
||||
cx_hash((cx_hash_t *)&global_sha3, CX_LAST, workBuffer, 0, tmpCtx.messageSigningContext.hash, 32);
|
||||
cx_hash((cx_hash_t *)&tmpContent.sha2, CX_LAST, workBuffer, 0, hashMessage, 32);
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "%.*H", sizeof(hashMessage), hashMessage);
|
||||
if (p2 != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if ((p1 == P1_MORE) && (appState != APP_STATE_SIGNING_MESSAGE)) {
|
||||
PRINTF("Signature not initialized\n");
|
||||
THROW(0x6985);
|
||||
}
|
||||
if (dataLength > tmpCtx.messageSigningContext.remainingLength) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
cx_hash((cx_hash_t *) &global_sha3, 0, workBuffer, dataLength, NULL, 0);
|
||||
cx_hash((cx_hash_t *) &tmpContent.sha2, 0, workBuffer, dataLength, NULL, 0);
|
||||
tmpCtx.messageSigningContext.remainingLength -= dataLength;
|
||||
if (tmpCtx.messageSigningContext.remainingLength == 0) {
|
||||
cx_hash((cx_hash_t *) &global_sha3,
|
||||
CX_LAST,
|
||||
workBuffer,
|
||||
0,
|
||||
tmpCtx.messageSigningContext.hash,
|
||||
32);
|
||||
cx_hash((cx_hash_t *) &tmpContent.sha2, CX_LAST, workBuffer, 0, hashMessage, 32);
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"%.*H",
|
||||
sizeof(hashMessage),
|
||||
hashMessage);
|
||||
|
||||
#ifdef NO_CONSENT
|
||||
io_seproxyhal_touch_signMessage_ok(NULL);
|
||||
#else //NO_CONSENT
|
||||
ux_flow_init(0, ux_sign_flow, NULL);
|
||||
#endif // NO_CONSENT
|
||||
io_seproxyhal_touch_signMessage_ok(NULL);
|
||||
#else // NO_CONSENT
|
||||
ux_flow_init(0, ux_sign_flow, NULL);
|
||||
#endif // NO_CONSENT
|
||||
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
|
||||
} else {
|
||||
THROW(0x9000);
|
||||
}
|
||||
} else {
|
||||
THROW(0x9000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,25 +8,31 @@ unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) {
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint32_t tx = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
os_perso_derive_node_bip32(
|
||||
CX_CURVE_256K1, tmpCtx.messageSigningContext.bip32Path,
|
||||
tmpCtx.messageSigningContext.pathLength, privateKeyData, NULL);
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1,
|
||||
tmpCtx.messageSigningContext.bip32Path,
|
||||
tmpCtx.messageSigningContext.pathLength,
|
||||
privateKeyData,
|
||||
NULL);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
unsigned int info = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
signatureLength =
|
||||
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
|
||||
tmpCtx.messageSigningContext.hash,
|
||||
sizeof(tmpCtx.messageSigningContext.hash), signature, sizeof(signature), &info);
|
||||
signatureLength = cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
tmpCtx.messageSigningContext.hash,
|
||||
sizeof(tmpCtx.messageSigningContext.hash),
|
||||
signature,
|
||||
sizeof(signature),
|
||||
&info);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
G_io_apdu_buffer[0] = 27;
|
||||
if (info & CX_ECCINFO_PARITY_ODD) {
|
||||
G_io_apdu_buffer[0]++;
|
||||
G_io_apdu_buffer[0]++;
|
||||
}
|
||||
if (info & CX_ECCINFO_xGTn) {
|
||||
G_io_apdu_buffer[0] += 2;
|
||||
G_io_apdu_buffer[0] += 2;
|
||||
}
|
||||
format_signature_out(signature);
|
||||
tx = 65;
|
||||
@@ -37,7 +43,7 @@ unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_signMessage_cancel(const bagl_element_t *e) {
|
||||
@@ -48,6 +54,5 @@ unsigned int io_seproxyhal_touch_signMessage_cancel(const bagl_element_t *e) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "shared_context.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_sign_flow_1_step,
|
||||
pnn,
|
||||
@@ -34,11 +35,10 @@ UX_STEP_CB(
|
||||
"Cancel",
|
||||
"signature",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_sign_flow,
|
||||
&ux_sign_flow_1_step,
|
||||
&ux_sign_flow_2_step,
|
||||
&ux_sign_flow_3_step,
|
||||
&ux_sign_flow_4_step
|
||||
);
|
||||
|
||||
&ux_sign_flow_1_step,
|
||||
&ux_sign_flow_2_step,
|
||||
&ux_sign_flow_3_step,
|
||||
&ux_sign_flow_4_step);
|
||||
|
||||
@@ -3,52 +3,58 @@
|
||||
#include "utils.h"
|
||||
#include "ui_flow.h"
|
||||
|
||||
static const char const SIGN_MAGIC[] = "\x19"
|
||||
"Ethereum Signed Message:\n";
|
||||
static const char const SIGN_MAGIC[] =
|
||||
"\x19"
|
||||
"Ethereum Signed Message:\n";
|
||||
|
||||
void handleSignEIP712Message(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
uint8_t i;
|
||||
void handleSignEIP712Message(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *workBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
uint8_t i;
|
||||
|
||||
UNUSED(tx);
|
||||
if ((p1 != 00) || (p2 != 00)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
if (dataLength < 1) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
tmpCtx.messageSigningContext712.pathLength = workBuffer[0];
|
||||
if ((tmpCtx.messageSigningContext712.pathLength < 0x01) ||
|
||||
(tmpCtx.messageSigningContext712.pathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
workBuffer++;
|
||||
dataLength--;
|
||||
for (i = 0; i < tmpCtx.messageSigningContext712.pathLength; i++) {
|
||||
if (dataLength < 4) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
UNUSED(tx);
|
||||
if ((p1 != 00) || (p2 != 00)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
tmpCtx.messageSigningContext712.bip32Path[i] = U4BE(workBuffer, 0);
|
||||
workBuffer += 4;
|
||||
dataLength -= 4;
|
||||
}
|
||||
if (dataLength < 32 + 32) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
memmove(tmpCtx.messageSigningContext712.domainHash, workBuffer, 32);
|
||||
memmove(tmpCtx.messageSigningContext712.messageHash, workBuffer + 32, 32);
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
if (dataLength < 1) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
tmpCtx.messageSigningContext712.pathLength = workBuffer[0];
|
||||
if ((tmpCtx.messageSigningContext712.pathLength < 0x01) ||
|
||||
(tmpCtx.messageSigningContext712.pathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
workBuffer++;
|
||||
dataLength--;
|
||||
for (i = 0; i < tmpCtx.messageSigningContext712.pathLength; i++) {
|
||||
if (dataLength < 4) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
tmpCtx.messageSigningContext712.bip32Path[i] = U4BE(workBuffer, 0);
|
||||
workBuffer += 4;
|
||||
dataLength -= 4;
|
||||
}
|
||||
if (dataLength < 32 + 32) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
memmove(tmpCtx.messageSigningContext712.domainHash, workBuffer, 32);
|
||||
memmove(tmpCtx.messageSigningContext712.messageHash, workBuffer + 32, 32);
|
||||
|
||||
#ifdef NO_CONSENT
|
||||
io_seproxyhal_touch_signMessage_ok(NULL);
|
||||
#else //NO_CONSENT
|
||||
#else // NO_CONSENT
|
||||
ux_flow_init(0, ux_sign_712_v0_flow, NULL);
|
||||
#endif // NO_CONSENT
|
||||
#endif // NO_CONSENT
|
||||
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "shared_context.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
static const uint8_t const EIP_712_MAGIC[] = { 0x19, 0x01 };
|
||||
static const uint8_t const EIP_712_MAGIC[] = {0x19, 0x01};
|
||||
|
||||
unsigned int io_seproxyhal_touch_signMessage712_v0_ok(const bagl_element_t *e) {
|
||||
uint8_t privateKeyData[32];
|
||||
@@ -12,32 +12,51 @@ unsigned int io_seproxyhal_touch_signMessage712_v0_ok(const bagl_element_t *e) {
|
||||
uint32_t tx = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_keccak_init(&global_sha3, 256);
|
||||
cx_hash((cx_hash_t *)&global_sha3, 0, (uint8_t*)EIP_712_MAGIC, sizeof(EIP_712_MAGIC), NULL, 0);
|
||||
cx_hash((cx_hash_t *)&global_sha3, 0, tmpCtx.messageSigningContext712.domainHash,
|
||||
sizeof(tmpCtx.messageSigningContext712.domainHash), NULL, 0);
|
||||
cx_hash((cx_hash_t *)&global_sha3, CX_LAST, tmpCtx.messageSigningContext712.messageHash,
|
||||
sizeof(tmpCtx.messageSigningContext712.messageHash), hash, sizeof(hash));
|
||||
cx_hash((cx_hash_t *) &global_sha3,
|
||||
0,
|
||||
(uint8_t *) EIP_712_MAGIC,
|
||||
sizeof(EIP_712_MAGIC),
|
||||
NULL,
|
||||
0);
|
||||
cx_hash((cx_hash_t *) &global_sha3,
|
||||
0,
|
||||
tmpCtx.messageSigningContext712.domainHash,
|
||||
sizeof(tmpCtx.messageSigningContext712.domainHash),
|
||||
NULL,
|
||||
0);
|
||||
cx_hash((cx_hash_t *) &global_sha3,
|
||||
CX_LAST,
|
||||
tmpCtx.messageSigningContext712.messageHash,
|
||||
sizeof(tmpCtx.messageSigningContext712.messageHash),
|
||||
hash,
|
||||
sizeof(hash));
|
||||
PRINTF("EIP712 hash to sign %.*H\n", 32, hash);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
os_perso_derive_node_bip32(
|
||||
CX_CURVE_256K1, tmpCtx.messageSigningContext712.bip32Path,
|
||||
tmpCtx.messageSigningContext712.pathLength, privateKeyData, NULL);
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1,
|
||||
tmpCtx.messageSigningContext712.bip32Path,
|
||||
tmpCtx.messageSigningContext712.pathLength,
|
||||
privateKeyData,
|
||||
NULL);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
unsigned int info = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
signatureLength =
|
||||
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
|
||||
hash,
|
||||
sizeof(hash), signature, sizeof(signature), &info);
|
||||
signatureLength = cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
hash,
|
||||
sizeof(hash),
|
||||
signature,
|
||||
sizeof(signature),
|
||||
&info);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
G_io_apdu_buffer[0] = 27;
|
||||
if (info & CX_ECCINFO_PARITY_ODD) {
|
||||
G_io_apdu_buffer[0]++;
|
||||
G_io_apdu_buffer[0]++;
|
||||
}
|
||||
if (info & CX_ECCINFO_xGTn) {
|
||||
G_io_apdu_buffer[0] += 2;
|
||||
G_io_apdu_buffer[0] += 2;
|
||||
}
|
||||
format_signature_out(signature);
|
||||
tx = 65;
|
||||
@@ -48,7 +67,7 @@ unsigned int io_seproxyhal_touch_signMessage712_v0_ok(const bagl_element_t *e) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_signMessage712_v0_cancel(const bagl_element_t *e) {
|
||||
@@ -59,6 +78,5 @@ unsigned int io_seproxyhal_touch_signMessage712_v0_cancel(const bagl_element_t *
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
void prepare_domain_hash_v0() {
|
||||
snprintf(strings.tmp.tmp, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.domainHash);
|
||||
snprintf(strings.tmp.tmp, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.domainHash);
|
||||
}
|
||||
|
||||
void prepare_message_hash_v0() {
|
||||
snprintf(strings.tmp.tmp, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.messageHash);
|
||||
snprintf(strings.tmp.tmp, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.messageHash);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_sign_712_v0_flow_1_step,
|
||||
pnn,
|
||||
@@ -51,12 +52,11 @@ UX_STEP_CB(
|
||||
"Cancel",
|
||||
"signature",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_sign_712_v0_flow,
|
||||
&ux_sign_712_v0_flow_1_step,
|
||||
&ux_sign_712_v0_flow_2_step,
|
||||
&ux_sign_712_v0_flow_3_step,
|
||||
&ux_sign_712_v0_flow_4_step,
|
||||
&ux_sign_712_v0_flow_5_step
|
||||
);
|
||||
|
||||
&ux_sign_712_v0_flow_1_step,
|
||||
&ux_sign_712_v0_flow_2_step,
|
||||
&ux_sign_712_v0_flow_3_step,
|
||||
&ux_sign_712_v0_flow_4_step,
|
||||
&ux_sign_712_v0_flow_5_step);
|
||||
|
||||
@@ -3,74 +3,79 @@
|
||||
#include "ui_flow.h"
|
||||
#include "feature_signTx.h"
|
||||
|
||||
void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
UNUSED(tx);
|
||||
parserStatus_e txResult;
|
||||
uint32_t i;
|
||||
if (p1 == P1_FIRST) {
|
||||
if (dataLength < 1) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
void handleSign(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *workBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
UNUSED(tx);
|
||||
parserStatus_e txResult;
|
||||
uint32_t i;
|
||||
if (p1 == P1_FIRST) {
|
||||
if (dataLength < 1) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
appState = APP_STATE_SIGNING_TX;
|
||||
tmpCtx.transactionContext.pathLength = workBuffer[0];
|
||||
if ((tmpCtx.transactionContext.pathLength < 0x01) ||
|
||||
(tmpCtx.transactionContext.pathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
workBuffer++;
|
||||
dataLength--;
|
||||
for (i = 0; i < tmpCtx.transactionContext.pathLength; i++) {
|
||||
if (dataLength < 4) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
tmpCtx.transactionContext.bip32Path[i] = U4BE(workBuffer, 0);
|
||||
workBuffer += 4;
|
||||
dataLength -= 4;
|
||||
}
|
||||
dataPresent = false;
|
||||
dataContext.tokenContext.pluginAvailable = 0;
|
||||
initTx(&txContext, &global_sha3, &tmpContent.txContent, customProcessor, NULL);
|
||||
} else if (p1 != P1_MORE) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
if (p2 != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
appState = APP_STATE_SIGNING_TX;
|
||||
tmpCtx.transactionContext.pathLength = workBuffer[0];
|
||||
if ((tmpCtx.transactionContext.pathLength < 0x01) ||
|
||||
(tmpCtx.transactionContext.pathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
if ((p1 == P1_MORE) && (appState != APP_STATE_SIGNING_TX)) {
|
||||
PRINTF("Signature not initialized\n");
|
||||
THROW(0x6985);
|
||||
}
|
||||
workBuffer++;
|
||||
dataLength--;
|
||||
for (i = 0; i < tmpCtx.transactionContext.pathLength; i++) {
|
||||
if (dataLength < 4) {
|
||||
PRINTF("Invalid data\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
tmpCtx.transactionContext.bip32Path[i] = U4BE(workBuffer, 0);
|
||||
workBuffer += 4;
|
||||
dataLength -= 4;
|
||||
if (txContext.currentField == TX_RLP_NONE) {
|
||||
PRINTF("Parser not initialized\n");
|
||||
THROW(0x6985);
|
||||
}
|
||||
txResult = processTx(&txContext,
|
||||
workBuffer,
|
||||
dataLength,
|
||||
(chainConfig->kind == CHAIN_KIND_WANCHAIN ? TX_FLAG_TYPE : 0));
|
||||
switch (txResult) {
|
||||
case USTREAM_SUSPENDED:
|
||||
break;
|
||||
case USTREAM_FINISHED:
|
||||
break;
|
||||
case USTREAM_PROCESSING:
|
||||
THROW(0x9000);
|
||||
case USTREAM_FAULT:
|
||||
THROW(0x6A80);
|
||||
default:
|
||||
PRINTF("Unexpected parser status\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
dataPresent = false;
|
||||
dataContext.tokenContext.pluginAvailable = 0;
|
||||
initTx(&txContext, &global_sha3, &tmpContent.txContent, customProcessor, NULL);
|
||||
}
|
||||
else
|
||||
if (p1 != P1_MORE) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (p2 != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if ((p1 == P1_MORE) && (appState != APP_STATE_SIGNING_TX)) {
|
||||
PRINTF("Signature not initialized\n");
|
||||
THROW(0x6985);
|
||||
}
|
||||
if (txContext.currentField == TX_RLP_NONE) {
|
||||
PRINTF("Parser not initialized\n");
|
||||
THROW(0x6985);
|
||||
}
|
||||
txResult = processTx(&txContext, workBuffer, dataLength, (chainConfig->kind == CHAIN_KIND_WANCHAIN ? TX_FLAG_TYPE : 0));
|
||||
switch (txResult) {
|
||||
case USTREAM_SUSPENDED:
|
||||
break;
|
||||
case USTREAM_FINISHED:
|
||||
break;
|
||||
case USTREAM_PROCESSING:
|
||||
THROW(0x9000);
|
||||
case USTREAM_FAULT:
|
||||
THROW(0x6A80);
|
||||
default:
|
||||
PRINTF("Unexpected parser status\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
|
||||
if (txResult == USTREAM_FINISHED) {
|
||||
finalizeParsing(false);
|
||||
}
|
||||
if (txResult == USTREAM_FINISHED) {
|
||||
finalizeParsing(false);
|
||||
}
|
||||
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
|
||||
customStatus_e customProcessor(txContext_t *context);
|
||||
void finalizeParsing(bool direct);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
uint32_t splitBinaryParameterPart(char *result, uint8_t *parameter) {
|
||||
uint32_t i;
|
||||
for (i=0; i<8; i++) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (parameter[i] != 0x00) {
|
||||
break;
|
||||
}
|
||||
@@ -21,16 +21,14 @@ uint32_t splitBinaryParameterPart(char *result, uint8_t *parameter) {
|
||||
result[1] = '0';
|
||||
result[2] = '\0';
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
array_hexstr(result, parameter + i, 8 - i);
|
||||
return ((8 - i) * 2);
|
||||
}
|
||||
}
|
||||
|
||||
customStatus_e customProcessor(txContext_t *context) {
|
||||
if ((context->currentField == TX_RLP_DATA) &&
|
||||
(context->currentFieldLength != 0)) {
|
||||
if ((context->currentField == TX_RLP_DATA) && (context->currentFieldLength != 0)) {
|
||||
dataPresent = true;
|
||||
// If handling a new contract rather than a function call, abort immediately
|
||||
if (tmpContent.txContent.destinationLength == 0) {
|
||||
@@ -38,320 +36,341 @@ customStatus_e customProcessor(txContext_t *context) {
|
||||
}
|
||||
if (context->currentFieldPos == 0) {
|
||||
ethPluginInitContract_t pluginInit;
|
||||
// If handling the beginning of the data field, assume that the function selector is present
|
||||
// If handling the beginning of the data field, assume that the function selector is
|
||||
// present
|
||||
if (context->commandLength < 4) {
|
||||
PRINTF("Missing function selector\n");
|
||||
return CUSTOM_FAULT;
|
||||
}
|
||||
eth_plugin_prepare_init(&pluginInit, context->workBuffer, context->currentFieldLength);
|
||||
dataContext.tokenContext.pluginAvailable = eth_plugin_perform_init(tmpContent.txContent.destination, &pluginInit);
|
||||
dataContext.tokenContext.pluginAvailable =
|
||||
eth_plugin_perform_init(tmpContent.txContent.destination, &pluginInit);
|
||||
PRINTF("pluginAvailable %d\n", dataContext.tokenContext.pluginAvailable);
|
||||
if (dataContext.tokenContext.pluginAvailable) {
|
||||
dataContext.tokenContext.fieldIndex = 0;
|
||||
dataContext.tokenContext.fieldOffset = 0;
|
||||
copyTxData(context, NULL, 4);
|
||||
if (context->currentFieldLength == 4) {
|
||||
return CUSTOM_NOT_HANDLED;
|
||||
}
|
||||
dataContext.tokenContext.fieldIndex = 0;
|
||||
dataContext.tokenContext.fieldOffset = 0;
|
||||
copyTxData(context, NULL, 4);
|
||||
if (context->currentFieldLength == 4) {
|
||||
return CUSTOM_NOT_HANDLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
uint32_t blockSize;
|
||||
uint32_t copySize;
|
||||
uint32_t fieldPos = context->currentFieldPos;
|
||||
if (fieldPos == 0) { // not reached if a plugin is available
|
||||
if (!N_storage.dataAllowed) {
|
||||
uint32_t blockSize;
|
||||
uint32_t copySize;
|
||||
uint32_t fieldPos = context->currentFieldPos;
|
||||
if (fieldPos == 0) { // not reached if a plugin is available
|
||||
if (!N_storage.dataAllowed) {
|
||||
PRINTF("Data field forbidden\n");
|
||||
return CUSTOM_FAULT;
|
||||
}
|
||||
if (!N_storage.contractDetails) {
|
||||
}
|
||||
if (!N_storage.contractDetails) {
|
||||
return CUSTOM_NOT_HANDLED;
|
||||
}
|
||||
dataContext.tokenContext.fieldIndex = 0;
|
||||
dataContext.tokenContext.fieldOffset = 0;
|
||||
blockSize = 4;
|
||||
}
|
||||
else {
|
||||
if (!N_storage.contractDetails && !dataContext.tokenContext.pluginAvailable) {
|
||||
}
|
||||
dataContext.tokenContext.fieldIndex = 0;
|
||||
dataContext.tokenContext.fieldOffset = 0;
|
||||
blockSize = 4;
|
||||
} else {
|
||||
if (!N_storage.contractDetails && !dataContext.tokenContext.pluginAvailable) {
|
||||
return CUSTOM_NOT_HANDLED;
|
||||
}
|
||||
blockSize = 32 - (dataContext.tokenContext.fieldOffset % 32);
|
||||
}
|
||||
}
|
||||
blockSize = 32 - (dataContext.tokenContext.fieldOffset % 32);
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if ((context->currentFieldLength - fieldPos) < blockSize) {
|
||||
PRINTF("Unconsistent data\n");
|
||||
return CUSTOM_FAULT;
|
||||
}
|
||||
// Sanity check
|
||||
if ((context->currentFieldLength - fieldPos) < blockSize) {
|
||||
PRINTF("Unconsistent data\n");
|
||||
return CUSTOM_FAULT;
|
||||
}
|
||||
|
||||
copySize = (context->commandLength < blockSize ? context->commandLength : blockSize);
|
||||
copySize = (context->commandLength < blockSize ? context->commandLength : blockSize);
|
||||
|
||||
PRINTF("currentFieldPos %d copySize %d\n", context->currentFieldPos, copySize);
|
||||
PRINTF("currentFieldPos %d copySize %d\n", context->currentFieldPos, copySize);
|
||||
|
||||
copyTxData(context,
|
||||
dataContext.tokenContext.data + dataContext.tokenContext.fieldOffset,
|
||||
copySize);
|
||||
copyTxData(context,
|
||||
dataContext.tokenContext.data + dataContext.tokenContext.fieldOffset,
|
||||
copySize);
|
||||
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->currentField++;
|
||||
context->processingField = false;
|
||||
}
|
||||
if (context->currentFieldPos == context->currentFieldLength) {
|
||||
context->currentField++;
|
||||
context->processingField = false;
|
||||
}
|
||||
|
||||
dataContext.tokenContext.fieldOffset += copySize;
|
||||
dataContext.tokenContext.fieldOffset += copySize;
|
||||
|
||||
if (copySize == blockSize) {
|
||||
// Can process or display
|
||||
if (dataContext.tokenContext.pluginAvailable) {
|
||||
if (copySize == blockSize) {
|
||||
// Can process or display
|
||||
if (dataContext.tokenContext.pluginAvailable) {
|
||||
ethPluginProvideParameter_t pluginProvideParameter;
|
||||
eth_plugin_prepare_provide_parameter(&pluginProvideParameter,
|
||||
dataContext.tokenContext.data,
|
||||
dataContext.tokenContext.fieldIndex * 32 + 4);
|
||||
if (!eth_plugin_call(NULL, ETH_PLUGIN_PROVIDE_PARAMETER, (void*)&pluginProvideParameter)) {
|
||||
PRINTF("Plugin parameter call failed\n");
|
||||
return CUSTOM_FAULT;
|
||||
eth_plugin_prepare_provide_parameter(&pluginProvideParameter,
|
||||
dataContext.tokenContext.data,
|
||||
dataContext.tokenContext.fieldIndex * 32 + 4);
|
||||
if (!eth_plugin_call(NULL,
|
||||
ETH_PLUGIN_PROVIDE_PARAMETER,
|
||||
(void *) &pluginProvideParameter)) {
|
||||
PRINTF("Plugin parameter call failed\n");
|
||||
return CUSTOM_FAULT;
|
||||
}
|
||||
dataContext.tokenContext.fieldIndex++;
|
||||
dataContext.tokenContext.fieldOffset = 0;
|
||||
return CUSTOM_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldPos != 0) {
|
||||
dataContext.tokenContext.fieldIndex++;
|
||||
}
|
||||
dataContext.tokenContext.fieldOffset = 0;
|
||||
if (fieldPos == 0) {
|
||||
array_hexstr(strings.tmp.tmp, dataContext.tokenContext.data, 4);
|
||||
ux_flow_init(0, ux_confirm_selector_flow, NULL);
|
||||
}
|
||||
else {
|
||||
uint32_t offset = 0;
|
||||
uint32_t i;
|
||||
snprintf(strings.tmp.tmp2, sizeof(strings.tmp.tmp2), "Field %d", dataContext.tokenContext.fieldIndex);
|
||||
for (i=0; i<4; i++) {
|
||||
offset += splitBinaryParameterPart(strings.tmp.tmp + offset, dataContext.tokenContext.data + 8 * i);
|
||||
if (i != 3) {
|
||||
strings.tmp.tmp[offset++] = ':';
|
||||
}
|
||||
}
|
||||
ux_flow_init(0, ux_confirm_parameter_flow, NULL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return CUSTOM_HANDLED;
|
||||
}
|
||||
if (fieldPos != 0) {
|
||||
dataContext.tokenContext.fieldIndex++;
|
||||
}
|
||||
dataContext.tokenContext.fieldOffset = 0;
|
||||
if (fieldPos == 0) {
|
||||
array_hexstr(strings.tmp.tmp, dataContext.tokenContext.data, 4);
|
||||
ux_flow_init(0, ux_confirm_selector_flow, NULL);
|
||||
} else {
|
||||
uint32_t offset = 0;
|
||||
uint32_t i;
|
||||
snprintf(strings.tmp.tmp2,
|
||||
sizeof(strings.tmp.tmp2),
|
||||
"Field %d",
|
||||
dataContext.tokenContext.fieldIndex);
|
||||
for (i = 0; i < 4; i++) {
|
||||
offset += splitBinaryParameterPart(strings.tmp.tmp + offset,
|
||||
dataContext.tokenContext.data + 8 * i);
|
||||
if (i != 3) {
|
||||
strings.tmp.tmp[offset++] = ':';
|
||||
}
|
||||
}
|
||||
ux_flow_init(0, ux_confirm_parameter_flow, NULL);
|
||||
}
|
||||
} else {
|
||||
return CUSTOM_HANDLED;
|
||||
}
|
||||
|
||||
return CUSTOM_SUSPENDED;
|
||||
return CUSTOM_SUSPENDED;
|
||||
}
|
||||
return CUSTOM_NOT_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
void to_uppercase(char* str, unsigned char size){
|
||||
for (unsigned char i = 0; i < size && str[i] != 0; i++)
|
||||
{
|
||||
void to_uppercase(char *str, unsigned char size) {
|
||||
for (unsigned char i = 0; i < size && str[i] != 0; i++) {
|
||||
str[i] = str[i] >= 'a' ? str[i] - ('a' - 'A') : str[i];
|
||||
}
|
||||
}
|
||||
|
||||
void compareOrCopy(char* preapproved_string, char* parsed_string, bool silent_mode){
|
||||
if(silent_mode){
|
||||
/* ETH address are not fundamentally case sensitive but might
|
||||
have some for checksum purpose, so let's get rid of these diffs */
|
||||
to_uppercase(preapproved_string, strlen(preapproved_string));
|
||||
to_uppercase(parsed_string, strlen(parsed_string));
|
||||
if(memcmp(preapproved_string, parsed_string, strlen(preapproved_string))){
|
||||
THROW(ERR_SILENT_MODE_CHECK_FAILED);
|
||||
void compareOrCopy(char *preapproved_string, char *parsed_string, bool silent_mode) {
|
||||
if (silent_mode) {
|
||||
/* ETH address are not fundamentally case sensitive but might
|
||||
have some for checksum purpose, so let's get rid of these diffs */
|
||||
to_uppercase(preapproved_string, strlen(preapproved_string));
|
||||
to_uppercase(parsed_string, strlen(parsed_string));
|
||||
if (memcmp(preapproved_string, parsed_string, strlen(preapproved_string))) {
|
||||
THROW(ERR_SILENT_MODE_CHECK_FAILED);
|
||||
}
|
||||
} else {
|
||||
strcpy(preapproved_string, parsed_string);
|
||||
}
|
||||
}
|
||||
else{
|
||||
strcpy(preapproved_string, parsed_string);
|
||||
}
|
||||
}
|
||||
|
||||
void reportFinalizeError(bool direct) {
|
||||
reset_app_context();
|
||||
if (direct) {
|
||||
THROW(0x6A80);
|
||||
}
|
||||
else {
|
||||
io_seproxyhal_send_status(0x6A80);
|
||||
ui_idle();
|
||||
}
|
||||
reset_app_context();
|
||||
if (direct) {
|
||||
THROW(0x6A80);
|
||||
} else {
|
||||
io_seproxyhal_send_status(0x6A80);
|
||||
ui_idle();
|
||||
}
|
||||
}
|
||||
|
||||
void computeFees(char *displayBuffer, uint32_t displayBufferSize) {
|
||||
uint256_t gasPrice, startGas, uint256;
|
||||
uint8_t *feeTicker = (uint8_t *)PIC(chainConfig->coinName);
|
||||
uint8_t tickerOffset = 0;
|
||||
uint32_t i;
|
||||
uint256_t gasPrice, startGas, uint256;
|
||||
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);
|
||||
i = 0;
|
||||
while (G_io_apdu_buffer[100 + i]) {
|
||||
i++;
|
||||
}
|
||||
adjustDecimals((char *)(G_io_apdu_buffer + 100), i, (char *)G_io_apdu_buffer, 100, WEI_TO_ETHER);
|
||||
i = 0;
|
||||
tickerOffset=0;
|
||||
memset(displayBuffer, 0, displayBufferSize);
|
||||
while (feeTicker[tickerOffset]) {
|
||||
displayBuffer[tickerOffset] = feeTicker[tickerOffset];
|
||||
tickerOffset++;
|
||||
}
|
||||
while (G_io_apdu_buffer[i]) {
|
||||
displayBuffer[tickerOffset + i] = G_io_apdu_buffer[i];
|
||||
i++;
|
||||
}
|
||||
displayBuffer[tickerOffset + i] = '\0';
|
||||
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);
|
||||
i = 0;
|
||||
while (G_io_apdu_buffer[100 + i]) {
|
||||
i++;
|
||||
}
|
||||
adjustDecimals((char *) (G_io_apdu_buffer + 100),
|
||||
i,
|
||||
(char *) G_io_apdu_buffer,
|
||||
100,
|
||||
WEI_TO_ETHER);
|
||||
i = 0;
|
||||
tickerOffset = 0;
|
||||
memset(displayBuffer, 0, displayBufferSize);
|
||||
while (feeTicker[tickerOffset]) {
|
||||
displayBuffer[tickerOffset] = feeTicker[tickerOffset];
|
||||
tickerOffset++;
|
||||
}
|
||||
while (G_io_apdu_buffer[i]) {
|
||||
displayBuffer[tickerOffset + i] = G_io_apdu_buffer[i];
|
||||
i++;
|
||||
}
|
||||
displayBuffer[tickerOffset + i] = '\0';
|
||||
}
|
||||
|
||||
void finalizeParsing(bool direct) {
|
||||
char displayBuffer[50];
|
||||
uint8_t decimals = WEI_TO_ETHER;
|
||||
uint8_t *ticker = (uint8_t *)PIC(chainConfig->coinName);
|
||||
ethPluginFinalize_t pluginFinalize;
|
||||
tokenDefinition_t *token1 = NULL, *token2 = NULL;
|
||||
bool genericUI = true;
|
||||
void finalizeParsing(bool direct) {
|
||||
char displayBuffer[50];
|
||||
uint8_t decimals = WEI_TO_ETHER;
|
||||
uint8_t *ticker = (uint8_t *) PIC(chainConfig->coinName);
|
||||
ethPluginFinalize_t pluginFinalize;
|
||||
tokenDefinition_t *token1 = NULL, *token2 = NULL;
|
||||
bool genericUI = true;
|
||||
|
||||
// Verify the chain
|
||||
if (chainConfig->chainId != 0) {
|
||||
uint32_t v = getV(&tmpContent.txContent);
|
||||
if (chainConfig->chainId != v) {
|
||||
reset_app_context();
|
||||
PRINTF("Invalid chainId %d expected %d\n", v, chainConfig->chainId);
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Store the hash
|
||||
cx_hash((cx_hash_t *)&global_sha3, CX_LAST, tmpCtx.transactionContext.hash, 0, tmpCtx.transactionContext.hash, 32);
|
||||
|
||||
// Finalize the plugin handling
|
||||
if (dataContext.tokenContext.pluginAvailable) {
|
||||
genericUI = false;
|
||||
eth_plugin_prepare_finalize(&pluginFinalize);
|
||||
if (!eth_plugin_call(NULL, ETH_PLUGIN_FINALIZE, (void*)&pluginFinalize)) {
|
||||
PRINTF("Plugin finalize call failed\n");
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Lookup tokens if requested
|
||||
if (pluginFinalize.tokenLookup1 != NULL) {
|
||||
ethPluginProvideToken_t pluginProvideToken;
|
||||
token1 = getKnownToken(pluginFinalize.tokenLookup1);
|
||||
if (pluginFinalize.tokenLookup2 != NULL) {
|
||||
token2 = getKnownToken(pluginFinalize.tokenLookup2);
|
||||
}
|
||||
eth_plugin_prepare_provide_token(&pluginProvideToken, token1, token2);
|
||||
if (!eth_plugin_call(NULL, ETH_PLUGIN_PROVIDE_TOKEN, (void*)&pluginProvideToken)) {
|
||||
PRINTF("Plugin provide token call failed\n");
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
pluginFinalize.result = pluginProvideToken.result;
|
||||
}
|
||||
if (pluginFinalize.result != ETH_PLUGIN_RESULT_FALLBACK) {
|
||||
// Handle the right interface
|
||||
switch(pluginFinalize.uiType) {
|
||||
case ETH_UI_TYPE_GENERIC:
|
||||
dataPresent = false;
|
||||
dataContext.tokenContext.pluginUiMaxItems = pluginFinalize.numScreens;
|
||||
break;
|
||||
case ETH_UI_TYPE_AMOUNT_ADDRESS:
|
||||
genericUI = true;
|
||||
dataPresent = false;
|
||||
if ((pluginFinalize.amount == NULL) || (pluginFinalize.address == NULL)) {
|
||||
PRINTF("Incorrect amount/address set by plugin\n");
|
||||
// Verify the chain
|
||||
if (chainConfig->chainId != 0) {
|
||||
uint32_t v = getV(&tmpContent.txContent);
|
||||
if (chainConfig->chainId != v) {
|
||||
reset_app_context();
|
||||
PRINTF("Invalid chainId %d expected %d\n", v, chainConfig->chainId);
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
memmove(tmpContent.txContent.value.value, pluginFinalize.amount, 32);
|
||||
tmpContent.txContent.value.length = 32;
|
||||
memmove(tmpContent.txContent.destination, pluginFinalize.address, 20);
|
||||
tmpContent.txContent.destinationLength = 20;
|
||||
if (token1 != NULL) {
|
||||
decimals = token1->decimals;
|
||||
ticker = token1->ticker;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PRINTF("ui type %d not supported\n", pluginFinalize.uiType);
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Store the hash
|
||||
cx_hash((cx_hash_t *) &global_sha3,
|
||||
CX_LAST,
|
||||
tmpCtx.transactionContext.hash,
|
||||
0,
|
||||
tmpCtx.transactionContext.hash,
|
||||
32);
|
||||
|
||||
// Finalize the plugin handling
|
||||
if (dataContext.tokenContext.pluginAvailable) {
|
||||
genericUI = false;
|
||||
eth_plugin_prepare_finalize(&pluginFinalize);
|
||||
if (!eth_plugin_call(NULL, ETH_PLUGIN_FINALIZE, (void *) &pluginFinalize)) {
|
||||
PRINTF("Plugin finalize call failed\n");
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Lookup tokens if requested
|
||||
if (pluginFinalize.tokenLookup1 != NULL) {
|
||||
ethPluginProvideToken_t pluginProvideToken;
|
||||
token1 = getKnownToken(pluginFinalize.tokenLookup1);
|
||||
if (pluginFinalize.tokenLookup2 != NULL) {
|
||||
token2 = getKnownToken(pluginFinalize.tokenLookup2);
|
||||
}
|
||||
eth_plugin_prepare_provide_token(&pluginProvideToken, token1, token2);
|
||||
if (!eth_plugin_call(NULL, ETH_PLUGIN_PROVIDE_TOKEN, (void *) &pluginProvideToken)) {
|
||||
PRINTF("Plugin provide token call failed\n");
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
pluginFinalize.result = pluginProvideToken.result;
|
||||
}
|
||||
if (pluginFinalize.result != ETH_PLUGIN_RESULT_FALLBACK) {
|
||||
// Handle the right interface
|
||||
switch (pluginFinalize.uiType) {
|
||||
case ETH_UI_TYPE_GENERIC:
|
||||
dataPresent = false;
|
||||
dataContext.tokenContext.pluginUiMaxItems = pluginFinalize.numScreens;
|
||||
break;
|
||||
case ETH_UI_TYPE_AMOUNT_ADDRESS:
|
||||
genericUI = true;
|
||||
dataPresent = false;
|
||||
if ((pluginFinalize.amount == NULL) || (pluginFinalize.address == NULL)) {
|
||||
PRINTF("Incorrect amount/address set by plugin\n");
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
memmove(tmpContent.txContent.value.value, pluginFinalize.amount, 32);
|
||||
tmpContent.txContent.value.length = 32;
|
||||
memmove(tmpContent.txContent.destination, pluginFinalize.address, 20);
|
||||
tmpContent.txContent.destinationLength = 20;
|
||||
if (token1 != NULL) {
|
||||
decimals = token1->decimals;
|
||||
ticker = token1->ticker;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PRINTF("ui type %d not supported\n", pluginFinalize.uiType);
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
genericUI = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dataPresent && !N_storage.dataAllowed) {
|
||||
PRINTF("Data field forbidden\n");
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
genericUI = true;
|
||||
// Prepare destination address to display
|
||||
if (genericUI) {
|
||||
if (tmpContent.txContent.destinationLength != 0) {
|
||||
displayBuffer[0] = '0';
|
||||
displayBuffer[1] = 'x';
|
||||
getEthAddressStringFromBinary(tmpContent.txContent.destination,
|
||||
(uint8_t *) displayBuffer + 2,
|
||||
&global_sha3,
|
||||
chainConfig);
|
||||
compareOrCopy(strings.common.fullAddress, displayBuffer, called_from_swap);
|
||||
} else {
|
||||
strcpy(strings.common.fullAddress, "Contract");
|
||||
}
|
||||
}
|
||||
// Prepare amount to display
|
||||
if (genericUI) {
|
||||
amountToString(tmpContent.txContent.value.value,
|
||||
tmpContent.txContent.value.length,
|
||||
decimals,
|
||||
(char *) ticker,
|
||||
displayBuffer,
|
||||
sizeof(displayBuffer));
|
||||
compareOrCopy(strings.common.fullAmount, displayBuffer, called_from_swap);
|
||||
}
|
||||
// Compute maximum fee
|
||||
if (genericUI) {
|
||||
computeFees(displayBuffer, sizeof(displayBuffer));
|
||||
compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataPresent && !N_storage.dataAllowed) {
|
||||
PRINTF("Data field forbidden\n");
|
||||
reportFinalizeError(direct);
|
||||
if (!direct) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Prepare destination address to display
|
||||
if (genericUI) {
|
||||
if (tmpContent.txContent.destinationLength != 0) {
|
||||
displayBuffer[0] = '0';
|
||||
displayBuffer[1] = 'x';
|
||||
getEthAddressStringFromBinary(tmpContent.txContent.destination, (uint8_t*)displayBuffer+2, &global_sha3, chainConfig);
|
||||
compareOrCopy(strings.common.fullAddress, displayBuffer, called_from_swap);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(strings.common.fullAddress, "Contract");
|
||||
}
|
||||
}
|
||||
// Prepare amount to display
|
||||
if (genericUI) {
|
||||
amountToString(tmpContent.txContent.value.value, tmpContent.txContent.value.length, decimals, (char*)ticker, displayBuffer, sizeof(displayBuffer));
|
||||
compareOrCopy(strings.common.fullAmount, displayBuffer, called_from_swap);
|
||||
}
|
||||
// Compute maximum fee
|
||||
if (genericUI) {
|
||||
computeFees(displayBuffer, sizeof(displayBuffer));
|
||||
compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap);
|
||||
}
|
||||
bool no_consent = false;
|
||||
|
||||
bool no_consent = false;
|
||||
|
||||
no_consent = called_from_swap;
|
||||
no_consent = called_from_swap;
|
||||
|
||||
#ifdef NO_CONSENT
|
||||
no_consent = true;
|
||||
#endif // NO_CONSENT
|
||||
no_consent = true;
|
||||
#endif // NO_CONSENT
|
||||
|
||||
if(no_consent){
|
||||
io_seproxyhal_touch_tx_ok(NULL);
|
||||
}
|
||||
else{
|
||||
|
||||
if (genericUI) {
|
||||
ux_flow_init(0,
|
||||
((dataPresent && !N_storage.contractDetails) ? ux_approval_tx_data_warning_flow : ux_approval_tx_flow),
|
||||
NULL);
|
||||
if (no_consent) {
|
||||
io_seproxyhal_touch_tx_ok(NULL);
|
||||
} else {
|
||||
if (genericUI) {
|
||||
ux_flow_init(
|
||||
0,
|
||||
((dataPresent && !N_storage.contractDetails) ? ux_approval_tx_data_warning_flow
|
||||
: ux_approval_tx_flow),
|
||||
NULL);
|
||||
} else {
|
||||
plugin_ui_start();
|
||||
}
|
||||
}
|
||||
else {
|
||||
plugin_ui_start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,34 +10,38 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) {
|
||||
uint32_t tx = 0;
|
||||
uint32_t v = getV(&tmpContent.txContent);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1, tmpCtx.transactionContext.bip32Path,
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1,
|
||||
tmpCtx.transactionContext.bip32Path,
|
||||
tmpCtx.transactionContext.pathLength,
|
||||
privateKeyData, NULL);
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32,
|
||||
&privateKey);
|
||||
privateKeyData,
|
||||
NULL);
|
||||
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
unsigned int info = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
signatureLength =
|
||||
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
|
||||
tmpCtx.transactionContext.hash,
|
||||
sizeof(tmpCtx.transactionContext.hash), signature, sizeof(signature), &info);
|
||||
signatureLength = cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
tmpCtx.transactionContext.hash,
|
||||
sizeof(tmpCtx.transactionContext.hash),
|
||||
signature,
|
||||
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;
|
||||
}
|
||||
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;
|
||||
// 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]++;
|
||||
G_io_apdu_buffer[0]++;
|
||||
}
|
||||
if (info & CX_ECCINFO_xGTn) {
|
||||
G_io_apdu_buffer[0] += 2;
|
||||
G_io_apdu_buffer[0] += 2;
|
||||
}
|
||||
format_signature_out(signature);
|
||||
tx = 65;
|
||||
@@ -45,13 +49,13 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) {
|
||||
G_io_apdu_buffer[tx++] = 0x00;
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
if(called_from_swap){
|
||||
if (called_from_swap) {
|
||||
os_sched_exit(0);
|
||||
}
|
||||
reset_app_context();
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_tx_cancel(const bagl_element_t *e) {
|
||||
@@ -62,31 +66,31 @@ unsigned int io_seproxyhal_touch_tx_cancel(const bagl_element_t *e) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
unsigned int io_seproxyhal_touch_data_ok(const bagl_element_t *e) {
|
||||
parserStatus_e txResult = USTREAM_FINISHED;
|
||||
txResult = continueTx(&txContext);
|
||||
switch (txResult) {
|
||||
case USTREAM_SUSPENDED:
|
||||
break;
|
||||
case USTREAM_FINISHED:
|
||||
break;
|
||||
case USTREAM_PROCESSING:
|
||||
io_seproxyhal_send_status(0x9000);
|
||||
ui_idle();
|
||||
break;
|
||||
case USTREAM_FAULT:
|
||||
reset_app_context();
|
||||
io_seproxyhal_send_status(0x6A80);
|
||||
ui_idle();
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unexpected parser status\n");
|
||||
reset_app_context();
|
||||
io_seproxyhal_send_status(0x6A80);
|
||||
ui_idle();
|
||||
case USTREAM_SUSPENDED:
|
||||
break;
|
||||
case USTREAM_FINISHED:
|
||||
break;
|
||||
case USTREAM_PROCESSING:
|
||||
io_seproxyhal_send_status(0x9000);
|
||||
ui_idle();
|
||||
break;
|
||||
case USTREAM_FAULT:
|
||||
reset_app_context();
|
||||
io_seproxyhal_send_status(0x6A80);
|
||||
ui_idle();
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unexpected parser status\n");
|
||||
reset_app_context();
|
||||
io_seproxyhal_send_status(0x6A80);
|
||||
ui_idle();
|
||||
}
|
||||
|
||||
if (txResult == USTREAM_FINISHED) {
|
||||
@@ -101,6 +105,5 @@ unsigned int io_seproxyhal_touch_data_cancel(const bagl_element_t *e) {
|
||||
io_seproxyhal_send_status(0x6985);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "shared_context.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_confirm_selector_flow_1_step,
|
||||
pnn,
|
||||
@@ -33,15 +34,16 @@ UX_STEP_CB(
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_confirm_selector_flow,
|
||||
&ux_confirm_selector_flow_1_step,
|
||||
&ux_confirm_selector_flow_2_step,
|
||||
&ux_confirm_selector_flow_3_step,
|
||||
&ux_confirm_selector_flow_4_step
|
||||
);
|
||||
UX_FLOW(ux_confirm_selector_flow,
|
||||
&ux_confirm_selector_flow_1_step,
|
||||
&ux_confirm_selector_flow_2_step,
|
||||
&ux_confirm_selector_flow_3_step,
|
||||
&ux_confirm_selector_flow_4_step);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_confirm_parameter_flow_1_step,
|
||||
pnn,
|
||||
@@ -73,15 +75,16 @@ UX_STEP_CB(
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_confirm_parameter_flow,
|
||||
&ux_confirm_parameter_flow_1_step,
|
||||
&ux_confirm_parameter_flow_2_step,
|
||||
&ux_confirm_parameter_flow_3_step,
|
||||
&ux_confirm_parameter_flow_4_step
|
||||
);
|
||||
&ux_confirm_parameter_flow_1_step,
|
||||
&ux_confirm_parameter_flow_2_step,
|
||||
&ux_confirm_parameter_flow_3_step,
|
||||
&ux_confirm_parameter_flow_4_step);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(ux_approval_tx_1_step,
|
||||
pnn,
|
||||
{
|
||||
@@ -135,23 +138,21 @@ UX_STEP_NOCB(ux_approval_tx_data_warning_step,
|
||||
"Data",
|
||||
"Present",
|
||||
});
|
||||
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_approval_tx_flow,
|
||||
&ux_approval_tx_1_step,
|
||||
&ux_approval_tx_2_step,
|
||||
&ux_approval_tx_3_step,
|
||||
&ux_approval_tx_4_step,
|
||||
&ux_approval_tx_5_step,
|
||||
&ux_approval_tx_6_step
|
||||
);
|
||||
&ux_approval_tx_1_step,
|
||||
&ux_approval_tx_2_step,
|
||||
&ux_approval_tx_3_step,
|
||||
&ux_approval_tx_4_step,
|
||||
&ux_approval_tx_5_step,
|
||||
&ux_approval_tx_6_step);
|
||||
|
||||
UX_FLOW(ux_approval_tx_data_warning_flow,
|
||||
&ux_approval_tx_1_step,
|
||||
&ux_approval_tx_data_warning_step,
|
||||
&ux_approval_tx_2_step,
|
||||
&ux_approval_tx_3_step,
|
||||
&ux_approval_tx_4_step,
|
||||
&ux_approval_tx_5_step,
|
||||
&ux_approval_tx_6_step
|
||||
);
|
||||
&ux_approval_tx_1_step,
|
||||
&ux_approval_tx_data_warning_step,
|
||||
&ux_approval_tx_2_step,
|
||||
&ux_approval_tx_3_step,
|
||||
&ux_approval_tx_4_step,
|
||||
&ux_approval_tx_5_step,
|
||||
&ux_approval_tx_6_step);
|
||||
@@ -6,55 +6,61 @@
|
||||
#include "feature_stark_getPublicKey.h"
|
||||
#include "ui_flow.h"
|
||||
|
||||
void handleStarkwareGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
UNUSED(dataLength);
|
||||
uint8_t privateKeyData[32];
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = *(dataBuffer++);
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
reset_app_context();
|
||||
if ((bip32PathLength < 0x01) ||
|
||||
(bip32PathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (p2 != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
bip32Path[i] = U4BE(dataBuffer, 0);
|
||||
dataBuffer += 4;
|
||||
}
|
||||
io_seproxyhal_io_heartbeat();
|
||||
starkDerivePrivateKey(bip32Path, bip32PathLength, privateKeyData);
|
||||
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_generate_pair(CX_CURVE_Stark256, &tmpCtx.publicKeyContext.publicKey, &privateKey, 1);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
io_seproxyhal_io_heartbeat();
|
||||
void handleStarkwareGetPublicKey(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
UNUSED(dataLength);
|
||||
uint8_t privateKeyData[32];
|
||||
uint32_t bip32Path[MAX_BIP32_PATH];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = *(dataBuffer++);
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
reset_app_context();
|
||||
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (p2 != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
bip32Path[i] = U4BE(dataBuffer, 0);
|
||||
dataBuffer += 4;
|
||||
}
|
||||
io_seproxyhal_io_heartbeat();
|
||||
starkDerivePrivateKey(bip32Path, bip32PathLength, privateKeyData);
|
||||
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_generate_pair(CX_CURVE_Stark256, &tmpCtx.publicKeyContext.publicKey, &privateKey, 1);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
io_seproxyhal_io_heartbeat();
|
||||
#ifndef NO_CONSENT
|
||||
if (p1 == P1_NON_CONFIRM)
|
||||
#endif // NO_CONSENT
|
||||
{
|
||||
*tx = set_result_get_stark_publicKey();
|
||||
THROW(0x9000);
|
||||
}
|
||||
if (p1 == P1_NON_CONFIRM)
|
||||
#endif // NO_CONSENT
|
||||
{
|
||||
*tx = set_result_get_stark_publicKey();
|
||||
THROW(0x9000);
|
||||
}
|
||||
#ifndef NO_CONSENT
|
||||
else
|
||||
{
|
||||
// prepare for a UI based reply
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, tmpCtx.publicKeyContext.publicKey.W + 1);
|
||||
ux_flow_init(0, ux_display_stark_public_flow, NULL);
|
||||
else {
|
||||
// prepare for a UI based reply
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"0x%.*H",
|
||||
32,
|
||||
tmpCtx.publicKeyContext.publicKey.W + 1);
|
||||
ux_flow_init(0, ux_display_stark_public_flow, NULL);
|
||||
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
#endif // NO_CONSENT
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
#endif // NO_CONSENT
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "shared_context.h"
|
||||
|
||||
uint32_t set_result_get_stark_publicKey(void);
|
||||
|
||||
|
||||
@@ -11,5 +11,3 @@ uint32_t set_result_get_stark_publicKey() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -13,8 +13,7 @@ unsigned int io_seproxyhal_touch_stark_pubkey_ok(const bagl_element_t *e) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
unsigned int io_seproxyhal_touch_stark_pubkey_ok(const bagl_element_t *e);
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(
|
||||
ux_display_stark_public_flow_1_step,
|
||||
pnn,
|
||||
@@ -36,13 +37,12 @@ UX_STEP_CB(
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_display_stark_public_flow,
|
||||
&ux_display_stark_public_flow_1_step,
|
||||
&ux_display_stark_public_flow_2_step,
|
||||
&ux_display_stark_public_flow_3_step,
|
||||
&ux_display_stark_public_flow_4_step
|
||||
);
|
||||
&ux_display_stark_public_flow_1_step,
|
||||
&ux_display_stark_public_flow_2_step,
|
||||
&ux_display_stark_public_flow_3_step,
|
||||
&ux_display_stark_public_flow_4_step);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,56 +4,61 @@
|
||||
#include "apdu_constants.h"
|
||||
#include "ui_flow.h"
|
||||
|
||||
void handleStarkwareProvideQuantum(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
size_t i = 0;
|
||||
uint8_t expectedDataSize = 20 + 32;
|
||||
uint8_t addressZero = 0;
|
||||
tokenDefinition_t *currentToken = NULL;
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
switch(p1) {
|
||||
case STARK_QUANTUM_LEGACY:
|
||||
break;
|
||||
case STARK_QUANTUM_ETH:
|
||||
case STARK_QUANTUM_ERC20:
|
||||
case STARK_QUANTUM_ERC721:
|
||||
case STARK_QUANTUM_MINTABLE_ERC20:
|
||||
case STARK_QUANTUM_MINTABLE_ERC721:
|
||||
expectedDataSize += 32;
|
||||
break;
|
||||
default:
|
||||
THROW(0x6B00);
|
||||
}
|
||||
if (dataLength != expectedDataSize) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
if (p1 == STARK_QUANTUM_LEGACY) {
|
||||
addressZero = allzeroes(dataBuffer, 20);
|
||||
}
|
||||
if ((p1 != STARK_QUANTUM_ETH) && !addressZero) {
|
||||
for(i=0; i<MAX_TOKEN; i++){
|
||||
currentToken = &tmpCtx.transactionContext.tokens[i];
|
||||
if (tmpCtx.transactionContext.tokenSet[i] && (memcmp(currentToken->address, dataBuffer, 20) == 0)) {
|
||||
break;
|
||||
}
|
||||
void handleStarkwareProvideQuantum(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
size_t i = 0;
|
||||
uint8_t expectedDataSize = 20 + 32;
|
||||
uint8_t addressZero = 0;
|
||||
tokenDefinition_t *currentToken = NULL;
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
if (i == MAX_TOKEN) {
|
||||
PRINTF("Associated token not found\n");
|
||||
THROW(0x6A80);
|
||||
switch (p1) {
|
||||
case STARK_QUANTUM_LEGACY:
|
||||
break;
|
||||
case STARK_QUANTUM_ETH:
|
||||
case STARK_QUANTUM_ERC20:
|
||||
case STARK_QUANTUM_ERC721:
|
||||
case STARK_QUANTUM_MINTABLE_ERC20:
|
||||
case STARK_QUANTUM_MINTABLE_ERC721:
|
||||
expectedDataSize += 32;
|
||||
break;
|
||||
default:
|
||||
THROW(0x6B00);
|
||||
}
|
||||
}
|
||||
else {
|
||||
i = MAX_TOKEN;
|
||||
}
|
||||
memmove(dataContext.tokenContext.quantum, dataBuffer + 20, 32);
|
||||
if (p1 != STARK_QUANTUM_LEGACY) {
|
||||
memmove(dataContext.tokenContext.mintingBlob, dataBuffer + 20 + 32, 32);
|
||||
}
|
||||
dataContext.tokenContext.quantumIndex = i;
|
||||
dataContext.tokenContext.quantumType = p1;
|
||||
quantumSet = true;
|
||||
THROW(0x9000);
|
||||
if (dataLength != expectedDataSize) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
if (p1 == STARK_QUANTUM_LEGACY) {
|
||||
addressZero = allzeroes(dataBuffer, 20);
|
||||
}
|
||||
if ((p1 != STARK_QUANTUM_ETH) && !addressZero) {
|
||||
for (i = 0; i < MAX_TOKEN; i++) {
|
||||
currentToken = &tmpCtx.transactionContext.tokens[i];
|
||||
if (tmpCtx.transactionContext.tokenSet[i] &&
|
||||
(memcmp(currentToken->address, dataBuffer, 20) == 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == MAX_TOKEN) {
|
||||
PRINTF("Associated token not found\n");
|
||||
THROW(0x6A80);
|
||||
}
|
||||
} else {
|
||||
i = MAX_TOKEN;
|
||||
}
|
||||
memmove(dataContext.tokenContext.quantum, dataBuffer + 20, 32);
|
||||
if (p1 != STARK_QUANTUM_LEGACY) {
|
||||
memmove(dataContext.tokenContext.mintingBlob, dataBuffer + 20 + 32, 32);
|
||||
}
|
||||
dataContext.tokenContext.quantumIndex = i;
|
||||
dataContext.tokenContext.quantumType = p1;
|
||||
quantumSet = true;
|
||||
THROW(0x9000);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,208 +7,253 @@
|
||||
#include "poorstream.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
#define U8BE(buf, off) (uint64_t)((((uint64_t)U4BE(buf, off)) << 32) | (((uint64_t)U4BE(buf, off + 4)) & 0xFFFFFFFF))
|
||||
#define U8BE(buf, off) \
|
||||
(uint64_t)((((uint64_t) U4BE(buf, off)) << 32) | (((uint64_t) U4BE(buf, off + 4)) & 0xFFFFFFFF))
|
||||
#define TMP_OFFSET 140
|
||||
|
||||
void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
uint8_t privateKeyData[32];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = *(dataBuffer);
|
||||
uint8_t offset = 1;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
poorstream_t bitstream;
|
||||
bool selfTransfer = false;
|
||||
uint8_t order = 1;
|
||||
uint8_t protocol = 2;
|
||||
uint8_t preOffset, postOffset;
|
||||
uint8_t zeroTest;
|
||||
// Initial checks
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
if ((bip32PathLength < 0x01) ||
|
||||
(bip32PathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
switch(p1) {
|
||||
case P1_STARK_ORDER:
|
||||
protocol = 1;
|
||||
break;
|
||||
case P1_STARK_TRANSFER:
|
||||
protocol = 1;
|
||||
order = 0;
|
||||
break;
|
||||
case P1_STARK_ORDER_V2:
|
||||
break;
|
||||
case P1_STARK_TRANSFER_V2:
|
||||
case P1_STARK_CONDITIONAL_TRANSFER:
|
||||
order = 0;
|
||||
break;
|
||||
default:
|
||||
THROW(0x6B00);
|
||||
}
|
||||
postOffset = (protocol == 2 ? 1 + 32 : 0);
|
||||
preOffset = (protocol == 2 ? 1 : 0);
|
||||
if (order) {
|
||||
if (dataLength != (20 + 32 + 20 + 32 + 4 + 4 + 8 + 8 + 4 + 4 + 1 + 4 * bip32PathLength +
|
||||
2 * postOffset)) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (dataLength != (20 + 32 + 32 + 4 + 4 + 8 + 4 + 4 + 1 + 4 * bip32PathLength +
|
||||
postOffset + (p1 == P1_STARK_CONDITIONAL_TRANSFER ? 32 + 20 : 0))) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
}
|
||||
if (p2 != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
tmpCtx.transactionContext.pathLength = bip32PathLength;
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
tmpCtx.transactionContext.bip32Path[i] = U4BE(dataBuffer, offset);
|
||||
PRINTF("Storing path %d %d\n", i, tmpCtx.transactionContext.bip32Path[i]);
|
||||
offset += 4;
|
||||
}
|
||||
// Discard the path to use part of dataBuffer as a temporary buffer
|
||||
memmove(dataBuffer, dataBuffer + offset, dataLength - offset);
|
||||
dataContext.starkContext.conditional = (p1 == P1_STARK_CONDITIONAL_TRANSFER);
|
||||
if (dataContext.starkContext.conditional) {
|
||||
memmove(dataContext.starkContext.fact, dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4 + 8 + 4 + 4, 32);
|
||||
memmove(dataContext.starkContext.conditionAddress, dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4 + 8 + 4 + 4 + 32, 20);
|
||||
PRINTF("Fact %.*H\n", 32, dataContext.starkContext.fact);
|
||||
PRINTF("Address %.*H\n", 20, dataContext.starkContext.conditionAddress);
|
||||
}
|
||||
|
||||
zeroTest = allzeroes(dataBuffer + preOffset, 20);
|
||||
if (zeroTest && (protocol == 2) && (dataBuffer[0] != STARK_QUANTUM_ETH)) {
|
||||
PRINTF("stark - unexpected quantum descriptor type for null first address %d\n", dataBuffer[0]);
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (!zeroTest && getKnownToken(dataBuffer + preOffset) == NULL) {
|
||||
PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer + preOffset);
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (order) {
|
||||
zeroTest = allzeroes(dataBuffer + 20 + 32 + postOffset + preOffset, 20);
|
||||
if (zeroTest && (protocol == 2) && (dataBuffer[1 + 20 + 32 + 32] != STARK_QUANTUM_ETH)) {
|
||||
PRINTF("stark - unexpected quantum descriptor type for null second address %d\n", dataBuffer[1 + 20 + 32 + 32]);
|
||||
THROW(0x6A80);
|
||||
void handleStarkwareSignMessage(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
uint8_t privateKeyData[32];
|
||||
uint32_t i;
|
||||
uint8_t bip32PathLength = *(dataBuffer);
|
||||
uint8_t offset = 1;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
poorstream_t bitstream;
|
||||
bool selfTransfer = false;
|
||||
uint8_t order = 1;
|
||||
uint8_t protocol = 2;
|
||||
uint8_t preOffset, postOffset;
|
||||
uint8_t zeroTest;
|
||||
// Initial checks
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
if (!zeroTest && getKnownToken(dataBuffer + 20 + 32 + postOffset + preOffset) == NULL) {
|
||||
PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer + 20 + 32 + postOffset + preOffset);
|
||||
THROW(0x6A80);
|
||||
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
}
|
||||
// Prepare the Stark parameters
|
||||
io_seproxyhal_io_heartbeat();
|
||||
compute_token_id(&global_sha3, dataBuffer + preOffset,
|
||||
(protocol == 2 ? dataBuffer[0] : STARK_QUANTUM_LEGACY),
|
||||
dataBuffer + preOffset + 20,
|
||||
(protocol == 2 ? dataBuffer + 1 + 20 + 32 : NULL), false, dataContext.starkContext.w1);
|
||||
if (order) {
|
||||
io_seproxyhal_io_heartbeat();
|
||||
compute_token_id(&global_sha3, dataBuffer + 20 + 32 + postOffset + preOffset,
|
||||
(protocol == 2 ? dataBuffer[1 + 20 + 32 + 32] : STARK_QUANTUM_LEGACY),
|
||||
dataBuffer + 20 + 32 + postOffset + preOffset + 20,
|
||||
(protocol == 2 ? dataBuffer + 1 + 20 + 32 + 32 + 1 + 20 + 32 : NULL), false, dataContext.starkContext.w2);
|
||||
offset = 20 + 32 + postOffset + 20 + 32 + postOffset;
|
||||
}
|
||||
else {
|
||||
memmove(dataContext.starkContext.w2, dataBuffer + 20 + 32 + postOffset, 32);
|
||||
offset = 20 + 32 + postOffset + 32;
|
||||
}
|
||||
|
||||
poorstream_init(&bitstream, dataContext.starkContext.w3);
|
||||
poorstream_write_bits(&bitstream, 0, 11); // padding
|
||||
poorstream_write_bits(&bitstream,
|
||||
(p1 == P1_STARK_CONDITIONAL_TRANSFER ? STARK_CONDITIONAL_TRANSFER_TYPE :
|
||||
order ? STARK_ORDER_TYPE : STARK_TRANSFER_TYPE), 4);
|
||||
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset), 31);
|
||||
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset + 4), 31);
|
||||
poorstream_write_bits(&bitstream, U8BE(dataBuffer, offset + 4 + 4), 63);
|
||||
if (order) {
|
||||
poorstream_write_bits(&bitstream, U8BE(dataBuffer, offset + 4 + 4 + 8), 63);
|
||||
offset += 4 + 4 + 8 + 8;
|
||||
}
|
||||
else {
|
||||
poorstream_write_bits(&bitstream, 0, 63);
|
||||
offset += 4 + 4 + 8;
|
||||
}
|
||||
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset), 31);
|
||||
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset + 4), 22);
|
||||
|
||||
PRINTF("stark w1 %.*H\n", 32, dataContext.starkContext.w1);
|
||||
PRINTF("stark w2 %.*H\n", 32, dataContext.starkContext.w2);
|
||||
PRINTF("stark w3 %.*H\n", 32, dataContext.starkContext.w3);
|
||||
|
||||
if (dataContext.starkContext.conditional) {
|
||||
cx_keccak_init(&global_sha3, 256);
|
||||
cx_hash((cx_hash_t*)&global_sha3, 0, dataContext.starkContext.conditionAddress, 20, NULL, 0);
|
||||
cx_hash((cx_hash_t*)&global_sha3, CX_LAST, dataContext.starkContext.fact, 32, dataContext.starkContext.w4, 32);
|
||||
dataContext.starkContext.w4[0] &= 0x03;
|
||||
PRINTF("stark w4 %.*H\n", 32, dataContext.starkContext.w4);
|
||||
}
|
||||
// Prepare the UI
|
||||
if (order) {
|
||||
io_seproxyhal_io_heartbeat();
|
||||
// amount to sell
|
||||
stark_get_amount_string(dataBuffer + preOffset,
|
||||
dataBuffer + preOffset + 20,
|
||||
dataBuffer + 20 + 32 + postOffset + 20 + 32 + postOffset + 4 + 4,
|
||||
(char*)(dataBuffer + TMP_OFFSET), strings.common.fullAmount);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
// amount to buy
|
||||
stark_get_amount_string(dataBuffer + 20 + 32 + postOffset + preOffset,
|
||||
dataBuffer + 20 + 32 + postOffset + preOffset + 20,
|
||||
dataBuffer + 20 + 32 + postOffset + 20 + 32 + postOffset + 4 + 4 + 8,
|
||||
(char*)(dataBuffer + TMP_OFFSET), strings.common.maxFee);
|
||||
// src vault ID
|
||||
snprintf(strings.common.fullAddress, sizeof(strings.common.fullAddress), "%d",
|
||||
U4BE(dataBuffer, 20 + 32 + postOffset + 20 + 32 + postOffset));
|
||||
}
|
||||
else {
|
||||
cx_ecfp_public_key_t publicKey;
|
||||
// Check if the transfer is a self transfer
|
||||
io_seproxyhal_io_heartbeat();
|
||||
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, bip32PathLength, privateKeyData);
|
||||
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_generate_pair(CX_CURVE_Stark256, &publicKey, &privateKey, 1);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
io_seproxyhal_io_heartbeat();
|
||||
selfTransfer = (memcmp(publicKey.W + 1, dataBuffer + 20 + 32 + postOffset, 32) == 0);
|
||||
PRINTF("self transfer %d\n", selfTransfer);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
// amount to transfer
|
||||
stark_get_amount_string(dataBuffer + preOffset,
|
||||
dataBuffer + preOffset + 20,
|
||||
dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4, (char*)(dataBuffer + TMP_OFFSET), tmpContent.tmp);
|
||||
// dest vault ID
|
||||
snprintf(strings.tmp.tmp2, sizeof(strings.tmp.tmp2), "%d",
|
||||
U4BE(dataBuffer, 20 + 32 + postOffset + 32 + 4));
|
||||
if (!selfTransfer) {
|
||||
memmove(dataContext.starkContext.transferDestination, dataBuffer + 20 + 32 + postOffset, 32);
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataBuffer + 20 + 32 + postOffset);
|
||||
switch (p1) {
|
||||
case P1_STARK_ORDER:
|
||||
protocol = 1;
|
||||
break;
|
||||
case P1_STARK_TRANSFER:
|
||||
protocol = 1;
|
||||
order = 0;
|
||||
break;
|
||||
case P1_STARK_ORDER_V2:
|
||||
break;
|
||||
case P1_STARK_TRANSFER_V2:
|
||||
case P1_STARK_CONDITIONAL_TRANSFER:
|
||||
order = 0;
|
||||
break;
|
||||
default:
|
||||
THROW(0x6B00);
|
||||
}
|
||||
}
|
||||
if (order) {
|
||||
ux_flow_init(0, ux_stark_limit_order_flow, NULL);
|
||||
}
|
||||
else {
|
||||
if (selfTransfer) {
|
||||
ux_flow_init(0, (dataContext.starkContext.conditional ? ux_stark_self_transfer_conditional_flow :
|
||||
ux_stark_self_transfer_flow), NULL);
|
||||
postOffset = (protocol == 2 ? 1 + 32 : 0);
|
||||
preOffset = (protocol == 2 ? 1 : 0);
|
||||
if (order) {
|
||||
if (dataLength != (20 + 32 + 20 + 32 + 4 + 4 + 8 + 8 + 4 + 4 + 1 + 4 * bip32PathLength +
|
||||
2 * postOffset)) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
} else {
|
||||
if (dataLength != (20 + 32 + 32 + 4 + 4 + 8 + 4 + 4 + 1 + 4 * bip32PathLength + postOffset +
|
||||
(p1 == P1_STARK_CONDITIONAL_TRANSFER ? 32 + 20 : 0))) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ux_flow_init(0, (dataContext.starkContext.conditional ? ux_stark_transfer_conditional_flow :
|
||||
ux_stark_transfer_flow), NULL);
|
||||
if (p2 != 0) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
tmpCtx.transactionContext.pathLength = bip32PathLength;
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
tmpCtx.transactionContext.bip32Path[i] = U4BE(dataBuffer, offset);
|
||||
PRINTF("Storing path %d %d\n", i, tmpCtx.transactionContext.bip32Path[i]);
|
||||
offset += 4;
|
||||
}
|
||||
// Discard the path to use part of dataBuffer as a temporary buffer
|
||||
memmove(dataBuffer, dataBuffer + offset, dataLength - offset);
|
||||
dataContext.starkContext.conditional = (p1 == P1_STARK_CONDITIONAL_TRANSFER);
|
||||
if (dataContext.starkContext.conditional) {
|
||||
memmove(dataContext.starkContext.fact,
|
||||
dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4 + 8 + 4 + 4,
|
||||
32);
|
||||
memmove(dataContext.starkContext.conditionAddress,
|
||||
dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4 + 8 + 4 + 4 + 32,
|
||||
20);
|
||||
PRINTF("Fact %.*H\n", 32, dataContext.starkContext.fact);
|
||||
PRINTF("Address %.*H\n", 20, dataContext.starkContext.conditionAddress);
|
||||
}
|
||||
}
|
||||
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
zeroTest = allzeroes(dataBuffer + preOffset, 20);
|
||||
if (zeroTest && (protocol == 2) && (dataBuffer[0] != STARK_QUANTUM_ETH)) {
|
||||
PRINTF("stark - unexpected quantum descriptor type for null first address %d\n",
|
||||
dataBuffer[0]);
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (!zeroTest && getKnownToken(dataBuffer + preOffset) == NULL) {
|
||||
PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer + preOffset);
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (order) {
|
||||
zeroTest = allzeroes(dataBuffer + 20 + 32 + postOffset + preOffset, 20);
|
||||
if (zeroTest && (protocol == 2) && (dataBuffer[1 + 20 + 32 + 32] != STARK_QUANTUM_ETH)) {
|
||||
PRINTF("stark - unexpected quantum descriptor type for null second address %d\n",
|
||||
dataBuffer[1 + 20 + 32 + 32]);
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if (!zeroTest && getKnownToken(dataBuffer + 20 + 32 + postOffset + preOffset) == NULL) {
|
||||
PRINTF("stark - cannot process unknown token %.*H",
|
||||
20,
|
||||
dataBuffer + 20 + 32 + postOffset + preOffset);
|
||||
THROW(0x6A80);
|
||||
}
|
||||
}
|
||||
// Prepare the Stark parameters
|
||||
io_seproxyhal_io_heartbeat();
|
||||
compute_token_id(&global_sha3,
|
||||
dataBuffer + preOffset,
|
||||
(protocol == 2 ? dataBuffer[0] : STARK_QUANTUM_LEGACY),
|
||||
dataBuffer + preOffset + 20,
|
||||
(protocol == 2 ? dataBuffer + 1 + 20 + 32 : NULL),
|
||||
false,
|
||||
dataContext.starkContext.w1);
|
||||
if (order) {
|
||||
io_seproxyhal_io_heartbeat();
|
||||
compute_token_id(&global_sha3,
|
||||
dataBuffer + 20 + 32 + postOffset + preOffset,
|
||||
(protocol == 2 ? dataBuffer[1 + 20 + 32 + 32] : STARK_QUANTUM_LEGACY),
|
||||
dataBuffer + 20 + 32 + postOffset + preOffset + 20,
|
||||
(protocol == 2 ? dataBuffer + 1 + 20 + 32 + 32 + 1 + 20 + 32 : NULL),
|
||||
false,
|
||||
dataContext.starkContext.w2);
|
||||
offset = 20 + 32 + postOffset + 20 + 32 + postOffset;
|
||||
} else {
|
||||
memmove(dataContext.starkContext.w2, dataBuffer + 20 + 32 + postOffset, 32);
|
||||
offset = 20 + 32 + postOffset + 32;
|
||||
}
|
||||
|
||||
poorstream_init(&bitstream, dataContext.starkContext.w3);
|
||||
poorstream_write_bits(&bitstream, 0, 11); // padding
|
||||
poorstream_write_bits(
|
||||
&bitstream,
|
||||
(p1 == P1_STARK_CONDITIONAL_TRANSFER ? STARK_CONDITIONAL_TRANSFER_TYPE
|
||||
: order ? STARK_ORDER_TYPE : STARK_TRANSFER_TYPE),
|
||||
4);
|
||||
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset), 31);
|
||||
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset + 4), 31);
|
||||
poorstream_write_bits(&bitstream, U8BE(dataBuffer, offset + 4 + 4), 63);
|
||||
if (order) {
|
||||
poorstream_write_bits(&bitstream, U8BE(dataBuffer, offset + 4 + 4 + 8), 63);
|
||||
offset += 4 + 4 + 8 + 8;
|
||||
} else {
|
||||
poorstream_write_bits(&bitstream, 0, 63);
|
||||
offset += 4 + 4 + 8;
|
||||
}
|
||||
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset), 31);
|
||||
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset + 4), 22);
|
||||
|
||||
PRINTF("stark w1 %.*H\n", 32, dataContext.starkContext.w1);
|
||||
PRINTF("stark w2 %.*H\n", 32, dataContext.starkContext.w2);
|
||||
PRINTF("stark w3 %.*H\n", 32, dataContext.starkContext.w3);
|
||||
|
||||
if (dataContext.starkContext.conditional) {
|
||||
cx_keccak_init(&global_sha3, 256);
|
||||
cx_hash((cx_hash_t *) &global_sha3,
|
||||
0,
|
||||
dataContext.starkContext.conditionAddress,
|
||||
20,
|
||||
NULL,
|
||||
0);
|
||||
cx_hash((cx_hash_t *) &global_sha3,
|
||||
CX_LAST,
|
||||
dataContext.starkContext.fact,
|
||||
32,
|
||||
dataContext.starkContext.w4,
|
||||
32);
|
||||
dataContext.starkContext.w4[0] &= 0x03;
|
||||
PRINTF("stark w4 %.*H\n", 32, dataContext.starkContext.w4);
|
||||
}
|
||||
// Prepare the UI
|
||||
if (order) {
|
||||
io_seproxyhal_io_heartbeat();
|
||||
// amount to sell
|
||||
stark_get_amount_string(dataBuffer + preOffset,
|
||||
dataBuffer + preOffset + 20,
|
||||
dataBuffer + 20 + 32 + postOffset + 20 + 32 + postOffset + 4 + 4,
|
||||
(char *) (dataBuffer + TMP_OFFSET),
|
||||
strings.common.fullAmount);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
// amount to buy
|
||||
stark_get_amount_string(
|
||||
dataBuffer + 20 + 32 + postOffset + preOffset,
|
||||
dataBuffer + 20 + 32 + postOffset + preOffset + 20,
|
||||
dataBuffer + 20 + 32 + postOffset + 20 + 32 + postOffset + 4 + 4 + 8,
|
||||
(char *) (dataBuffer + TMP_OFFSET),
|
||||
strings.common.maxFee);
|
||||
// src vault ID
|
||||
snprintf(strings.common.fullAddress,
|
||||
sizeof(strings.common.fullAddress),
|
||||
"%d",
|
||||
U4BE(dataBuffer, 20 + 32 + postOffset + 20 + 32 + postOffset));
|
||||
} else {
|
||||
cx_ecfp_public_key_t publicKey;
|
||||
// Check if the transfer is a self transfer
|
||||
io_seproxyhal_io_heartbeat();
|
||||
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, bip32PathLength, privateKeyData);
|
||||
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_generate_pair(CX_CURVE_Stark256, &publicKey, &privateKey, 1);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
io_seproxyhal_io_heartbeat();
|
||||
selfTransfer = (memcmp(publicKey.W + 1, dataBuffer + 20 + 32 + postOffset, 32) == 0);
|
||||
PRINTF("self transfer %d\n", selfTransfer);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
// amount to transfer
|
||||
stark_get_amount_string(dataBuffer + preOffset,
|
||||
dataBuffer + preOffset + 20,
|
||||
dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4,
|
||||
(char *) (dataBuffer + TMP_OFFSET),
|
||||
tmpContent.tmp);
|
||||
// dest vault ID
|
||||
snprintf(strings.tmp.tmp2,
|
||||
sizeof(strings.tmp.tmp2),
|
||||
"%d",
|
||||
U4BE(dataBuffer, 20 + 32 + postOffset + 32 + 4));
|
||||
if (!selfTransfer) {
|
||||
memmove(dataContext.starkContext.transferDestination,
|
||||
dataBuffer + 20 + 32 + postOffset,
|
||||
32);
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"0x%.*H",
|
||||
32,
|
||||
dataBuffer + 20 + 32 + postOffset);
|
||||
}
|
||||
}
|
||||
if (order) {
|
||||
ux_flow_init(0, ux_stark_limit_order_flow, NULL);
|
||||
} else {
|
||||
if (selfTransfer) {
|
||||
ux_flow_init(
|
||||
0,
|
||||
(dataContext.starkContext.conditional ? ux_stark_self_transfer_conditional_flow
|
||||
: ux_stark_self_transfer_flow),
|
||||
NULL);
|
||||
} else {
|
||||
ux_flow_init(0,
|
||||
(dataContext.starkContext.conditional ? ux_stark_transfer_conditional_flow
|
||||
: ux_stark_transfer_flow),
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,12 +9,17 @@ unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e) {
|
||||
uint8_t signature[72];
|
||||
uint32_t tx = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, tmpCtx.transactionContext.pathLength, privateKeyData);
|
||||
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path,
|
||||
tmpCtx.transactionContext.pathLength,
|
||||
privateKeyData);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
stark_sign(signature, privateKeyData, dataContext.starkContext.w1, dataContext.starkContext.w2,
|
||||
dataContext.starkContext.w3,
|
||||
(dataContext.starkContext.conditional ? dataContext.starkContext.w4 : NULL));
|
||||
G_io_apdu_buffer[0] = 0;
|
||||
stark_sign(signature,
|
||||
privateKeyData,
|
||||
dataContext.starkContext.w1,
|
||||
dataContext.starkContext.w2,
|
||||
dataContext.starkContext.w3,
|
||||
(dataContext.starkContext.conditional ? dataContext.starkContext.w4 : NULL));
|
||||
G_io_apdu_buffer[0] = 0;
|
||||
format_signature_out(signature);
|
||||
tx = 65;
|
||||
G_io_apdu_buffer[tx++] = 0x90;
|
||||
@@ -24,7 +29,7 @@ unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,20 +6,28 @@
|
||||
unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e);
|
||||
|
||||
void stark_sign_display_master_account() {
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.transferDestination);
|
||||
snprintf(strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
"0x%.*H",
|
||||
32,
|
||||
dataContext.starkContext.transferDestination);
|
||||
}
|
||||
|
||||
void stark_sign_display_condition_address() {
|
||||
strings.tmp.tmp[0] = '0';
|
||||
strings.tmp.tmp[1] = 'x';
|
||||
getEthAddressStringFromBinary(dataContext.starkContext.conditionAddress, (uint8_t*)(strings.tmp.tmp + 2), &global_sha3, chainConfig);
|
||||
strings.tmp.tmp[42] = '\0';
|
||||
}
|
||||
|
||||
void stark_sign_display_condition_fact() {
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.fact);
|
||||
strings.tmp.tmp[0] = '0';
|
||||
strings.tmp.tmp[1] = 'x';
|
||||
getEthAddressStringFromBinary(dataContext.starkContext.conditionAddress,
|
||||
(uint8_t *) (strings.tmp.tmp + 2),
|
||||
&global_sha3,
|
||||
chainConfig);
|
||||
strings.tmp.tmp[42] = '\0';
|
||||
}
|
||||
|
||||
void stark_sign_display_condition_fact() {
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.fact);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(ux_stark_limit_order_1_step,
|
||||
pnn,
|
||||
{
|
||||
@@ -80,19 +88,20 @@ UX_STEP_CB(
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_stark_limit_order_flow,
|
||||
&ux_stark_limit_order_1_step,
|
||||
&ux_stark_limit_order_2_step,
|
||||
&ux_stark_limit_order_3_step,
|
||||
&ux_stark_limit_order_4_step,
|
||||
&ux_stark_limit_order_5_step,
|
||||
&ux_stark_limit_order_6_step,
|
||||
&ux_stark_limit_order_7_step,
|
||||
&ux_stark_limit_order_8_step
|
||||
);
|
||||
&ux_stark_limit_order_1_step,
|
||||
&ux_stark_limit_order_2_step,
|
||||
&ux_stark_limit_order_3_step,
|
||||
&ux_stark_limit_order_4_step,
|
||||
&ux_stark_limit_order_5_step,
|
||||
&ux_stark_limit_order_6_step,
|
||||
&ux_stark_limit_order_7_step,
|
||||
&ux_stark_limit_order_8_step);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(ux_stark_transfer_1_step,
|
||||
pnn,
|
||||
{
|
||||
@@ -194,47 +203,44 @@ UX_STEP_NOCB_INIT(
|
||||
.title = "Cond. Fact",
|
||||
.text = strings.tmp.tmp
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_stark_transfer_flow,
|
||||
&ux_stark_transfer_1_step,
|
||||
&ux_stark_transfer_2_step,
|
||||
&ux_stark_transfer_3_step,
|
||||
&ux_stark_transfer_4_step,
|
||||
&ux_stark_transfer_5_step,
|
||||
&ux_stark_transfer_6_step,
|
||||
&ux_stark_transfer_7_step
|
||||
);
|
||||
&ux_stark_transfer_1_step,
|
||||
&ux_stark_transfer_2_step,
|
||||
&ux_stark_transfer_3_step,
|
||||
&ux_stark_transfer_4_step,
|
||||
&ux_stark_transfer_5_step,
|
||||
&ux_stark_transfer_6_step,
|
||||
&ux_stark_transfer_7_step);
|
||||
|
||||
UX_FLOW(ux_stark_self_transfer_flow,
|
||||
&ux_stark_transfer_1_step,
|
||||
&ux_stark_self_transfer_2_step,
|
||||
&ux_stark_transfer_3_step,
|
||||
&ux_stark_transfer_5_step,
|
||||
&ux_stark_transfer_6_step,
|
||||
&ux_stark_transfer_7_step
|
||||
);
|
||||
&ux_stark_transfer_1_step,
|
||||
&ux_stark_self_transfer_2_step,
|
||||
&ux_stark_transfer_3_step,
|
||||
&ux_stark_transfer_5_step,
|
||||
&ux_stark_transfer_6_step,
|
||||
&ux_stark_transfer_7_step);
|
||||
|
||||
UX_FLOW(ux_stark_transfer_conditional_flow,
|
||||
&ux_stark_transfer_1_step,
|
||||
&ux_stark_conditional_transfer_2_step,
|
||||
&ux_stark_transfer_3_step,
|
||||
&ux_stark_conditional_transfer_4_step,
|
||||
&ux_stark_transfer_5_step,
|
||||
&ux_stark_conditional_transfer_8_step,
|
||||
&ux_stark_conditional_transfer_9_step,
|
||||
&ux_stark_transfer_6_step,
|
||||
&ux_stark_transfer_7_step
|
||||
);
|
||||
&ux_stark_transfer_1_step,
|
||||
&ux_stark_conditional_transfer_2_step,
|
||||
&ux_stark_transfer_3_step,
|
||||
&ux_stark_conditional_transfer_4_step,
|
||||
&ux_stark_transfer_5_step,
|
||||
&ux_stark_conditional_transfer_8_step,
|
||||
&ux_stark_conditional_transfer_9_step,
|
||||
&ux_stark_transfer_6_step,
|
||||
&ux_stark_transfer_7_step);
|
||||
|
||||
UX_FLOW(ux_stark_self_transfer_conditional_flow,
|
||||
&ux_stark_transfer_1_step,
|
||||
&ux_stark_self_conditional_transfer_2_step,
|
||||
&ux_stark_transfer_3_step,
|
||||
&ux_stark_transfer_5_step,
|
||||
&ux_stark_conditional_transfer_8_step,
|
||||
&ux_stark_conditional_transfer_9_step,
|
||||
&ux_stark_transfer_6_step,
|
||||
&ux_stark_transfer_7_step
|
||||
);
|
||||
&ux_stark_transfer_1_step,
|
||||
&ux_stark_self_conditional_transfer_2_step,
|
||||
&ux_stark_transfer_3_step,
|
||||
&ux_stark_transfer_5_step,
|
||||
&ux_stark_conditional_transfer_8_step,
|
||||
&ux_stark_conditional_transfer_9_step,
|
||||
&ux_stark_transfer_6_step,
|
||||
&ux_stark_transfer_7_step);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,49 +6,53 @@
|
||||
#include "ui_flow.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
void handleStarkwareUnsafeSign(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
|
||||
uint32_t i;
|
||||
uint8_t privateKeyData[32];
|
||||
cx_ecfp_public_key_t publicKey;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint8_t bip32PathLength = *(dataBuffer);
|
||||
uint8_t offset = 1;
|
||||
// Initial checks
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
if ((bip32PathLength < 0x01) ||
|
||||
(bip32PathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((p1 != 0) || (p2 != 0)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
void handleStarkwareUnsafeSign(uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint8_t *dataBuffer,
|
||||
uint16_t dataLength,
|
||||
unsigned int *flags,
|
||||
unsigned int *tx) {
|
||||
uint32_t i;
|
||||
uint8_t privateKeyData[32];
|
||||
cx_ecfp_public_key_t publicKey;
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint8_t bip32PathLength = *(dataBuffer);
|
||||
uint8_t offset = 1;
|
||||
// Initial checks
|
||||
if (appState != APP_STATE_IDLE) {
|
||||
reset_app_context();
|
||||
}
|
||||
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
|
||||
PRINTF("Invalid path\n");
|
||||
THROW(0x6a80);
|
||||
}
|
||||
if ((p1 != 0) || (p2 != 0)) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
|
||||
if (dataLength != 32 + 4 * bip32PathLength + 1) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
if (dataLength != 32 + 4 * bip32PathLength + 1) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
|
||||
tmpCtx.transactionContext.pathLength = bip32PathLength;
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
tmpCtx.transactionContext.bip32Path[i] = U4BE(dataBuffer, offset);
|
||||
PRINTF("Storing path %d %d\n", i, tmpCtx.transactionContext.bip32Path[i]);
|
||||
offset += 4;
|
||||
}
|
||||
memmove(dataContext.starkContext.w2, dataBuffer + offset, 32);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, bip32PathLength, privateKeyData);
|
||||
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_generate_pair(CX_CURVE_Stark256, &publicKey, &privateKey, 1);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
io_seproxyhal_io_heartbeat();
|
||||
memmove(dataContext.starkContext.w1, publicKey.W + 1, 32);
|
||||
ux_flow_init(0, ux_stark_unsafe_sign_flow, NULL);
|
||||
tmpCtx.transactionContext.pathLength = bip32PathLength;
|
||||
for (i = 0; i < bip32PathLength; i++) {
|
||||
tmpCtx.transactionContext.bip32Path[i] = U4BE(dataBuffer, offset);
|
||||
PRINTF("Storing path %d %d\n", i, tmpCtx.transactionContext.bip32Path[i]);
|
||||
offset += 4;
|
||||
}
|
||||
memmove(dataContext.starkContext.w2, dataBuffer + offset, 32);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, bip32PathLength, privateKeyData);
|
||||
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_generate_pair(CX_CURVE_Stark256, &publicKey, &privateKey, 1);
|
||||
explicit_bzero(&privateKey, sizeof(privateKey));
|
||||
explicit_bzero(privateKeyData, sizeof(privateKeyData));
|
||||
io_seproxyhal_io_heartbeat();
|
||||
memmove(dataContext.starkContext.w1, publicKey.W + 1, 32);
|
||||
ux_flow_init(0, ux_stark_unsafe_sign_flow, NULL);
|
||||
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,11 +11,19 @@ unsigned int io_seproxyhal_touch_stark_unsafe_sign_ok(const bagl_element_t *e) {
|
||||
unsigned int info = 0;
|
||||
uint32_t tx = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, tmpCtx.transactionContext.pathLength, privateKeyData);
|
||||
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path,
|
||||
tmpCtx.transactionContext.pathLength,
|
||||
privateKeyData);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
|
||||
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
|
||||
dataContext.starkContext.w2, sizeof(dataContext.starkContext.w2), signature, sizeof(signature), &info);
|
||||
cx_ecdsa_sign(&privateKey,
|
||||
CX_RND_RFC6979 | CX_LAST,
|
||||
CX_SHA256,
|
||||
dataContext.starkContext.w2,
|
||||
sizeof(dataContext.starkContext.w2),
|
||||
signature,
|
||||
sizeof(signature),
|
||||
&info);
|
||||
G_io_apdu_buffer[0] = 0;
|
||||
format_signature_out(signature);
|
||||
tx = 65;
|
||||
@@ -26,7 +34,7 @@ unsigned int io_seproxyhal_touch_stark_unsafe_sign_ok(const bagl_element_t *e) {
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
unsigned int io_seproxyhal_touch_stark_unsafe_sign_ok(const bagl_element_t *e);
|
||||
|
||||
void stark_unsafe_sign_display_account() {
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.w1);
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.w1);
|
||||
}
|
||||
|
||||
void stark_unsafe_sign_display_hash() {
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.w2);
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.w2);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
UX_STEP_NOCB(ux_stark_unsafe_sign_1_step,
|
||||
pnn,
|
||||
{
|
||||
@@ -57,13 +58,13 @@ UX_STEP_CB(
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
UX_FLOW(ux_stark_unsafe_sign_flow,
|
||||
&ux_stark_unsafe_sign_1_step,
|
||||
&ux_stark_unsafe_sign_2_step,
|
||||
&ux_stark_unsafe_sign_3_step,
|
||||
&ux_stark_unsafe_sign_4_step,
|
||||
&ux_stark_unsafe_sign_5_step
|
||||
);
|
||||
&ux_stark_unsafe_sign_1_step,
|
||||
&ux_stark_unsafe_sign_2_step,
|
||||
&ux_stark_unsafe_sign_3_step,
|
||||
&ux_stark_unsafe_sign_4_step,
|
||||
&ux_stark_unsafe_sign_5_step);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <string.h>
|
||||
#include "eth_plugin_interface.h"
|
||||
#include "shared_context.h" // TODO : rewrite as independant code
|
||||
#include "eth_plugin_internal.h" // TODO : rewrite as independant code
|
||||
#include "shared_context.h" // TODO : rewrite as independant code
|
||||
#include "eth_plugin_internal.h" // TODO : rewrite as independant code
|
||||
#include "utils.h"
|
||||
|
||||
typedef enum {
|
||||
@@ -39,11 +39,9 @@ typedef struct underlying_asset_decimals_t {
|
||||
uint8_t decimals;
|
||||
} underlying_asset_decimals_t;
|
||||
|
||||
|
||||
|
||||
/* Sadly, we don't have the information about the underlying asset's decimals, which can differ from the cToken decimals.
|
||||
Therefore, we hardcode a binding table. If Compound adds a lot of token in the future, we will have to move to a CAL
|
||||
based architecture instead, as this one doesn't scale well.*/
|
||||
/* Sadly, we don't have the information about the underlying asset's decimals, which can differ from
|
||||
the cToken decimals. Therefore, we hardcode a binding table. If Compound adds a lot of token in the
|
||||
future, we will have to move to a CAL based architecture instead, as this one doesn't scale well.*/
|
||||
#define NUM_COMPOUND_BINDINGS 9
|
||||
const underlying_asset_decimals_t const UNDERLYING_ASSET_DECIMALS[NUM_COMPOUND_BINDINGS] = {
|
||||
{"cDAI", 18},
|
||||
@@ -57,10 +55,13 @@ const underlying_asset_decimals_t const UNDERLYING_ASSET_DECIMALS[NUM_COMPOUND_B
|
||||
{"cSAI", 18},
|
||||
};
|
||||
|
||||
bool get_underlying_asset_decimals(char* compound_ticker, uint8_t* out_decimals){
|
||||
for(size_t i = 0; i < NUM_COMPOUND_BINDINGS; i++){
|
||||
underlying_asset_decimals_t* binding = (underlying_asset_decimals_t *)PIC(&UNDERLYING_ASSET_DECIMALS[i]);
|
||||
if (strncmp(binding->c_ticker, compound_ticker, strnlen(binding->c_ticker, MAX_TICKER_LEN)) == 0){
|
||||
bool get_underlying_asset_decimals(char *compound_ticker, uint8_t *out_decimals) {
|
||||
for (size_t i = 0; i < NUM_COMPOUND_BINDINGS; i++) {
|
||||
underlying_asset_decimals_t *binding =
|
||||
(underlying_asset_decimals_t *) PIC(&UNDERLYING_ASSET_DECIMALS[i]);
|
||||
if (strncmp(binding->c_ticker,
|
||||
compound_ticker,
|
||||
strnlen(binding->c_ticker, MAX_TICKER_LEN)) == 0) {
|
||||
*out_decimals = binding->decimals;
|
||||
return true;
|
||||
}
|
||||
@@ -69,21 +70,21 @@ bool get_underlying_asset_decimals(char* compound_ticker, uint8_t* out_decimals)
|
||||
}
|
||||
|
||||
void compound_plugin_call(int message, void *parameters) {
|
||||
|
||||
switch(message) {
|
||||
switch (message) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT: {
|
||||
ethPluginInitContract_t *msg = (ethPluginInitContract_t*)parameters;
|
||||
compound_parameters_t *context = (compound_parameters_t*)msg->pluginContext;
|
||||
ethPluginInitContract_t *msg = (ethPluginInitContract_t *) parameters;
|
||||
compound_parameters_t *context = (compound_parameters_t *) msg->pluginContext;
|
||||
size_t i;
|
||||
for (i=0; i<NUM_COMPOUND_SELECTORS; i++) {
|
||||
if (memcmp((uint8_t *)PIC(COMPOUND_SELECTORS[i]), msg->selector, SELECTOR_SIZE) == 0) {
|
||||
for (i = 0; i < NUM_COMPOUND_SELECTORS; i++) {
|
||||
if (memcmp((uint8_t *) PIC(COMPOUND_SELECTORS[i]), msg->selector, SELECTOR_SIZE) ==
|
||||
0) {
|
||||
context->selectorIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// enforce that ETH amount should be 0, except in ceth.mint case
|
||||
if (!allzeroes(msg->pluginSharedRO->txContent->value.value, 32)){
|
||||
if(context->selectorIndex != CETH_MINT){
|
||||
if (!allzeroes(msg->pluginSharedRO->txContent->value.value, 32)) {
|
||||
if (context->selectorIndex != CETH_MINT) {
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
@@ -94,27 +95,35 @@ void compound_plugin_call(int message, void *parameters) {
|
||||
break;
|
||||
}
|
||||
if (msg->dataSize != COMPOUND_EXPECTED_DATA_SIZE[context->selectorIndex]) {
|
||||
PRINTF("Unexpected data size for command %d expected %d got %d\n", context->selectorIndex,
|
||||
COMPOUND_EXPECTED_DATA_SIZE[context->selectorIndex], msg->dataSize);
|
||||
PRINTF("Unexpected data size for command %d expected %d got %d\n",
|
||||
context->selectorIndex,
|
||||
COMPOUND_EXPECTED_DATA_SIZE[context->selectorIndex],
|
||||
msg->dataSize);
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
if(context->selectorIndex == CETH_MINT){
|
||||
// ETH amount 0x1234 is stored 0x12340000...000 instead of 0x00....001234, so we strip the following zeroes when copying
|
||||
if (context->selectorIndex == CETH_MINT) {
|
||||
// ETH amount 0x1234 is stored 0x12340000...000 instead of 0x00....001234, so we
|
||||
// strip the following zeroes when copying
|
||||
memset(context->amount, 0, sizeof(context->amount));
|
||||
memmove(context->amount + sizeof(context->amount) - msg->pluginSharedRO->txContent->value.length, msg->pluginSharedRO->txContent->value.value, msg->pluginSharedRO->txContent->value.length);
|
||||
memmove(context->amount + sizeof(context->amount) -
|
||||
msg->pluginSharedRO->txContent->value.length,
|
||||
msg->pluginSharedRO->txContent->value.value,
|
||||
msg->pluginSharedRO->txContent->value.length);
|
||||
}
|
||||
PRINTF("compound plugin inititialized\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER : {
|
||||
ethPluginProvideParameter_t *msg = (ethPluginProvideParameter_t*)parameters;
|
||||
compound_parameters_t *context = (compound_parameters_t*)msg->pluginContext;
|
||||
PRINTF("compound plugin provide parameter %d %.*H\n", msg->parameterOffset, 32, msg->parameter);
|
||||
if (context->selectorIndex != CETH_MINT){
|
||||
switch(msg->parameterOffset) {
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER: {
|
||||
ethPluginProvideParameter_t *msg = (ethPluginProvideParameter_t *) parameters;
|
||||
compound_parameters_t *context = (compound_parameters_t *) msg->pluginContext;
|
||||
PRINTF("compound plugin provide parameter %d %.*H\n",
|
||||
msg->parameterOffset,
|
||||
32,
|
||||
msg->parameter);
|
||||
if (context->selectorIndex != CETH_MINT) {
|
||||
switch (msg->parameterOffset) {
|
||||
case 4:
|
||||
memmove(context->amount, msg->parameter, 32);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
@@ -124,36 +133,35 @@ void compound_plugin_call(int message, void *parameters) {
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
PRINTF("CETH contract expects no parameters\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_FINALIZE: {
|
||||
ethPluginFinalize_t *msg = (ethPluginFinalize_t*)parameters;
|
||||
ethPluginFinalize_t *msg = (ethPluginFinalize_t *) parameters;
|
||||
PRINTF("compound plugin finalize\n");
|
||||
msg->tokenLookup1 = msg->pluginSharedRO->txContent->destination;
|
||||
msg->numScreens = 2;
|
||||
msg->uiType = ETH_UI_TYPE_GENERIC;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_PROVIDE_TOKEN: {
|
||||
ethPluginProvideToken_t *msg = (ethPluginProvideToken_t*)parameters;
|
||||
compound_parameters_t *context = (compound_parameters_t*)msg->pluginContext;
|
||||
ethPluginProvideToken_t *msg = (ethPluginProvideToken_t *) parameters;
|
||||
compound_parameters_t *context = (compound_parameters_t *) msg->pluginContext;
|
||||
PRINTF("compound plugin provide token: %d\n", (msg->token1 != NULL));
|
||||
if (msg->token1 != NULL) {
|
||||
strcpy((char *)context->ticker_1, (char *)msg->token1->ticker);
|
||||
switch (context->selectorIndex)
|
||||
{
|
||||
strcpy((char *) context->ticker_1, (char *) msg->token1->ticker);
|
||||
switch (context->selectorIndex) {
|
||||
case COMPOUND_REDEEM_UNDERLYING:
|
||||
case COMPOUND_MINT:
|
||||
case CETH_MINT:
|
||||
msg->result = get_underlying_asset_decimals(context->ticker_1, &context->decimals) ? ETH_PLUGIN_RESULT_OK : ETH_PLUGIN_RESULT_FALLBACK;
|
||||
msg->result =
|
||||
get_underlying_asset_decimals(context->ticker_1, &context->decimals)
|
||||
? ETH_PLUGIN_RESULT_OK
|
||||
: ETH_PLUGIN_RESULT_FALLBACK;
|
||||
break;
|
||||
|
||||
// Only case where we use the compound contract decimals
|
||||
@@ -166,19 +174,16 @@ void compound_plugin_call(int message, void *parameters) {
|
||||
msg->result = ETH_PLUGIN_RESULT_FALLBACK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
msg->result = ETH_PLUGIN_RESULT_FALLBACK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID: {
|
||||
ethQueryContractID_t *msg = (ethQueryContractID_t*)parameters;
|
||||
compound_parameters_t *context = (compound_parameters_t*)msg->pluginContext;
|
||||
ethQueryContractID_t *msg = (ethQueryContractID_t *) parameters;
|
||||
compound_parameters_t *context = (compound_parameters_t *) msg->pluginContext;
|
||||
strcpy(msg->name, "Type");
|
||||
switch (context->selectorIndex)
|
||||
{
|
||||
switch (context->selectorIndex) {
|
||||
case COMPOUND_REDEEM_UNDERLYING:
|
||||
case COMPOUND_REDEEM:
|
||||
strcpy(msg->version, "Redeem");
|
||||
@@ -194,37 +199,41 @@ void compound_plugin_call(int message, void *parameters) {
|
||||
}
|
||||
strcat(msg->version, " Assets");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI: {
|
||||
ethQueryContractUI_t *msg = (ethQueryContractUI_t*)parameters;
|
||||
compound_parameters_t *context = (compound_parameters_t*)msg->pluginContext;
|
||||
switch(msg->screenIndex) {
|
||||
ethQueryContractUI_t *msg = (ethQueryContractUI_t *) parameters;
|
||||
compound_parameters_t *context = (compound_parameters_t *) msg->pluginContext;
|
||||
switch (msg->screenIndex) {
|
||||
case 0: {
|
||||
strcpy(msg->title, "Amount");
|
||||
char * ticker_ptr = (char *)context->ticker_1;
|
||||
char *ticker_ptr = (char *) context->ticker_1;
|
||||
/* skip "c" in front of cToken unless we use "redeem", as
|
||||
redeem is the only operation dealing with a cToken amount */
|
||||
if(context->selectorIndex != COMPOUND_REDEEM){
|
||||
if (context->selectorIndex != COMPOUND_REDEEM) {
|
||||
ticker_ptr++;
|
||||
}
|
||||
amountToString(context->amount, sizeof(context->amount), context->decimals, ticker_ptr, msg->msg, 100);
|
||||
amountToString(context->amount,
|
||||
sizeof(context->amount),
|
||||
context->decimals,
|
||||
ticker_ptr,
|
||||
msg->msg,
|
||||
100);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case 1:
|
||||
strcpy(msg->title, "Contract");
|
||||
strcpy(msg->msg, "Compound ");
|
||||
strcat(msg->msg, (char *)context->ticker_1 + 1); // remove the 'c' char at beginning of compound ticker
|
||||
strcat(msg->msg,
|
||||
(char *) context->ticker_1 +
|
||||
1); // remove the 'c' char at beginning of compound ticker
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
default:
|
||||
PRINTF("Unhandled message %d\n", message);
|
||||
|
||||
@@ -5,221 +5,223 @@
|
||||
#include "ethUtils.h"
|
||||
#include "utils.h"
|
||||
|
||||
typedef enum {
|
||||
ERC20_TRANSFER = 0,
|
||||
ERC20_APPROVE
|
||||
} erc20Selector_t;
|
||||
typedef enum { ERC20_TRANSFER = 0, ERC20_APPROVE } erc20Selector_t;
|
||||
|
||||
typedef enum {
|
||||
TARGET_ADDRESS = 0,
|
||||
TARGET_CONTRACT,
|
||||
TARGET_COMPOUND
|
||||
} targetType_t;
|
||||
typedef enum { TARGET_ADDRESS = 0, TARGET_CONTRACT, TARGET_COMPOUND } targetType_t;
|
||||
|
||||
typedef struct erc20_parameters_t {
|
||||
uint8_t selectorIndex;
|
||||
uint8_t destinationAddress[21];
|
||||
uint8_t amount[32];
|
||||
uint8_t ticker_1[MAX_TICKER_LEN];
|
||||
uint8_t ticker_2[MAX_TICKER_LEN];
|
||||
uint8_t decimals;
|
||||
uint8_t target;
|
||||
uint8_t selectorIndex;
|
||||
uint8_t destinationAddress[21];
|
||||
uint8_t amount[32];
|
||||
uint8_t ticker_1[MAX_TICKER_LEN];
|
||||
uint8_t ticker_2[MAX_TICKER_LEN];
|
||||
uint8_t decimals;
|
||||
uint8_t target;
|
||||
} erc20_parameters_t;
|
||||
|
||||
typedef struct ticker_binding_t {
|
||||
char ticker1[MAX_TICKER_LEN];
|
||||
char ticker2[MAX_TICKER_LEN];
|
||||
char ticker1[MAX_TICKER_LEN];
|
||||
char ticker2[MAX_TICKER_LEN];
|
||||
} ticker_binding_t;
|
||||
|
||||
#define NUM_COMPOUND_BINDINGS 9
|
||||
const ticker_binding_t const COMPOUND_BINDINGS[NUM_COMPOUND_BINDINGS] = {
|
||||
{"DAI", "CDAI"},
|
||||
{"WETH", "CETH"},
|
||||
{"USDC", "CUSDC"},
|
||||
{"ZRX", "CZRX"},
|
||||
{"USDT", "CUSDT"},
|
||||
{"WBTC", "CBTC"},
|
||||
{"BAT", "CBAT"},
|
||||
{"REPv2", "CREP"},
|
||||
{"SAI", "CSAI"},
|
||||
{"DAI", "CDAI"},
|
||||
{"WETH", "CETH"},
|
||||
{"USDC", "CUSDC"},
|
||||
{"ZRX", "CZRX"},
|
||||
{"USDT", "CUSDT"},
|
||||
{"WBTC", "CBTC"},
|
||||
{"BAT", "CBAT"},
|
||||
{"REPv2", "CREP"},
|
||||
{"SAI", "CSAI"},
|
||||
};
|
||||
|
||||
bool check_token_binding(char* ticker1, char* ticker2, const ticker_binding_t* bindings, size_t num_bindings){
|
||||
for(size_t i = 0; i < num_bindings; i++){
|
||||
ticker_binding_t* binding = (ticker_binding_t *)PIC(&bindings[i]);
|
||||
if (strncmp(binding->ticker1, ticker1, strnlen(binding->ticker1, MAX_TICKER_LEN)) == 0 &&
|
||||
strncmp(binding->ticker2, ticker2, strnlen(binding->ticker2, MAX_TICKER_LEN)) == 0){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
bool check_token_binding(char *ticker1,
|
||||
char *ticker2,
|
||||
const ticker_binding_t *bindings,
|
||||
size_t num_bindings) {
|
||||
for (size_t i = 0; i < num_bindings; i++) {
|
||||
ticker_binding_t *binding = (ticker_binding_t *) PIC(&bindings[i]);
|
||||
if (strncmp(binding->ticker1, ticker1, strnlen(binding->ticker1, MAX_TICKER_LEN)) == 0 &&
|
||||
strncmp(binding->ticker2, ticker2, strnlen(binding->ticker2, MAX_TICKER_LEN)) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool erc20_plugin_available_check() {
|
||||
#ifdef HAVE_STARKWARE
|
||||
if (quantumSet) {
|
||||
switch(dataContext.tokenContext.quantumType) {
|
||||
case STARK_QUANTUM_LEGACY:
|
||||
case STARK_QUANTUM_ETH:
|
||||
case STARK_QUANTUM_ERC20:
|
||||
case STARK_QUANTUM_MINTABLE_ERC20:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (quantumSet) {
|
||||
switch (dataContext.tokenContext.quantumType) {
|
||||
case STARK_QUANTUM_LEGACY:
|
||||
case STARK_QUANTUM_ETH:
|
||||
case STARK_QUANTUM_ERC20:
|
||||
case STARK_QUANTUM_MINTABLE_ERC20:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void erc20_plugin_call(int message, void *parameters) {
|
||||
switch (message) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT: {
|
||||
ethPluginInitContract_t *msg = (ethPluginInitContract_t *) parameters;
|
||||
erc20_parameters_t *context = (erc20_parameters_t *) msg->pluginContext;
|
||||
// enforce that ETH amount should be 0
|
||||
if (!allzeroes(msg->pluginSharedRO->txContent->value.value, 32)) {
|
||||
PRINTF("Err: Transaction amount is not 0\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
} else {
|
||||
size_t i;
|
||||
for (i = 0; i < NUM_ERC20_SELECTORS; i++) {
|
||||
if (memcmp((uint8_t *) PIC(ERC20_SELECTORS[i]), msg->selector, SELECTOR_SIZE) ==
|
||||
0) {
|
||||
context->selectorIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == NUM_ERC20_SELECTORS) {
|
||||
PRINTF("Unknown selector %.*H\n", SELECTOR_SIZE, msg->selector);
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
PRINTF("erc20 plugin init\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
} break;
|
||||
|
||||
switch(message) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT: {
|
||||
ethPluginInitContract_t *msg = (ethPluginInitContract_t*)parameters;
|
||||
erc20_parameters_t *context = (erc20_parameters_t*)msg->pluginContext;
|
||||
// enforce that ETH amount should be 0
|
||||
if (!allzeroes(msg->pluginSharedRO->txContent->value.value, 32)){
|
||||
PRINTF("Err: Transaction amount is not 0\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
}
|
||||
else {
|
||||
size_t i;
|
||||
for (i=0; i<NUM_ERC20_SELECTORS; i++) {
|
||||
if (memcmp((uint8_t *)PIC(ERC20_SELECTORS[i]), msg->selector, SELECTOR_SIZE) == 0) {
|
||||
context->selectorIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == NUM_ERC20_SELECTORS) {
|
||||
PRINTF("Unknown selector %.*H\n", SELECTOR_SIZE, msg->selector);
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
PRINTF("erc20 plugin init\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER: {
|
||||
ethPluginProvideParameter_t *msg = (ethPluginProvideParameter_t *) parameters;
|
||||
erc20_parameters_t *context = (erc20_parameters_t *) msg->pluginContext;
|
||||
PRINTF("erc20 plugin provide parameter %d %.*H\n",
|
||||
msg->parameterOffset,
|
||||
32,
|
||||
msg->parameter);
|
||||
switch (msg->parameterOffset) {
|
||||
case 4:
|
||||
memmove(context->destinationAddress, msg->parameter + 12, 20);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
case 4 + 32:
|
||||
memmove(context->amount, msg->parameter, 32);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unhandled parameter offset\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER : {
|
||||
ethPluginProvideParameter_t *msg = (ethPluginProvideParameter_t*)parameters;
|
||||
erc20_parameters_t *context = (erc20_parameters_t*)msg->pluginContext;
|
||||
PRINTF("erc20 plugin provide parameter %d %.*H\n", msg->parameterOffset, 32, msg->parameter);
|
||||
switch(msg->parameterOffset) {
|
||||
case 4:
|
||||
memmove(context->destinationAddress, msg->parameter + 12, 20);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
case 4 + 32:
|
||||
memmove(context->amount, msg->parameter, 32);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unhandled parameter offset\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_FINALIZE: {
|
||||
ethPluginFinalize_t *msg = (ethPluginFinalize_t *) parameters;
|
||||
erc20_parameters_t *context = (erc20_parameters_t *) msg->pluginContext;
|
||||
PRINTF("erc20 plugin finalize\n");
|
||||
if (context->selectorIndex == ERC20_TRANSFER) {
|
||||
msg->tokenLookup1 = msg->pluginSharedRO->txContent->destination;
|
||||
msg->amount = context->amount;
|
||||
msg->address = context->destinationAddress;
|
||||
msg->uiType = ETH_UI_TYPE_AMOUNT_ADDRESS;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} else if (context->selectorIndex == ERC20_APPROVE) {
|
||||
msg->tokenLookup1 = msg->pluginSharedRO->txContent->destination;
|
||||
msg->tokenLookup2 = context->destinationAddress;
|
||||
msg->numScreens = 2;
|
||||
msg->uiType = ETH_UI_TYPE_GENERIC;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_FINALIZE: {
|
||||
ethPluginFinalize_t *msg = (ethPluginFinalize_t*)parameters;
|
||||
erc20_parameters_t *context = (erc20_parameters_t*)msg->pluginContext;
|
||||
PRINTF("erc20 plugin finalize\n");
|
||||
if (context->selectorIndex == ERC20_TRANSFER){
|
||||
msg->tokenLookup1 = msg->pluginSharedRO->txContent->destination;
|
||||
msg->amount = context->amount;
|
||||
msg->address = context->destinationAddress;
|
||||
msg->uiType = ETH_UI_TYPE_AMOUNT_ADDRESS;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
else if (context->selectorIndex == ERC20_APPROVE){
|
||||
msg->tokenLookup1 = msg->pluginSharedRO->txContent->destination;
|
||||
msg->tokenLookup2 = context->destinationAddress;
|
||||
msg->numScreens = 2;
|
||||
msg->uiType = ETH_UI_TYPE_GENERIC;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_TOKEN: {
|
||||
ethPluginProvideToken_t *msg = (ethPluginProvideToken_t *) parameters;
|
||||
erc20_parameters_t *context = (erc20_parameters_t *) msg->pluginContext;
|
||||
PRINTF("erc20 plugin provide token 1: %d - 2: %d\n",
|
||||
(msg->token1 != NULL),
|
||||
(msg->token2 != NULL));
|
||||
if (msg->token1 != NULL) {
|
||||
context->target = TARGET_ADDRESS;
|
||||
strcpy((char *) context->ticker_1, (char *) msg->token1->ticker);
|
||||
context->decimals = msg->token1->decimals;
|
||||
if (context->selectorIndex == ERC20_APPROVE) {
|
||||
if (msg->token2 != NULL) {
|
||||
context->target = TARGET_CONTRACT;
|
||||
strcpy((char *) context->ticker_2, (char *) msg->token2->ticker);
|
||||
// test if we're doing a Compound allowance
|
||||
if (check_token_binding((char *) msg->token1->ticker,
|
||||
(char *) msg->token2->ticker,
|
||||
COMPOUND_BINDINGS,
|
||||
NUM_COMPOUND_BINDINGS)) {
|
||||
context->target = TARGET_COMPOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} else {
|
||||
msg->result = ETH_PLUGIN_RESULT_FALLBACK;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_PROVIDE_TOKEN: {
|
||||
ethPluginProvideToken_t *msg = (ethPluginProvideToken_t*)parameters;
|
||||
erc20_parameters_t *context = (erc20_parameters_t*)msg->pluginContext;
|
||||
PRINTF("erc20 plugin provide token 1: %d - 2: %d\n", (msg->token1 != NULL), (msg->token2 != NULL));
|
||||
if (msg->token1 != NULL) {
|
||||
context->target = TARGET_ADDRESS;
|
||||
strcpy((char *)context->ticker_1, (char *)msg->token1->ticker);
|
||||
context->decimals = msg->token1->decimals;
|
||||
if (context->selectorIndex == ERC20_APPROVE){
|
||||
if(msg->token2 != NULL){
|
||||
context->target = TARGET_CONTRACT;
|
||||
strcpy((char *)context->ticker_2, (char *)msg->token2->ticker);
|
||||
// test if we're doing a Compound allowance
|
||||
if (check_token_binding((char *)msg->token1->ticker, (char *)msg->token2->ticker, COMPOUND_BINDINGS, NUM_COMPOUND_BINDINGS)){
|
||||
context->target = TARGET_COMPOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
else {
|
||||
msg->result = ETH_PLUGIN_RESULT_FALLBACK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID: {
|
||||
ethQueryContractID_t *msg = (ethQueryContractID_t *) parameters;
|
||||
strcpy(msg->name, "Type");
|
||||
strcpy(msg->version, "Approve");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID: {
|
||||
ethQueryContractID_t *msg = (ethQueryContractID_t*)parameters;
|
||||
strcpy(msg->name, "Type");
|
||||
strcpy(msg->version, "Approve");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI: {
|
||||
ethQueryContractUI_t *msg = (ethQueryContractUI_t *) parameters;
|
||||
erc20_parameters_t *context = (erc20_parameters_t *) msg->pluginContext;
|
||||
switch (msg->screenIndex) {
|
||||
case 0:
|
||||
strcpy(msg->title, "Amount");
|
||||
if (ismaxint(context->amount, sizeof(context->amount))) {
|
||||
strcpy(msg->msg, "Unlimited ");
|
||||
strcat(msg->msg, (char *) context->ticker_1);
|
||||
} else {
|
||||
amountToString(context->amount,
|
||||
sizeof(context->amount),
|
||||
context->decimals,
|
||||
(char *) context->ticker_1,
|
||||
msg->msg,
|
||||
100);
|
||||
}
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
case 1:
|
||||
if (context->target >= TARGET_CONTRACT) {
|
||||
strcpy(msg->title, "Contract");
|
||||
if (context->target == TARGET_COMPOUND) {
|
||||
strcpy(msg->msg, "Compound ");
|
||||
strcat(msg->msg,
|
||||
(char *) context->ticker_2 +
|
||||
1); // remove the 'c' char at beginning of compound ticker
|
||||
} else {
|
||||
strcpy(msg->msg, (char *) context->ticker_2);
|
||||
}
|
||||
} else {
|
||||
strcpy(msg->title, "Address");
|
||||
msg->msg[0] = '0';
|
||||
msg->msg[1] = 'x';
|
||||
getEthAddressStringFromBinary(context->destinationAddress,
|
||||
(uint8_t *) msg->msg + 2,
|
||||
msg->pluginSharedRW->sha3,
|
||||
chainConfig);
|
||||
}
|
||||
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI: {
|
||||
ethQueryContractUI_t *msg = (ethQueryContractUI_t*)parameters;
|
||||
erc20_parameters_t *context = (erc20_parameters_t*)msg->pluginContext;
|
||||
switch(msg->screenIndex) {
|
||||
case 0:
|
||||
strcpy(msg->title, "Amount");
|
||||
if(ismaxint(context->amount, sizeof(context->amount))){
|
||||
strcpy(msg->msg, "Unlimited ");
|
||||
strcat(msg->msg, (char *)context->ticker_1);
|
||||
}
|
||||
else{
|
||||
amountToString(context->amount, sizeof(context->amount), context->decimals, (char *)context->ticker_1, msg->msg, 100);
|
||||
}
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
case 1:
|
||||
if(context->target >= TARGET_CONTRACT){
|
||||
strcpy(msg->title, "Contract");
|
||||
if (context->target == TARGET_COMPOUND){
|
||||
strcpy(msg->msg, "Compound ");
|
||||
strcat(msg->msg, (char *)context->ticker_2 + 1); // remove the 'c' char at beginning of compound ticker
|
||||
}
|
||||
else {
|
||||
strcpy(msg->msg, (char *)context->ticker_2);
|
||||
}
|
||||
}
|
||||
else{
|
||||
strcpy(msg->title, "Address");
|
||||
msg->msg[0] = '0';
|
||||
msg->msg[1] = 'x';
|
||||
getEthAddressStringFromBinary(context->destinationAddress, (uint8_t *)msg->msg + 2, msg->pluginSharedRW->sha3, chainConfig);
|
||||
}
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINTF("Unhandled message %d\n", message);
|
||||
}
|
||||
default:
|
||||
PRINTF("Unhandled message %d\n", message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,140 +9,139 @@ void starkware_print_stark_key(uint8_t *starkKey, char *destination);
|
||||
void starkware_print_eth_address(uint8_t *address, char *destination);
|
||||
|
||||
typedef struct erc721_parameters_t {
|
||||
uint8_t selectorIndex;
|
||||
uint8_t address[20];
|
||||
uint8_t tokenId[32];
|
||||
//tokenDefinition_t *tokenSelf;
|
||||
//tokenDefinition_t *tokenAddress;
|
||||
uint8_t selectorIndex;
|
||||
uint8_t address[20];
|
||||
uint8_t tokenId[32];
|
||||
// tokenDefinition_t *tokenSelf;
|
||||
// tokenDefinition_t *tokenAddress;
|
||||
} erc721_parameters_t;
|
||||
|
||||
bool erc721_plugin_available_check() {
|
||||
#ifdef HAVE_STARKWARE
|
||||
if (quantumSet) {
|
||||
switch(dataContext.tokenContext.quantumType) {
|
||||
case STARK_QUANTUM_ERC721:
|
||||
case STARK_QUANTUM_MINTABLE_ERC721:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (quantumSet) {
|
||||
switch (dataContext.tokenContext.quantumType) {
|
||||
case STARK_QUANTUM_ERC721:
|
||||
case STARK_QUANTUM_MINTABLE_ERC721:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void erc721_plugin_call(int message, void *parameters) {
|
||||
switch (message) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT: {
|
||||
ethPluginInitContract_t *msg = (ethPluginInitContract_t *) parameters;
|
||||
erc721_parameters_t *context = (erc721_parameters_t *) msg->pluginContext;
|
||||
// enforce that ETH amount should be 0
|
||||
if (!allzeroes(msg->pluginSharedRO->txContent->value.value, 32)) {
|
||||
PRINTF("Err: Transaction amount is not 0 for erc721 approval\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
} else {
|
||||
size_t i;
|
||||
for (i = 0; i < NUM_ERC721_SELECTORS; i++) {
|
||||
if (memcmp((uint8_t *) PIC(ERC721_SELECTORS[i]),
|
||||
msg->selector,
|
||||
SELECTOR_SIZE) == 0) {
|
||||
context->selectorIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == NUM_ERC721_SELECTORS) {
|
||||
PRINTF("Unknown erc721 selector %.*H\n", SELECTOR_SIZE, msg->selector);
|
||||
break;
|
||||
}
|
||||
if (msg->dataSize != 4 + 32 + 32) {
|
||||
PRINTF("Invalid erc721 approval data size %d\n", msg->dataSize);
|
||||
break;
|
||||
}
|
||||
PRINTF("erc721 plugin init\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
} break;
|
||||
|
||||
switch(message) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT: {
|
||||
ethPluginInitContract_t *msg = (ethPluginInitContract_t*)parameters;
|
||||
erc721_parameters_t *context = (erc721_parameters_t*)msg->pluginContext;
|
||||
// enforce that ETH amount should be 0
|
||||
if (!allzeroes(msg->pluginSharedRO->txContent->value.value, 32)){
|
||||
PRINTF("Err: Transaction amount is not 0 for erc721 approval\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_ERROR;
|
||||
}
|
||||
else {
|
||||
size_t i;
|
||||
for (i=0; i<NUM_ERC721_SELECTORS; i++) {
|
||||
if (memcmp((uint8_t *)PIC(ERC721_SELECTORS[i]), msg->selector, SELECTOR_SIZE) == 0) {
|
||||
context->selectorIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == NUM_ERC721_SELECTORS) {
|
||||
PRINTF("Unknown erc721 selector %.*H\n", SELECTOR_SIZE, msg->selector);
|
||||
break;
|
||||
}
|
||||
if (msg->dataSize != 4 + 32 + 32) {
|
||||
PRINTF("Invalid erc721 approval data size %d\n", msg->dataSize);
|
||||
break;
|
||||
}
|
||||
PRINTF("erc721 plugin init\n");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER: {
|
||||
ethPluginProvideParameter_t *msg = (ethPluginProvideParameter_t *) parameters;
|
||||
erc721_parameters_t *context = (erc721_parameters_t *) msg->pluginContext;
|
||||
PRINTF("erc721 plugin provide parameter %d %.*H\n",
|
||||
msg->parameterOffset,
|
||||
32,
|
||||
msg->parameter);
|
||||
switch (msg->parameterOffset) {
|
||||
case 4:
|
||||
memmove(context->address, msg->parameter + 32 - 20, 20);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
case 4 + 32:
|
||||
memmove(context->tokenId, msg->parameter, 32);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unhandled parameter offset\n");
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER : {
|
||||
ethPluginProvideParameter_t *msg = (ethPluginProvideParameter_t*)parameters;
|
||||
erc721_parameters_t *context = (erc721_parameters_t*)msg->pluginContext;
|
||||
PRINTF("erc721 plugin provide parameter %d %.*H\n", msg->parameterOffset, 32, msg->parameter);
|
||||
switch(msg->parameterOffset) {
|
||||
case 4:
|
||||
memmove(context->address, msg->parameter + 32 - 20, 20);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
case 4 + 32:
|
||||
memmove(context->tokenId, msg->parameter, 32);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unhandled parameter offset\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_FINALIZE: {
|
||||
ethPluginFinalize_t *msg = (ethPluginFinalize_t *) parameters;
|
||||
erc721_parameters_t *context = (erc721_parameters_t *) msg->pluginContext;
|
||||
PRINTF("erc721 plugin finalize\n");
|
||||
msg->tokenLookup1 = msg->pluginSharedRO->txContent->destination;
|
||||
msg->tokenLookup2 = context->address;
|
||||
msg->numScreens = 3;
|
||||
msg->uiType = ETH_UI_TYPE_GENERIC;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_FINALIZE: {
|
||||
ethPluginFinalize_t *msg = (ethPluginFinalize_t*)parameters;
|
||||
erc721_parameters_t *context = (erc721_parameters_t*)msg->pluginContext;
|
||||
PRINTF("erc721 plugin finalize\n");
|
||||
msg->tokenLookup1 = msg->pluginSharedRO->txContent->destination;
|
||||
msg->tokenLookup2 = context->address;
|
||||
msg->numScreens = 3;
|
||||
msg->uiType = ETH_UI_TYPE_GENERIC;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_TOKEN: {
|
||||
ethPluginProvideToken_t *msg = (ethPluginProvideToken_t *) parameters;
|
||||
erc721_parameters_t *context = (erc721_parameters_t *) msg->pluginContext;
|
||||
PRINTF("erc721 plugin provide token dest: %d - address: %d\n",
|
||||
(msg->token1 != NULL),
|
||||
(msg->token2 != NULL));
|
||||
// context->tokenSelf = msg->token1;
|
||||
// context->tokenAddress = msg->token2;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_PROVIDE_TOKEN: {
|
||||
ethPluginProvideToken_t *msg = (ethPluginProvideToken_t*)parameters;
|
||||
erc721_parameters_t *context = (erc721_parameters_t*)msg->pluginContext;
|
||||
PRINTF("erc721 plugin provide token dest: %d - address: %d\n", (msg->token1 != NULL), (msg->token2 != NULL));
|
||||
//context->tokenSelf = msg->token1;
|
||||
//context->tokenAddress = msg->token2;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID: {
|
||||
ethQueryContractID_t *msg = (ethQueryContractID_t *) parameters;
|
||||
strcpy(msg->name, "Allowance");
|
||||
strcpy(msg->version, "");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID: {
|
||||
ethQueryContractID_t *msg = (ethQueryContractID_t*)parameters;
|
||||
strcpy(msg->name, "Allowance");
|
||||
strcpy(msg->version, "");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI: {
|
||||
ethQueryContractUI_t *msg = (ethQueryContractUI_t *) parameters;
|
||||
erc721_parameters_t *context = (erc721_parameters_t *) msg->pluginContext;
|
||||
switch (msg->screenIndex) {
|
||||
case 0:
|
||||
strcpy(msg->title, "Contract Name");
|
||||
starkware_print_eth_address(tmpContent.txContent.destination, msg->msg);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI: {
|
||||
ethQueryContractUI_t *msg = (ethQueryContractUI_t*)parameters;
|
||||
erc721_parameters_t *context = (erc721_parameters_t*)msg->pluginContext;
|
||||
switch(msg->screenIndex) {
|
||||
case 0:
|
||||
strcpy(msg->title, "Contract Name");
|
||||
starkware_print_eth_address(tmpContent.txContent.destination, msg->msg);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
case 1:
|
||||
strcpy(msg->title, "NFT Contract");
|
||||
starkware_print_eth_address(context->address, msg->msg);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
strcpy(msg->title, "NFT Contract");
|
||||
starkware_print_eth_address(context->address, msg->msg);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
case 2:
|
||||
strcpy(msg->title, "TokenID");
|
||||
starkware_print_stark_key(context->tokenId, msg->msg);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
strcpy(msg->title, "TokenID");
|
||||
starkware_print_stark_key(context->tokenId, msg->msg);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINTF("Unhandled message %d\n", message);
|
||||
}
|
||||
default:
|
||||
PRINTF("Unhandled message %d\n", message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,155 +13,156 @@ void getEth2PublicKey(uint32_t *bip32Path, uint8_t bip32PathLength, uint8_t *out
|
||||
#define WITHDRAWAL_KEY_PATH_2 3600
|
||||
#define WITHDRAWAL_KEY_PATH_4 0
|
||||
|
||||
#define ETH2_DEPOSIT_PUBKEY_OFFSET 0x80
|
||||
#define ETH2_DEPOSIT_PUBKEY_OFFSET 0x80
|
||||
#define ETH2_WITHDRAWAL_CREDENTIALS_OFFSET 0xE0
|
||||
#define ETH2_SIGNATURE_OFFSET 0x120
|
||||
#define ETH2_DEPOSIT_PUBKEY_LENGTH 0x30
|
||||
#define ETH2_SIGNATURE_OFFSET 0x120
|
||||
#define ETH2_DEPOSIT_PUBKEY_LENGTH 0x30
|
||||
#define ETH2_WITHDRAWAL_CREDENTIALS_LENGTH 0x20
|
||||
#define ETH2_SIGNATURE_LENGTH 0x60
|
||||
#define ETH2_SIGNATURE_LENGTH 0x60
|
||||
|
||||
typedef struct eth2_deposit_parameters_t {
|
||||
uint8_t valid;
|
||||
uint8_t valid;
|
||||
} eth2_deposit_parameters_t;
|
||||
|
||||
void eth2_plugin_call(int message, void *parameters) {
|
||||
switch (message) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT: {
|
||||
ethPluginInitContract_t *msg = (ethPluginInitContract_t *) parameters;
|
||||
eth2_deposit_parameters_t *context = (eth2_deposit_parameters_t *) msg->pluginContext;
|
||||
context->valid = 1;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} break;
|
||||
|
||||
switch(message) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT: {
|
||||
ethPluginInitContract_t *msg = (ethPluginInitContract_t*)parameters;
|
||||
eth2_deposit_parameters_t *context = (eth2_deposit_parameters_t*)msg->pluginContext;
|
||||
context->valid = 1;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER: {
|
||||
ethPluginProvideParameter_t *msg = (ethPluginProvideParameter_t *) parameters;
|
||||
eth2_deposit_parameters_t *context = (eth2_deposit_parameters_t *) msg->pluginContext;
|
||||
uint32_t index;
|
||||
PRINTF("eth2 plugin provide parameter %d %.*H\n",
|
||||
msg->parameterOffset,
|
||||
32,
|
||||
msg->parameter);
|
||||
switch (msg->parameterOffset) {
|
||||
case 4 + (32 * 0): // pubkey offset
|
||||
case 4 + (32 * 1): // withdrawal credentials offset
|
||||
case 4 + (32 * 2): // signature offset
|
||||
case 4 + (32 * 4): // deposit pubkey length
|
||||
case 4 + (32 * 7): // withdrawal credentials length
|
||||
case 4 + (32 * 9): // signature length
|
||||
{
|
||||
uint32_t check = 0;
|
||||
switch (msg->parameterOffset) {
|
||||
case 4 + (32 * 0):
|
||||
check = ETH2_DEPOSIT_PUBKEY_OFFSET;
|
||||
break;
|
||||
case 4 + (32 * 1):
|
||||
check = ETH2_WITHDRAWAL_CREDENTIALS_OFFSET;
|
||||
break;
|
||||
case 4 + (32 * 2):
|
||||
check = ETH2_SIGNATURE_OFFSET;
|
||||
break;
|
||||
case 4 + (32 * 4):
|
||||
check = ETH2_DEPOSIT_PUBKEY_LENGTH;
|
||||
break;
|
||||
case 4 + (32 * 7):
|
||||
check = ETH2_WITHDRAWAL_CREDENTIALS_LENGTH;
|
||||
break;
|
||||
case 4 + (32 * 9):
|
||||
check = ETH2_SIGNATURE_LENGTH;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
index = U4BE(msg->parameter, 32 - 4);
|
||||
if (index != check) {
|
||||
PRINTF("eth2 plugin parameter check %d failed, expected %d got %d\n",
|
||||
msg->parameterOffset,
|
||||
check,
|
||||
index);
|
||||
context->valid = 0;
|
||||
}
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_PROVIDE_PARAMETER : {
|
||||
ethPluginProvideParameter_t *msg = (ethPluginProvideParameter_t*)parameters;
|
||||
eth2_deposit_parameters_t *context = (eth2_deposit_parameters_t*)msg->pluginContext;
|
||||
uint32_t index;
|
||||
PRINTF("eth2 plugin provide parameter %d %.*H\n", msg->parameterOffset, 32, msg->parameter);
|
||||
switch(msg->parameterOffset) {
|
||||
case 4 + (32 * 0): // pubkey offset
|
||||
case 4 + (32 * 1): // withdrawal credentials offset
|
||||
case 4 + (32 * 2): // signature offset
|
||||
case 4 + (32 * 4): // deposit pubkey length
|
||||
case 4 + (32 * 7): // withdrawal credentials length
|
||||
case 4 + (32 * 9): // signature length
|
||||
{
|
||||
uint32_t check = 0;
|
||||
switch(msg->parameterOffset) {
|
||||
case 4 + (32 * 0):
|
||||
check = ETH2_DEPOSIT_PUBKEY_OFFSET;
|
||||
break;
|
||||
case 4 + (32 * 1):
|
||||
check = ETH2_WITHDRAWAL_CREDENTIALS_OFFSET;
|
||||
break;
|
||||
case 4 + (32 * 2):
|
||||
check = ETH2_SIGNATURE_OFFSET;
|
||||
break;
|
||||
case 4 + (32 * 4):
|
||||
check = ETH2_DEPOSIT_PUBKEY_LENGTH;
|
||||
break;
|
||||
case 4 + (32 * 7):
|
||||
check = ETH2_WITHDRAWAL_CREDENTIALS_LENGTH;
|
||||
break;
|
||||
case 4 + (32 * 9):
|
||||
check = ETH2_SIGNATURE_LENGTH;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
index = U4BE(msg->parameter, 32 - 4);
|
||||
if (index != check) {
|
||||
PRINTF("eth2 plugin parameter check %d failed, expected %d got %d\n", msg->parameterOffset, check, index);
|
||||
context->valid = 0;
|
||||
}
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
case 4 + (32 * 3): // deposit data root
|
||||
case 4 + (32 * 5): // deposit pubkey
|
||||
case 4 + (32 * 6):
|
||||
case 4 + (32 * 10): // signature
|
||||
case 4 + (32 * 11):
|
||||
case 4 + (32 * 12):
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
|
||||
case 4 + (32 * 3): // deposit data root
|
||||
case 4 + (32 * 5): // deposit pubkey
|
||||
case 4 + (32 * 6):
|
||||
case 4 + (32 * 10): // signature
|
||||
case 4 + (32 * 11):
|
||||
case 4 + (32 * 12):
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
case 4 + (32 * 8): // withdrawal credentials
|
||||
{
|
||||
uint8_t tmp[48];
|
||||
uint32_t withdrawalKeyPath[4];
|
||||
withdrawalKeyPath[0] = WITHDRAWAL_KEY_PATH_1;
|
||||
withdrawalKeyPath[1] = WITHDRAWAL_KEY_PATH_2;
|
||||
withdrawalKeyPath[2] = eth2WithdrawalIndex;
|
||||
withdrawalKeyPath[3] = WITHDRAWAL_KEY_PATH_4;
|
||||
getEth2PublicKey(withdrawalKeyPath, 4, tmp);
|
||||
PRINTF("eth2 plugin computed withdrawal public key %.*H\n", 48, tmp);
|
||||
cx_hash_sha256(tmp, 48, tmp, 32);
|
||||
tmp[0] = 0;
|
||||
if (memcmp(tmp, msg->parameter, 32) != 0) {
|
||||
PRINTF("eth2 plugin invalid withdrawal credentials\n");
|
||||
PRINTF("Got %.*H\n", 32, msg->parameter);
|
||||
PRINTF("Expected %.*H\n", 32, tmp);
|
||||
context->valid = 0;
|
||||
}
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} break;
|
||||
|
||||
case 4 + (32 * 8): // withdrawal credentials
|
||||
{
|
||||
uint8_t tmp[48];
|
||||
uint32_t withdrawalKeyPath[4];
|
||||
withdrawalKeyPath[0] = WITHDRAWAL_KEY_PATH_1;
|
||||
withdrawalKeyPath[1] = WITHDRAWAL_KEY_PATH_2;
|
||||
withdrawalKeyPath[2] = eth2WithdrawalIndex;
|
||||
withdrawalKeyPath[3] = WITHDRAWAL_KEY_PATH_4;
|
||||
getEth2PublicKey(withdrawalKeyPath, 4, tmp);
|
||||
PRINTF("eth2 plugin computed withdrawal public key %.*H\n", 48, tmp);
|
||||
cx_hash_sha256(tmp, 48, tmp, 32);
|
||||
tmp[0] = 0;
|
||||
if (memcmp(tmp, msg->parameter, 32) != 0) {
|
||||
PRINTF("eth2 plugin invalid withdrawal credentials\n");
|
||||
PRINTF("Got %.*H\n", 32, msg->parameter);
|
||||
PRINTF("Expected %.*H\n", 32, tmp);
|
||||
context->valid = 0;
|
||||
}
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PRINTF("Unhandled parameter offset\n");
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
PRINTF("Unhandled parameter offset\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_FINALIZE: {
|
||||
ethPluginFinalize_t *msg = (ethPluginFinalize_t *) parameters;
|
||||
eth2_deposit_parameters_t *context = (eth2_deposit_parameters_t *) msg->pluginContext;
|
||||
PRINTF("eth2 plugin finalize\n");
|
||||
if (context->valid) {
|
||||
msg->numScreens = 1;
|
||||
msg->uiType = ETH_UI_TYPE_GENERIC;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} else {
|
||||
msg->result = ETH_PLUGIN_RESULT_FALLBACK;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_FINALIZE: {
|
||||
ethPluginFinalize_t *msg = (ethPluginFinalize_t*)parameters;
|
||||
eth2_deposit_parameters_t *context = (eth2_deposit_parameters_t*)msg->pluginContext;
|
||||
PRINTF("eth2 plugin finalize\n");
|
||||
if (context->valid) {
|
||||
msg->numScreens = 1;
|
||||
msg->uiType = ETH_UI_TYPE_GENERIC;
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
else {
|
||||
msg->result = ETH_PLUGIN_RESULT_FALLBACK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID: {
|
||||
ethQueryContractID_t *msg = (ethQueryContractID_t *) parameters;
|
||||
strcpy(msg->name, "ETH2");
|
||||
strcpy(msg->version, "Deposit");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_ID: {
|
||||
ethQueryContractID_t *msg = (ethQueryContractID_t*)parameters;
|
||||
strcpy(msg->name, "ETH2");
|
||||
strcpy(msg->version, "Deposit");
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI: {
|
||||
ethQueryContractUI_t *msg = (ethQueryContractUI_t *) parameters;
|
||||
// eth2_deposit_parameters_t *context = (eth2_deposit_parameters_t*)msg->pluginContext;
|
||||
switch (msg->screenIndex) {
|
||||
case 0: {
|
||||
uint8_t decimals = WEI_TO_ETHER;
|
||||
uint8_t *ticker = (uint8_t *) PIC(chainConfig->coinName);
|
||||
strcpy(msg->title, "Amount");
|
||||
amountToString(tmpContent.txContent.value.value,
|
||||
tmpContent.txContent.value.length,
|
||||
decimals,
|
||||
(char *) ticker,
|
||||
msg->msg,
|
||||
100);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case ETH_PLUGIN_QUERY_CONTRACT_UI: {
|
||||
ethQueryContractUI_t *msg = (ethQueryContractUI_t*)parameters;
|
||||
//eth2_deposit_parameters_t *context = (eth2_deposit_parameters_t*)msg->pluginContext;
|
||||
switch(msg->screenIndex) {
|
||||
case 0: {
|
||||
uint8_t decimals = WEI_TO_ETHER;
|
||||
uint8_t *ticker = (uint8_t *)PIC(chainConfig->coinName);
|
||||
strcpy(msg->title, "Amount");
|
||||
amountToString(tmpContent.txContent.value.value, tmpContent.txContent.value.length, decimals, (char*)ticker, msg->msg, 100);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINTF("Unhandled message %d\n", message);
|
||||
}
|
||||
default:
|
||||
PRINTF("Unhandled message %d\n", message);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user