Skip to content

Commit 1fbc2ac

Browse files
Merge pull request #1000 from LedgerHQ/ref/asset_handling
Asset handling refactoring
2 parents 9a58b33 + fac9b1b commit 1fbc2ac

34 files changed

Lines changed: 515 additions & 361 deletions

src/apdu_constants.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,15 @@ uint16_t handle_get_public_key(uint8_t p1,
8686
const uint8_t *dataBuffer,
8787
uint8_t dataLength,
8888
unsigned int *tx);
89-
uint16_t handle_provide_erc20_token_information(const uint8_t *workBuffer,
90-
uint8_t dataLength,
89+
uint16_t handle_provide_erc20_token_information(uint8_t p1,
90+
uint8_t p2,
91+
uint8_t lc,
92+
const uint8_t *data,
9193
unsigned int *tx);
92-
uint16_t handle_provide_nft_information(const uint8_t *dataBuffer,
93-
uint8_t dataLength,
94+
uint16_t handle_provide_nft_information(uint8_t p1,
95+
uint8_t p2,
96+
uint8_t lc,
97+
const uint8_t *data,
9498
unsigned int *tx);
9599
uint16_t handle_sign(uint8_t p1, uint8_t p2, const uint8_t *dataBuffer, uint8_t dataLength);
96100
uint16_t handle_get_app_configuration(unsigned int *tx);

src/features/generic_tx_parser/gtp_param_nft.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#include "gtp_param_nft.h"
2-
#include "manage_asset_info.h"
32
#include "utils.h"
43
#include "gtp_field_table.h"
54
#include "tlv_library.h"
65
#include "tlv_utils.h"
6+
#include "shared_context.h"
7+
#include "tx_ctx.h"
8+
#include "nft_info.h"
79

810
#define PARAM_NFT_TAGS(X) \
911
X(0x00, TAG_VERSION, handle_version, ENFORCE_UNIQUE_TAG) \
@@ -41,13 +43,16 @@ bool format_param_nft(const s_param_nft *param, const char *name) {
4143
bool ret;
4244
s_parsed_value_collection collections = {0};
4345
s_parsed_value_collection ids = {0};
44-
const nftInfo_t *asset;
46+
const s_nft_info *asset;
4547
char *buf = strings.tmp.tmp;
4648
size_t buf_size = sizeof(strings.tmp.tmp);
4749
uint8_t collection_idx;
4850
uint8_t addr_buf[ADDRESS_LENGTH];
4951
char tmp[80];
52+
uint64_t chain_id;
5053

54+
if (get_current_tx_info() == NULL) return false;
55+
chain_id = get_current_tx_info()->chain_id;
5156
if ((ret = value_get(&param->collection, &collections))) {
5257
if ((ret = value_get(&param->id, &ids))) {
5358
if (collections.size == 0) {
@@ -62,8 +67,7 @@ bool format_param_nft(const s_param_nft *param, const char *name) {
6267
collections.value[collection_idx].length,
6368
addr_buf,
6469
sizeof(addr_buf));
65-
if ((asset = (const nftInfo_t *) get_asset_info_by_addr(addr_buf)) ==
66-
NULL) {
70+
if ((asset = get_matching_nft_info(&chain_id, addr_buf)) == NULL) {
6771
ret = false;
6872
break;
6973
}
@@ -73,7 +77,7 @@ bool format_param_nft(const s_param_nft *param, const char *name) {
7377
sizeof(tmp)))) {
7478
break;
7579
}
76-
snprintf(buf, buf_size, "%s #%s", asset->collectionName, tmp);
80+
snprintf(buf, buf_size, "%s #%s", asset->collection_name, tmp);
7781
if (!(ret = add_to_field_table(PARAM_TYPE_NFT, name, buf, asset))) {
7882
break;
7983
}

src/features/generic_tx_parser/gtp_param_token.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include "gtp_param_token.h"
33
#include "shared_context.h"
44
#include "utils.h"
5-
#include "manage_asset_info.h"
5+
#include "token_info.h"
66
#include "network.h"
77
#include "gtp_field_table.h"
88
#include "tx_ctx.h"
@@ -61,7 +61,7 @@ bool format_param_token(const s_param_token *param, const char *name) {
6161
bool ret;
6262
s_parsed_value_collection collec = {0};
6363
uint8_t addr[ADDRESS_LENGTH];
64-
const tokenDefinition_t *token_def = NULL;
64+
const s_token_info *token_info = NULL;
6565
uint64_t chain_id;
6666
const char *ticker = NULL;
6767

@@ -72,14 +72,14 @@ bool format_param_token(const s_param_token *param, const char *name) {
7272
buf_shrink_expand(collec.value[i].ptr, collec.value[i].length, addr, sizeof(addr));
7373
if (match_native(addr, param)) {
7474
ticker = get_displayable_ticker(&chain_id, g_chain_config, true);
75-
} else if ((token_def = (const tokenDefinition_t *) get_asset_info_by_addr(addr))) {
76-
ticker = token_def->ticker;
75+
} else if ((token_info = get_matching_token_info(&chain_id, addr))) {
76+
ticker = token_info->ticker;
7777
}
7878
if (ticker == NULL) {
7979
ret = false;
8080
break;
8181
}
82-
if (!(ret = add_to_field_table(PARAM_TYPE_TOKEN, name, ticker, token_def))) {
82+
if (!(ret = add_to_field_table(PARAM_TYPE_TOKEN, name, ticker, token_info))) {
8383
break;
8484
}
8585
}

src/features/generic_tx_parser/gtp_param_token_amount.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
#include "network.h"
55
#include "utils.h"
66
#include "gtp_field_table.h"
7-
#include "manage_asset_info.h"
7+
#include "token_info.h"
88
#include "tx_ctx.h"
99
#include "tlv_utils.h"
10+
#include "shared_context.h"
1011

1112
#define PARAM_TOKEN_AMOUNT_TAGS(X) \
1213
X(0x00, TAG_VERSION, handle_version, ENFORCE_UNIQUE_TAG) \
@@ -95,7 +96,7 @@ static bool process_token_amount(const s_param_token_amount *param,
9596
uint8_t addr_buf[ADDRESS_LENGTH];
9697
uint256_t zero256 = {0};
9798
uint256_t val256;
98-
const tokenDefinition_t *token_def = NULL;
99+
const s_token_info *token_info = NULL;
99100
uint64_t chain_id;
100101
const char *ticker = g_unknown_ticker;
101102
uint8_t decimals = 0;
@@ -108,10 +109,9 @@ static bool process_token_amount(const s_param_token_amount *param,
108109
ticker = get_displayable_ticker(&chain_id, g_chain_config, true);
109110
decimals = WEI_TO_ETHER;
110111
} else {
111-
if ((token_def = (const tokenDefinition_t *) get_asset_info_by_addr(addr_buf)) !=
112-
NULL) {
113-
ticker = token_def->ticker;
114-
decimals = token_def->decimals;
112+
if ((token_info = get_matching_token_info(&chain_id, addr_buf)) != NULL) {
113+
ticker = token_info->ticker;
114+
decimals = token_info->decimals;
115115
}
116116
}
117117
}
@@ -128,10 +128,10 @@ static bool process_token_amount(const s_param_token_amount *param,
128128
return false;
129129
}
130130
}
131-
if (!add_to_field_table(token_def ? PARAM_TYPE_TOKEN_AMOUNT : PARAM_TYPE_AMOUNT,
131+
if (!add_to_field_table(token_info ? PARAM_TYPE_TOKEN_AMOUNT : PARAM_TYPE_AMOUNT,
132132
name,
133133
buf,
134-
token_def)) {
134+
token_info)) {
135135
return false;
136136
}
137137
return true;
Lines changed: 74 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,108 @@
11
#include "apdu_constants.h"
22
#include "public_keys.h"
33
#include "network.h"
4-
#include "manage_asset_info.h"
54
#include "os_pki.h"
5+
#include "token_info.h"
66

7-
uint16_t handle_provide_erc20_token_information(const uint8_t *workBuffer,
8-
uint8_t dataLength,
7+
uint16_t handle_provide_erc20_token_information(uint8_t p1,
8+
uint8_t p2,
9+
uint8_t lc,
10+
const uint8_t *data,
911
unsigned int *tx) {
1012
uint32_t offset = 0;
11-
uint8_t tickerLength;
13+
uint8_t ticker_length;
14+
const char *ticker;
15+
const uint8_t *address;
16+
uint32_t decimals_32;
17+
uint32_t chain_id_32;
1218
uint64_t chain_id;
1319
uint8_t hash[INT256_LENGTH];
14-
tokenDefinition_t *token = &get_current_asset_info()->token;
20+
int index;
21+
s_token_info info = {0};
1522

16-
PRINTF("Provisioning currentAssetIndex %d\n", tmpCtx.transactionContext.currentAssetIndex);
17-
18-
if (dataLength < 1) {
23+
if ((p1 != 0) || (p2 != 0)) {
24+
return SWO_INCORRECT_P1_P2;
25+
}
26+
if ((offset + sizeof(ticker_length)) > lc) {
1927
return SWO_INCORRECT_DATA;
2028
}
21-
tickerLength = workBuffer[offset++];
22-
dataLength--;
23-
if ((tickerLength + 1) > sizeof(token->ticker)) {
29+
ticker_length = data[offset];
30+
offset += sizeof(ticker_length);
31+
32+
if ((offset + ticker_length) > lc) {
2433
return SWO_INCORRECT_DATA;
2534
}
26-
if (dataLength < tickerLength + 20 + 4 + 4) {
35+
ticker = (const char *) &data[offset];
36+
offset += ticker_length;
37+
38+
if ((offset + ADDRESS_LENGTH) > lc) {
2739
return SWO_INCORRECT_DATA;
2840
}
29-
cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32);
30-
memmove(token->ticker, workBuffer + offset, tickerLength);
31-
token->ticker[tickerLength] = '\0';
32-
offset += tickerLength;
33-
dataLength -= tickerLength;
34-
memmove(token->address, workBuffer + offset, 20);
35-
offset += 20;
36-
dataLength -= 20;
41+
address = &data[offset];
42+
offset += ADDRESS_LENGTH;
43+
3744
// TODO: 4 bytes for this is overkill
38-
token->decimals = U4BE(workBuffer, offset);
39-
offset += 4;
40-
dataLength -= 4;
45+
if ((offset + sizeof(decimals_32)) > lc) {
46+
return SWO_INCORRECT_DATA;
47+
}
48+
decimals_32 = U4BE(data, offset);
49+
offset += sizeof(decimals_32);
50+
4151
// TODO: Handle 64-bit long chain IDs
42-
chain_id = U4BE(workBuffer, offset);
52+
if ((offset + sizeof(chain_id_32)) > lc) {
53+
return SWO_INCORRECT_DATA;
54+
}
55+
chain_id_32 = U4BE(data, offset);
56+
chain_id = (uint64_t) chain_id_32;
57+
offset += sizeof(chain_id_32);
58+
59+
if (offset >= lc) {
60+
// no signature
61+
return SWO_INCORRECT_DATA;
62+
}
63+
64+
// sanity checks
65+
if (decimals_32 > UINT8_MAX) {
66+
PRINTF("Error: decimals received does not fit on one byte!\n");
67+
return SWO_INCORRECT_DATA;
68+
}
69+
if ((ticker_length + 1) > sizeof(info.ticker)) {
70+
return SWO_INCORRECT_DATA;
71+
}
4372
if (!app_compatible_with_chain_id(&chain_id)) {
4473
UNSUPPORTED_CHAIN_ID_MSG(chain_id);
4574
return SWO_INCORRECT_DATA;
4675
}
47-
offset += 4;
48-
dataLength -= 4;
4976

77+
// signature is computed on everything but the ticker length
78+
cx_hash_sha256(&data[sizeof(ticker_length)],
79+
offset - sizeof(ticker_length),
80+
hash,
81+
CX_SHA256_SIZE);
5082
if (check_signature_with_pubkey(hash,
5183
sizeof(hash),
5284
LEDGER_SIGNATURE_PUBLIC_KEY,
5385
sizeof(LEDGER_SIGNATURE_PUBLIC_KEY),
5486
CERTIFICATE_PUBLIC_KEY_USAGE_COIN_META,
55-
(uint8_t *) (workBuffer + offset),
56-
dataLength) != true) {
87+
&data[offset],
88+
lc - offset) != true) {
89+
return SWO_INCORRECT_DATA;
90+
}
91+
92+
memcpy(info.address, address, sizeof(info.address));
93+
memcpy(info.ticker, ticker, ticker_length);
94+
info.decimals = (uint8_t) decimals_32;
95+
info.chain_id = (uint64_t) chain_id_32;
96+
97+
if ((index = set_token_info(&info)) == -1) {
98+
return SWO_INSUFFICIENT_MEMORY;
99+
}
100+
if (index > UINT8_MAX) {
101+
// Could not represent it on one byte
57102
return SWO_INCORRECT_DATA;
58103
}
59104

60-
G_io_tx_buffer[0] = tmpCtx.transactionContext.currentAssetIndex;
61-
validate_current_asset_info();
105+
G_io_tx_buffer[0] = (uint8_t) index;
62106
*tx += 1;
63107
return SWO_SUCCESS;
64108
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include <string.h>
2+
#include "lists.h"
3+
#include "app_mem_utils.h"
4+
#include "token_info.h"
5+
6+
typedef struct {
7+
flist_node_t _list;
8+
s_token_info info;
9+
} s_token_info_node;
10+
11+
static s_token_info_node *g_token_info_list;
12+
13+
int set_token_info(const s_token_info *info) {
14+
s_token_info_node *node;
15+
int idx = 0;
16+
17+
if (info == NULL) {
18+
return -1;
19+
}
20+
// look for an existing matching node
21+
for (node = g_token_info_list; node != NULL;
22+
node = (s_token_info_node *) ((flist_node_t *) node)->next) {
23+
if (info->chain_id == node->info.chain_id) {
24+
if (memcmp(info->address, node->info.address, sizeof(node->info.address)) == 0) {
25+
break;
26+
}
27+
}
28+
idx += 1;
29+
}
30+
31+
if (node == NULL) {
32+
if ((node = APP_MEM_ALLOC(sizeof(*node))) == NULL) {
33+
return -1;
34+
}
35+
flist_push_back((flist_node_t **) &g_token_info_list, (flist_node_t *) node);
36+
}
37+
memcpy(&node->info, info, sizeof(node->info));
38+
return idx;
39+
}
40+
41+
static void delete_token_info(s_token_info_node *node) {
42+
APP_MEM_FREE(node);
43+
}
44+
45+
void clear_token_infos(void) {
46+
flist_clear((flist_node_t **) &g_token_info_list, (f_list_node_del) &delete_token_info);
47+
}
48+
49+
const s_token_info *get_matching_token_info(const uint64_t *chain_id, const uint8_t *address) {
50+
if ((chain_id != NULL) && (address != NULL)) {
51+
for (const s_token_info_node *node = g_token_info_list; node != NULL;
52+
node = (s_token_info_node *) ((flist_node_t *) node)->next) {
53+
if (*chain_id == node->info.chain_id) {
54+
if (memcmp(address, node->info.address, sizeof(node->info.address)) == 0) {
55+
return &node->info;
56+
}
57+
}
58+
}
59+
}
60+
return NULL;
61+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
#include "common_utils.h"
5+
#include "asset_info.h"
6+
7+
typedef struct {
8+
uint8_t address[ADDRESS_LENGTH];
9+
char ticker[MAX_TICKER_LEN];
10+
uint8_t decimals;
11+
12+
uint64_t chain_id;
13+
} s_token_info;
14+
15+
int set_token_info(const s_token_info *info);
16+
void clear_token_infos(void);
17+
const s_token_info *get_matching_token_info(const uint64_t *chain_id, const uint8_t *address);

0 commit comments

Comments
 (0)