Skip to content

Commit 26250c4

Browse files
committed
add schema parser and merkle proof
1 parent 82cf1ea commit 26250c4

32 files changed

Lines changed: 2758 additions & 98 deletions

.github/workflows/codeql.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
if: github.event.repository.private == false
1818
strategy:
1919
matrix:
20-
sdk: ["$NANOS_SDK", "$NANOX_SDK", "$NANOSP_SDK", "$STAX_SDK", "$FLEX_SDK"]
20+
sdk: ["$NANOX_SDK", "$NANOSP_SDK", "$STAX_SDK", "$FLEX_SDK"]
2121
container:
2222
image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest
2323

.github/workflows/main.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,18 @@ jobs:
2424
with:
2525
upload_app_binaries_artifact: "compiled_app_binaries"
2626

27-
27+
cpp_tests:
28+
runs-on: ubuntu-latest
29+
steps:
30+
- name: Checkout
31+
uses: actions/checkout@v4
32+
with:
33+
submodules: true
34+
- name: Install deps
35+
run: |
36+
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 10
37+
make deps
38+
- run: make cpp_test
2839

2940
build:
3041
runs-on: ${{ github.repository_owner == 'zondax' && 'zondax-runners' || 'ubuntu-latest' }}

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@
77
[submodule "deps/ledger-secure-sdk"]
88
path = deps/ledger-secure-sdk
99
url = https://github.com/LedgerHQ/ledger-secure-sdk.git
10+
[submodule "js"]
11+
path = js
12+
url = https://github.com/Zondax/ledger-sovereign-js.git

CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ file(GLOB_RECURSE LIB_SRC
138138
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser.c
139139
${CMAKE_CURRENT_SOURCE_DIR}/app/src/parser_impl.c
140140
${CMAKE_CURRENT_SOURCE_DIR}/app/src/crypto_helper.c
141+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/schema_reader.c
142+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/borsh.c
143+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/schema_proof.c
144+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/schema_helper.c
145+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/schema_txn_parser.c
146+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/ui_item_manager.c
147+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/ui_item_buffer.c
148+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/stack_manager.c
149+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/render.c
141150
)
142151

143152
add_library(app_lib STATIC ${LIB_SRC})
@@ -147,6 +156,8 @@ target_include_directories(app_lib PUBLIC
147156
${CMAKE_CURRENT_SOURCE_DIR}/app/src
148157
${CMAKE_CURRENT_SOURCE_DIR}/app/src/lib
149158
${CMAKE_CURRENT_SOURCE_DIR}/app/src/common
159+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/txdefs
160+
${CMAKE_CURRENT_SOURCE_DIR}/app/src/modules
150161
${CMAKE_CURRENT_SOURCE_DIR}/deps/picohash
151162
)
152163

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
# BOLOS_SDK IS DEFINED We use the plain Makefile for Ledger
1919
# BOLOS_SDK NOT DEFINED We use a containerized build approach
2020

21-
TESTS_JS_PACKAGE = "@zondax/ledger-sovereign"
22-
TESTS_JS_DIR = $(CURDIR)/../ledger-sovereign-js
21+
# TESTS_JS_PACKAGE = "@zondax/ledger-sovereign"
22+
# TESTS_JS_DIR = $(CURDIR)/../ledger-sovereign-js
2323

2424
ifeq ($(BOLOS_SDK),)
2525
# In this case, there is not predefined SDK and we run dockerized

app/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ VARIANT_PARAM=COIN
7676
VARIANT_VALUES=$(COIN)
7777

7878
INCLUDES_PATH += $(CURDIR)/src/common
79+
INCLUDES_PATH += $(BOLOS_SDK)/lib_cxng/src
7980

8081
########################################
8182
# Application communication interfaces #

app/src/borsh.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*******************************************************************************
2+
* (c) 2018 - 2025 Zondax AG
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 "bech32.h"
17+
#include "crypto_helper.h"
18+
#include "parser_impl.h"
19+
#include "zxformat.h"
20+
21+
// void print_buffer(bytes_t *buffer, const char *title) {
22+
// #if defined(LEDGER_SPECIFIC)
23+
// ZEMU_LOGF(50, "%s\n", title);
24+
// char print[1000] = {0};
25+
// array_to_hexstr(print, sizeof(print), buffer->ptr, buffer->len);
26+
// ZEMU_LOGF(1000, "%s\n", print);
27+
// #else
28+
// printf("%s %d: ", title, buffer->len);
29+
// for (uint16_t i = 0; i < buffer->len; i++) {
30+
// printf("%02x", buffer->ptr[i]);
31+
// }
32+
// printf("\n");
33+
// #endif
34+
// }
35+
36+
// void print_buffer_u8(bytes_t *buffer, const char *title) {
37+
// #if defined(LEDGER_SPECIFIC)
38+
// ZEMU_LOGF(50, "%s\n", title);
39+
// char print[1000] = {0};
40+
// array_to_hexstr(print, sizeof(print), buffer->ptr, buffer->len);
41+
// ZEMU_LOGF(1000, "%s\n", print);
42+
// #else
43+
// printf("%s %d: [", title, buffer->len);
44+
// for (uint16_t i = 0; i < buffer->len; i++) {
45+
// printf("%d, ", buffer->ptr[i]);
46+
// }
47+
// printf("]\n");
48+
// #endif
49+
// }
50+
51+
// void print_buffer_str(bytes_t *buffer, const char *title) {
52+
// #if defined(LEDGER_SPECIFIC)
53+
// ZEMU_LOGF(50, "%s\n", title);
54+
// char print[1000] = {0};
55+
// array_to_hexstr(print, sizeof(print), buffer->ptr, buffer->len);
56+
// ZEMU_LOGF(1000, "%s\n", print);
57+
// #else
58+
// uint8_t buff[1000] = {0};
59+
// memcpy(buff, buffer->ptr, buffer->len);
60+
// printf("%s %s\n", title, buff);
61+
// #endif
62+
// }
63+
64+
void print_string(const char *str) {
65+
#if defined(LEDGER_SPECIFIC)
66+
char print[1000] = {0};
67+
MEMCPY(print, str, strlen(str));
68+
ZEMU_LOGF(100, "%s\n", str);
69+
#else
70+
printf("%s\n", str);
71+
#endif
72+
}
73+
74+
// void print_string_title(const char *str, const char *title) {
75+
// #if defined(LEDGER_SPECIFIC)
76+
// ZEMU_LOGF(100, "%s: %s\n", title, str);
77+
// #else
78+
// printf("%s: %s\n", title, str);
79+
// #endif
80+
// }
81+
82+
// void print_u8(const char *str, uint8_t val) {
83+
// #if defined(LEDGER_SPECIFIC)
84+
// ZEMU_LOGF(100, "%s: %d\n", str, val);
85+
// #else
86+
// printf("%s: %d\n", str, val);
87+
// #endif
88+
// }
89+
90+
// void print_u16(const char *str, uint16_t val) {
91+
// #if defined(LEDGER_SPECIFIC)
92+
// ZEMU_LOGF(100, "%s: %d\n", str, val);
93+
// #else
94+
// printf("%s: %d\n", str, val);
95+
// #endif
96+
// }
97+
98+
// void print_u32(const char *str, uint32_t val) {
99+
// #if defined(LEDGER_SPECIFIC)
100+
// ZEMU_LOGF(100, "%s: %d\n", str, val);
101+
// #else
102+
// printf("%s: %u\n", str, val);
103+
// #endif
104+
// }
105+
106+
// void print_u64(const char *str, uint64_t val) {
107+
// #if defined(LEDGER_SPECIFIC)
108+
// ZEMU_LOGF(100, "%s: %lu\n", str, val);
109+
// #else
110+
// printf("%s: %llu\n", str, val);
111+
// #endif
112+
// }
113+
114+
// void print_u64_hex(const char *str, uint64_t val) {
115+
// #if defined(LEDGER_SPECIFIC)
116+
// ZEMU_LOGF(100, "%s: %lu\n", str, val);
117+
// #else
118+
// printf("%s: 0x%llx\n", str, val);
119+
// #endif
120+
// }

app/src/borsh.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*******************************************************************************
2+
* (c) 2018 - 2025 Zondax AG
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+
17+
#pragma once
18+
19+
#ifdef __cplusplus
20+
extern "C" {
21+
#endif
22+
23+
#include <sigutils.h>
24+
#include <stdbool.h>
25+
26+
#include "parser_impl.h"
27+
28+
#define OFFSET_U8 1
29+
#define OFFSET_U16 2
30+
#define OFFSET_U32 4
31+
#define OFFSET_U64 8
32+
33+
#define DEFINE_READ_UINT(bits) \
34+
static inline parser_error_t read_u##bits(parser_context_t *ctx, uint##bits##_t *val) { \
35+
CHECK_INPUT(ctx); \
36+
CHECK_INPUT(val); \
37+
*val = *(uint##bits##_t *)(ctx->buffer.ptr + ctx->offset); \
38+
CTX_CHECK_AND_ADVANCE(ctx, OFFSET_U##bits); \
39+
return parser_ok; \
40+
}
41+
42+
DEFINE_READ_UINT(8)
43+
DEFINE_READ_UINT(16)
44+
DEFINE_READ_UINT(32)
45+
DEFINE_READ_UINT(64)
46+
47+
#undef DEFINE_READ_UINT
48+
49+
// TODO: Remove these functions
50+
// void print_buffer(bytes_t *buffer, const char *title);
51+
// void print_buffer_str(bytes_t *buffer, const char *title);
52+
// void print_buffer_u8(bytes_t *buffer, const char *title);
53+
void print_string(const char *str);
54+
// void print_string_title(const char *str, const char *title);
55+
// void print_u8(const char *str, uint8_t val);
56+
// void print_u16(const char *str, uint16_t val);
57+
// void print_u32(const char *str, uint32_t val);
58+
// void print_u64(const char *str, uint64_t val);
59+
// void print_u64_hex(const char *str, uint64_t val);
60+
61+
#ifdef __cplusplus
62+
}
63+
#endif

app/src/common/parser_common.h

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ typedef enum {
4444
parser_unexpected_type,
4545
parser_unexpected_method,
4646
parser_unexpected_buffer_end,
47+
parser_encoding_failed,
48+
parser_invalid_crypto_settings,
49+
parser_ledger_api_error,
4750
parser_unexpected_value,
4851
parser_unexpected_number_items,
4952
parser_unexpected_version,
@@ -54,15 +57,29 @@ typedef enum {
5457
parser_invalid_address,
5558
parser_unexpected_chain,
5659
parser_missing_field,
57-
paser_unknown_transaction,
58-
} parser_error_t;
60+
parser_unknown_transaction,
61+
parser_running_out_of_stack,
62+
parser_root_type_indices_overflow,
63+
parser_unexpected_root_hash,
64+
parser_unexpected_chain_hash,
65+
parser_schema_index_not_found,
66+
parser_scheme_discriminant_overflow,
67+
parser_name_registry_not_found,
68+
parser_too_many_items,
69+
parser_push_item_too_long,
70+
71+
// parser specific
72+
parser_schema_unknown_type,
73+
parser_schema_parser_txn_failed,
74+
parser_schema_merkle_proofs_indices_mismatch,
5975

60-
typedef struct {
61-
const uint8_t *buffer;
62-
uint16_t bufferLen;
63-
uint16_t offset;
64-
parser_tx_t *tx_obj;
65-
} parser_context_t;
76+
// ui specific
77+
parser_ui_item_title_empty,
78+
parser_ui_separator_not_found,
79+
parser_ui_buffer_not_initialized,
80+
parser_ui_buffer_init_failed,
81+
parser_ui_buffer_too_small,
82+
} parser_error_t;
6683

6784
#ifdef __cplusplus
6885
}

app/src/crypto_helper.c

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,42 @@
1919
#include "zxformat.h"
2020
#if defined(LEDGER_SPECIFIC)
2121
#include "cx.h"
22+
#include "cx_sha256.h"
23+
cx_sha256_t ctx;
2224
#else
2325
#include "picohash.h"
24-
#define CX_SHA256_SIZE 32
26+
picohash_ctx_t ctx;
2527
#endif
2628

27-
zxerr_t crypto_computeSha256(uint8_t *output, uint16_t outputLen, const uint8_t *input, uint16_t inputLen) {
29+
zxerr_t crypto_sha256_init() {
30+
#if defined(LEDGER_SPECIFIC)
31+
memset(&ctx, 0, sizeof(ctx));
32+
cx_sha256_init_no_throw(&ctx);
33+
#else
34+
picohash_init_sha256(&ctx);
35+
#endif
36+
return zxerr_ok;
37+
}
38+
39+
zxerr_t crypto_sha256_update(const uint8_t *input, uint16_t inputLen) {
40+
#if defined(LEDGER_SPECIFIC)
41+
CHECK_CX_OK(cx_sha256_update(&ctx, input, inputLen));
42+
#else
43+
picohash_update(&ctx, input, inputLen);
44+
#endif
45+
return zxerr_ok;
46+
}
47+
48+
zxerr_t crypto_sha256_final(uint8_t *output) {
49+
#if defined(LEDGER_SPECIFIC)
50+
CHECK_CX_OK(cx_sha256_final(&ctx, output));
51+
#else
52+
picohash_final(&ctx, output);
53+
#endif
54+
return zxerr_ok;
55+
}
56+
57+
zxerr_t crypto_sha256_one_shot(uint8_t *output, uint16_t outputLen, const uint8_t *input, uint16_t inputLen) {
2858
if (output == NULL || outputLen == 0 || input == NULL) {
2959
return zxerr_invalid_crypto_settings;
3060
}
@@ -35,14 +65,10 @@ zxerr_t crypto_computeSha256(uint8_t *output, uint16_t outputLen, const uint8_t
3565

3666
MEMZERO(output, outputLen);
3767

38-
#if defined(LEDGER_SPECIFIC)
39-
cx_hash_sha256(input, inputLen, output, outputLen);
40-
#else
41-
picohash_ctx_t ctx;
42-
picohash_init_sha256(&ctx);
43-
picohash_update(&ctx, input, inputLen);
44-
picohash_final(&ctx, output);
45-
#endif
68+
CHECK_ZXERR(crypto_sha256_init());
69+
CHECK_ZXERR(crypto_sha256_update(input, inputLen));
70+
CHECK_ZXERR(crypto_sha256_final(output));
71+
4672
return zxerr_ok;
4773
}
4874

@@ -59,7 +85,7 @@ zxerr_t crypto_computeAddress(uint8_t *address, uint16_t addressLen, const uint8
5985
MEMZERO(address, addressLen);
6086

6187
uint8_t sha[PK_LEN_25519] = {0};
62-
CHECK_ZXERR(crypto_computeSha256(sha, sizeof(sha), pubkey, PK_LEN_25519));
88+
CHECK_ZXERR(crypto_sha256_one_shot(sha, sizeof(sha), pubkey, PK_LEN_25519));
6389
CHECK_ZXERR(
6490
bech32EncodeFromBytes((char *)address, ADDRESS_MAX_LENGTH, HRP, sha, PUBKEY_SHA_LEN, 1, BECH32_ENCODING_BECH32M));
6591

0 commit comments

Comments
 (0)