Skip to content

Commit 07bd8fd

Browse files
authored
Merge pull request #53 from Zondax/feature/formatting
Custom number formatting
2 parents 6a7eb7a + 118f6cd commit 07bd8fd

File tree

17 files changed

+475
-166
lines changed

17 files changed

+475
-166
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ file(GLOB_RECURSE LIB_SRC
101101
${CMAKE_CURRENT_SOURCE_DIR}/deps/ledger-zxlib/src/zxformat.c
102102
####
103103
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser.c
104+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/formatting.c
104105
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c
105106
${CMAKE_CURRENT_SOURCE_DIR}/app/src/crypto.c
106107
${CMAKE_CURRENT_SOURCE_DIR}/app/src/base32.c

app/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ endif
5252

5353
APPVERSION_M=0
5454
APPVERSION_N=3
55-
APPVERSION_P=0
55+
APPVERSION_P=1
5656

5757
$(info COIN = [$(COIN)])
5858
ifeq ($(COIN),DFN)

app/src/coin.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@ typedef enum {
4545
addr_secp256k1 = 0,
4646
} address_kind_e;
4747

48-
#define CBOR_PARSER_MAX_RECURSIONS 4
49-
#define COIN_SECRET_REQUIRED_CLICKS 0
50-
#define COIN_AMOUNT_DECIMAL_PLACES 0 // FIXME: Adjust this
48+
#define CBOR_PARSER_MAX_RECURSIONS 4
49+
#define COIN_SECRET_REQUIRED_CLICKS 0
50+
#define COIN_AMOUNT_DECIMAL_PLACES 8
51+
#define COIN_AMOUNT_DECIMAL_NON_TRIMMED_PLACES 2
52+
#define COIN_AMOUNT_THOUSAND_SEPARATOR '\''
5153

5254
#define VIEW_ADDRESS_OFFSET_SECP256K1 (SECP256K1_PK_LEN )
5355
#define VIEW_PRINCIPAL_OFFSET_TEXT (SECP256K1_PK_LEN + DFINITY_PRINCIPAL_LEN + DFINITY_SUBACCOUNT_LEN)

app/src/crypto.c

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,14 @@ zxerr_t crypto_principalToTextual(const uint8_t *address_in, uint8_t addressLen,
391391
input[1] = (uint8_t) ((crc & 0x00FF0000) >> 16);
392392
input[2] = (uint8_t) ((crc & 0x0000FF00) >> 8);
393393
input[3] = (uint8_t) ((crc & 0x000000FF) >> 0);
394+
394395
MEMCPY(input + 4, address_in, addressLen);
395-
uint32_t enc_len = base32_encode(input, 4 + addressLen, textual, 100);
396+
uint32_t enc_len = base32_encode(input, 4 + addressLen, textual, *outLen);
397+
396398
if (enc_len == 0) {
397399
return zxerr_unknown;
398400
}
401+
399402
*outLen = enc_len;
400403
return zxerr_ok;
401404
}
@@ -433,34 +436,6 @@ zxerr_t compressLEB128(const uint64_t input, uint16_t maxSize, uint8_t *output,
433436
return zxerr_ok;
434437
}
435438

436-
uint8_t decompressLEB128(const uint8_t *input, uint16_t inputSize, uint64_t *v) {
437-
unsigned int i = 0;
438-
439-
*v = 0;
440-
uint16_t shift = 0;
441-
while (i < 10u && i < inputSize) {
442-
uint64_t b = input[i] & 0x7fu;
443-
444-
if (shift >= 63 && b > 1) {
445-
// This will overflow uint64_t
446-
break;
447-
}
448-
449-
*v |= b << shift;
450-
451-
if (!(input[i] & 0x80u)) {
452-
return 1;
453-
}
454-
455-
shift += 7;
456-
i++;
457-
}
458-
459-
// exit because of overflowing outputSize
460-
*v = 0;
461-
return 0;
462-
}
463-
464439
typedef struct {
465440
uint8_t publicKey[SECP256K1_PK_LEN];
466441
uint8_t principalBytes[DFINITY_PRINCIPAL_LEN];
@@ -491,7 +466,7 @@ zxerr_t crypto_fillAddress(uint8_t *buffer, uint16_t buffer_len, uint16_t *addrL
491466
zero_subaccount, DFINITY_SUBACCOUNT_LEN, answer->subAccountBytes,
492467
sizeof_field(answer_t, subAccountBytes)));
493468

494-
uint16_t outLen = 0;
469+
uint16_t outLen = DFINITY_TEXTUAL_SIZE;
495470

496471
CHECK_ZXERR(crypto_principalToTextual(answer->principalBytes, DFINITY_PRINCIPAL_LEN, answer->addrText, &outLen));
497472

app/src/formatting.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*******************************************************************************
2+
* (c) 2021 Zondax GmbH
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
********************************************************************************/
16+
#include "formatting.h"
17+
18+
zxerr_t inplace_insert_char(char *s, uint16_t sMaxLen, uint16_t pos, char separator) {
19+
const size_t len = strlen(s);
20+
if (len >= sMaxLen) {
21+
return zxerr_buffer_too_small;
22+
}
23+
24+
if (pos > len) {
25+
return zxerr_out_of_bounds;
26+
}
27+
28+
MEMMOVE(s + pos + 1, s + pos, len - pos + 1); // len-pos+1 because we copy zero terminator
29+
s[pos] = separator;
30+
31+
return zxerr_ok;
32+
}
33+
34+
zxerr_t number_inplace_thousands(char *s, uint16_t sMaxLen, char separator) {
35+
const size_t len = strlen(s);
36+
if (len > sMaxLen) {
37+
return zxerr_encoding_failed;
38+
}
39+
40+
// find decimal point
41+
int32_t dec_point = -1;
42+
for (int32_t i = 0; i < len && dec_point < 0; i++) {
43+
if (s[i] == '.') {
44+
dec_point = i;
45+
}
46+
}
47+
48+
if (dec_point < 0) {
49+
dec_point = (uint16_t) len;
50+
}
51+
52+
if (dec_point < 4) {
53+
return zxerr_ok;
54+
}
55+
56+
const uint8_t numSep = (dec_point - 1) / 3;
57+
58+
if (len + numSep >= sMaxLen) {
59+
return zxerr_buffer_too_small;
60+
}
61+
62+
size_t pos = dec_point;
63+
64+
while (pos > 3) {
65+
pos -= 3;
66+
CHECK_ZXERR(inplace_insert_char(s, sMaxLen, pos, separator));
67+
}
68+
69+
return zxerr_ok;
70+
}
71+
72+
zxerr_t formatICP(char *out, uint16_t outLen, uint64_t value) {
73+
MEMZERO(out, outLen);
74+
75+
fpuint64_to_str(out, outLen, value, COIN_AMOUNT_DECIMAL_PLACES);
76+
number_inplace_trimming(out, COIN_AMOUNT_DECIMAL_NON_TRIMMED_PLACES);
77+
CHECK_ZXERR(number_inplace_thousands(out, outLen, COIN_AMOUNT_THOUSAND_SEPARATOR));
78+
79+
return zxerr_ok;
80+
}

app/src/formatting.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*******************************************************************************
2+
* (c) 2021 Zondax GmbH
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
********************************************************************************/
16+
#pragma once
17+
#include "stdint.h"
18+
#include "parser.h"
19+
20+
#ifdef __cplusplus
21+
extern "C" {
22+
#endif
23+
24+
zxerr_t inplace_insert_char(char *s, uint16_t sMaxLen, uint16_t pos, char separator);
25+
26+
zxerr_t number_inplace_thousands(char *s, uint16_t sMaxLen, char separator);
27+
28+
zxerr_t formatICP(char *out, uint16_t outLen, uint64_t value);
29+
30+
#ifdef __cplusplus
31+
}
32+
#endif

0 commit comments

Comments
 (0)