Skip to content

Commit 1fe4085

Browse files
author
ldg-github-ci
committed
[update] Branch develop | Commit c65b20872034ac6208a6e1ed742a8d6c12d8eb4b
1 parent b9777e7 commit 1fe4085

File tree

7 files changed

+273
-28
lines changed

7 files changed

+273
-28
lines changed

CHANGELOG.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Ethereum Plugin SDK changelog
2+
3+
| Icon | Impact |
4+
|----------------------|-------------------------------|
5+
| :rotating_light: | Breaks build |
6+
| :warning: | Breaks compatibility with app |
7+
8+
## [latest](/) - 2023/10/19
9+
10+
### Changed
11+
12+
* Now only uses *\_no\_throw* functions, SDK functions now return a boolean
13+
(keeps the guidelines enforcer happy)
14+
15+
### Added
16+
17+
* *main* & *dispatch\_call* functions are now part of the SDK and don't need to
18+
be implemented by each plugin :rotating_light:
19+
20+
## [b9777e7](/../../commit/b9777e7) - 2023/05/16
21+
22+
### Added
23+
24+
* Stax support with information passed from plugin to app-ethereum (with caller app struct)
25+
26+
## [a4b971f](/../../commit/a4b971f) - 2023/01/24
27+
28+
### Changed
29+
30+
* Removed end space in tickers :warning:
31+
32+
## [81eb658](/../../commit/81eb658) - 2022/11/17
33+
34+
### Added
35+
36+
* *U2BE\_from\_parameter* & *U4BE\_from\_parameter* safe functions

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ Be careful, and weight your choices.
1313

1414
If for some reasons you want to rebuild this SDK manually from [app-ethereum](https://github.com/LedgerHQ/app-ethereum) (reminder: it is rebuild automatically when building app-ethereum itself):
1515

16-
```
17-
cd app-ethereum
18-
python3 ethereum-plugin-sdk/build_sdk.py
16+
```shell
17+
$> python3 tools/build_sdk.py
1918
```

include/eth_internals.c

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#include "eth_internals.h"
44

5-
void getEthAddressStringFromBinary(uint8_t *address,
5+
bool getEthAddressStringFromBinary(uint8_t *address,
66
char *out,
77
cx_sha3_t *sha3Context,
88
uint64_t chainId) {
@@ -22,7 +22,9 @@ void getEthAddressStringFromBinary(uint8_t *address,
2222
break;
2323
}
2424
if (eip1191) {
25-
u64_to_string(chainId, (char *) locals_union.tmp, sizeof(locals_union.tmp));
25+
if (!u64_to_string(chainId, (char *) locals_union.tmp, sizeof(locals_union.tmp))) {
26+
return false;
27+
}
2628
offset = strnlen((char *) locals_union.tmp, sizeof(locals_union.tmp));
2729
strlcat((char *) locals_union.tmp + offset, "0x", sizeof(locals_union.tmp) - offset);
2830
offset = strnlen((char *) locals_union.tmp, sizeof(locals_union.tmp));
@@ -32,13 +34,18 @@ void getEthAddressStringFromBinary(uint8_t *address,
3234
locals_union.tmp[offset + 2 * i] = HEXDIGITS[(digit >> 4) & 0x0f];
3335
locals_union.tmp[offset + 2 * i + 1] = HEXDIGITS[digit & 0x0f];
3436
}
35-
cx_keccak_init(sha3Context, 256);
36-
cx_hash((cx_hash_t *) sha3Context,
37-
CX_LAST,
38-
locals_union.tmp,
39-
offset + 40,
40-
locals_union.hashChecksum,
41-
32);
37+
if (cx_keccak_init_no_throw(sha3Context, 256) != CX_OK) {
38+
return false;
39+
}
40+
41+
if (cx_hash_no_throw((cx_hash_t *) sha3Context,
42+
CX_LAST,
43+
locals_union.tmp,
44+
offset + 40,
45+
locals_union.hashChecksum,
46+
32) != CX_OK) {
47+
return false;
48+
}
4249
for (i = 0; i < 40; i++) {
4350
uint8_t digit = address[i / 2];
4451
if ((i % 2) == 0) {
@@ -58,27 +65,47 @@ void getEthAddressStringFromBinary(uint8_t *address,
5865
}
5966
}
6067
out[40] = '\0';
68+
69+
return true;
6170
}
6271

63-
void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3_t *sha3Context) {
72+
bool getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3_t *sha3Context) {
6473
uint8_t hashAddress[INT256_LENGTH];
65-
cx_keccak_init(sha3Context, 256);
66-
cx_hash((cx_hash_t *) sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32);
74+
75+
if (cx_keccak_init_no_throw(sha3Context, 256) != CX_OK) {
76+
return false;
77+
}
78+
79+
if (cx_hash_no_throw((cx_hash_t *) sha3Context,
80+
CX_LAST,
81+
publicKey->W + 1,
82+
64,
83+
hashAddress,
84+
32) != CX_OK) {
85+
return false;
86+
}
87+
6788
memmove(out, hashAddress + 12, 20);
89+
return true;
6890
}
6991

70-
void getEthDisplayableAddress(uint8_t *in,
92+
bool getEthDisplayableAddress(uint8_t *in,
7193
char *out,
7294
size_t out_len,
7395
cx_sha3_t *sha3,
7496
uint64_t chainId) {
7597
if (out_len < 43) {
7698
strlcpy(out, "ERROR", out_len);
77-
return;
99+
return false;
78100
}
79101
out[0] = '0';
80102
out[1] = 'x';
81-
getEthAddressStringFromBinary(in, out + 2, sha3, chainId);
103+
if (!getEthAddressStringFromBinary(in, out + 2, sha3, chainId)) {
104+
strlcpy(out, "ERROR", out_len);
105+
return false;
106+
}
107+
108+
return true;
82109
}
83110

84111
bool adjustDecimals(const char *src,
@@ -191,7 +218,7 @@ bool uint256_to_decimal(const uint8_t *value, size_t value_len, char *out, size_
191218
return true;
192219
}
193220

194-
void amountToString(const uint8_t *amount,
221+
bool amountToString(const uint8_t *amount,
195222
uint8_t amount_size,
196223
uint8_t decimals,
197224
const char *ticker,
@@ -200,7 +227,7 @@ void amountToString(const uint8_t *amount,
200227
char tmp_buffer[100] = {0};
201228

202229
if (uint256_to_decimal(amount, amount_size, tmp_buffer, sizeof(tmp_buffer)) == false) {
203-
THROW(EXCEPTION_OVERFLOW);
230+
return false;
204231
}
205232

206233
uint8_t amount_len = strnlen(tmp_buffer, sizeof(tmp_buffer));
@@ -216,19 +243,20 @@ void amountToString(const uint8_t *amount,
216243
out_buffer + ticker_len,
217244
out_buffer_size - ticker_len - 1,
218245
decimals) == false) {
219-
THROW(EXCEPTION_OVERFLOW);
246+
return false;
220247
}
221248

222249
out_buffer[out_buffer_size - 1] = '\0';
250+
return true;
223251
}
224252

225-
void u64_to_string(uint64_t src, char *dst, uint8_t dst_size) {
253+
bool u64_to_string(uint64_t src, char *dst, uint8_t dst_size) {
226254
// Copy the numbers in ASCII format.
227255
uint8_t i = 0;
228256
do {
229257
// Checking `i + 1` to make sure we have enough space for '\0'.
230258
if (i + 1 >= dst_size) {
231-
THROW(0x6502);
259+
return false;
232260
}
233261
dst[i] = src % 10 + '0';
234262
src /= 10;
@@ -248,6 +276,7 @@ void u64_to_string(uint64_t src, char *dst, uint8_t dst_size) {
248276
i--;
249277
j++;
250278
}
279+
return true;
251280
}
252281

253282
void copy_address(uint8_t* dst, const uint8_t* parameter, uint8_t dst_size) {

include/eth_internals.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "cx.h"
99
#ifdef HAVE_NBGL
1010
#include "nbgl_types.h"
11+
#include "glyphs.h"
1112
#endif
1213

1314
#define MAX_TICKER_LEN 11 // 10 characters + '\0'
@@ -83,14 +84,14 @@ static __attribute__((no_instrument_function)) inline int allzeroes(const void *
8384

8485
static const char HEXDIGITS[] = "0123456789abcdef";
8586

86-
void getEthAddressStringFromBinary(uint8_t *address,
87+
bool getEthAddressStringFromBinary(uint8_t *address,
8788
char *out,
8889
cx_sha3_t *sha3Context,
8990
uint64_t chainId);
9091

91-
void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3_t *sha3Context);
92+
bool getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3_t *sha3Context);
9293

93-
void getEthDisplayableAddress(uint8_t *in,
94+
bool getEthDisplayableAddress(uint8_t *in,
9495
char *out,
9596
size_t out_len,
9697
cx_sha3_t *sha3,
@@ -104,14 +105,14 @@ bool adjustDecimals(const char *src,
104105

105106
bool uint256_to_decimal(const uint8_t* value, size_t value_len, char* out, size_t out_len);
106107

107-
void amountToString(const uint8_t* amount,
108+
bool amountToString(const uint8_t* amount,
108109
uint8_t amount_len,
109110
uint8_t decimals,
110111
const char* ticker,
111112
char* out_buffer,
112113
size_t out_buffer_size);
113114

114-
void u64_to_string(uint64_t src, char *dst, uint8_t dst_size);
115+
bool u64_to_string(uint64_t src, char *dst, uint8_t dst_size);
115116

116117
void copy_address(uint8_t* dst, const uint8_t* parameter, uint8_t dst_size);
117118

include/main.c

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*****************************************************************************
2+
* Ledger Plugin SDK
3+
* (c) 2023 Ledger SAS
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*****************************************************************************/
17+
18+
#include "eth_internals.h"
19+
#include "eth_plugin_interface.h"
20+
21+
// Functions implemented by the plugin
22+
void handle_init_contract(ethPluginInitContract_t *parameters);
23+
void handle_provide_parameter(ethPluginProvideParameter_t *parameters);
24+
void handle_finalize(ethPluginFinalize_t *parameters);
25+
void handle_provide_token(ethPluginProvideInfo_t *parameters);
26+
void handle_query_contract_id(ethQueryContractID_t *parameters);
27+
void handle_query_contract_ui(ethQueryContractUI_t *parameters);
28+
29+
// Calls the ethereum app.
30+
static void call_app_ethereum() {
31+
unsigned int libcall_params[5];
32+
libcall_params[0] = (unsigned int) "Ethereum";
33+
libcall_params[1] = 0x100;
34+
libcall_params[2] = RUN_APPLICATION;
35+
libcall_params[3] = (unsigned int) NULL;
36+
#ifdef HAVE_NBGL
37+
caller_app_t capp;
38+
const char name[] = APPNAME;
39+
nbgl_icon_details_t icon_details;
40+
uint8_t bitmap[sizeof(ICONBITMAP)];
41+
42+
memcpy(&icon_details, &ICONGLYPH, sizeof(ICONGLYPH));
43+
memcpy(&bitmap, &ICONBITMAP, sizeof(bitmap));
44+
icon_details.bitmap = (const uint8_t *) bitmap;
45+
capp.name = (const char *) name;
46+
capp.icon = &icon_details;
47+
libcall_params[4] = (unsigned int) &capp;
48+
#else
49+
libcall_params[4] = (unsigned int) NULL;
50+
#endif
51+
os_lib_call((unsigned int *) &libcall_params);
52+
}
53+
54+
// Function to dispatch calls from the ethereum app.
55+
static void dispatch_call(int message, void *parameters) {
56+
switch (message) {
57+
case ETH_PLUGIN_INIT_CONTRACT:
58+
handle_init_contract(parameters);
59+
break;
60+
case ETH_PLUGIN_PROVIDE_PARAMETER:
61+
handle_provide_parameter(parameters);
62+
break;
63+
case ETH_PLUGIN_FINALIZE:
64+
handle_finalize(parameters);
65+
break;
66+
case ETH_PLUGIN_PROVIDE_INFO:
67+
handle_provide_token(parameters);
68+
break;
69+
case ETH_PLUGIN_QUERY_CONTRACT_ID:
70+
handle_query_contract_id(parameters);
71+
break;
72+
case ETH_PLUGIN_QUERY_CONTRACT_UI:
73+
handle_query_contract_ui(parameters);
74+
break;
75+
default:
76+
PRINTF("Unhandled message %d\n", message);
77+
break;
78+
}
79+
}
80+
81+
// Low-level main for plugins.
82+
__attribute__((section(".boot"))) int main(int arg0) {
83+
// Exit critical section
84+
__asm volatile("cpsie i");
85+
86+
os_boot();
87+
88+
BEGIN_TRY {
89+
TRY {
90+
// Check if plugin is called from the dashboard.
91+
if (!arg0) {
92+
// Called from dashboard, launch Ethereum app
93+
call_app_ethereum();
94+
95+
// Will not get reached.
96+
__builtin_unreachable();
97+
98+
os_sched_exit(-1);
99+
100+
} else {
101+
// Not called from dashboard: called from the ethereum app!
102+
const unsigned int *args = (unsigned int *) arg0;
103+
104+
// If `ETH_PLUGIN_CHECK_PRESENCE` is set, this means the caller is just trying to
105+
// know whether this app exists or not. We can skip `paraswap_plugin_call`.
106+
if (args[0] != ETH_PLUGIN_CHECK_PRESENCE) {
107+
dispatch_call(args[0], (void *) args[1]);
108+
}
109+
}
110+
111+
// Call `os_lib_end`, go back to the ethereum app.
112+
os_lib_end();
113+
114+
// Will not get reached.
115+
__builtin_unreachable();
116+
}
117+
CATCH_OTHER(e) {
118+
PRINTF("Exiting following exception: %d\n", e);
119+
}
120+
FINALLY {
121+
os_lib_end();
122+
}
123+
}
124+
END_TRY;
125+
}

include/utils.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*****************************************************************************
2+
* Ledger Plugin SDK
3+
* (c) 2023 Ledger SAS
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*****************************************************************************/
17+
18+
#include "utils.h"
19+
20+
bool find_selector(uint32_t selector, const uint32_t *array, size_t size, size_t *idx) {
21+
for (size_t i = 0; i < size; ++i) {
22+
if (selector == array[i]) {
23+
if (idx != NULL) *idx = i;
24+
return true;
25+
}
26+
}
27+
return false;
28+
}

0 commit comments

Comments
 (0)