From 68c78e4a27f30e7dd1353b7119db074d99f24739 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 25 Jun 2024 18:35:04 +0300 Subject: [PATCH] feat: implement compute_inputs_hash without cdrop --- miden-lib/asm/miden/note.masm | 146 +++++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 2 deletions(-) diff --git a/miden-lib/asm/miden/note.masm b/miden-lib/asm/miden/note.masm index ce533db0a..62a0fac73 100644 --- a/miden-lib/asm/miden/note.masm +++ b/miden-lib/asm/miden/note.masm @@ -311,8 +311,6 @@ export.compute_inputs_hash_cdrop # if num_inputs%8 is not ZERO dup.14 push.0 neq if.true - # check whether we need to drop more than 4 elements - # load the remaining double word mem_stream # => [E, D, A', inputs_ptr'+2, end_addr, num_inputs%8] @@ -433,3 +431,147 @@ export.compute_inputs_hash_cdrop # => [B'] end end + +#! Computes hash of note inputs starting at the specified memory address. +#! +#! Inputs: [inputs_ptr, num_inputs] +#! Outputs: [HASH] +#! +#! Panics if num_inputs is greater than 128. +export.compute_inputs_hash_simple + # move number of inputs to the top of the stack + swap + # => [num_inputs, inputs_ptr] + + # check that number of inputs is less than 128 + dup push.128 u32assert2 u32lte assert.err=ERR_NOTE_TOO_MANY_INPUTS + # => [num_inputs, inputs_ptr] + + # get the number of double words + u32divmod.8 swap + # => [num_inputs/8, num_inputs%8, inputs_ptr] + + # get the end_addr for hash_memory_even proc (end address for pairs of words) + u32wrapping_mul.2 dup.2 u32wrapping_add movup.2 + # => [inputs_ptr, end_addr, num_inputs%8] + + # get the padding flag to add it to the capacity part + dup.2 push.0 neq + # => [pad_flag, inputs_ptr, end_addr, num_inputs%8] + + # prepare hasher state for RPO permutation + push.0.0.0 padw padw + # => [C, B, A, inputs_ptr, end_addr, num_inputs%8] + + # hash every pair of words + dup.13 dup.13 neq + if.true + exec.native::hash_memory_even + end + # => [C', B', A', inputs_ptr', end_addr, num_inputs%8] where inputs_ptr' = end_addr + + # hash remaining input values if there any left + # if num_inputs%8 is not ZERO + dup.14 push.0 neq + if.true + # load the remaining double word + mem_stream + # => [E, D, A', inputs_ptr'+2, end_addr, num_inputs%8] + + # clean the stack + movup.12 drop movup.12 drop + # => [E, D, A', num_inputs%8] + + # get the number of elements we need to drop + # notice that drop_counter could be any number from 1 to 7 + push.8 movup.13 u32wrapping_sub movdn.12 + # => [E, D, A', drop_counter] + + ### 0th value ######################################################## + + # we need to drop first value anyway, since number of values is not divisible by 8 + drop + # => [e_1, e_2, e_3, d_0, d_1, d_2, d_3, A', drop_counter] + + # if current value is the last value to drop (\"cycle\" number equals to the number of values + # to drop), push 1 instead of 0 to the stack + dup.11 eq.1 + # => [0/1, e_1, e_2, e_3, d_0, d_1, d_2, d_3, A', drop_counter] + + # move the calculated value down the stack + movdn.6 + # => [e_1, e_2, e_3, d_0, d_1, d_2, 0/1, d_3, A', drop_counter] + + ### 1st value ######################################################## + + # check whether we still need to drop top stack value and change it to the 0/1 + dup.12 gt.1 + if.true + # if we still need to do so, drop the value and push 0/1 on the stack, depending on + # whether this prop was the last + drop dup.11 eq.2 + end + # if we already dropped all necessary values, just move top stack value to its position + movdn.6 + # => [e_2, e_3, d_0, d_1, d_2, 0/1, e_1_or_0/1, d_3, A', drop_counter] + + ### 2nd value ######################################################## + + dup.12 gt.2 + if.true + drop dup.11 eq.3 + end + movdn.6 + # => [e_3, d_0, d_1, d_2, 0/1, e_1_or_0/1, e_2_or_0/1, d_3, A', drop_counter] + + ### 3rd value ######################################################## + + dup.12 gt.3 + if.true + drop dup.11 eq.4 + end + movdn.6 + # => [d_0, d_1, d_2, 0/1, e_1_or_0/1, e_2_or_0/1, e_3_or_0/1, d_3, A', drop_counter] + + ### 4th value ######################################################## + + dup.12 gt.4 + if.true + drop dup.11 eq.5 + end + movdn.6 + # => [d_1, d_2, 0/1, e_1_or_0/1, e_2_or_0/1, e_3_or_0/1, d_0_or_0/1, d_3, A', drop_counter] + + ### 5th value ######################################################## + + dup.12 gt.5 + if.true + drop dup.11 eq.6 + end + movdn.6 + # => [d_2, 0/1, e_1_or_0/1, e_2_or_0/1, e_3_or_0/1, d_0_or_0/1, d_1_or_0/1, d_3, A', drop_counter] + + ### 6th value ######################################################## + + dup.12 gt.6 + if.true + drop dup.11 eq.7 + end + movdn.6 + # => [0/1, e_1_or_0/1, e_2_or_0/1, e_3_or_0/1, d_0_or_0/1, d_1_or_0/1, d_2_or_0/1, d_3, A', drop_counter] + + + # drop the drop_counter + movup.12 drop + # => [C, B, A'] + + hperm + # => [F, E, D] + + exec.native::state_to_digest + # => [E] + else + dropw movdnw.2 dropw dropw + # => [B'] + end +end \ No newline at end of file