@@ -70,6 +70,29 @@ static uint8_t log2i(uint32_t input) {
7070 return log2 ;
7171}
7272
73+ /**
74+ * @brief Calculate the largest power of two which is strictly less than the argument.
75+ *
76+ * @param n The input value.
77+ * @return The largest power of two which is strictly less than the argument.
78+ */
79+ static uint32_t next_smaller_po2 (uint32_t n ) {
80+ if ((n & (n - 1 )) == 0 ) {
81+ return n >> 1 ;
82+ }
83+ // Find the next power of two greater than or equal to n
84+ n |= n >> 1 ;
85+ n |= n >> 2 ;
86+ n |= n >> 4 ;
87+ n |= n >> 8 ;
88+ n |= n >> 16 ;
89+ n += 1 ;
90+
91+ // Return the next smaller power of two
92+ return n >> 1 ;
93+ }
94+
95+
7396/**
7497 * @brief Compute the number of left siblings needed for a given node index.
7598 *
@@ -82,14 +105,42 @@ static uint32_t compute_num_left_siblings(uint32_t node_idx) {
82105 uint32_t num_left_siblings = 0 ;
83106 uint32_t start_idx = node_idx ;
84107 while (start_idx != 0 ) {
85- if (start_idx & 1 != 0 ) {
108+ if (( start_idx & 1 ) != 0 ) {
86109 num_left_siblings += 1 ;
87110 }
88111 start_idx >>= 1 ;
89112 }
90113 return num_left_siblings ;
91114}
92115
116+ /**
117+ * @brief Compute the size of the tree needed to prove a given index.
118+ *
119+ * @param num_right_siblings The number of right siblings needed.
120+ * @param index_of_last_included_leaf The index of the last included leaf.
121+ * @param tree_size The output buffer for the computed tree size.
122+ * @return parser_error_t Error code indicating the result of the operation.
123+ */
124+ parser_error_t compute_tree_size (uint32_t num_right_siblings , uint32_t index_of_last_included_leaf , uint32_t * tree_size ) {
125+ uint32_t index_of_final_node = index_of_last_included_leaf ;
126+ uint32_t mask = 1 ;
127+ uint32_t remaining_right_siblings = num_right_siblings ;
128+
129+ while (remaining_right_siblings > 0 ) {
130+ if ((index_of_final_node & mask ) == 0 ) {
131+ index_of_final_node |= mask ;
132+ remaining_right_siblings -- ;
133+ }
134+ mask <<= 1 ;
135+ if (index_of_final_node == UINT32_MAX ) {
136+ return parser_value_out_of_range ;
137+ }
138+ }
139+
140+ * tree_size = index_of_final_node + 1 ;
141+ return parser_ok ;
142+ }
143+
93144/**
94145 * @brief Check if a given index is a descendant of a leaf in a binary tree.
95146 *
@@ -141,6 +192,7 @@ static bool isLemma(uint32_t index, uint32_t leaf) {
141192 * @return parser_error_t Error code indicating the result of the operation.
142193 */
143194static parser_error_t hash_leaf (proof_t * proof ) {
195+ CHECK_INPUT (proof );
144196 // const uint16_t initialOffset = proof->registry.registry.offset;
145197 // CHECK_ERROR(readType(&proof->registry.registry, &proof->lastEntry));
146198
@@ -149,12 +201,7 @@ static parser_error_t hash_leaf(proof_t *proof) {
149201 crypto_sha256_init ();
150202 crypto_sha256_update (& LEAF_PREFIX , 1 );
151203 crypto_sha256_update (proof -> registry .registry .buffer .ptr , proof -> registry .registry .buffer .len );
152- crypto_sha256_final (proof -> hash , CX_SHA256_SIZE );
153-
154- bytes_t buffer = {0 };
155- buffer .ptr = proof -> hash ;
156- buffer .len = CX_SHA256_SIZE ;
157- print_buffer (& buffer , "hash leaf" );
204+ crypto_sha256_final (proof -> hash_leaf , CX_SHA256_SIZE );
158205
159206 return parser_ok ;
160207}
@@ -266,6 +313,80 @@ static parser_error_t get_hash(uint32_t index, proof_t *proof) {
266313 return freeStack ();
267314}
268315
316+ static parser_error_t check_range_proof_inner (proof_t * proof , uint32_t start_index , uint32_t subtrie_size , uint32_t offset ) {
317+ CHECK_INPUT (proof );
318+
319+ uint32_t split_index = next_smaller_po2 (subtrie_size );
320+ print_u32 ("split_point:" , split_index );
321+
322+ uint32_t leaves_end_idx = (proof -> indices .entries + start_index ) - 1 ;
323+ print_u32 ("leaves_end_idx:" , leaves_end_idx );
324+
325+ // Check right subtree
326+ bytes_t right = {0 };
327+ if (leaves_end_idx >= (split_index + offset )) {
328+ uint32_t right_subtrie_size = subtrie_size - split_index ;
329+ if (right_subtrie_size == 1 ) {
330+ right .ptr = proof -> hash_leaf ;
331+ right .len = CX_SHA256_SIZE ;
332+ print_buffer (& right , "right inside if true" );
333+ } else {
334+ print_u32 ("right inside else:" , right_subtrie_size );
335+ CHECK_ERROR (check_range_proof_inner (
336+ proof ,
337+ start_index ,
338+ right_subtrie_size ,
339+ offset + split_index
340+ ));
341+ right .ptr = proof -> hash ;
342+ right .len = CX_SHA256_SIZE ;
343+ }
344+ } else {
345+ if (proof -> lemmas .last_index == 0 ) {
346+ return parser_value_out_of_range ;
347+ }
348+ right .ptr = proof -> lemmas .lemmas .buffer .ptr + CX_SHA256_SIZE * proof -> lemmas .last_index ;
349+ right .len = CX_SHA256_SIZE ;
350+ proof -> lemmas .last_index -- ;
351+ print_buffer (& right , "proof right outside if else" );
352+ }
353+
354+ // Check left subtree
355+ bytes_t left = {0 };
356+ if (start_index < (split_index + offset )) {
357+ uint32_t left_subtrie_size = split_index ;
358+ if (left_subtrie_size == 1 ) {
359+ left .ptr = proof -> hash_leaf ;
360+ left .len = CX_SHA256_SIZE ;
361+ print_buffer (& left , "left inside if true" );
362+ } else {
363+ print_u32 ("left inside else:" , left_subtrie_size );
364+ CHECK_ERROR (check_range_proof_inner (
365+ proof ,
366+ start_index ,
367+ left_subtrie_size ,
368+ offset
369+ ));
370+ left .ptr = proof -> hash ;
371+ left .len = CX_SHA256_SIZE ;
372+ }
373+ } else {
374+ left .ptr = proof -> lemmas .lemmas .buffer .ptr + CX_SHA256_SIZE * proof -> lemmas .last_index ;
375+ left .len = CX_SHA256_SIZE ;
376+ if (proof -> lemmas .last_index > 0 ) {
377+ proof -> lemmas .last_index -- ;
378+ }
379+ print_buffer (& left , "proof left outside if else" );
380+ }
381+
382+ print_string ("MERGING LEFT AND RIGHT" );
383+ print_buffer (& left , "left outside if else" );
384+ print_buffer (& right , "right outside if else" );
385+ merge_branches (left .ptr , right .ptr , proof -> hash );
386+
387+ return parser_ok ;
388+ }
389+
269390/**
270391 * @brief Compute the hash for a given index in the proof.
271392 *
@@ -274,42 +395,33 @@ static parser_error_t get_hash(uint32_t index, proof_t *proof) {
274395 * @return parser_error_t Error code indicating the result of the operation.
275396 */
276397static parser_error_t get_hash_single_proof (uint32_t index , proof_t * proof ) {
277- const uint16_t tmpOffset = proof -> indices .indices .offset ;
278- uint32_t nextIndex = 0 ;
279- CHECK_ERROR (get_next_index (& proof -> indices .indices , & nextIndex ));
398+ CHECK_INPUT (proof );
280399
281- // Check if this index is used
282- if (index == nextIndex ) {
283- CHECK_ERROR (hash_leaf (proof ));
284- return parser_ok ;
285- }
400+ // Compute hash of leaf data
401+ CHECK_ERROR (hash_leaf (proof ));
402+ bytes_t buffer = {0 };
403+ buffer .ptr = proof -> hash_leaf ;
404+ buffer .len = CX_SHA256_SIZE ;
405+ print_buffer (& buffer , "hash leaf" );
286406
287- // If nextIndex doesn't match the requested, restore the offset
288- proof -> indices . indices . offset = tmpOffset ;
407+ // Get the number of left siblings needed
408+ uint32_t num_left_siblings = compute_num_left_siblings ( index ) ;
289409
290- // Check if this index is a lemma
291- if (isLemma (index , nextIndex )) {
292- CTX_CHECK (& proof -> lemmas .lemmas , CX_SHA256_SIZE );
293- memcpy (proof -> hash , proof -> lemmas .lemmas .buffer .ptr + proof -> lemmas .lemmas .offset , CX_SHA256_SIZE );
294- proof -> lemmas .lemmas .offset += CX_SHA256_SIZE ;
295- return parser_ok ;
410+ // Get the number of right siblings needed
411+ if (num_left_siblings > proof -> lemmas .entries ) {
412+ return parser_value_out_of_range ;
296413 }
414+ uint32_t num_right_siblings = proof -> lemmas .entries - num_left_siblings ;
415+ print_u32 ("num_left_siblings:" , num_left_siblings );
416+ print_u32 ("num_right_siblings:" , num_right_siblings );
297417
298- CHECK_ERROR (checkStack ());
418+ uint32_t tree_size = 0 ;
419+ CHECK_ERROR (compute_tree_size (num_right_siblings , index , & tree_size ));
420+ print_u32 ("tree_size:" , tree_size );
299421
300- // Go and find left and right children
301- uint8_t leftHash [CX_SHA256_SIZE ] = {0 };
302- uint8_t rightHash [CX_SHA256_SIZE ] = {0 };
303-
304- CHECK_ERROR (get_hash (get_left_child (index ), proof ));
305- memcpy (leftHash , proof -> hash , CX_SHA256_SIZE );
422+ CHECK_ERROR (check_range_proof_inner (proof , index , tree_size , 0 ));
306423
307- CHECK_ERROR (get_hash (get_right_child (index ), proof ));
308- memcpy (rightHash , proof -> hash , CX_SHA256_SIZE );
309-
310- merge_branches (leftHash , rightHash , proof -> hash );
311-
312- return freeStack ();
424+ return parser_ok ;
313425}
314426
315427/**
@@ -336,6 +448,9 @@ parser_error_t get_metadata_digest(metadata_t *metadata, uint8_t metadataDigest[
336448 CHECK_ERROR (read_u32 (& proof .indices .indices , & leaves_start ));
337449 print_u32 ("leaves_start:" , leaves_start );
338450
451+ CHECK_ERROR (get_hash_single_proof (leaves_start , & proof ));
452+ memcpy (metadataDigest , proof .hash , CX_SHA256_SIZE );
453+
339454 // // CHECK_ERROR(setInitialConditions(&proof));
340455 // const uint8_t MAX_ONE_BYTE_COMPACT = 0x3F;
341456
0 commit comments