Skip to content

Commit 22849d4

Browse files
committed
proof fixes
1 parent c2a0d32 commit 22849d4

5 files changed

Lines changed: 269 additions & 215 deletions

File tree

app/src/schema_proof.c

Lines changed: 95 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,19 @@
2828
const uint8_t LEAF_PREFIX = 0x00;
2929
const uint8_t INNER_PREFIX = 0x01;
3030

31+
static parser_error_t check_range_proof_inner(proof_t *proof, uint32_t start_index, uint32_t subtrie_size, uint32_t offset);
32+
3133
/**
3234
* @brief Calculate the largest power of two which is strictly less than the argument.
3335
*
3436
* @param n The input value.
3537
* @return The largest power of two which is strictly less than the argument.
3638
*/
3739
static uint32_t next_smaller_po2(uint32_t n) {
40+
if (n == 0) {
41+
return 0;
42+
}
43+
3844
if ((n & (n - 1)) == 0) {
3945
return n >> 1;
4046
}
@@ -44,6 +50,11 @@ static uint32_t next_smaller_po2(uint32_t n) {
4450
n |= n >> 4;
4551
n |= n >> 8;
4652
n |= n >> 16;
53+
54+
if (n == UINT32_MAX) {
55+
return (UINT32_MAX >> 1) + 1;
56+
}
57+
4758
n += 1;
4859

4960
// Return the next smaller power of two
@@ -85,6 +96,9 @@ parser_error_t compute_tree_size(uint32_t num_right_siblings, uint32_t index_of_
8596

8697
while (remaining_right_siblings > 0) {
8798
if ((index_of_final_node & mask) == 0) {
99+
if (index_of_final_node > UINT32_MAX - mask) {
100+
return parser_value_out_of_range;
101+
}
88102
index_of_final_node |= mask;
89103
remaining_right_siblings--;
90104
}
@@ -128,6 +142,10 @@ static parser_error_t hash_leaf(proof_t *proof) {
128142
// Declaring array sizes as static will trigger a warning if the user pass an array smaller than the size
129143
static parser_error_t merge_branches(const uint8_t left[CX_SHA256_SIZE], const uint8_t right[CX_SHA256_SIZE],
130144
uint8_t output[CX_SHA256_SIZE]) {
145+
CHECK_INPUT(left);
146+
CHECK_INPUT(right);
147+
CHECK_INPUT(output);
148+
131149
bytes_t buffer_left = {0};
132150
buffer_left.ptr = left;
133151
buffer_left.len = CX_SHA256_SIZE;
@@ -151,82 +169,87 @@ static parser_error_t merge_branches(const uint8_t left[CX_SHA256_SIZE], const u
151169
return parser_ok;
152170
}
153171

172+
/**
173+
* @brief Get the subtree hash.
174+
*
175+
* @param proof The proof structure containing the necessary data.
176+
* @param start_index The start index.
177+
* @param subtrie_size The subtrie size.
178+
* @param offset The offset.
179+
* @param hash The output buffer for the hash.
180+
* @return parser_error_t Error code indicating the result of the operation.
181+
*/
182+
static parser_error_t get_subtree_hash(proof_t *proof, uint32_t start_index, uint32_t subtrie_size, uint32_t offset,
183+
const uint8_t **hash) {
184+
CHECK_INPUT(proof);
185+
CHECK_INPUT(proof->hash);
186+
CHECK_INPUT(hash);
187+
188+
if (subtrie_size == 1) {
189+
*hash = proof->hash;
190+
} else {
191+
CHECK_ERROR(check_range_proof_inner(proof, start_index, subtrie_size, offset));
192+
*hash = proof->hash;
193+
}
194+
return parser_ok;
195+
}
196+
197+
/**
198+
* @brief Get the lemma hash.
199+
*
200+
* @param proof The proof structure containing the necessary data.
201+
* @param hash The output buffer for the hash.
202+
* @return parser_error_t Error code indicating the result of the operation.
203+
*/
204+
static parser_error_t get_lemma_hash(proof_t *proof, const uint8_t **hash) {
205+
CHECK_INPUT(proof);
206+
CHECK_INPUT(hash);
207+
208+
if (proof->lemma_index < 0) {
209+
return parser_value_out_of_range;
210+
}
211+
uint32_t offset = CX_SHA256_SIZE * proof->lemma_index;
212+
if (offset >= proof->lemmas.data.buffer.len) {
213+
return parser_value_out_of_range;
214+
}
215+
*hash = proof->lemmas.data.buffer.ptr + offset;
216+
proof->lemma_index--;
217+
return parser_ok;
218+
}
219+
220+
/**
221+
* @brief Recursively check the range proof inner to merge the branches of the proof.
222+
*
223+
* @param proof The proof structure containing the necessary data.
224+
* @param start_index The start index.
225+
* @param subtrie_size The subtrie size.
226+
* @param offset The offset.
227+
* @return parser_error_t Error code indicating the result of the operation.
228+
*/
154229
static parser_error_t check_range_proof_inner(proof_t *proof, uint32_t start_index, uint32_t subtrie_size, uint32_t offset) {
155230
CHECK_INPUT(proof);
156231

157232
uint32_t split_index = next_smaller_po2(subtrie_size);
158-
print_u32("split_point:", split_index);
159-
160233
uint32_t leaves_end_idx = (proof->indices.entries + start_index) - 1;
161-
print_u32("leaves_end_idx:", leaves_end_idx);
162-
163-
// TODO: remove this
164-
bytes_t buffer_left = {0};
165-
bytes_t buffer_right = {0};
166234

167235
// Check right subtree
168236
const uint8_t *right;
169237
if (leaves_end_idx >= (split_index + offset)) {
170238
uint32_t right_subtrie_size = subtrie_size - split_index;
171-
if (right_subtrie_size == 1) {
172-
right = proof->hash;
173-
174-
buffer_right.ptr = right;
175-
buffer_right.len = CX_SHA256_SIZE;
176-
print_buffer(&buffer_right, "right inside if true");
177-
} else {
178-
print_u32("right inside else:", right_subtrie_size);
179-
CHECK_ERROR(check_range_proof_inner(proof, start_index, right_subtrie_size, offset + split_index));
180-
right = proof->hash;
181-
}
239+
CHECK_ERROR(get_subtree_hash(proof, start_index, right_subtrie_size, offset + split_index, &right));
182240
} else {
183-
if (proof->lemmas_ctx.last_index < 0) {
184-
return parser_value_out_of_range;
185-
}
186-
right = proof->lemmas_ctx.lemmas.data.buffer.ptr + CX_SHA256_SIZE * proof->lemmas_ctx.last_index;
187-
proof->lemmas_ctx.last_index--;
188-
189-
buffer_right.ptr = right;
190-
buffer_right.len = CX_SHA256_SIZE;
191-
print_buffer(&buffer_right, "proof right outside if else");
241+
CHECK_ERROR(get_lemma_hash(proof, &right));
192242
}
193243

194244
// Check left subtree
195245
const uint8_t *left;
196246
if (start_index < (split_index + offset)) {
197247
uint32_t left_subtrie_size = split_index;
198-
if (left_subtrie_size == 1) {
199-
left = proof->hash;
200-
201-
buffer_left.ptr = left;
202-
buffer_left.len = CX_SHA256_SIZE;
203-
print_buffer(&buffer_left, "left inside if true");
204-
} else {
205-
print_u32("left inside else:", left_subtrie_size);
206-
CHECK_ERROR(check_range_proof_inner(proof, start_index, left_subtrie_size, offset));
207-
left = proof->hash;
208-
}
248+
CHECK_ERROR(get_subtree_hash(proof, start_index, left_subtrie_size, offset, &left));
209249
} else {
210-
left = proof->lemmas_ctx.lemmas.data.buffer.ptr + CX_SHA256_SIZE * proof->lemmas_ctx.last_index;
211-
if (proof->lemmas_ctx.last_index < 0) {
212-
return parser_value_out_of_range;
213-
}
214-
proof->lemmas_ctx.last_index--;
215-
216-
buffer_left.ptr = left;
217-
buffer_left.len = CX_SHA256_SIZE;
218-
print_buffer(&buffer_left, "proof left outside if else");
250+
CHECK_ERROR(get_lemma_hash(proof, &left));
219251
}
220252

221-
print_string("MERGING LEFT AND RIGHT");
222-
223-
buffer_left.ptr = left;
224-
buffer_left.len = CX_SHA256_SIZE;
225-
print_buffer(&buffer_left, "left outside if else");
226-
227-
buffer_right.ptr = right;
228-
buffer_right.len = CX_SHA256_SIZE;
229-
print_buffer(&buffer_right, "right outside if else");
230253
merge_branches(left, right, proof->hash);
231254

232255
return parser_ok;
@@ -253,10 +276,10 @@ static parser_error_t get_hash_single_proof(uint32_t index, proof_t *proof) {
253276
uint32_t num_left_siblings = compute_num_left_siblings(index);
254277

255278
// Get the number of right siblings needed
256-
if (num_left_siblings > proof->lemmas_ctx.lemmas.entries) {
279+
if (num_left_siblings > proof->lemmas.entries) {
257280
return parser_value_out_of_range;
258281
}
259-
uint32_t num_right_siblings = proof->lemmas_ctx.lemmas.entries - num_left_siblings;
282+
uint32_t num_right_siblings = proof->lemmas.entries - num_left_siblings;
260283
print_u32("num_left_siblings:", num_left_siblings);
261284
print_u32("num_right_siblings:", num_right_siblings);
262285

@@ -277,17 +300,22 @@ static parser_error_t get_hash_single_proof(uint32_t index, proof_t *proof) {
277300
* @return parser_error_t Error code indicating the result of the operation.
278301
*/
279302
parser_error_t get_root_hash(const merkle_proof_t *metadata, uint8_t metadataDigest[CX_SHA256_SIZE]) {
303+
CHECK_INPUT(metadata);
304+
CHECK_INPUT(metadataDigest);
305+
280306
proof_t proof = {0};
281307
proof.leaves = metadata->leaves;
282-
proof.lemmas_ctx = metadata->lemmas_ctx;
308+
proof.lemmas = metadata->lemmas;
283309
proof.indices = metadata->indices;
310+
proof.lemma_index = metadata->lemmas.entries - 1;
311+
MEMSET(proof.hash, 0, CX_SHA256_SIZE);
284312

285313
print_buffer(&proof.leaves.data.buffer, "leaves data");
286314
print_u32("leaves.qty:", proof.leaves.entries);
287315
print_buffer(&proof.indices.indices.buffer, "indices");
288316
print_u32("indices.qty:", proof.indices.entries);
289-
print_buffer(&proof.lemmas_ctx.lemmas.data.buffer, "lemmas");
290-
print_u32("lemmas.qty:", proof.lemmas_ctx.lemmas.entries);
317+
print_buffer(&proof.lemmas.data.buffer, "lemmas");
318+
print_u32("lemmas.qty:", proof.lemmas.entries);
291319

292320
uint32_t leaves_start = 0;
293321
CHECK_ERROR(read_u32(&proof.indices.indices, &leaves_start));
@@ -301,12 +329,17 @@ parser_error_t get_root_hash(const merkle_proof_t *metadata, uint8_t metadataDig
301329

302330
parser_error_t verify_merkle_proofs(const merkle_proof_t *metadata) {
303331
CHECK_INPUT(metadata);
332+
CHECK_INPUT(metadata->root_hash.ptr);
333+
334+
if (metadata->root_hash.len < CX_SHA256_SIZE) {
335+
return parser_unexpected_buffer_end;
336+
}
304337

305338
uint8_t root_hash[CX_SHA256_SIZE] = {0};
306339
CHECK_ERROR(get_root_hash(metadata, root_hash));
307340

308341
// compare root_hash received with computed root_hash
309-
if (memcmp(metadata->root_hash.ptr, root_hash, 32) != 0) {
342+
if (memcmp(metadata->root_hash.ptr, root_hash, CX_SHA256_SIZE) != 0) {
310343
return parser_unexpected_root_hash;
311344
}
312345

app/src/schema_proof.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ typedef struct {
3131
uint8_t hash[CX_SHA256_SIZE];
3232
merkle_leaves_data_t leaves;
3333
merkle_leaves_indices_t indices;
34-
merkle_lemmas_ctx_t lemmas_ctx;
34+
merkle_lemmas_t lemmas;
35+
int64_t lemma_index;
3536
} proof_t;
3637

3738
parser_error_t get_root_hash(const merkle_proof_t *metadata, uint8_t metadataDigest[CX_SHA256_SIZE]);

app/src/schema_reader.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -946,15 +946,14 @@ parser_error_t merkle_proofs_read(parser_context_t *ctx, parser_tx_t *txObj) {
946946
CHECK_INPUT(ctx);
947947
CHECK_INPUT(txObj);
948948

949-
CHECK_ERROR(read_u32(ctx, &txObj->merkle_proofs.lemmas_ctx.lemmas.entries));
950-
print_u32("registry_qty:", txObj->merkle_proofs.lemmas_ctx.lemmas.entries);
951-
txObj->merkle_proofs.lemmas_ctx.last_index = txObj->merkle_proofs.lemmas_ctx.lemmas.entries - 1;
949+
CHECK_ERROR(read_u32(ctx, &txObj->merkle_proofs.lemmas.entries));
950+
print_u32("registry_qty:", txObj->merkle_proofs.lemmas.entries);
952951

953952
// read short_registry
954-
txObj->merkle_proofs.lemmas_ctx.lemmas.data.buffer.ptr = ctx->buffer.ptr + ctx->offset;
955-
txObj->merkle_proofs.lemmas_ctx.lemmas.data.buffer.len = txObj->merkle_proofs.lemmas_ctx.lemmas.entries * 32;
956-
CTX_CHECK_AND_ADVANCE(ctx, txObj->merkle_proofs.lemmas_ctx.lemmas.data.buffer.len);
957-
print_buffer(&txObj->merkle_proofs.lemmas_ctx.lemmas.data.buffer, "lemmas");
953+
txObj->merkle_proofs.lemmas.data.buffer.ptr = ctx->buffer.ptr + ctx->offset;
954+
txObj->merkle_proofs.lemmas.data.buffer.len = txObj->merkle_proofs.lemmas.entries * 32;
955+
CTX_CHECK_AND_ADVANCE(ctx, txObj->merkle_proofs.lemmas.data.buffer.len);
956+
print_buffer(&txObj->merkle_proofs.lemmas.data.buffer, "lemmas");
958957

959958
// read schema
960959
uint8_t schema_type = 0;

app/src/txdefs/merkle_txdef.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,10 @@ typedef struct {
3636
parser_context_t data;
3737
} merkle_lemmas_t;
3838

39-
typedef struct {
40-
int64_t last_index;
41-
merkle_lemmas_t lemmas;
42-
} merkle_lemmas_ctx_t;
43-
4439
typedef struct {
4540
merkle_leaves_data_t leaves;
4641
merkle_leaves_indices_t indices;
47-
merkle_lemmas_ctx_t lemmas_ctx;
42+
merkle_lemmas_t lemmas;
4843
bytes_t root_hash;
4944
} merkle_proof_t;
5045

0 commit comments

Comments
 (0)